summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml24
-rw-r--r--DONORS.md76
-rw-r--r--core/color.cpp2
-rw-r--r--core/hash_map.h19
-rw-r--r--core/image.cpp4
-rw-r--r--core/input_map.cpp2
-rw-r--r--core/io/config_file.cpp4
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_network.cpp6
-rw-r--r--core/io/http_client.cpp6
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/list.h3
-rw-r--r--core/math/expression.cpp9
-rw-r--r--core/math/expression.h1
-rw-r--r--core/math/math_funcs.h2
-rw-r--r--core/math/vector2.cpp7
-rw-r--r--core/math/vector2.h1
-rw-r--r--core/math/vector3.cpp7
-rw-r--r--core/math/vector3.h1
-rw-r--r--core/os/input_event.cpp13
-rw-r--r--core/os/input_event.h4
-rw-r--r--core/os/os.h2
-rw-r--r--core/project_settings.cpp22
-rw-r--r--core/script_language.h4
-rw-r--r--core/sort_array.h6
-rw-r--r--core/ustring.cpp47
-rw-r--r--core/variant_call.cpp12
-rw-r--r--core/vector.h2
-rw-r--r--doc/classes/@GDScript.xml27
-rw-r--r--doc/classes/Animation.xml13
-rw-r--r--doc/classes/ArrayMesh.xml11
-rw-r--r--doc/classes/AudioEffectReverb.xml2
-rw-r--r--doc/classes/Control.xml8
-rw-r--r--doc/classes/EditorPlugin.xml4
-rw-r--r--doc/classes/Environment.xml2
-rw-r--r--doc/classes/InputEventAction.xml3
-rw-r--r--doc/classes/InputEventKey.xml2
-rw-r--r--doc/classes/LineEdit.xml1
-rw-r--r--doc/classes/Mesh.xml11
-rw-r--r--doc/classes/MultiMeshInstance2D.xml27
-rw-r--r--doc/classes/Navigation.xml2
-rw-r--r--doc/classes/OS.xml13
-rw-r--r--doc/classes/Object.xml15
-rw-r--r--doc/classes/Particles.xml3
-rw-r--r--doc/classes/ParticlesMaterial.xml7
-rw-r--r--doc/classes/Polygon2D.xml2
-rw-r--r--doc/classes/PopupMenu.xml3
-rw-r--r--doc/classes/Position2D.xml2
-rw-r--r--doc/classes/ProjectSettings.xml9
-rw-r--r--doc/classes/Resource.xml2
-rw-r--r--doc/classes/RigidBody.xml4
-rw-r--r--doc/classes/String.xml32
-rw-r--r--doc/classes/TextEdit.xml4
-rw-r--r--doc/classes/Theme.xml2
-rw-r--r--doc/classes/TileSet.xml12
-rw-r--r--doc/classes/Translation.xml4
-rw-r--r--doc/classes/TranslationServer.xml4
-rw-r--r--doc/classes/TreeItem.xml6
-rw-r--r--doc/classes/Vector2.xml11
-rw-r--r--doc/classes/Vector3.xml11
-rw-r--r--doc/classes/VehicleWheel.xml2
-rwxr-xr-xdoc/tools/makerst.py47
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp2
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp25
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp8
-rw-r--r--drivers/gles2/shader_gles2.h2
-rw-r--r--drivers/gles2/shaders/canvas.glsl5
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp17
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp32
-rw-r--r--drivers/gles3/shaders/canvas.glsl5
-rw-r--r--drivers/windows/file_access_windows.cpp4
-rw-r--r--editor/animation_track_editor.cpp10
-rw-r--r--editor/animation_track_editor_plugins.cpp33
-rw-r--r--editor/audio_stream_preview.cpp2
-rw-r--r--editor/code_editor.cpp34
-rw-r--r--editor/code_editor.h1
-rw-r--r--editor/collada/collada.cpp4
-rw-r--r--editor/connections_dialog.cpp70
-rw-r--r--editor/connections_dialog.h8
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/doc/doc_data.cpp3
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_atlas_packer.cpp30
-rw-r--r--editor/editor_atlas_packer.h30
-rw-r--r--editor/editor_audio_buses.cpp417
-rw-r--r--editor/editor_audio_buses.h18
-rw-r--r--editor/editor_data.cpp1
-rw-r--r--editor/editor_export.cpp6
-rw-r--r--editor/editor_feature_profile.cpp30
-rw-r--r--editor/editor_feature_profile.h30
-rw-r--r--editor/editor_file_dialog.cpp9
-rw-r--r--editor/editor_file_dialog.h1
-rw-r--r--editor/editor_help.cpp3
-rw-r--r--editor/editor_help_search.cpp95
-rw-r--r--editor/editor_help_search.h2
-rw-r--r--editor/editor_inspector.cpp5
-rw-r--r--editor/editor_node.cpp119
-rw-r--r--editor/editor_node.h13
-rw-r--r--editor/editor_plugin.cpp43
-rw-r--r--editor/editor_plugin.h2
-rw-r--r--editor/editor_resource_preview.cpp4
-rw-r--r--editor/editor_run_native.cpp12
-rw-r--r--editor/editor_run_native.h5
-rw-r--r--editor/editor_settings.cpp10
-rw-r--r--editor/filesystem_dock.cpp35
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/icons/icon_multi_mesh_instance_2d.svg4
-rw-r--r--editor/icons/icon_project_icon_loading.svg1
-rw-r--r--editor/icons/icon_visual_shader.svg113
-rw-r--r--editor/import/resource_importer_scene.cpp6
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp30
-rw-r--r--editor/import/resource_importer_texture_atlas.h30
-rw-r--r--editor/import/resource_importer_wav.cpp2
-rw-r--r--editor/inspector_dock.cpp6
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp46
-rw-r--r--editor/plugins/animation_player_editor_plugin.h2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp78
-rw-r--r--editor/plugins/asset_library_editor_plugin.h5
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp13
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp41
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp23
-rw-r--r--editor/plugins/editor_preview_plugins.cpp2
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp30
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/particles_editor_plugin.cpp10
-rw-r--r--editor/plugins/script_editor_plugin.cpp47
-rw-r--r--editor/plugins/script_editor_plugin.h1
-rw-r--r--editor/plugins/script_text_editor.cpp96
-rw-r--r--editor/plugins/script_text_editor.h1
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp5
-rw-r--r--editor/plugins/text_editor.h1
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp128
-rw-r--r--editor/plugins/tile_map_editor_plugin.h3
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp1
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/scene_tree_dock.cpp3
-rw-r--r--editor/scene_tree_editor.cpp33
-rw-r--r--editor/scene_tree_editor.h2
-rw-r--r--editor/script_create_dialog.cpp62
-rw-r--r--editor/script_create_dialog.h3
-rw-r--r--editor/script_editor_debugger.cpp7
-rw-r--r--editor/spatial_editor_gizmos.cpp9
-rw-r--r--main/main.cpp7
-rwxr-xr-xmisc/scripts/fix_headers.py8
-rw-r--r--modules/bullet/SCsub6
-rw-r--r--modules/bullet/bullet_physics_server.cpp2
-rw-r--r--modules/bullet/cone_twist_joint_bullet.cpp2
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp4
-rw-r--r--modules/bullet/hinge_joint_bullet.cpp2
-rw-r--r--modules/bullet/pin_joint_bullet.cpp2
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp4
-rw-r--r--modules/gdnative/gdnative/vector2.cpp8
-rw-r--r--modules/gdnative/gdnative/vector3.cpp8
-rw-r--r--modules/gdnative/gdnative_api.json18
-rw-r--r--modules/gdnative/include/gdnative/vector2.h2
-rw-r--r--modules/gdnative/include/gdnative/vector3.h2
-rw-r--r--modules/gdnative/include/pluginscript/godot_pluginscript.h2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.h2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp12
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp8
-rw-r--r--modules/gdscript/gdscript_editor.cpp14
-rw-r--r--modules/gdscript/gdscript_functions.cpp16
-rw-r--r--modules/gdscript/gdscript_functions.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp53
-rw-r--r--modules/gridmap/grid_map.cpp4
-rw-r--r--modules/mono/SCsub5
-rw-r--r--modules/mono/build_scripts/godotsharptools_build.py35
-rw-r--r--modules/mono/build_scripts/mono_configure.py133
-rw-r--r--modules/mono/build_scripts/patches/fix-mono-android-tkill.diff70
-rw-r--r--modules/mono/config.py10
-rw-r--r--modules/mono/csharp_script.h1
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs3
-rw-r--r--modules/mono/editor/godotsharp_export.cpp22
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs5
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs8
-rw-r--r--modules/mono/glue/base_object_glue.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_property.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp26
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h18
-rw-r--r--modules/mono/signal_awaiter_utils.cpp2
-rw-r--r--modules/opus/audio_stream_opus.cpp2
-rw-r--r--modules/recast/navigation_mesh_editor_plugin.cpp4
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml75
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp20
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h1
-rw-r--r--modules/visual_script/visual_script_editor.cpp3
-rw-r--r--modules/visual_script/visual_script_editor.h1
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp3
-rw-r--r--modules/webm/video_stream_webm.cpp7
-rw-r--r--platform/android/export/export.cpp2
-rw-r--r--platform/iphone/export/export.cpp2
-rw-r--r--platform/iphone/icloud.mm2
-rw-r--r--platform/javascript/os_javascript.cpp48
-rw-r--r--platform/javascript/os_javascript.h3
-rw-r--r--platform/osx/os_osx.h1
-rw-r--r--platform/osx/os_osx.mm136
-rw-r--r--platform/server/detect.py6
-rw-r--r--platform/uwp/export/export.cpp4
-rw-r--r--platform/windows/godot_res.rc2
-rw-r--r--platform/windows/os_windows.cpp2
-rw-r--r--platform/x11/detect.py6
-rw-r--r--platform/x11/joypad_linux.cpp6
-rw-r--r--platform/x11/os_x11.cpp31
-rw-r--r--scene/2d/animated_sprite.cpp1
-rw-r--r--scene/2d/camera_2d.cpp7
-rw-r--r--scene/2d/cpu_particles_2d.cpp22
-rw-r--r--scene/2d/cpu_particles_2d.h2
-rw-r--r--scene/2d/line_2d.cpp1
-rw-r--r--scene/2d/mesh_instance_2d.cpp2
-rw-r--r--scene/2d/multimesh_instance_2d.cpp111
-rw-r--r--scene/2d/multimesh_instance_2d.h65
-rw-r--r--scene/2d/physics_body_2d.cpp32
-rw-r--r--scene/2d/position_2d.cpp34
-rw-r--r--scene/2d/position_2d.h7
-rw-r--r--scene/2d/tile_map.cpp16
-rw-r--r--scene/3d/arvr_nodes.cpp4
-rw-r--r--scene/3d/camera.cpp28
-rw-r--r--scene/3d/camera.h1
-rw-r--r--scene/3d/collision_shape.cpp4
-rw-r--r--scene/3d/cpu_particles.cpp20
-rw-r--r--scene/3d/physics_body.cpp32
-rw-r--r--scene/3d/visual_instance.h1
-rw-r--r--scene/animation/animation_blend_tree.cpp2
-rw-r--r--scene/animation/animation_tree.cpp2
-rw-r--r--scene/animation/animation_tree_player.cpp2
-rw-r--r--scene/gui/graph_node.cpp4
-rw-r--r--scene/gui/item_list.cpp20
-rw-r--r--scene/gui/line_edit.cpp7
-rw-r--r--scene/gui/option_button.cpp1
-rw-r--r--scene/gui/popup_menu.cpp56
-rw-r--r--scene/gui/popup_menu.h7
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/text_edit.cpp8
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/gui/tree.cpp59
-rw-r--r--scene/gui/tree.h4
-rw-r--r--scene/main/node.cpp4
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp36
-rw-r--r--scene/register_scene_types.cpp16
-rw-r--r--scene/resources/animation.cpp75
-rw-r--r--scene/resources/animation.h1
-rw-r--r--scene/resources/default_theme/default_theme.cpp12
-rw-r--r--scene/resources/height_map_shape.cpp1
-rw-r--r--scene/resources/mesh.cpp2
-rw-r--r--scene/resources/mesh.h5
-rw-r--r--scene/resources/packed_scene.cpp4
-rw-r--r--scene/resources/particles_material.cpp1
-rw-r--r--scene/resources/primitive_meshes.cpp6
-rw-r--r--scene/resources/primitive_meshes.h1
-rw-r--r--scene/resources/resource_format_text.cpp6
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--scene/resources/tile_set.cpp32
-rw-r--r--scene/resources/tile_set.h1
-rw-r--r--scene/resources/visual_shader.cpp2
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp30
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.h30
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp30
-rw-r--r--servers/audio/effects/audio_stream_generator.h36
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp2
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Quaternion.h5
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Vector3.h2
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp5
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp1
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h12
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp14
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp6
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp206
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h27
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h23
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp16
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h2
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h23
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h28
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h12
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp2
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h1
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp4
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp5
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h1
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h2
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp13
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h2
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp877
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h164
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp4
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp15
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h45
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp86
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h5
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp37
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h2
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h4
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp12
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h2
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h6
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp2
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp33
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.cpp4
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp6
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedObjectArray.h15
-rw-r--r--thirdparty/bullet/LinearMath/btMatrixX.h7
-rw-r--r--thirdparty/bullet/LinearMath/btScalar.h4
-rw-r--r--thirdparty/bullet/LinearMath/btVector3.h2
-rw-r--r--thirdparty/bullet/btBulletCollisionAll.cpp96
-rw-r--r--thirdparty/bullet/btBulletDynamicsAll.cpp42
-rw-r--r--thirdparty/bullet/btLinearMathAll.cpp14
324 files changed, 4536 insertions, 1872 deletions
diff --git a/.travis.yml b/.travis.yml
index b8e02a5be8..587e57c741 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,8 @@ cache:
matrix:
include:
- - env: STATIC_CHECKS=yes
+ - name: Static checks (clang-format)
+ env: STATIC_CHECKS=yes
os: linux
compiler: gcc
addons:
@@ -27,7 +28,8 @@ matrix:
packages:
- clang-format-8
- - env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no warnings=extra werror=yes"
+ - name: Linux editor (debug, GCC 8, with Mono)
+ env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no warnings=extra werror=yes"
os: linux
compiler: gcc-8
addons:
@@ -49,7 +51,8 @@ matrix:
build_command: "scons p=x11 -j2 $OPTIONS"
branch_pattern: coverity_scan
- - env: PLATFORM=x11 TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
+ - name: Linux export template (release, Clang)
+ env: PLATFORM=x11 TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: clang
addons:
@@ -57,19 +60,23 @@ matrix:
packages:
- *linux_deps
- - env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
+ - name: Android export template (release_debug, Clang)
+ env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: clang
- - env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang
+ - name: macOS editor (debug, Clang)
+ env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang
os: osx
compiler: clang
- - env: PLATFORM=iphone TOOLS=no TARGET=debug CACHE_NAME=${PLATFORM}-clang
+ - name: iOS export template (debug, Clang)
+ env: PLATFORM=iphone TOOLS=no TARGET=debug CACHE_NAME=${PLATFORM}-clang
os: osx
compiler: clang
- - env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="warnings=extra werror=yes"
+ - name: Linux headless editor (release_debug, GCC 8)
+ env: PLATFORM=server TOOLS=yes TARGET=release_debug CACHE_NAME=${PLATFORM}-tools-gcc-8 MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: gcc-8
addons:
@@ -80,7 +87,8 @@ matrix:
- *gcc8_deps
- *linux_deps
- - env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5
+ - name: Linux export template (release_debug, GCC 5, without 3D support)
+ env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-5 EXTRA_ARGS="disable_3d=yes"
os: linux
compiler: gcc
addons:
diff --git a/DONORS.md b/DONORS.md
index 95c46c139b..30eb5c220f 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -17,25 +17,24 @@ generous deed immortalized in the next stable release of Godot Engine.
## Gold sponsors
Gamblify <https://www.gamblify.com>
- Image Campus <https://www.imagecampus.edu.ar>
## Mini sponsors
Alan Beauchamp
+ Aleksandar Kordic
Anandarup Mallik
Andrew Dunai
Brandon Lamb
+ Christian Chipont
Christian Uldall Pedersen
Christoph Woinke
- Connor Hill
Denis Malyavin
Edward Flick
GameDev.net
GameDev.tv
Hein-Pieter van Braam
Jacob McKenney
- Javary Games
- Jay Sistar
+ Javary Co.
Justin Arnold
Kyle Szklenski
Leonard Meagher
@@ -44,15 +43,13 @@ generous deed immortalized in the next stable release of Godot Engine.
Mike King
Neal Gompa (Conan Kudo)
Patrick Aarstad
- "Rainway "
Slobodan Milnovic
- StarFlare Software
Stephan Lanfermann
Stephen Telford
Steve
- TigerJ
VilliHaukka
Xananax
+ Y8.com
Zashi
## Gold donors
@@ -77,12 +74,14 @@ generous deed immortalized in the next stable release of Godot Engine.
Andreas Schüle
Asher Glick
Austen McRae
+ Brian van der Stel
+ Carlo Cabanilla
Daniel James
David Giardi
- David Graham
Edward E
Florian Breisch
Gero
+ Javier Roman
Jay Horton
Jon Smith
Jon Woodward
@@ -107,12 +106,12 @@ generous deed immortalized in the next stable release of Godot Engine.
William Wold
Wyatt Goodin
+ Alex Khayrullin
Chris Goddard
Chris Serino
Christian Padilla
Conrad Curry
Craig Smith
- Daniel Egger
Dean Harmon
Ian Richard Kunert
Ivan Trombley
@@ -135,17 +134,18 @@ generous deed immortalized in the next stable release of Godot Engine.
Wojciech Chojnacki
Xavier PATRICELLI
+ Adam Neumann
Alessandra Pereyra
+ Alexander J Maynard
Alexey Dyadchenko
Andrew Bowen
Asdf
- Benjamin W Flint
+ Ben Botwin
Carlos de Sousa Marques
Chris Petrich
Christian Leth Jeppesen
Christoph Schröder
Cody Parker
- ComicSads
D
Daniel
Daniel Eichler
@@ -163,6 +163,8 @@ generous deed immortalized in the next stable release of Godot Engine.
Guilherme Felipe de C. G. da Silva
Heath Hayes
Hysteria
+ Idzard Kwadijk
+ Jared White
Jose Malheiro
Joshua Flores
Juan T Chen
@@ -173,7 +175,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Leandro Voltolino
Maarten Elings
Malcolm Peralty
- Marius Kamm
Markus Fehr
Markus Wiesner
Martin Eigel
@@ -184,6 +185,7 @@ generous deed immortalized in the next stable release of Godot Engine.
M H
Nick Nikitin
Oliver Dick
+ Paolo Munoz
Paul Hocker
Paul Von Zimmerman
Pete Goodwin
@@ -197,7 +199,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Urho
WytRabbit
Xavier Fumado Beltran
- yuanzhe zhou
## Silver donors
@@ -208,6 +209,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Adam Nakonieczny
Adam Smeltzer
Adisibio
+ Agustinus Arya
Aidan O'Flannagain
Alder Stefano
Alessandro Senese
@@ -231,21 +233,23 @@ generous deed immortalized in the next stable release of Godot Engine.
Benedikt
Ben Phelan
Ben Vercammen
+ Ben Woodley
+ Berbank
Bernd Jänichen
Black Block
Blair Allen
Bobby CC Wong
Boyquotes
- Branwen Zak
+ Branwyn Tylwyth
Bryan Stevenson
- Carl Winder
Carwyn Edwards
Chris Brown
Chris Chapin
+ Chris Gonzales
Christian Baune
Christian Winter
Christoffer Sundbom
- Christopher Fisher
+ Christopher Schmitt
Chris Wilson
Clay Heaton
Cobaltum
@@ -262,7 +266,6 @@ generous deed immortalized in the next stable release of Godot Engine.
Dominik Wetzel
Duobix
Edward Herbert
- E.G.
Egon Elbre
Ellen Marie Dash
Elmeri '- Duy Kevin Nguyen
@@ -271,30 +274,33 @@ generous deed immortalized in the next stable release of Godot Engine.
Eric Martini
Eric McCarthy
Eric Williams
- Fabian Lökes
+ Evan Rose
Felix Kollmann
fengjiongmax
- Foomf
+ Flaredown
G3Dev sàrl
Gary Hulst
Gerrit Großkopf
gmmath
Grant Clarke
Greg Olson
- Greg Pennefather
+ Greg P
Guldoman
Heribert Hirth
Hiroshi Naruo
HMan
Hunter Jones
+ Hylpher
ialex32x
Igor Buzatovic
Iiari
+ IndustrialRobot
Isaac Morton
Jaime Ruiz-Borau Vizárraga
Jako Danar
James A F Manley
Jax
+ Jed
Jeff Hungerford
Jeff Nyte
Jeremy Kahn
@@ -302,6 +308,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Joe Alden
Joel Fivat
Joel Setterberg
+ Johannes Eichler
Johannes Wuensch
Jonas Rudlang
Jonas Yamazaki
@@ -316,6 +323,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Juan Negrier
Judd
Julian Murgia
+ Kasier Bald0
KC Chan
kickmaniac
Kiyohiro Kawamura (kyorohiro)
@@ -324,22 +332,24 @@ generous deed immortalized in the next stable release of Godot Engine.
KsyTek Games
Kuan Cheang
kycho
+ Lavik1988
Levi Lindsey
Linus Lind Lundgren
Lionel Gaillard
Luis Moraes
+ LunaticInAHat
+ Lurkars
Macil
- magodev
Major Haul
Malcolm
Malik Ahmed
+ Malik Nejer
+ Marcus Richter
Markus Michael Egger
Martin Holas
Matthew Little
Maxwell
medecau
- Menno Finlay-Smits
- Mertcan Mermerkaya
mhilbrunner
Michael Dürwald
Michael Gringauz
@@ -347,9 +357,9 @@ generous deed immortalized in the next stable release of Godot Engine.
Mikael Olsson
Mikayla Hutchinson
Mike Cunningham
+ mlevin cantu
MoM
Moritz Laass
- Moritz Weissenberger
MuffinManKen
Natrim
nee
@@ -360,6 +370,7 @@ generous deed immortalized in the next stable release of Godot Engine.
Nicolas SAN AGUSTIN
Nithin Jino
NZ
+ Omar Delarosa
Oscar Norlander
Pan Ip
Patrick Forringer
@@ -370,30 +381,30 @@ generous deed immortalized in the next stable release of Godot Engine.
Philip O. Staiger
Pierre-Igor Berthet
Pietro Vertechi
- Piotr Kaczmarski
Pitsanu Tongprasin
Poryg
+ Rafa Laguna
+ Rafal Wyszomirski
Raphael Leroux
- Red Hara
Rémi Verschelde
Ricardo Alcantara
- Rob Crowle
Robert Farr (Larington)
Robert Hernandez
Rodrigo Loli
- Roger Burgess
Roger Smith
Roland RzÄ…sa
Roman Tinkov
Ryan Groom
Ryan Hentz
Saad Khoudmi
- Samdze
+ Samuele Zolfanelli
+ Sanka.X
Sasori Olkof
Scott D. Yelich
Sebastian Michailidis
Shane Sicienski
Shane Spoor
+ Simon Ledam
Simon Wenner
SK
Sootstone
@@ -408,13 +419,18 @@ generous deed immortalized in the next stable release of Godot Engine.
Tim Drumheller
Tim Gudex
Timo Schmidt
+ Timothy B. MacDonald
+ Tobbun
Tom Larrow
Torsten Crass
Travis O'Brien
+ Trent Skinner
Tryggve Sollid
- Tyler Strafos
+ Turgut Temucin
+ Tyler Stafos
UltyX
Vaiktorg
+ Valeria Viana Gusmao
Veodok
Victor
Vigilant Watch
diff --git a/core/color.cpp b/core/color.cpp
index efd2941b47..8959fce4e3 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -525,7 +525,7 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
float Color::gray() const {
ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
return (r + g + b) / 3.0;
}
diff --git a/core/hash_map.h b/core/hash_map.h
index 44459a3080..31332991de 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -162,20 +162,21 @@ private:
new_hash_table[i] = 0;
}
- for (int i = 0; i < (1 << hash_table_power); i++) {
+ if (hash_table) {
+ for (int i = 0; i < (1 << hash_table_power); i++) {
- while (hash_table[i]) {
+ while (hash_table[i]) {
- Element *se = hash_table[i];
- hash_table[i] = se->next;
- int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
- se->next = new_hash_table[new_pos];
- new_hash_table[new_pos] = se;
+ Element *se = hash_table[i];
+ hash_table[i] = se->next;
+ int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
+ se->next = new_hash_table[new_pos];
+ new_hash_table[new_pos] = se;
+ }
}
- }
- if (hash_table)
memdelete_arr(hash_table);
+ }
hash_table = new_hash_table;
hash_table_power = new_hash_table_power;
}
diff --git a/core/image.cpp b/core/image.cpp
index 30af724de9..c85d7f6bcc 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -749,7 +749,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
float scale_factor = MAX(x_scale, 1); // A larger kernel is required only when downscaling
int32_t half_kernel = LANCZOS_TYPE * scale_factor;
- float *kernel = memnew_arr(float, half_kernel * 2 - 1);
+ float *kernel = memnew_arr(float, half_kernel * 2);
for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) {
@@ -800,7 +800,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
float scale_factor = MAX(y_scale, 1);
int32_t half_kernel = LANCZOS_TYPE * scale_factor;
- float *kernel = memnew_arr(float, half_kernel * 2 - 1);
+ float *kernel = memnew_arr(float, half_kernel * 2);
for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) {
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 15f68f9c2a..012c6a7c4f 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -202,7 +202,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
if (p_pressed != NULL)
*p_pressed = input_event_action->is_pressed();
if (p_strength != NULL)
- *p_strength = (*p_pressed) ? 1.0f : 0.0f;
+ *p_strength = (*p_pressed) ? input_event_action->get_strength() : 0.0f;
return input_event_action->get_action() == p_action;
}
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 414742deeb..871e21df3e 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -198,10 +198,6 @@ Error ConfigFile::load(const String &p_path) {
section = next_tag.name;
}
}
-
- memdelete(f);
-
- return OK;
}
void ConfigFile::_bind_methods() {
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 3ff9fa569c..7dea749a43 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -308,8 +308,8 @@ uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
}
Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
-
- return FAILED;
+ ERR_PRINT("Setting UNIX permissions on encrypted files is not implemented yet");
+ return ERR_UNAVAILABLE;
}
FileAccessEncrypted::FileAccessEncrypted() {
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 2572602e16..5dd167c581 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -501,13 +501,13 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
}
uint32_t FileAccessNetwork::_get_unix_permissions(const String &p_file) {
- //could be implemented, not sure if worth it
+ ERR_PRINT("Getting UNIX permissions from network drives is not implemented yet");
return 0;
}
Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
-
- return FAILED;
+ ERR_PRINT("Setting UNIX permissions on network drives is not implemented yet");
+ return ERR_UNAVAILABLE;
}
void FileAccessNetwork::configure() {
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index ce2054db36..891fb7b0ca 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -346,6 +346,12 @@ Error HTTPClient::poll() {
} else {
// We are already handshaking, which means we can use your already active SSL connection
ssl = static_cast<Ref<StreamPeerSSL> >(connection);
+ if (ssl.is_null()) {
+ close();
+ status = STATUS_SSL_HANDSHAKE_ERROR;
+ return ERR_CANT_CONNECT;
+ }
+
ssl->poll(); // Try to finish the handshake
}
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 4638ddcc09..f55af5a96a 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -348,7 +348,7 @@ uint64_t XMLParser::get_node_offset() const {
Error XMLParser::seek(uint64_t p_pos) {
- ERR_FAIL_COND_V(!data, ERR_FILE_EOF)
+ ERR_FAIL_COND_V(!data, ERR_FILE_EOF);
ERR_FAIL_COND_V(p_pos >= length, ERR_FILE_EOF);
P = data + p_pos;
diff --git a/core/list.h b/core/list.h
index 103a82a31d..d1b528562d 100644
--- a/core/list.h
+++ b/core/list.h
@@ -602,9 +602,6 @@ public:
Element *next = current->next_ptr;
- //disconnect
- current->next_ptr = NULL;
-
if (from != current) {
current->prev_ptr = NULL;
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 079c9b524f..e484e9194d 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -70,6 +70,7 @@ const char *Expression::func_name[Expression::FUNC_MAX] = {
"inverse_lerp",
"range_lerp",
"smoothstep",
+ "move_toward",
"dectime",
"randomize",
"randi",
@@ -189,6 +190,7 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) {
case MATH_LERP:
case MATH_INVERSE_LERP:
case MATH_SMOOTHSTEP:
+ case MATH_MOVE_TOWARD:
case MATH_DECTIME:
case MATH_WRAP:
case MATH_WRAPF:
@@ -407,6 +409,13 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
VALIDATE_ARG_NUM(2);
*r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
} break;
+ case MATH_MOVE_TOWARD: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
+ } break;
case MATH_DECTIME: {
VALIDATE_ARG_NUM(0);
diff --git a/core/math/expression.h b/core/math/expression.h
index f20619f0b6..79f6f3989d 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -68,6 +68,7 @@ public:
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
MATH_SMOOTHSTEP,
+ MATH_MOVE_TOWARD,
MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RAND,
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 82b5b56c01..0e3bd8a318 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -224,6 +224,8 @@ public:
float x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f);
return x * x * (3.0f - 2.0f * x);
}
+ static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
+ static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; }
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index 5c1ea5943d..779a28be66 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -164,6 +164,13 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c
return out;
}
+Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
+ Vector2 v = *this;
+ Vector2 vd = p_to - v;
+ real_t len = vd.length();
+ return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
+}
+
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector2 Vector2::slide(const Vector2 &p_normal) const {
#ifdef MATH_CHECKS
diff --git a/core/math/vector2.h b/core/math/vector2.h
index a0c6024c9f..78a1641c1e 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -79,6 +79,7 @@ struct Vector2 {
_FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const;
_FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const;
Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const;
+ Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
Vector2 slide(const Vector2 &p_normal) const;
Vector2 bounce(const Vector2 &p_normal) const;
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 1c28934422..73927821cf 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -127,6 +127,13 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c
return out;
}
+Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
+ Vector3 v = *this;
+ Vector3 vd = p_to - v;
+ real_t len = vd.length();
+ return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
+}
+
Vector3::operator String() const {
return (rtos(x) + ", " + rtos(y) + ", " + rtos(z));
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 21fc09653f..6423147282 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -94,6 +94,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 slerp(const Vector3 &p_b, real_t p_t) const;
Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const;
Vector3 cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const;
+ Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index a072017353..9c5066da3d 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -1010,6 +1010,14 @@ bool InputEventAction::is_pressed() const {
return pressed;
}
+void InputEventAction::set_strength(float p_strength) {
+ strength = CLAMP(p_strength, 0.0f, 1.0f);
+}
+
+float InputEventAction::get_strength() const {
+ return strength;
+}
+
bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event) const {
if (p_event.is_null())
return false;
@@ -1051,14 +1059,19 @@ void InputEventAction::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventAction::set_pressed);
//ClassDB::bind_method(D_METHOD("is_pressed"), &InputEventAction::is_pressed);
+ ClassDB::bind_method(D_METHOD("set_strength", "strength"), &InputEventAction::set_strength);
+ ClassDB::bind_method(D_METHOD("get_strength"), &InputEventAction::get_strength);
+
// ClassDB::bind_method(D_METHOD("is_action", "name"), &InputEventAction::is_action);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength");
}
InputEventAction::InputEventAction() {
pressed = false;
+ strength = 1.0f;
}
/////////////////////////////
diff --git a/core/os/input_event.h b/core/os/input_event.h
index ba01516519..7a9a1f71c3 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -475,6 +475,7 @@ class InputEventAction : public InputEvent {
StringName action;
bool pressed;
+ float strength;
protected:
static void _bind_methods();
@@ -486,6 +487,9 @@ public:
void set_pressed(bool p_pressed);
virtual bool is_pressed() const;
+ void set_strength(float p_strength);
+ float get_strength() const;
+
virtual bool is_action(const StringName &p_action) const;
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
diff --git a/core/os/os.h b/core/os/os.h
index 4f6a539e78..b128e6424c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -104,7 +104,6 @@ public:
bool maximized;
bool always_on_top;
bool use_vsync;
- bool layered_splash;
bool layered;
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, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) {
@@ -117,7 +116,6 @@ public:
always_on_top = p_always_on_top;
use_vsync = p_use_vsync;
layered = false;
- layered_splash = false;
}
};
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 2fd22d4789..0508806a35 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -75,11 +75,19 @@ String ProjectSettings::localize_path(const String &p_path) const {
memdelete(dir);
- if (!cwd.begins_with(resource_path)) {
+ // Ensure that we end with a '/'.
+ // This is important to ensure that we do not wrongly localize the resource path
+ // in an absolute path that just happens to contain this string but points to a
+ // different folder (e.g. "/my/project" as resource_path would be contained in
+ // "/my/project_data", even though the latter is not part of res://.
+ // `plus_file("")` is an easy way to ensure we have a trailing '/'.
+ const String res_path = resource_path.plus_file("");
+
+ if (!cwd.begins_with(res_path)) {
return p_path;
};
- return cwd.replace_first(resource_path, "res:/");
+ return cwd.replace_first(res_path, "res://");
} else {
memdelete(dir);
@@ -481,7 +489,7 @@ Error ProjectSettings::_load_settings_binary(const String p_path) {
memdelete(f);
ERR_EXPLAIN("Corrupted header in binary project.binary (not ECFG)");
- ERR_FAIL_V(ERR_FILE_CORRUPT;)
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
}
uint32_t count = f->get_32();
@@ -571,10 +579,6 @@ Error ProjectSettings::_load_settings_text(const String p_path) {
section = next_tag.name;
}
}
-
- memdelete(f);
-
- return OK;
}
Error ProjectSettings::_load_settings_text_or_binary(const String p_text_path, const String p_bin_path) {
@@ -632,7 +636,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
if (err != OK) {
ERR_EXPLAIN("Couldn't save project.binary at " + p_file);
- ERR_FAIL_COND_V(err, err)
+ ERR_FAIL_COND_V(err, err);
}
uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
@@ -724,7 +728,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
if (err) {
ERR_EXPLAIN("Couldn't save project.godot - " + p_file);
- ERR_FAIL_COND_V(err, err)
+ ERR_FAIL_COND_V(err, err);
}
file->store_line("; Engine configuration file.");
diff --git a/core/script_language.h b/core/script_language.h
index b2dab666c4..b0c60b4e90 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -250,7 +250,7 @@ public:
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual bool overrides_external_editor() { return false; }
- 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) { return ERR_UNAVAILABLE; }
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
struct LookupResult {
enum Type {
@@ -269,7 +269,7 @@ public:
int location;
};
- virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; }
+ virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; }
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const = 0;
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) = 0;
diff --git a/core/sort_array.h b/core/sort_array.h
index 0f258aec3e..8660ee3333 100644
--- a/core/sort_array.h
+++ b/core/sort_array.h
@@ -179,14 +179,14 @@ public:
while (true) {
while (compare(p_array[p_first], p_pivot)) {
if (Validate) {
- ERR_BAD_COMPARE(p_first == unmodified_last - 1)
+ ERR_BAD_COMPARE(p_first == unmodified_last - 1);
}
p_first++;
}
p_last--;
while (compare(p_pivot, p_array[p_last])) {
if (Validate) {
- ERR_BAD_COMPARE(p_last == unmodified_first)
+ ERR_BAD_COMPARE(p_last == unmodified_first);
}
p_last--;
}
@@ -259,7 +259,7 @@ public:
int next = p_last - 1;
while (compare(p_value, p_array[next])) {
if (Validate) {
- ERR_BAD_COMPARE(next == 0)
+ ERR_BAD_COMPARE(next == 0);
}
p_array[p_last] = p_array[next];
p_last = next;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 954c39c150..741c825448 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -2956,26 +2956,12 @@ String String::replace(const char *p_key, const char *p_with) const {
String String::replace_first(const String &p_key, const String &p_with) const {
- String new_string;
- int search_from = 0;
- int result = 0;
-
- while ((result = find(p_key, search_from)) >= 0) {
-
- new_string += substr(search_from, result - search_from);
- new_string += p_with;
- search_from = result + p_key.length();
- break;
+ int pos = find(p_key);
+ if (pos >= 0) {
+ return substr(0, pos) + p_with + substr(pos + p_key.length(), length());
}
- if (search_from == 0) {
-
- return *this;
- }
-
- new_string += substr(search_from, length() - search_from);
-
- return new_string;
+ return *this;
}
String String::replacen(const String &p_key, const String &p_with) const {
@@ -3102,29 +3088,16 @@ String String::strip_edges(bool left, bool right) const {
String String::strip_escapes() const {
- int len = length();
- int beg = 0, end = len;
-
+ String new_string;
for (int i = 0; i < length(); i++) {
- if (operator[](i) <= 31)
- beg++;
- else
- break;
- }
-
- for (int i = (int)(length() - 1); i >= 0; i--) {
-
- if (operator[](i) <= 31)
- end--;
- else
- break;
+ // Escape characters on first page of the ASCII table, before 32 (Space).
+ if (operator[](i) < 32)
+ continue;
+ new_string += operator[](i);
}
- if (beg == 0 && end == len)
- return *this;
-
- return substr(beg, end - beg);
+ return new_string;
}
String String::lstrip(const String &p_chars) const {
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index f9f73b4e51..b3a4a13b08 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -265,6 +265,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(String, right);
VCALL_LOCALMEM0R(String, dedent);
VCALL_LOCALMEM2R(String, strip_edges);
+ VCALL_LOCALMEM0R(String, strip_escapes);
VCALL_LOCALMEM1R(String, lstrip);
VCALL_LOCALMEM1R(String, rstrip);
VCALL_LOCALMEM0R(String, get_extension);
@@ -347,6 +348,7 @@ struct _VariantCall {
VCALL_LOCALMEM2R(Vector2, linear_interpolate);
VCALL_LOCALMEM2R(Vector2, slerp);
VCALL_LOCALMEM4R(Vector2, cubic_interpolate);
+ VCALL_LOCALMEM2R(Vector2, move_toward);
VCALL_LOCALMEM1R(Vector2, rotated);
VCALL_LOCALMEM0R(Vector2, tangent);
VCALL_LOCALMEM0R(Vector2, floor);
@@ -388,6 +390,7 @@ struct _VariantCall {
VCALL_LOCALMEM2R(Vector3, linear_interpolate);
VCALL_LOCALMEM2R(Vector3, slerp);
VCALL_LOCALMEM4R(Vector3, cubic_interpolate);
+ VCALL_LOCALMEM2R(Vector3, move_toward);
VCALL_LOCALMEM1R(Vector3, dot);
VCALL_LOCALMEM1R(Vector3, cross);
VCALL_LOCALMEM1R(Vector3, outer);
@@ -1516,9 +1519,9 @@ void register_variant_methods() {
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());
- ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0));
- ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, rsplit, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0));
- ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
+ ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0));
+ ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0));
+ ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true));
ADDFUNC0R(STRING, STRING, String, to_upper, varray());
ADDFUNC0R(STRING, STRING, String, to_lower, varray());
@@ -1526,6 +1529,7 @@ void register_variant_methods() {
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, strip_escapes, varray());
ADDFUNC1R(STRING, STRING, String, lstrip, STRING, "chars", varray());
ADDFUNC1R(STRING, STRING, String, rstrip, STRING, "chars", varray());
ADDFUNC0R(STRING, STRING, String, get_extension, varray());
@@ -1583,6 +1587,7 @@ void register_variant_methods() {
ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray());
ADDFUNC2R(VECTOR2, VECTOR2, Vector2, slerp, VECTOR2, "b", REAL, "t", varray());
ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray());
+ ADDFUNC2R(VECTOR2, VECTOR2, Vector2, move_toward, VECTOR2, "to", REAL, "delta", varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray());
ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray());
ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray());
@@ -1624,6 +1629,7 @@ void register_variant_methods() {
ADDFUNC2R(VECTOR3, VECTOR3, Vector3, slerp, VECTOR3, "b", REAL, "t", varray());
ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray());
ADDFUNC1R(VECTOR3, VECTOR3, Vector3, direction_to, VECTOR3, "b", varray());
+ ADDFUNC2R(VECTOR3, VECTOR3, Vector3, move_toward, VECTOR3, "to", REAL, "delta", 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());
diff --git a/core/vector.h b/core/vector.h
index 93ee003519..e6bb4a96fc 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -150,7 +150,7 @@ template <class T>
bool Vector<T>::push_back(const T &p_elem) {
Error err = resize(size() + 1);
- ERR_FAIL_COND_V(err, true)
+ ERR_FAIL_COND_V(err, true);
set(size() - 1, p_elem);
return false;
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index 63b9ef13fd..b6de5dbf62 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -92,13 +92,13 @@
<argument index="0" name="condition" type="bool">
</argument>
<description>
- Assert that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code] a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always [code]true[/code].
+ Asserts that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code], an error is generated and the program is halted until you resume it. Only executes in debug builds, or when running the game from the editor. Use it for debugging purposes, to make sure a statement is [code]true[/code] during development.
[codeblock]
- # Speed should always be between 0 and 20
+ # Imagine we always want speed to be between 0 and 20
speed = -10
- assert(speed &lt; 20) # Is true and program continues
- assert(speed &gt;= 0) # Is false and program stops
- assert(speed &gt;= 0 &amp;&amp; speed &lt; 20) # Or combined
+ assert(speed &lt; 20) # True, the program will continue
+ assert(speed &gt;= 0) # False, the program will stop
+ assert(speed &gt;= 0 &amp;&amp; speed &lt; 20) # You can also combine the two conditional statements in one check
[/codeblock]
</description>
</method>
@@ -640,6 +640,23 @@
[/codeblock]
</description>
</method>
+ <method name="move_toward">
+ <return type="float">
+ </return>
+ <argument index="0" name="from" type="float">
+ </argument>
+ <argument index="1" name="to" type="float">
+ </argument>
+ <argument index="2" name="delta" type="float">
+ </argument>
+ <description>
+ Moves [code]from[/code] toward [code]to[/code] by the [code]delta[/code] value.
+ Use a negative [code]delta[/code] value to move away.
+ [codeblock]
+ move_toward(10, 5, 4) # returns 6
+ [/codeblock]
+ </description>
+ </method>
<method name="nearest_po2">
<return type="int">
</return>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 9885f30883..c79903cb80 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -536,6 +536,19 @@
Set the interpolation type of a given track, from the INTERPOLATION_* enum.
</description>
</method>
+ <method name="track_set_key_time">
+ <return type="void">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <argument index="1" name="key_idx" type="int">
+ </argument>
+ <argument index="2" name="time" type="float">
+ </argument>
+ <description>
+ Set the time of an existing key.
+ </description>
+ </method>
<method name="track_set_key_transition">
<return type="void">
</return>
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 1707ea07e0..745d803a30 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -155,17 +155,6 @@
Remove a surface at position surf_idx, shifting greater surfaces one surf_idx slot down.
</description>
</method>
- <method name="surface_set_material">
- <return type="void">
- </return>
- <argument index="0" name="surf_idx" type="int">
- </argument>
- <argument index="1" name="material" type="Material">
- </argument>
- <description>
- Set a [Material] for a given surface. Surface will be rendered using this material.
- </description>
- </method>
<method name="surface_set_name">
<return type="void">
</return>
diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml
index fde22c9238..8c9652eee2 100644
--- a/doc/classes/AudioEffectReverb.xml
+++ b/doc/classes/AudioEffectReverb.xml
@@ -21,7 +21,7 @@
<member name="hipass" type="float" setter="set_hpf" getter="get_hpf">
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">
+ <member name="predelay_feedback" type="float" setter="set_predelay_feedback" getter="get_predelay_feedback">
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">
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 22061322c8..fea706987c 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -4,7 +4,7 @@
All User Interface nodes inherit from Control. A control's anchors and margins adapt its position and size relative to its parent.
</brief_description>
<description>
- Base class for all User Interface or [i]UI[/i] related nodes. [Control] features a bounding rectangle that defines its extents, an anchor position relative to its parent and margins that represent an offset to the anchor. The margins update automatically when the node, any of its parents, or the screen size change.
+ Base class for all User Interface or [i]UI[/i] related nodes. [Control] features a bounding rectangle that defines its extents, an anchor position relative to its parent control or the current viewport, and margins that represent an offset to the anchor. The margins update automatically when the node, any of its parents, or the screen size change.
For more information on Godot's UI system, anchors, margins, and containers, see the related tutorials in the manual. To build flexible UIs, you'll need a mix of UI elements that inherit from [Control] and [Container] nodes.
[b]User Interface nodes and input[/b]
Godot sends input events to the scene's root node first, by calling [method Node._input]. [method Node._input] forwards the event down the node tree to the nodes under the mouse cursor, or on keyboard focus. To do so, it calls [method MainLoop._input_event]. Call [method accept_event] so no other node receives the event. Once you accepted an input, it becomes handled so [method Node._unhandled_input] will not process it.
@@ -714,7 +714,7 @@
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents">
Enables whether rendering of children should be clipped to this control's rectangle. If [code]true[/code], parts of a child which would be visibly outside of this control's rectangle will not be rendered.
</member>
- <member name="rect_global_position" type="Vector2" setter="set_global_position" getter="get_global_position">
+ <member name="rect_global_position" type="Vector2" setter="_set_global_position" getter="get_global_position">
The node's global position, relative to the world (usually to the top-left corner of the window).
</member>
<member name="rect_min_size" type="Vector2" setter="set_custom_minimum_size" getter="get_custom_minimum_size">
@@ -723,7 +723,7 @@
<member name="rect_pivot_offset" type="Vector2" setter="set_pivot_offset" getter="get_pivot_offset">
By default, the node's pivot is its top-left corner. When you change its [member rect_scale], it will scale around this pivot. Set this property to [member rect_size] / 2 to center the pivot in the node's rectangle.
</member>
- <member name="rect_position" type="Vector2" setter="set_position" getter="get_position">
+ <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_degrees" getter="get_rotation_degrees">
@@ -732,7 +732,7 @@
<member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale">
The node's scale, relative to its [member rect_size]. Change this property to scale the node around its [member rect_pivot_offset].
</member>
- <member name="rect_size" type="Vector2" setter="set_size" getter="get_size">
+ <member name="rect_size" type="Vector2" setter="_set_size" getter="get_size">
The size of the node's bounding rectangle, in pixels. [Container] nodes update this property automatically.
</member>
<member name="size_flags_horizontal" type="int" setter="set_h_size_flags" getter="get_h_size_flags">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 97ad4f6829..3d91bff0aa 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -525,6 +525,10 @@
</constant>
<constant name="CONTAINER_PROPERTY_EDITOR_BOTTOM" value="9" enum="CustomControlContainer">
</constant>
+ <constant name="CONTAINER_PROJECT_SETTING_TAB_LEFT" value="10" enum="CustomControlContainer">
+ </constant>
+ <constant name="CONTAINER_PROJECT_SETTING_TAB_RIGHT" value="11" enum="CustomControlContainer">
+ </constant>
<constant name="DOCK_SLOT_LEFT_UL" value="0" enum="DockSlot">
</constant>
<constant name="DOCK_SLOT_LEFT_BL" value="1" enum="DockSlot">
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 5f8dc552d7..2a4ab4ce0d 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -217,7 +217,7 @@
</member>
<member name="ssao_bias" type="float" setter="set_ssao_bias" getter="get_ssao_bias">
</member>
- <member name="ssao_blur" type="int" setter="set_ssao_blur" getter="is_ssao_blur_enabled" enum="Environment.SSAOBlur">
+ <member name="ssao_blur" type="int" setter="set_ssao_blur" getter="get_ssao_blur" enum="Environment.SSAOBlur">
</member>
<member name="ssao_color" type="Color" setter="set_ssao_color" getter="get_ssao_color">
</member>
diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml
index 25e9073ec7..9df7bbca74 100644
--- a/doc/classes/InputEventAction.xml
+++ b/doc/classes/InputEventAction.xml
@@ -18,6 +18,9 @@
<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>
+ <member name="strength" type="float" setter="set_strength" getter="get_strength">
+ The action's strength between 0 and 1. This value is consired as equal to 0 if pressed is [code]false[/code]. The event strength allows faking analog joypad motion events, by precising how strongly is the joypad axis bent or pressed.
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml
index 86a1362230..53b1f74bd4 100644
--- a/doc/classes/InputEventKey.xml
+++ b/doc/classes/InputEventKey.xml
@@ -29,7 +29,7 @@
Key scancode, one of the [enum KeyList] constants.
</member>
<member name="unicode" type="int" setter="set_unicode" getter="get_unicode">
- Key unicode identifier when relevant.
+ Key unicode identifier when relevant. Unicode identifiers for the composite characters and complex scripts may not be available unless IME input mode is active. See [method OS.set_ime_active] for more information.
</member>
</members>
<constants>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index bb180b591d..184987d2dd 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -166,6 +166,7 @@
</constant>
<constant name="MENU_PASTE" value="2" enum="MenuItems">
Pastes the clipboard text over the selected text (or at the cursor's position).
+ Non-printable escape characters are automatically stripped from the OS clipboard via [method String.strip_escapes].
</constant>
<constant name="MENU_CLEAR" value="3" enum="MenuItems">
Erases the whole [LineEdit] text.
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index b8bc5cbd11..048e7074f1 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -80,6 +80,17 @@
Returns a [Material] in a given surface. Surface is rendered using this material.
</description>
</method>
+ <method name="surface_set_material">
+ <return type="void">
+ </return>
+ <argument index="0" name="surf_idx" type="int">
+ </argument>
+ <argument index="1" name="material" type="Material">
+ </argument>
+ <description>
+ Set a [Material] for a given surface. Surface will be rendered using this material.
+ </description>
+ </method>
</methods>
<members>
<member name="lightmap_size_hint" type="Vector2" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint">
diff --git a/doc/classes/MultiMeshInstance2D.xml b/doc/classes/MultiMeshInstance2D.xml
new file mode 100644
index 0000000000..0bf243ee24
--- /dev/null
+++ b/doc/classes/MultiMeshInstance2D.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MultiMeshInstance2D" inherits="Node2D" category="Core" version="3.2">
+ <brief_description>
+ Node that instances a [MultiMesh] in 2D.
+ </brief_description>
+ <description>
+ [MultiMeshInstance2D] is a specialized node to instance a [MultiMesh] resource in 2D.
+ Usage is the same as [MultiMeshInstance].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="multimesh" type="MultiMesh" setter="set_multimesh" getter="get_multimesh">
+ The [MultiMesh] that will be drawn by the [MultiMeshInstance2D].
+ </member>
+ <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
+ The normal map that will be used if using the default [CanvasItemMaterial].
+ </member>
+ <member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml
index 3690c1d682..f0ae3fef99 100644
--- a/doc/classes/Navigation.xml
+++ b/doc/classes/Navigation.xml
@@ -59,7 +59,7 @@
<argument index="2" name="optimize" type="bool" default="true">
</argument>
<description>
- Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (raidus, height, etc.) are considered in the path calculation, otherwise they are ignored.
+ Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (radius, height, etc.) are considered in the path calculation, otherwise they are ignored.
</description>
</method>
<method name="navmesh_add">
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index dd0fcd63e7..2592bc6775 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -221,14 +221,16 @@
<return type="Vector2">
</return>
<description>
- Returns IME selection range.
+ Returns IME cursor position (currently edited portion of the string) relative to the characters in the composition string.
+ [code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME cursor position.
</description>
</method>
<method name="get_ime_text" qualifiers="const">
<return type="String">
</return>
<description>
- Returns IME intermediate text.
+ Returns IME intermediate composition string.
+ [code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME composition string.
</description>
</method>
<method name="get_latin_keyboard_variant" qualifiers="const">
@@ -710,6 +712,9 @@
</argument>
<description>
Sets whether IME input mode should be enabled.
+ If active IME handles key events before the application and creates an composition string and suggestion list.
+ Application can retrieve the composition status by using [method get_ime_selection] and [method get_ime_text] functions.
+ Completed composition string is committed when input is finished.
</description>
</method>
<method name="set_ime_position">
@@ -813,6 +818,7 @@
</member>
<member name="window_borderless" type="bool" setter="set_borderless_window" getter="get_borderless_window">
If [code]true[/code], removes the window frame.
+ Note: Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency.
</member>
<member name="window_fullscreen" type="bool" setter="set_window_fullscreen" getter="is_window_fullscreen">
If [code]true[/code], the window is fullscreen.
@@ -824,6 +830,9 @@
If [code]true[/code], the window is minimized.
</member>
<member name="window_per_pixel_transparency_enabled" type="bool" setter="set_window_per_pixel_transparency_enabled" getter="get_window_per_pixel_transparency_enabled">
+ If [code]true[/code], the window background is transparent and window frame is removed.
+ Use [code]get_tree().get_root().set_transparent_background(true)[/code] to disable main viewport background rendering.
+ Note: This property has no effect if "Project &gt; Project Settings &gt; Display &gt; Window &gt; Per-pixel transparency &gt; Allowed" setting is disabled.
</member>
<member name="window_position" type="Vector2" setter="set_window_position" getter="get_window_position">
The window position relative to the screen, the origin is the top left corner, +Y axis goes to the bottom and +X axis goes to the right.
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index dbbd974b04..c9910360ed 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -4,12 +4,12 @@
Base class for all non built-in types.
</brief_description>
<description>
- Base class for all non built-in types. Everything which is not a built-in type starts the inheritance chain from this class.
- Objects can be constructed from scripting languages, using [code]Object.new()[/code] in GDScript, [code]new Object[/code] in C#, or the "Construct Object" node in VisualScript.
- 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 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.
+ Every class which is not a built-in type inherits from this class.
+ You can construct Objects from scripting languages, using [code]Object.new()[/code] in GDScript, [code]new Object[/code] in C#, or the "Construct Object" node in VisualScript.
+ Objects do not manage memory. If a class inherits from Object, you will have to delete instances of it manually. To do so, call the [method free] method from your script or delete the instance from C++.
+ Some classes that extend Object add memory management. This is the case of [Reference], which counts references and deletes itself automatically when no longer referenced. [Node], another fundamental type, deletes all its children when freed from memory.
Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [method _set]. However, scripting languages and C++ have simpler means to export them.
- 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.
+ Objects also receive notifications. Notifications are a simple way to notify the object about simple events, so they can all be handled together. See [method _notification].
</description>
<tutorials>
</tutorials>
@@ -126,7 +126,9 @@
<argument index="4" name="flags" type="int" default="0">
</argument>
<description>
- 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.
+ 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.
+ If the [code]target[/code] is destroyed in the game's lifecycle, the connection will be lost.
</description>
</method>
<method name="disconnect">
@@ -140,6 +142,7 @@
</argument>
<description>
Disconnects a [code]signal[/code] from a [code]method[/code] on the given [code]target[/code].
+ If you try to disconnect a connection that does not exist, the method will throw an error. Use [method is_connected] to ensure that the connection exists.
</description>
</method>
<method name="emit_signal" qualifiers="vararg">
diff --git a/doc/classes/Particles.xml b/doc/classes/Particles.xml
index 0023fce97d..7820c63ad7 100644
--- a/doc/classes/Particles.xml
+++ b/doc/classes/Particles.xml
@@ -15,13 +15,14 @@
<return type="AABB">
</return>
<description>
+ Returns the bounding box that contains all the particles that are active in the current frame.
</description>
</method>
<method name="restart">
<return type="void">
</return>
<description>
- Restarts the particle emmission, clearing existing particles.
+ Restarts the particle emission, clearing existing particles.
</description>
</method>
</methods>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 6ae5afeac5..dd7a7cd151 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -214,14 +214,19 @@
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" enum="Parameter">
+ Represents the size of the [enum Parameter] enum.
</constant>
<constant name="FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="Flags">
Use with [method set_flag] to set [member flag_align_y].
</constant>
<constant name="FLAG_ROTATE_Y" value="1" enum="Flags">
- Use with [method set_flag] to set [member flag_rotate_y]
+ Use with [method set_flag] to set [member flag_rotate_y].
+ </constant>
+ <constant name="FLAG_DISABLE_Z" value="2" enum="Flags">
+ Use with [method set_flag] to set [member flag_disable_z].
</constant>
<constant name="FLAG_MAX" value="3" enum="Flags">
+ Represents the size of the [enum Flags] enum.
</constant>
<constant name="EMISSION_SHAPE_POINT" value="0" enum="EmissionShape">
All particles will be emitted from a single point.
diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml
index 7098f5f071..8f434e5499 100644
--- a/doc/classes/Polygon2D.xml
+++ b/doc/classes/Polygon2D.xml
@@ -109,7 +109,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_rotation_degrees" getter="get_texture_rotation_degrees">
+ <member name="texture_rotation" type="float" setter="set_texture_rotation" getter="get_texture_rotation">
The texture's rotation in radians.
</member>
<member name="texture_rotation_degrees" type="float" setter="set_texture_rotation_degrees" getter="get_texture_rotation_degrees">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index d4f4834a66..d6249f73aa 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -515,6 +515,9 @@
</method>
</methods>
<members>
+ <member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search">
+ If [code]true[/code], allows to navigate [PopupMenu] with letter keys. Default value: [code]false[/code].
+ </member>
<member name="hide_on_checkable_item_selection" type="bool" setter="set_hide_on_checkable_item_selection" getter="is_hide_on_checkable_item_selection">
</member>
<member name="hide_on_item_selection" type="bool" setter="set_hide_on_item_selection" getter="is_hide_on_item_selection">
diff --git a/doc/classes/Position2D.xml b/doc/classes/Position2D.xml
index 034e35d9d7..916bd99131 100644
--- a/doc/classes/Position2D.xml
+++ b/doc/classes/Position2D.xml
@@ -4,7 +4,7 @@
Generic 2D Position hint for editing.
</brief_description>
<description>
- Generic 2D Position hint for editing. It's just like a plain [Node2D] but displays as a cross in the 2D-Editor at all times.
+ Generic 2D Position hint for editing. It's just like a plain [Node2D] but displays as a cross in the 2D-Editor at all times. You can set visual size of the cross by changing Gizmo Extents in the inspector.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index ff8b702859..196fcbfaaa 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -374,11 +374,10 @@
Default orientation on mobile devices.
</member>
<member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter="">
- If [code]true[/code], allows per-pixel transparency in a desktop window. This affects performance if not needed, so leave it on [code]false[/code] unless you need it.
+ If [code]true[/code], allows per-pixel transparency in a desktop window. This affects performance, so leave it on [code]false[/code] unless you need it.
</member>
<member name="display/window/per_pixel_transparency/enabled" type="bool" setter="" getter="">
- </member>
- <member name="display/window/per_pixel_transparency/splash" type="bool" setter="" getter="">
+ Set the window background to transparent when it starts.
</member>
<member name="display/window/size/always_on_top" type="bool" setter="" getter="">
Force the window to be always on top.
@@ -410,6 +409,8 @@
<member name="editor/active" type="bool" setter="" getter="">
Internal editor setting, don't touch.
</member>
+ <member name="editor/search_in_file_extensions" type="PoolStringArray" setter="" getter="">
+ </member>
<member name="gui/common/default_scroll_deadzone" type="int" setter="" getter="">
</member>
<member name="gui/common/swap_ok_cancel" type="bool" setter="" getter="">
@@ -721,7 +722,7 @@
Shaders have a time variable that constantly increases. At some point, it needs to be rolled back to zero to avoid precision errors on shader animations. This setting specifies when (in seconds).
</member>
<member name="rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround" type="bool" setter="" getter="">
- Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913][/url] for details.
+ Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913]GitHub issue 9913[/url] for details.
If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option only impacts the GLES2 rendering backend (so the bug stays if you use GLES3), and only desktop platforms.
</member>
<member name="rendering/quality/2d/use_pixel_snap" type="bool" setter="" getter="">
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 8b6fb549aa..211bda1a09 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -7,7 +7,7 @@
Resource is the base class for all resource types, serving primarily as data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
</description>
<tutorials>
- <link>https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html</link>
+ <link>https://docs.godotengine.org/en/latest/getting_started/step_by_step/resources.html</link>
</tutorials>
<methods>
<method name="_setup_local_to_scene" qualifiers="virtual">
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index 9ea6bb0fe1..8dadca49e1 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -119,10 +119,10 @@
Lock the body's movement in the x-axis.
</member>
<member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock">
- Lock the body's movement in the x-axis.
+ Lock the body's movement in the y-axis.
</member>
<member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock">
- Lock the body's movement in the x-axis.
+ Lock the body's movement in the z-axis.
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
RigidBody's bounciness.
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index e06f0738b8..af7e5a395a 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -7,7 +7,7 @@
This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necessary means for string handling. Strings are reference counted and use a copy-on-write approach, so passing them around is cheap in resources.
</description>
<tutorials>
- <link>https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_format_string.html</link>
+ <link>https://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_format_string.html</link>
</tutorials>
<methods>
<method name="String">
@@ -662,16 +662,17 @@
<method name="rsplit">
<return type="PoolStringArray">
</return>
- <argument index="0" name="divisor" type="String">
+ <argument index="0" name="delimiter" type="String">
</argument>
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<argument index="2" name="maxsplit" type="int" default="0">
</argument>
<description>
- Splits the string by a [code]divisor[/code] string and returns an array of the substrings, starting from right.
- [b]Example:[/b] [code]"One,Two,Three"[/code] will return [code]["One","Two","Three"][/code] if split by [code]","[/code].
- If [code]maxsplit[/code] is specified, then it is number of splits to do, default is 0 which splits all the items.
+ Splits the string by a [code]delimiter[/code] string and returns an array of the substrings, starting from right.
+ The splits in the returned array are sorted in the same order as the original string, from left to right.
+ If [code]maxsplit[/code] is specified, it defines the number of splits to do from the right up to [code]maxsplit[/code]. The default value of 0 means that all items are split, thus giving the same result as [method split].
+ [b]Example:[/b] [code]"One,Two,Three,Four"[/code] will return [code]["Three","Four"][/code] if split by [code]","[/code] with [code]maxsplit[/code] of 2.
</description>
</method>
<method name="rstrip">
@@ -709,27 +710,27 @@
<method name="split">
<return type="PoolStringArray">
</return>
- <argument index="0" name="divisor" type="String">
+ <argument index="0" name="delimiter" type="String">
</argument>
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<argument index="2" name="maxsplit" type="int" default="0">
</argument>
<description>
- Splits the string by a divisor string and returns an array of the substrings.
- [b]Example:[/b] [code]"One,Two,Three"[/code] will return [code]["One","Two","Three"][/code] if split by [code]","[/code].
- If [code]maxsplit[/code] is given, at most maxsplit number of splits occur, and the remainder of the string is returned as the final element of the list (thus, the list will have at most maxsplit+1 elements)
+ Splits the string by a [code]delimiter[/code] string and returns an array of the substrings.
+ If [code]maxsplit[/code] is specified, it defines the number of splits to do from the left up to [code]maxsplit[/code]. The default value of 0 means that all items are split.
+ [b]Example:[/b] [code]"One,Two,Three"[/code] will return [code]["One","Two"][/code] if split by [code]","[/code] with [code]maxsplit[/code] of 2.
</description>
</method>
<method name="split_floats">
<return type="PoolRealArray">
</return>
- <argument index="0" name="divisor" type="String">
+ <argument index="0" name="delimiter" type="String">
</argument>
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<description>
- Splits the string in floats by using a divisor string and returns an array of the substrings.
+ Splits the string in floats by using a delimiter string and returns an array of the substrings.
[b]Example:[/b] [code]"1,2.5,3"[/code] will return [code][1,2.5,3][/code] if split by [code]","[/code].
</description>
</method>
@@ -741,7 +742,14 @@
<argument index="1" name="right" type="bool" default="True">
</argument>
<description>
- Returns a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
+ Returns a copy of the string stripped of any non-printable character (including tabulations, spaces and line breaks) at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
+ </description>
+ </method>
+ <method name="strip_escapes">
+ <return type="String">
+ </return>
+ <description>
+ Returns a copy of the string stripped of any escape character. These include all non-printable control characters of the first page of the ASCII table (&lt; 32), such as tabulation ([code]\t[/code] in C) and newline ([code]\n[/code] and [code]\r[/code]) characters, but not spaces.
</description>
</method>
<method name="substr">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index eb70d7a1c3..8ca553ccb8 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -388,10 +388,10 @@
<member name="draw_tabs" type="bool" setter="set_draw_tabs" getter="is_drawing_tabs">
If [code]true[/code], the "tab" character will have a visible representation.
</member>
- <member name="fold_gutter" type="bool" setter="set_fold_gutter_enabled" getter="is_fold_gutter_enabled">
+ <member name="fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter">
If [code]true[/code], the fold gutter is visible. This enables folding groups of indented lines.
</member>
- <member name="hiding_enabled" type="int" setter="set_hiding_enabled" getter="is_hiding_enabled">
+ <member name="hiding_enabled" type="bool" setter="set_hiding_enabled" getter="is_hiding_enabled">
</member>
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled">
</member>
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index c14e098b12..8fdef5540b 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -8,7 +8,7 @@
Theme resources can be alternatively loaded by writing them in a .theme file, see docs for more info.
</description>
<tutorials>
- <link>https://docs.godotengine.org/en/stable/tutorials/gui/gui_skinning.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/gui/gui_skinning.html</link>
</tutorials>
<methods>
<method name="clear">
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index 0bf602dcf7..f29a7990ed 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -10,6 +10,18 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_forward_atlas_subtile_selection" qualifiers="virtual">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="atlastile_id" type="int">
+ </argument>
+ <argument index="1" name="tilemap" type="Object">
+ </argument>
+ <argument index="2" name="tile_location" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="_forward_subtile_selection" qualifiers="virtual">
<return type="Vector2">
</return>
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index 5d51f7ee09..eea4f8ed03 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -7,8 +7,8 @@
Translations are resources that can be loaded/unloaded on demand. They map a string to another string.
</description>
<tutorials>
- <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
- <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/i18n/locales.html</link>
</tutorials>
<methods>
<method name="add_message">
diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml
index 05774635b8..400a6e31d5 100644
--- a/doc/classes/TranslationServer.xml
+++ b/doc/classes/TranslationServer.xml
@@ -7,8 +7,8 @@
Server that manages all translations. Translations can be set to it and removed from it.
</description>
<tutorials>
- <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
- <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/i18n/locales.html</link>
</tutorials>
<methods>
<method name="add_translation">
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 9524e048bb..f7887a87c8 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -163,8 +163,11 @@
<method name="get_next_visible">
<return type="TreeItem">
</return>
+ <argument index="0" name="wrap" type="bool" default="false">
+ </argument>
<description>
Returns the next visible TreeItem in the tree.
+ If [code]wrap[/code] is enabled, the method will wrap around to the first visible element in the tree when called on the last visible element, otherwise it returns [code]null[/code].
</description>
</method>
<method name="get_parent">
@@ -184,8 +187,11 @@
<method name="get_prev_visible">
<return type="TreeItem">
</return>
+ <argument index="0" name="wrap" type="bool" default="false">
+ </argument>
<description>
Returns the previous visible TreeItem in the tree.
+ If [code]wrap[/code] is enabled, the method will wrap around to the last visible element in the tree when called on the first visible element, otherwise it returns [code]null[/code].
</description>
</method>
<method name="get_range" qualifiers="const">
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 75221ccc82..243dbceced 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -185,6 +185,17 @@
Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], representing the amount of interpolation.
</description>
</method>
+ <method name="move_toward">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="to" type="Vector2">
+ </argument>
+ <argument index="1" name="delta" type="float">
+ </argument>
+ <description>
+ Moves the vector toward [code]to[/code] by the fixed [code]delta[/code] amount.
+ </description>
+ </method>
<method name="normalized">
<return type="Vector2">
</return>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index bcd745945e..99bf3d2610 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -175,6 +175,17 @@
Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants.
</description>
</method>
+ <method name="move_toward">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="to" type="Vector3">
+ </argument>
+ <argument index="1" name="delta" type="float">
+ </argument>
+ <description>
+ Moves the vector toward [code]to[/code] by the fixed [code]delta[/code] amount.
+ </description>
+ </method>
<method name="normalized">
<return type="Vector3">
</return>
diff --git a/doc/classes/VehicleWheel.xml b/doc/classes/VehicleWheel.xml
index c3b668c170..0bc0e351e4 100644
--- a/doc/classes/VehicleWheel.xml
+++ b/doc/classes/VehicleWheel.xml
@@ -19,7 +19,7 @@
<return type="float">
</return>
<description>
- Returns a value between 0.0 and 1.0 that indicates whether this wheel is skidding. 0.0 is not skidding, 1.0 means the wheel has lost grip.
+ Returns a value between 0.0 and 1.0 that indicates whether this wheel is skidding. 0.0 is skidding (the wheel has lost grip, e.g. icy terrain), 1.0 means not skidding (the wheel has full grip, e.g. dry asphalt road).
</description>
</method>
<method name="is_in_contact" qualifiers="const">
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index c3e15b2f9a..454c71d3c7 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -478,24 +478,7 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write(make_heading('Tutorials', '-'))
for t in class_def.tutorials:
link = t.strip()
- match = GODOT_DOCS_PATTERN.search(link)
- if match:
- groups = match.groups()
- if match.lastindex == 2:
- # Doc reference with fragment identifier: emit direct link to section with reference to page, for example:
- # `#calling-javascript-from-script in Exporting For Web`
- f.write("- `" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`\n\n")
- # Commented out alternative: Instead just emit:
- # `Subsection in Exporting For Web`
- # f.write("- `Subsection <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`\n\n")
- elif match.lastindex == 1:
- # Doc reference, for example:
- # `Math`
- f.write("- :doc:`../" + groups[0] + "`\n\n")
- else:
- # External link, for example:
- # `http://enet.bespin.org/usergroup0.html`
- f.write("- `" + link + " <" + link + ">`_\n\n")
+ f.write("- " + make_url(link) + "\n\n")
# Property descriptions
if len(class_def.properties) > 0:
@@ -802,15 +785,16 @@ def rstize_text(text, state): # type: (str, State) -> str
tag_text = "" # '![](' + cmd[6:] + ')'
elif cmd.find('url=') == 0:
url_link = cmd[4:]
- tag_text = ':ref:`'
+ tag_text = '`'
tag_depth += 1
- url_has_name = False
inside_url = True
+ url_has_name = False
elif cmd == '/url':
- tag_text = ('' if url_has_name else url_link) + '<' + url_link + ">`"
+ tag_text = ('' if url_has_name else url_link) + " <" + url_link + ">`_"
tag_depth -= 1
escape_post = True
inside_url = False
+ url_has_name = False
elif cmd == 'center':
tag_depth += 1
tag_text = ''
@@ -996,5 +980,26 @@ def make_heading(title, underline): # type: (str, str) -> str
return title + '\n' + (underline * len(title)) + "\n\n"
+def make_url(link): # type: (str) -> str
+ match = GODOT_DOCS_PATTERN.search(link)
+ if match:
+ groups = match.groups()
+ if match.lastindex == 2:
+ # Doc reference with fragment identifier: emit direct link to section with reference to page, for example:
+ # `#calling-javascript-from-script in Exporting For Web`
+ return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`"
+ # Commented out alternative: Instead just emit:
+ # `Subsection in Exporting For Web`
+ # return "`Subsection <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`"
+ elif match.lastindex == 1:
+ # Doc reference, for example:
+ # `Math`
+ return ":doc:`../" + groups[0] + "`"
+ else:
+ # External link, for example:
+ # `http://enet.bespin.org/usergroup0.html`
+ return "`" + link + " <" + link + ">`_"
+
+
if __name__ == '__main__':
main()
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index ee722e9d6c..b82186162d 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -1081,6 +1081,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
} else {
glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs);
}
+ } else {
+ glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0);
}
if (multi_mesh->custom_data_floats) {
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 50cb39b13f..0231bb5837 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -2261,7 +2261,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
bool rebind_reflection = false;
bool rebind_lightmap = false;
- if (!p_shadow) {
+ if (!p_shadow && material->shader) {
bool unshaded = material->shader->spatial.unshaded;
@@ -2281,7 +2281,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
bool depth_prepass = false;
- if (!p_alpha_pass && material->shader && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ if (!p_alpha_pass && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
depth_prepass = true;
}
@@ -2919,7 +2919,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
if (storage->frame.current_rt && state.used_screen_texture) {
//copy screen texture
- if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) {
+ if (storage->frame.current_rt->multisample_active) {
// Resolve framebuffer to front buffer before copying
#ifdef GLES_OVER_GL
@@ -2931,14 +2931,16 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
#elif IPHONE_ENABLED
+
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
glResolveMultisampleFramebufferAPPLE();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-#else
- // In GLES2 Blit is not available, so just copy color texture manually
+#elif ANDROID_ENABLED
+
+ // In GLES2 AndroidBlit is not available, so just copy color texture manually
_copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color);
#endif
}
@@ -2972,8 +2974,17 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-#else
- // In GLES2 Blit is not available, so just copy color texture manually
+#elif IPHONE_ENABLED
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
+ glResolveMultisampleFramebufferAPPLE();
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+#elif ANDROID_ENABLED
+
+ // In GLES2 Android Blit is not available, so just copy color texture manually
_copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color);
#endif
}
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index c610f31bc1..7b5f193b2b 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -91,7 +91,7 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
//void *glRenderbufferStorageMultisampleAPPLE;
//void *glResolveMultisampleFramebufferAPPLE;
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE
-#else
+#elif ANDROID_ENABLED
#include <GLES2/gl2ext.h>
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
@@ -4719,7 +4719,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color);
-#else
+#elif ANDROID_ENABLED
// Render to a texture in android
glGenTextures(1, &rt->multisample_color);
glBindTexture(GL_TEXTURE_2D, rt->multisample_color);
@@ -5602,11 +5602,11 @@ void RasterizerStorageGLES2::initialize() {
//Manually load extensions for android and ios
#ifdef IPHONE_ENABLED
-
+ // appears that IPhone doesn't need to dlopen TODO: test this rigorously before removing
//void *gles2_lib = dlopen(NULL, RTLD_LAZY);
//glRenderbufferStorageMultisampleAPPLE = dlsym(gles2_lib, "glRenderbufferStorageMultisampleAPPLE");
//glResolveMultisampleFramebufferAPPLE = dlsym(gles2_lib, "glResolveMultisampleFramebufferAPPLE");
-#else
+#elif ANDROID_ENABLED
void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY);
glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT");
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index ebea40e10e..2456a83d35 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -1,4 +1,4 @@
-/*************************************************************************/
+/*************************************************************************/
/* shader_gles2.h */
/*************************************************************************/
/* This file is part of: */
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 7dce784f52..0818942b0a 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -112,7 +112,12 @@ void main() {
#ifdef USE_INSTANCING
mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
color *= instance_color;
+
+#ifdef USE_INSTANCE_CUSTOM
vec4 instance_custom = instance_custom_data;
+#else
+ vec4 instance_custom = vec4(0.0);
+#endif
#else
mat4 extra_matrix_instance = extra_matrix;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 4552fddfe8..7e02f2f3f5 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -3304,7 +3304,7 @@ void RasterizerSceneGLES3::_prepare_depth_texture() {
void RasterizerSceneGLES3::_bind_depth_texture() {
if (!state.bound_depth_texture) {
- ERR_FAIL_COND(!state.prepared_depth_texture)
+ ERR_FAIL_COND(!state.prepared_depth_texture);
//bind depth for read
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
@@ -4552,8 +4552,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
}
_post_process(env, p_cam_projection);
-
- if (false && shadow_atlas) {
+ // Needed only for debugging
+ /* if (shadow_atlas && storage->frame.current_rt) {
//_copy_texture_to_front_buffer(shadow_atlas->depth);
storage->canvas->canvas_begin();
@@ -4563,7 +4563,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
}
- if (false && storage->frame.current_rt) {
+ if (storage->frame.current_rt) {
//_copy_texture_to_front_buffer(shadow_atlas->depth);
storage->canvas->canvas_begin();
@@ -4573,7 +4573,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1));
}
- if (false && reflection_atlas && storage->frame.current_rt) {
+ if (reflection_atlas && storage->frame.current_rt) {
//_copy_texture_to_front_buffer(shadow_atlas->depth);
storage->canvas->canvas_begin();
@@ -4582,7 +4582,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
}
- if (false && directional_shadow.fbo) {
+ if (directional_shadow.fbo) {
//_copy_texture_to_front_buffer(shadow_atlas->depth);
storage->canvas->canvas_begin();
@@ -4592,7 +4592,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
}
- if (false && env_radiance_tex) {
+ if ( env_radiance_tex) {
//_copy_texture_to_front_buffer(shadow_atlas->depth);
storage->canvas->canvas_begin();
@@ -4603,8 +4603,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
+ }*/
//disable all stuff
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 8311d0de84..561a3cae2d 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -3772,28 +3772,30 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m
Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>());
-
PoolVector<uint8_t> ret;
ret.resize(surface->index_array_byte_size);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
+
+ if (surface->index_array_byte_size > 0) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id);
#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__)
- {
- PoolVector<uint8_t>::Write w = ret.write();
- glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr());
- }
+ {
+ PoolVector<uint8_t>::Write w = ret.write();
+ glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr());
+ }
#else
- void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
- {
- PoolVector<uint8_t>::Write w = ret.write();
- copymem(w.ptr(), data, surface->index_array_byte_size);
- }
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+ void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, PoolVector<uint8_t>());
+ {
+ PoolVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(), data, surface->index_array_byte_size);
+ }
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
#endif
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
return ret;
}
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 0d1e7ee4a1..a46b31c92e 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -117,7 +117,12 @@ void main() {
#ifdef USE_INSTANCING
mat4 extra_matrix_instance = extra_matrix * transpose(mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)));
color *= instance_color;
+
+#ifdef USE_INSTANCE_CUSTOM
vec4 instance_custom = instance_custom_data;
+#else
+ vec4 instance_custom = vec4(0.0);
+#endif
#else
mat4 extra_matrix_instance = extra_matrix;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index c13300d09f..31360d319f 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -340,13 +340,11 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
}
uint32_t FileAccessWindows::_get_unix_permissions(const String &p_file) {
- ERR_PRINT("Windows does not support unix permissions");
return 0;
}
Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
- ERR_PRINT("Windows does not support unix permissions");
- return FAILED;
+ return ERR_UNAVAILABLE;
}
FileAccessWindows::FileAccessWindows() :
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index e8490e8729..0385220baa 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1214,7 +1214,7 @@ void AnimationTrackEdit::_notification(int p_what) {
Color accent = get_color("accent_color", "Editor");
accent.a *= 0.7;
// Offside so the horizontal sides aren't cutoff.
- draw_rect(Rect2(Point2(1, 0), get_size() - Size2(1, 0)), accent, false);
+ draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), accent, false);
}
Ref<Font> font = get_font("font", "Label");
@@ -3633,6 +3633,9 @@ void AnimationTrackEditor::_animation_update() {
bezier_edit->update();
_update_step_spinbox();
+ emit_signal("animation_step_changed", animation->get_step());
+ emit_signal("animation_len_changed", animation->get_length());
+ EditorNode::get_singleton()->get_inspector()->refresh();
animation_changing_awaiting_update = false;
}
@@ -3685,8 +3688,7 @@ void AnimationTrackEditor::_update_step(double p_new_step) {
step->set_block_signals(true);
undo_redo->commit_action();
step->set_block_signals(false);
- emit_signal("animation_step_changed", p_new_step);
- animation->_change_notify("step");
+ emit_signal("animation_step_changed", step_value);
}
void AnimationTrackEditor::_update_length(double p_new_len) {
@@ -4973,6 +4975,7 @@ void AnimationTrackEditor::_bind_methods() {
ClassDB::bind_method("_update_scroll", &AnimationTrackEditor::_update_scroll);
ClassDB::bind_method("_update_tracks", &AnimationTrackEditor::_update_tracks);
ClassDB::bind_method("_update_step", &AnimationTrackEditor::_update_step);
+ ClassDB::bind_method("_update_length", &AnimationTrackEditor::_update_length);
ClassDB::bind_method("_dropped_track", &AnimationTrackEditor::_dropped_track);
ClassDB::bind_method("_add_track", &AnimationTrackEditor::_add_track);
ClassDB::bind_method("_new_track_node_selected", &AnimationTrackEditor::_new_track_node_selected);
@@ -5033,6 +5036,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
timeline->connect("name_limit_changed", this, "_name_limit_changed");
timeline->connect("track_added", this, "_add_track");
timeline->connect("value_changed", this, "_timeline_value_changed");
+ timeline->connect("length_changed", this, "_update_length");
scroll = memnew(ScrollContainer);
timeline_vbox->add_child(scroll);
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index baf417fed7..07dbc1fd81 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -48,7 +48,7 @@ int AnimationTrackEditBool::get_key_height() const {
Rect2 AnimationTrackEditBool::get_key_rect(int p_index, float p_pixels_sec) {
Ref<Texture> checked = get_icon("checked", "CheckBox");
- return Rect2(0, 0, checked->get_width(), get_size().height);
+ return Rect2(-checked->get_width() / 2, 0, checked->get_width(), get_size().height);
}
bool AnimationTrackEditBool::is_key_selectable_by_distance() const {
@@ -57,17 +57,18 @@ bool AnimationTrackEditBool::is_key_selectable_by_distance() const {
}
void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) {
- Ref<Texture> icon;
bool checked = get_animation()->track_get_key_value(get_track(), p_index);
+ Ref<Texture> icon = get_icon(checked ? "checked" : "unchecked", "CheckBox");
- if (checked)
- icon = get_icon("checked", "CheckBox");
- else
- icon = get_icon("unchecked", "CheckBox");
+ Vector2 ofs(p_x - icon->get_width() / 2, int(get_size().height - icon->get_height()) / 2);
- Vector2 ofs(p_x, int(get_size().height - icon->get_height()) / 2);
+ if (ofs.x + icon->get_width() / 2 < p_clip_left)
+ return;
+
+ if (ofs.x + icon->get_width() / 2 > p_clip_right)
+ return;
- draw_texture_clipped(icon, ofs);
+ draw_texture(icon, ofs);
if (p_selected) {
Color color = get_color("accent_color", "Editor");
@@ -86,7 +87,7 @@ Rect2 AnimationTrackEditColor::get_key_rect(int p_index, float p_pixels_sec) {
Ref<Font> font = get_font("font", "Label");
int fh = font->get_height() * 0.8;
- return Rect2(0, 0, fh, get_size().height);
+ return Rect2(-fh / 2, 0, fh, get_size().height);
}
bool AnimationTrackEditColor::is_key_selectable_by_distance() const {
@@ -96,20 +97,14 @@ bool AnimationTrackEditColor::is_key_selectable_by_distance() const {
void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) {
- int x_from = p_x;
- int x_to = p_next_x;
-
Ref<Font> font = get_font("font", "Label");
int fh = (font->get_height() * 0.8);
- x_from += fh - 1;
- x_to += 1;
+ int x_from = p_x + fh / 2 - 1;
+ int x_to = p_next_x - fh / 2 + 1;
fh /= 3;
- if (x_from > p_clip_right)
- return;
-
- if (x_to < p_clip_left)
+ if (x_from > p_clip_right || x_to < p_clip_left)
return;
Color color = get_animation()->track_get_key_value(get_track(), p_index);
@@ -154,7 +149,7 @@ void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x,
Ref<Font> font = get_font("font", "Label");
int fh = font->get_height() * 0.8;
- Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
+ Rect2 rect(Vector2(p_x - fh / 2, int(get_size().height - fh) / 2), Size2(fh, fh));
draw_rect_clipped(Rect2(rect.position, rect.size / 2), Color(0.4, 0.4, 0.4));
draw_rect_clipped(Rect2(rect.position + rect.size / 2, rect.size / 2), Color(0.4, 0.4, 0.4));
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index 85db8b77f9..b30b94ab26 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -129,7 +129,7 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
float max = -1000;
float min = 1000;
int from = uint64_t(i) * to_read / to_write;
- int to = uint64_t(i + 1) * to_read / to_write;
+ int to = (uint64_t(i) + 1) * to_read / to_write;
to = MIN(to, to_read);
from = MIN(from, to_read - 1);
if (to == from) {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 695560ca34..01773a0bcd 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -675,14 +675,14 @@ void CodeTextEditor::_line_col_changed() {
}
}
- StringBuilder *sb = memnew(StringBuilder);
- sb->append("(");
- sb->append(itos(text_editor->cursor_get_line() + 1).lpad(3));
- sb->append(",");
- sb->append(itos(positional_column + 1).lpad(3));
- sb->append(")");
+ StringBuilder sb;
+ sb.append("(");
+ sb.append(itos(text_editor->cursor_get_line() + 1).lpad(3));
+ sb.append(",");
+ sb.append(itos(positional_column + 1).lpad(3));
+ sb.append(")");
- line_and_col_txt->set_text(sb->as_string());
+ line_and_col_txt->set_text(sb.as_string());
}
void CodeTextEditor::_text_changed() {
@@ -804,6 +804,24 @@ void CodeTextEditor::trim_trailing_whitespace() {
}
}
+void CodeTextEditor::insert_final_newline() {
+ int final_line = text_editor->get_line_count() - 1;
+
+ String line = text_editor->get_line(final_line);
+
+ //length 0 means it's already an empty line,
+ //no need to add a newline
+ if (line.length() > 0 && !line.ends_with("\n")) {
+ text_editor->begin_complex_operation();
+
+ line += "\n";
+ text_editor->set_line(final_line, line);
+
+ text_editor->end_complex_operation();
+ text_editor->update();
+ }
+}
+
void CodeTextEditor::convert_indent_to_spaces() {
int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size");
String indent = "";
@@ -912,7 +930,7 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
for (int i = begin; i <= end; i++) {
int len = text_editor->get_line(i).length();
if (i == end)
- len -= len - end_col;
+ len = end_col;
if (i == begin)
len -= begin_col;
String new_line = text_editor->get_line(i).substr(i == begin ? begin_col : 0, len);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 5c6b54ae44..cf97f30b72 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -195,6 +195,7 @@ protected:
public:
void trim_trailing_whitespace();
+ void insert_final_newline();
void convert_indent_to_spaces();
void convert_indent_to_tabs();
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index e9040b9d3e..a0d319c81b 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -651,7 +651,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &
effect.emission.texture = uri;
} else if (what == "bump") {
if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
+ WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
}
effect.bump.texture = uri;
@@ -707,7 +707,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &
String uri = effect.params[surface];
if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
+ WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
}
effect.bump.texture = uri;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index a9a96da7b1..82fc8e5cfa 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -307,39 +307,42 @@ void ConnectDialog::init(Connection c, bool bEdit) {
bEditMode = bEdit;
}
-void ConnectDialog::popup_dialog(const String &p_for_signal, bool p_advanced) {
+void ConnectDialog::popup_dialog(const String &p_for_signal) {
- advanced->set_pressed(p_advanced);
from_signal->set_text(p_for_signal);
error_label->add_color_override("font_color", get_color("error_color", "Editor"));
- vbc_right->set_visible(p_advanced);
+ if (!advanced->is_pressed())
+ error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root()));
- if (p_advanced) {
+ popup_centered();
+}
+
+void ConnectDialog::_advanced_pressed() {
- popup_centered(Size2(900, 500) * EDSCALE);
- connect_to_label->set_text("Connect to Node:");
+ if (advanced->is_pressed()) {
+ set_custom_minimum_size(Size2(900, 500) * EDSCALE);
+ connect_to_label->set_text(TTR("Connect to Node:"));
tree->set_connect_to_script_mode(false);
+
+ vbc_right->show();
error_label->hide();
} else {
- popup_centered(Size2(700, 500) * EDSCALE);
- connect_to_label->set_text("Connect to Script:");
+ set_custom_minimum_size(Size2(600, 500) * EDSCALE);
+ set_size(Size2());
+ connect_to_label->set_text(TTR("Connect to Script:"));
tree->set_connect_to_script_mode(true);
- if (!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root())) {
- error_label->show();
- } else {
- error_label->hide();
- }
+ vbc_right->hide();
+ error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root()));
}
-}
-void ConnectDialog::_advanced_pressed() {
-
- popup_dialog(from_signal->get_text(), advanced->is_pressed());
+ set_position((get_viewport_rect().size - get_custom_minimum_size()) / 2);
}
ConnectDialog::ConnectDialog() {
+ set_custom_minimum_size(Size2(600, 500) * EDSCALE);
+
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
@@ -356,6 +359,7 @@ ConnectDialog::ConnectDialog() {
vbc_left->add_margin_child(TTR("From Signal:"), from_signal);
tree = memnew(SceneTreeEditor(false));
+ tree->set_connecting_signal(true);
tree->get_scene_tree()->connect("item_activated", this, "_ok");
tree->connect("node_selected", this, "_tree_node_selected");
tree->set_connect_to_script_mode(true);
@@ -381,7 +385,7 @@ ConnectDialog::ConnectDialog() {
type_list->add_item("bool", Variant::BOOL);
type_list->add_item("int", Variant::INT);
type_list->add_item("real", Variant::REAL);
- type_list->add_item("string", Variant::STRING);
+ type_list->add_item("String", Variant::STRING);
type_list->add_item("Vector2", Variant::VECTOR2);
type_list->add_item("Rect2", Variant::RECT2);
type_list->add_item("Vector3", Variant::VECTOR3);
@@ -416,28 +420,26 @@ ConnectDialog::ConnectDialog() {
dst_method->set_h_size_flags(SIZE_EXPAND_FILL);
dstm_hb->add_child(dst_method);
- advanced = memnew(CheckBox);
+ advanced = memnew(CheckButton);
dstm_hb->add_child(advanced);
- advanced->set_text(TTR("Advanced..."));
+ advanced->set_text(TTR("Advanced"));
advanced->connect("pressed", this, "_advanced_pressed");
- /*
- dst_method_list = memnew( MenuButton );
- dst_method_list->set_text("List...");
- dst_method_list->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- dst_method_list->set_anchor( MARGIN_LEFT, ANCHOR_END );
- dst_method_list->set_anchor( MARGIN_TOP, ANCHOR_END );
- dst_method_list->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- dst_method_list->set_begin( Point2( 70,59) );
- dst_method_list->set_end( Point2( 15,39 ) );
- */
+ // Add spacing so the tree and inspector are the same size.
+ Control *spacing = memnew(Control);
+ spacing->set_custom_minimum_size(Size2(0, 4) * EDSCALE);
+ vbc_right->add_child(spacing);
- deferred = memnew(CheckButton);
+ deferred = memnew(CheckBox);
+ deferred->set_h_size_flags(0);
deferred->set_text(TTR("Deferred"));
+ deferred->set_tooltip(TTR("Defers the signal, storing it in a queue and only firing it at idle time."));
vbc_right->add_child(deferred);
- oneshot = memnew(CheckButton);
+ oneshot = memnew(CheckBox);
+ oneshot->set_h_size_flags(0);
oneshot->set_text(TTR("Oneshot"));
+ oneshot->set_tooltip(TTR("Disconnects the signal after its first emission."));
vbc_right->add_child(oneshot);
set_as_toplevel(true);
@@ -662,9 +664,7 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
c.signal = StringName(signalname);
c.target = dst_node;
c.method = dst_method;
-
- //connect_dialog->set_title(TTR("Connect Signal: ") + signalname);
- connect_dialog->popup_dialog(signalname, false);
+ connect_dialog->popup_dialog(signalname);
connect_dialog->init(c);
connect_dialog->set_title(TTR("Connect a Signal to a Method"));
}
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 9b35d84426..94f1510810 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -67,9 +67,9 @@ class ConnectDialog : public ConfirmationDialog {
AcceptDialog *error;
EditorInspector *bind_editor;
OptionButton *type_list;
- CheckButton *deferred;
- CheckButton *oneshot;
- CheckBox *advanced;
+ CheckBox *deferred;
+ CheckBox *oneshot;
+ CheckButton *advanced;
Label *error_label;
@@ -99,7 +99,7 @@ public:
void init(Connection c, bool bEdit = false);
- void popup_dialog(const String &p_for_signal, bool p_advanced);
+ void popup_dialog(const String &p_for_signal);
ConnectDialog();
~ConnectDialog();
};
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index bde73e9268..cc9e2c12e8 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -725,7 +725,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa
int ds = efsd->get_file_deps(i).size();
ti->set_text(1, itos(ds));
if (ds) {
- ti->add_button(1, get_icon("GuiVisibilityVisible", "EditorIcons"));
+ ti->add_button(1, get_icon("GuiVisibilityVisible", "EditorIcons"), -1, false, TTR("Show Dependencies"));
}
ti->set_metadata(0, path);
has_children = true;
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
index c2a492bc9a..7d2159d365 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -136,9 +136,6 @@ void DocData::merge_from(const DocData &p_data) {
const PropertyDoc &pf = cf.properties[j];
p.description = pf.description;
- p.setter = pf.setter;
- p.getter = pf.getter;
-
break;
}
}
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index e9dd6d7199..bea1980b09 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -131,7 +131,7 @@ EditorAbout::EditorAbout() {
String hash = String(VERSION_HASH);
if (hash.length() != 0)
- hash = "." + hash.left(7);
+ hash = "." + hash.left(9);
Label *about_text = memnew(Label);
about_text->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
diff --git a/editor/editor_atlas_packer.cpp b/editor/editor_atlas_packer.cpp
index 4e1d98399a..96ddc607df 100644
--- a/editor/editor_atlas_packer.cpp
+++ b/editor/editor_atlas_packer.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_atlas_packer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#include "editor_atlas_packer.h"
void EditorAtlasPacker::_plot_triangle(Ref<BitMap> p_bitmap, Vector2i *vertices) {
diff --git a/editor/editor_atlas_packer.h b/editor/editor_atlas_packer.h
index dd9caa340e..1627f74a28 100644
--- a/editor/editor_atlas_packer.h
+++ b/editor/editor_atlas_packer.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_atlas_packer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#ifndef EDITOR_ATLAS_PACKER_H
#define EDITOR_ATLAS_PACKER_H
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 9cd7d781a4..57fac241b0 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -63,118 +63,132 @@ void EditorAudioBus::_update_visible_channels() {
void EditorAudioBus::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
-
- for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
- channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
- channel[i].prev_active = true;
- }
-
- disabled_vu = get_icon("BusVuFrozen", "EditorIcons");
-
- Color solo_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ffe337" : "#ffeb70");
- Color mute_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ff2929" : "#ff7070");
- Color bypass_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#22ccff" : "#70deff");
-
- solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
- solo->add_color_override("icon_color_pressed", solo_color);
- mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
- mute->add_color_override("icon_color_pressed", mute_color);
- bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
- bypass->add_color_override("icon_color_pressed", bypass_color);
-
- bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
-
- update_bus();
- set_process(true);
- }
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+
+ for (int i = 0; i < CHANNELS_MAX; i++) {
+ channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
+ channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
+ channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
+ channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
+ channel[i].prev_active = true;
+ }
- if (p_what == NOTIFICATION_DRAW) {
+ disabled_vu = get_icon("BusVuFrozen", "EditorIcons");
- if (has_focus()) {
- draw_style_box(get_stylebox("focus", "Button"), Rect2(Vector2(), get_size()));
- } else if (is_master) {
- draw_style_box(get_stylebox("disabled", "Button"), Rect2(Vector2(), get_size()));
- }
- }
+ Color solo_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ffe337" : "#ffeb70");
+ Color mute_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ff2929" : "#ff7070");
+ Color bypass_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#22ccff" : "#70deff");
- if (p_what == NOTIFICATION_PROCESS) {
+ solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
+ solo->add_color_override("icon_color_pressed", solo_color);
+ mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
+ mute->add_color_override("icon_color_pressed", mute_color);
+ bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
+ bypass->add_color_override("icon_color_pressed", bypass_color);
- if (cc != AudioServer::get_singleton()->get_bus_channels(get_index())) {
- cc = AudioServer::get_singleton()->get_bus_channels(get_index());
- _update_visible_channels();
- }
+ bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
- for (int i = 0; i < cc; i++) {
- float real_peak[2] = { -100, -100 };
- bool activity_found = false;
+ update_bus();
+ set_process(true);
+ } break;
+ case NOTIFICATION_DRAW: {
- if (AudioServer::get_singleton()->is_bus_channel_active(get_index(), i)) {
- activity_found = true;
- real_peak[0] = MAX(real_peak[0], AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(), i));
- real_peak[1] = MAX(real_peak[1], AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(), i));
+ if (is_master) {
+ draw_style_box(get_stylebox("disabled", "Button"), Rect2(Vector2(), get_size()));
+ } else if (has_focus()) {
+ draw_style_box(get_stylebox("focus", "Button"), Rect2(Vector2(), get_size()));
+ } else {
+ draw_style_box(get_stylebox("panel", "TabContainer"), Rect2(Vector2(), get_size()));
}
- if (real_peak[0] > channel[i].peak_l) {
- channel[i].peak_l = real_peak[0];
- } else {
- channel[i].peak_l -= get_process_delta_time() * 60.0;
+ if (get_index() != 0 && hovering_drop) {
+ Color accent = get_color("accent_color", "Editor");
+ accent.a *= 0.7;
+ draw_rect(Rect2(Point2(), get_size()), accent, false);
}
+ } break;
+ case NOTIFICATION_PROCESS: {
- if (real_peak[1] > channel[i].peak_r) {
- channel[i].peak_r = real_peak[1];
- } else {
- channel[i].peak_r -= get_process_delta_time() * 60.0;
+ if (cc != AudioServer::get_singleton()->get_bus_channels(get_index())) {
+ cc = AudioServer::get_singleton()->get_bus_channels(get_index());
+ _update_visible_channels();
}
- channel[i].vu_l->set_value(channel[i].peak_l);
- channel[i].vu_r->set_value(channel[i].peak_r);
+ for (int i = 0; i < cc; i++) {
+ float real_peak[2] = { -100, -100 };
+ bool activity_found = false;
- if (activity_found != channel[i].prev_active) {
- if (activity_found) {
- channel[i].vu_l->set_over_texture(Ref<Texture>());
- channel[i].vu_r->set_over_texture(Ref<Texture>());
+ if (AudioServer::get_singleton()->is_bus_channel_active(get_index(), i)) {
+ activity_found = true;
+ real_peak[0] = MAX(real_peak[0], AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(), i));
+ real_peak[1] = MAX(real_peak[1], AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(), i));
+ }
+
+ if (real_peak[0] > channel[i].peak_l) {
+ channel[i].peak_l = real_peak[0];
} else {
- channel[i].vu_l->set_over_texture(disabled_vu);
- channel[i].vu_r->set_over_texture(disabled_vu);
+ channel[i].peak_l -= get_process_delta_time() * 60.0;
}
- channel[i].prev_active = activity_found;
- }
- }
- }
+ if (real_peak[1] > channel[i].peak_r) {
+ channel[i].peak_r = real_peak[1];
+ } else {
+ channel[i].peak_r -= get_process_delta_time() * 60.0;
+ }
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+ channel[i].vu_l->set_value(channel[i].peak_l);
+ channel[i].vu_r->set_value(channel[i].peak_r);
- for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].peak_l = -100;
- channel[i].peak_r = -100;
- channel[i].prev_active = true;
- }
+ if (activity_found != channel[i].prev_active) {
+ if (activity_found) {
+ channel[i].vu_l->set_over_texture(Ref<Texture>());
+ channel[i].vu_r->set_over_texture(Ref<Texture>());
+ } else {
+ channel[i].vu_l->set_over_texture(disabled_vu);
+ channel[i].vu_r->set_over_texture(disabled_vu);
+ }
- set_process(is_visible_in_tree());
- }
+ channel[i].prev_active = activity_found;
+ }
+ }
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
- if (p_what == NOTIFICATION_THEME_CHANGED) {
+ for (int i = 0; i < CHANNELS_MAX; i++) {
+ channel[i].peak_l = -100;
+ channel[i].peak_r = -100;
+ channel[i].prev_active = true;
+ }
- for (int i = 0; i < CHANNELS_MAX; i++) {
- channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
- channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
- channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
- channel[i].prev_active = true;
- }
+ set_process(is_visible_in_tree());
+ } break;
+ case NOTIFICATION_THEME_CHANGED: {
- disabled_vu = get_icon("BusVuFrozen", "EditorIcons");
+ for (int i = 0; i < CHANNELS_MAX; i++) {
+ channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
+ channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
+ channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
+ channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
+ channel[i].prev_active = true;
+ }
- solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
- mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
- bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
+ disabled_vu = get_icon("BusVuFrozen", "EditorIcons");
- bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
+ mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
+ bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
+
+ bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ } break;
+ case NOTIFICATION_MOUSE_EXIT:
+ case NOTIFICATION_DRAG_END: {
+
+ if (hovering_drop) {
+ hovering_drop = false;
+ update();
+ }
+ } break;
}
}
@@ -553,6 +567,7 @@ Variant EditorAudioBus::get_drag_data(const Point2 &p_point) {
Control *c = memnew(Control);
Panel *p = memnew(Panel);
c->add_child(p);
+ p->set_modulate(Color(1, 1, 1, 0.7));
p->add_style_override("panel", get_stylebox("focus", "Button"));
p->set_size(get_size());
p->set_position(-p_point);
@@ -560,21 +575,29 @@ Variant EditorAudioBus::get_drag_data(const Point2 &p_point) {
Dictionary d;
d["type"] = "move_audio_bus";
d["index"] = get_index();
- emit_signal("drop_end_request");
+
+ if (get_index() < AudioServer::get_singleton()->get_bus_count() - 1) {
+ emit_signal("drop_end_request");
+ }
+
return d;
}
bool EditorAudioBus::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
- if (get_index() == 0)
+ if (get_index() == 0) {
return false;
+ }
+
Dictionary d = p_data;
- if (d.has("type") && String(d["type"]) == "move_audio_bus") {
+ if (d.has("type") && String(d["type"]) == "move_audio_bus" && (int)d["index"] != get_index()) {
+ hovering_drop = true;
return true;
}
return false;
}
+
void EditorAudioBus::drop_data(const Point2 &p_point, const Variant &p_data) {
Dictionary d = p_data;
@@ -589,7 +612,6 @@ Variant EditorAudioBus::get_drag_data_fw(const Point2 &p_point, Control *p_from)
}
Variant md = item->get_metadata(0);
-
if (md.get_type() == Variant::INT) {
Dictionary fxd;
fxd["type"] = "audio_bus_effect";
@@ -749,6 +771,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
buses = p_buses;
updating_bus = false;
is_master = p_is_master;
+ hovering_drop = false;
set_tooltip(TTR("Audio Bus, Drag and Drop to rearrange."));
@@ -756,7 +779,6 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
add_child(vb);
set_v_size_flags(SIZE_EXPAND_FILL);
- set_custom_minimum_size(Size2(110, 0) * EDSCALE);
track_name = memnew(LineEdit);
track_name->connect("text_entered", this, "_name_changed");
@@ -800,7 +822,9 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
child->add_style_override("pressed", sbempty);
}
- vb->add_child(memnew(HSeparator));
+ HSeparator *separator = memnew(HSeparator);
+ separator->set_mouse_filter(MOUSE_FILTER_PASS);
+ vb->add_child(separator);
HBoxContainer *hb = memnew(HBoxContainer);
vb->add_child(hb);
@@ -811,20 +835,19 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
slider->set_clip_contents(false);
audio_value_preview_box = memnew(Panel);
- {
- HBoxContainer *audioprev_hbc = memnew(HBoxContainer);
- audioprev_hbc->set_v_size_flags(SIZE_EXPAND_FILL);
- audioprev_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
- audioprev_hbc->set_mouse_filter(MOUSE_FILTER_PASS);
- audio_value_preview_box->add_child(audioprev_hbc);
-
- audio_value_preview_label = memnew(Label);
- audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL);
- audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL);
- audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS);
-
- audioprev_hbc->add_child(audio_value_preview_label);
- }
+ HBoxContainer *audioprev_hbc = memnew(HBoxContainer);
+ audioprev_hbc->set_v_size_flags(SIZE_EXPAND_FILL);
+ audioprev_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ audioprev_hbc->set_mouse_filter(MOUSE_FILTER_PASS);
+ audio_value_preview_box->add_child(audioprev_hbc);
+
+ audio_value_preview_label = memnew(Label);
+ audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL);
+ audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL);
+ audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS);
+
+ audioprev_hbc->add_child(audio_value_preview_label);
+
slider->add_child(audio_value_preview_box);
audio_value_preview_box->set_as_toplevel(true);
Ref<StyleBoxFlat> panel_style = memnew(StyleBoxFlat);
@@ -863,17 +886,18 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
channel[i].peak_r = 0.0f;
}
- scale = memnew(EditorAudioMeterNotches);
+ EditorAudioMeterNotches *scale = memnew(EditorAudioMeterNotches);
for (float db = 6.0f; db >= -80.0f; db -= 6.0f) {
bool renderNotch = (db >= -6.0f || db == -24.0f || db == -72.0f);
scale->add_notch(_scaled_db_to_normalized_volume(db), db, renderNotch);
}
+ scale->set_mouse_filter(MOUSE_FILTER_PASS);
hb->add_child(scale);
effects = memnew(Tree);
effects->set_hide_root(true);
- effects->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
+ effects->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
effects->set_hide_folding(true);
effects->set_v_size_flags(SIZE_EXPAND_FILL);
vb->add_child(effects);
@@ -923,6 +947,36 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
delete_effect_popup->connect("index_pressed", this, "_delete_effect_pressed");
}
+void EditorAudioBusDrop::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ draw_style_box(get_stylebox("normal", "Button"), Rect2(Vector2(), get_size()));
+
+ if (hovering_drop) {
+ Color accent = get_color("accent_color", "Editor");
+ accent.a *= 0.7;
+ draw_rect(Rect2(Point2(), get_size()), accent, false);
+ }
+ } break;
+ case NOTIFICATION_MOUSE_ENTER: {
+
+ if (!hovering_drop) {
+ hovering_drop = true;
+ update();
+ }
+ } break;
+ case NOTIFICATION_MOUSE_EXIT:
+ case NOTIFICATION_DRAG_END: {
+
+ if (hovering_drop) {
+ hovering_drop = false;
+ update();
+ }
+ } break;
+ }
+}
+
bool EditorAudioBusDrop::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
Dictionary d = p_data;
@@ -932,10 +986,11 @@ bool EditorAudioBusDrop::can_drop_data(const Point2 &p_point, const Variant &p_d
return false;
}
+
void EditorAudioBusDrop::drop_data(const Point2 &p_point, const Variant &p_data) {
Dictionary d = p_data;
- emit_signal("dropped", d["index"], -1);
+ emit_signal("dropped", d["index"], AudioServer::get_singleton()->get_bus_count());
}
void EditorAudioBusDrop::_bind_methods() {
@@ -944,6 +999,8 @@ void EditorAudioBusDrop::_bind_methods() {
}
EditorAudioBusDrop::EditorAudioBusDrop() {
+
+ hovering_drop = false;
}
void EditorAudioBuses::_update_buses() {
@@ -976,37 +1033,43 @@ EditorAudioBuses *EditorAudioBuses::register_editor() {
void EditorAudioBuses::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
- _update_buses();
- }
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
- if (p_what == NOTIFICATION_DRAG_END) {
- if (drop_end) {
- drop_end->queue_delete();
- drop_end = NULL;
- }
- }
+ bus_scroll->add_style_override("bg", get_stylebox("bg", "Tree"));
+ } break;
+ case NOTIFICATION_READY: {
- if (p_what == NOTIFICATION_PROCESS) {
+ _update_buses();
+ } break;
+ case NOTIFICATION_DRAG_END: {
- //check if anything was edited
- bool edited = AudioServer::get_singleton()->is_edited();
- for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
- for (int j = 0; j < AudioServer::get_singleton()->get_bus_effect_count(i); j++) {
- Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i, j);
- if (effect->is_edited()) {
- edited = true;
- effect->set_edited(false);
+ if (drop_end) {
+ drop_end->queue_delete();
+ drop_end = NULL;
+ }
+ } break;
+ case NOTIFICATION_PROCESS: {
+
+ // Check if anything was edited.
+ bool edited = AudioServer::get_singleton()->is_edited();
+ for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
+ for (int j = 0; j < AudioServer::get_singleton()->get_bus_effect_count(i); j++) {
+ Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i, j);
+ if (effect->is_edited()) {
+ edited = true;
+ effect->set_edited(false);
+ }
}
}
- }
-
- AudioServer::get_singleton()->set_edited(false);
- if (edited) {
+ AudioServer::get_singleton()->set_edited(false);
- save_timer->start();
- }
+ if (edited) {
+ save_timer->start();
+ }
+ } break;
}
}
@@ -1014,7 +1077,6 @@ void EditorAudioBuses::_add_bus() {
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- //need to simulate new name, so we can undi :(
ur->create_action(TTR("Add Audio Bus"));
ur->add_do_method(AudioServer::get_singleton(), "set_bus_count", AudioServer::get_singleton()->get_bus_count() + 1);
ur->add_undo_method(AudioServer::get_singleton(), "set_bus_count", AudioServer::get_singleton()->get_bus_count());
@@ -1119,21 +1181,12 @@ void EditorAudioBuses::_request_drop_end() {
void EditorAudioBuses::_drop_at_index(int p_bus, int p_index) {
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- //need to simulate new name, so we can undi :(
ur->create_action(TTR("Move Audio Bus"));
+
ur->add_do_method(AudioServer::get_singleton(), "move_bus", p_bus, p_index);
- int final_pos;
- if (p_index == p_bus) {
- final_pos = p_bus;
- } else if (p_index == -1) {
- final_pos = AudioServer::get_singleton()->get_bus_count() - 1;
- } else if (p_index < p_bus) {
- final_pos = p_index;
- } else {
- final_pos = p_index - 1;
- }
- ur->add_undo_method(AudioServer::get_singleton(), "move_bus", final_pos, p_bus);
+ int real_bus = p_index > p_bus ? p_bus : p_bus + 1;
+ int real_index = p_index > p_bus ? p_index - 1 : p_index;
+ ur->add_undo_method(AudioServer::get_singleton(), "move_bus", real_index, real_bus);
ur->add_do_method(this, "_update_buses");
ur->add_undo_method(this, "_update_buses");
@@ -1189,7 +1242,7 @@ void EditorAudioBuses::_load_default_layout() {
}
edited_path = layout_path;
- file->set_text(layout_path.get_file());
+ file->set_text(String(TTR("Layout")) + ": " + layout_path.get_file());
AudioServer::get_singleton()->set_bus_layout(state);
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
@@ -1206,7 +1259,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
}
edited_path = p_string;
- file->set_text(p_string.get_file());
+ file->set_text(String(TTR("Layout")) + ": " + p_string.get_file());
AudioServer::get_singleton()->set_bus_layout(state);
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
@@ -1228,7 +1281,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
}
edited_path = p_string;
- file->set_text(p_string.get_file());
+ file->set_text(String(TTR("Layout")) + ": " + p_string.get_file());
_update_buses();
EditorNode::get_singleton()->get_undo_redo()->clear_history();
call_deferred("_select_layout");
@@ -1262,19 +1315,20 @@ EditorAudioBuses::EditorAudioBuses() {
top_hb = memnew(HBoxContainer);
add_child(top_hb);
- file = memnew(ToolButton);
- file->set_text("default_bus_layout.tres");
+ file = memnew(Label);
+ file->set_text(String(TTR("Layout")) + ": " + "default_bus_layout.tres");
+ file->set_clip_text(true);
+ file->set_h_size_flags(SIZE_EXPAND_FILL);
top_hb->add_child(file);
- file->connect("pressed", this, "_select_layout");
add = memnew(Button);
top_hb->add_child(add);
add->set_text(TTR("Add Bus"));
add->set_tooltip(TTR("Add a new Audio Bus to this layout."));
-
add->connect("pressed", this, "_add_bus");
- top_hb->add_spacer();
+ VSeparator *separator = memnew(VSeparator);
+ top_hb->add_child(separator);
load = memnew(Button);
load->set_text(TTR("Load"));
@@ -1301,7 +1355,6 @@ EditorAudioBuses::EditorAudioBuses() {
_new->connect("pressed", this, "_new_layout");
bus_scroll = memnew(ScrollContainer);
- bus_scroll->add_style_override("panel", memnew(StyleBoxEmpty));
bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
bus_scroll->set_enable_h_scroll(true);
bus_scroll->set_enable_v_scroll(false);
@@ -1377,38 +1430,65 @@ AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) {
AudioBusesEditorPlugin::~AudioBusesEditorPlugin() {
}
-void EditorAudioMeterNotches::add_notch(float normalized_offset, float db_value, bool render_value) {
- notches.push_back(AudioNotch(normalized_offset, db_value, render_value));
+void EditorAudioMeterNotches::add_notch(float p_normalized_offset, float p_db_value, bool p_render_value) {
+
+ notches.push_back(AudioNotch(p_normalized_offset, p_db_value, p_render_value));
+}
+
+Size2 EditorAudioMeterNotches::get_minimum_size() const {
+
+ Ref<Font> font = get_font("font", "Label");
+ float font_height = font->get_height();
+
+ float width = 0;
+ float height = top_padding + btm_padding;
+
+ for (uint8_t i = 0; i < notches.size(); i++) {
+ if (notches[i].render_db_value) {
+ width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB").x);
+ height += font_height;
+ }
+ }
+ width += line_length + label_space;
+
+ return Size2(width, height);
}
void EditorAudioMeterNotches::_bind_methods() {
+
ClassDB::bind_method("add_notch", &EditorAudioMeterNotches::add_notch);
ClassDB::bind_method("_draw_audio_notches", &EditorAudioMeterNotches::_draw_audio_notches);
}
void EditorAudioMeterNotches::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
- notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0f, 1.0f, 1.0f, 0.8f) : Color(0.0f, 0.0f, 0.0f, 0.8f);
- _draw_audio_notches();
+
+ switch (p_what) {
+ case NOTIFICATION_THEME_CHANGED: {
+ notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
+ } break;
+ case NOTIFICATION_DRAW: {
+ _draw_audio_notches();
+ } break;
}
}
void EditorAudioMeterNotches::_draw_audio_notches() {
+
Ref<Font> font = get_font("font", "Label");
float font_height = font->get_height();
for (uint8_t i = 0; i < notches.size(); i++) {
AudioNotch n = notches[i];
- draw_line(Vector2(0.0f, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
+ draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
Vector2(line_length, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
notch_color,
- 1.0f);
+ 1);
if (n.render_db_value) {
draw_string(font,
Vector2(line_length + label_space,
(1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding),
- String("{0}dB").format(varray(Math::abs(n.db_value))),
+ String::num(Math::abs(n.db_value)) + "dB",
notch_color);
}
}
@@ -1419,7 +1499,6 @@ EditorAudioMeterNotches::EditorAudioMeterNotches() :
label_space(2.0f),
btm_padding(9.0f),
top_padding(5.0f) {
- this->set_v_size_flags(SIZE_EXPAND_FILL);
- this->set_h_size_flags(SIZE_EXPAND_FILL);
- notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0f, 1.0f, 1.0f, 0.8f) : Color(0.0f, 0.0f, 0.0f, 0.8f);
+
+ notch_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(0, 0, 0);
}
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 50f2101fd8..20890fd3b5 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -72,7 +72,6 @@ class EditorAudioBus : public PanelContainer {
TextureProgress *vu_r;
} channel[CHANNELS_MAX];
- class EditorAudioMeterNotches *scale;
OptionButton *send;
PopupMenu *effect_options;
@@ -90,8 +89,8 @@ class EditorAudioBus : public PanelContainer {
Tree *effects;
bool updating_bus;
-
bool is_master;
+ mutable bool hovering_drop;
void _gui_input(const Ref<InputEvent> &p_event);
void _bus_popup_pressed(int p_option);
@@ -137,15 +136,18 @@ public:
EditorAudioBus(EditorAudioBuses *p_buses = NULL, bool p_is_master = false);
};
-class EditorAudioBusDrop : public Panel {
+class EditorAudioBusDrop : public Control {
- GDCLASS(EditorAudioBusDrop, Panel);
+ GDCLASS(EditorAudioBusDrop, Control);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
+ mutable bool hovering_drop;
+
protected:
static void _bind_methods();
+ void _notification(int p_what);
public:
EditorAudioBusDrop();
@@ -157,13 +159,14 @@ class EditorAudioBuses : public VBoxContainer {
HBoxContainer *top_hb;
- Button *add;
ScrollContainer *bus_scroll;
HBoxContainer *bus_hb;
EditorAudioBusDrop *drop_end;
- Button *file;
+ Label *file;
+
+ Button *add;
Button *load;
Button *save_as;
Button *_default;
@@ -242,7 +245,8 @@ public:
float top_padding;
Color notch_color;
- void add_notch(float normalized_offset, float db_value, bool render_value = false);
+ void add_notch(float p_normalized_offset, float p_db_value, bool p_render_value = false);
+ Size2 get_minimum_size() const;
private:
static void _bind_methods();
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index f61a831015..38f30df169 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -560,6 +560,7 @@ void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) {
ERR_FAIL_INDEX(p_to_idx, edited_scene.size());
SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]);
}
+
void EditorData::remove_scene(int p_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
if (edited_scene[p_idx].root) {
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 37f148bdbb..b5325a07a5 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -907,7 +907,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
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)
+ ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE);
PackData pd;
pd.ep = &ep;
@@ -924,7 +924,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
pd.file_ofs.sort(); //do sort, so we can do binary search later
FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE)
+ ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
f->store_32(0x43504447); //GDPK
f->store_32(1); //pack version
f->store_32(VERSION_MAJOR);
@@ -977,7 +977,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
ftmp = FileAccess::open(tmppath, FileAccess::READ);
if (!ftmp) {
memdelete(f);
- ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE)
+ ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE);
}
const int bufsize = 16384;
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 714df44e25..56358f059a 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_feature_profile.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#include "editor_feature_profile.h"
#include "core/io/json.h"
#include "core/os/dir_access.h"
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index b7c2ebc1b2..d670719d7d 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* editor_feature_profile.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#ifndef EDITOR_FEATURE_PROFILE_H
#define EDITOR_FEATURE_PROFILE_H
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 3d198dec67..1a293adb4b 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -1253,6 +1253,12 @@ void EditorFileDialog::_favorite_toggled(bool p_toggle) {
_update_favorites();
}
+void EditorFileDialog::_favorite_pressed() {
+
+ favorite->set_pressed(!favorite->is_pressed());
+ _favorite_toggled(favorite->is_pressed());
+}
+
void EditorFileDialog::_recent_selected(int p_idx) {
Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
@@ -1376,6 +1382,7 @@ void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_go_up"), &EditorFileDialog::_go_up);
ClassDB::bind_method(D_METHOD("_favorite_toggled"), &EditorFileDialog::_favorite_toggled);
+ ClassDB::bind_method(D_METHOD("_favorite_pressed"), &EditorFileDialog::_favorite_pressed);
ClassDB::bind_method(D_METHOD("_favorite_selected"), &EditorFileDialog::_favorite_selected);
ClassDB::bind_method(D_METHOD("_favorite_move_up"), &EditorFileDialog::_favorite_move_up);
ClassDB::bind_method(D_METHOD("_favorite_move_down"), &EditorFileDialog::_favorite_move_down);
@@ -1519,7 +1526,7 @@ EditorFileDialog::EditorFileDialog() {
favorite->set_flat(true);
favorite->set_toggle_mode(true);
favorite->set_tooltip(TTR("(Un)favorite current folder."));
- favorite->connect("toggled", this, "_favorite_toggled");
+ favorite->connect("pressed", this, "_favorite_pressed");
pathhb->add_child(favorite);
Ref<ButtonGroup> view_mode_group;
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index edaccac51d..529aaa71de 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -151,6 +151,7 @@ private:
void _update_favorites();
void _favorite_toggled(bool p_toggle);
+ void _favorite_pressed();
void _favorite_selected(int p_idx);
void _favorite_move_up();
void _favorite_move_down();
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 5917869988..df25b08b4c 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -203,8 +203,9 @@ String EditorHelp::_fix_constant(const String &p_constant) const {
if (p_constant.strip_edges() == "2147483647") {
return "0x7FFFFFFF";
}
+
if (p_constant.strip_edges() == "1048575") {
- return "0xfffff";
+ return "0xFFFFF";
}
return p_constant;
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 616a52e25b..55ab38ba6c 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -250,6 +250,25 @@ EditorHelpSearch::EditorHelpSearch() {
vbox->add_child(results_tree, true);
}
+bool EditorHelpSearch::Runner::_is_class_disabled_by_feature_profile(const StringName &p_class) {
+
+ Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+ if (profile.is_null()) {
+ return false;
+ }
+
+ StringName class_name = p_class;
+ while (class_name != StringName()) {
+
+ if (!ClassDB::class_exists(class_name) || profile->is_class_disabled(class_name)) {
+ return true;
+ }
+ class_name = ClassDB::get_parent_class(class_name);
+ }
+
+ return false;
+}
+
bool EditorHelpSearch::Runner::_slice() {
bool phase_done = false;
@@ -299,43 +318,45 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() {
bool EditorHelpSearch::Runner::_phase_match_classes() {
DocData::ClassDoc &class_doc = iterator_doc->value();
-
- matches[class_doc.name] = ClassMatch();
- ClassMatch &match = matches[class_doc.name];
-
- match.doc = &class_doc;
-
- // Match class name.
- if (search_flags & SEARCH_CLASSES)
- match.name = term == "" || _match_string(term, class_doc.name);
-
- // Match members if the term is long enough.
- if (term.length() > 1) {
- if (search_flags & SEARCH_METHODS)
- for (int i = 0; i < class_doc.methods.size(); i++) {
- String method_name = search_flags & SEARCH_CASE_SENSITIVE ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
- if (method_name.find(term) > -1 ||
- (term.begins_with(".") && method_name.begins_with(term.right(1))) ||
- (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
- (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges()))
- match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));
- }
- if (search_flags & SEARCH_SIGNALS)
- for (int i = 0; i < class_doc.signals.size(); i++)
- if (_match_string(term, class_doc.signals[i].name))
- match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i]));
- if (search_flags & SEARCH_CONSTANTS)
- for (int i = 0; i < class_doc.constants.size(); i++)
- if (_match_string(term, class_doc.constants[i].name))
- match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i]));
- if (search_flags & SEARCH_PROPERTIES)
- for (int i = 0; i < class_doc.properties.size(); i++)
- if (_match_string(term, class_doc.properties[i].name))
- match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i]));
- if (search_flags & SEARCH_THEME_ITEMS)
- for (int i = 0; i < class_doc.theme_properties.size(); i++)
- if (_match_string(term, class_doc.theme_properties[i].name))
- match.theme_properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.theme_properties[i]));
+ if (!_is_class_disabled_by_feature_profile(class_doc.name)) {
+
+ matches[class_doc.name] = ClassMatch();
+ ClassMatch &match = matches[class_doc.name];
+
+ match.doc = &class_doc;
+
+ // Match class name.
+ if (search_flags & SEARCH_CLASSES)
+ match.name = term == "" || _match_string(term, class_doc.name);
+
+ // Match members if the term is long enough.
+ if (term.length() > 1) {
+ if (search_flags & SEARCH_METHODS)
+ for (int i = 0; i < class_doc.methods.size(); i++) {
+ String method_name = search_flags & SEARCH_CASE_SENSITIVE ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
+ if (method_name.find(term) > -1 ||
+ (term.begins_with(".") && method_name.begins_with(term.right(1))) ||
+ (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
+ (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges()))
+ match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));
+ }
+ if (search_flags & SEARCH_SIGNALS)
+ for (int i = 0; i < class_doc.signals.size(); i++)
+ if (_match_string(term, class_doc.signals[i].name))
+ match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i]));
+ if (search_flags & SEARCH_CONSTANTS)
+ for (int i = 0; i < class_doc.constants.size(); i++)
+ if (_match_string(term, class_doc.constants[i].name))
+ match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i]));
+ if (search_flags & SEARCH_PROPERTIES)
+ for (int i = 0; i < class_doc.properties.size(); i++)
+ if (_match_string(term, class_doc.properties[i].name))
+ match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i]));
+ if (search_flags & SEARCH_THEME_ITEMS)
+ for (int i = 0; i < class_doc.theme_properties.size(); i++)
+ if (_match_string(term, class_doc.theme_properties[i].name))
+ match.theme_properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.theme_properties[i]));
+ }
}
iterator_doc = iterator_doc->next();
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index 93cf66a0dd..12ffd024a7 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -125,6 +125,8 @@ class EditorHelpSearch::Runner : public Reference {
Map<String, TreeItem *> class_items;
TreeItem *matched_item;
+ bool _is_class_disabled_by_feature_profile(const StringName &p_class);
+
bool _slice();
bool _phase_match_classes_init();
bool _phase_match_classes();
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index ecb9ea5f35..e4ddf44bc4 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -66,7 +66,7 @@ Size2 EditorProperty::get_minimum_size() const {
if (checkable) {
Ref<Texture> check = get_icon("checked", "CheckBox");
- ms.width += check->get_width() + get_constant("hseparator", "Tree");
+ ms.width += check->get_width() + get_constant("hseparation", "CheckBox") + get_constant("hseparator", "Tree");
}
if (bottom_editor != NULL && bottom_editor->is_visible()) {
@@ -228,8 +228,7 @@ void EditorProperty::_notification(int p_what) {
}
check_rect = Rect2(ofs, ((size.height - checkbox->get_height()) / 2), checkbox->get_width(), checkbox->get_height());
draw_texture(checkbox, check_rect.position, color2);
- ofs += get_constant("hseparator", "Tree");
- ofs += checkbox->get_width();
+ ofs += get_constant("hseparator", "Tree") + checkbox->get_width() + get_constant("hseparation", "CheckBox");
text_limit -= ofs;
} else {
check_rect = Rect2();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 90604a36f1..79c312b7b1 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -288,6 +288,7 @@ void EditorNode::_notification(int p_what) {
Engine::get_singleton()->set_editor_hint(true);
+ OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
get_tree()->get_root()->set_usage(Viewport::USAGE_2D_NO_SAMPLING); //reduce memory usage
get_tree()->get_root()->set_disable_3d(true);
get_tree()->get_root()->set_as_audio_listener(false);
@@ -323,9 +324,18 @@ void EditorNode::_notification(int p_what) {
if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
+ // Restore the original FPS cap after focusing back on the editor
+ OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
+
EditorFileSystem::get_singleton()->scan_changes();
}
+ if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT) {
+
+ // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused
+ OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec")));
+ }
+
if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
_menu_option_confirm(FILE_QUIT, false);
@@ -513,6 +523,7 @@ void EditorNode::_fs_changed() {
void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
List<String> scenes; //will load later
+ int current_tab = scene_tabs->get_current_tab();
for (int i = 0; i < p_resources.size(); i++) {
String file_type = ResourceLoader::get_resource_type(p_resources[i]);
@@ -535,6 +546,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
for (List<String>::Element *E = scenes.front(); E; E = E->next()) {
reload_scene(E->get());
}
+
+ scene_tabs->set_current_tab(current_tab);
}
void EditorNode::_sources_changed(bool p_exist) {
@@ -1204,6 +1217,17 @@ void EditorNode::save_all_scenes() {
_save_all_scenes();
}
+void EditorNode::save_scene_list(Vector<String> p_scene_filenames) {
+
+ for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
+ Node *scene = editor_data.get_edited_scene_root(i);
+
+ if (scene && (p_scene_filenames.find(scene->get_filename()) >= 0)) {
+ _save_scene(scene->get_filename(), i);
+ }
+ }
+}
+
void EditorNode::restart_editor() {
exiting = true;
@@ -1273,7 +1297,7 @@ void EditorNode::_dialog_action(String p_file) {
Node *scene = editor_data.get_edited_scene_root();
// If the previous scene is rootless, just close it in favor of the new one.
if (!scene)
- _menu_option_confirm(FILE_CLOSE, false);
+ _menu_option_confirm(FILE_CLOSE, true);
load_scene(p_file, false, true);
} break;
@@ -1286,7 +1310,12 @@ void EditorNode::_dialog_action(String p_file) {
ProjectSettings::get_singleton()->set("application/run/main_scene", p_file);
ProjectSettings::get_singleton()->save();
//would be nice to show the project manager opened with the highlighted field..
- _run(false, ""); // automatically run the project
+
+ if (pick_main_scene->has_meta("from_native") && (bool)pick_main_scene->get_meta("from_native")) {
+ run_native->resume_run_native();
+ } else {
+ _run(false, ""); // automatically run the project
+ }
} break;
case FILE_CLOSE:
case FILE_CLOSE_ALL_AND_QUIT:
@@ -1382,7 +1411,7 @@ void EditorNode::_dialog_action(String p_file) {
case RESOURCE_SAVE:
case RESOURCE_SAVE_AS: {
- ERR_FAIL_COND(saving_resource.is_null())
+ ERR_FAIL_COND(saving_resource.is_null());
save_resource_in_path(saving_resource, p_file);
saving_resource = Ref<Resource>();
ObjectID current = editor_history.get_current();
@@ -1799,28 +1828,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
if (run_filename == "") {
//evidently, run the scene
- main_scene = GLOBAL_DEF("application/run/main_scene", "");
- if (main_scene == "") {
-
- current_option = -1;
- pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category."));
- pick_main_scene->popup_centered_minsize();
- return;
- }
-
- if (!FileAccess::exists(main_scene)) {
-
- current_option = -1;
- pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
- pick_main_scene->popup_centered_minsize();
- return;
- }
-
- if (ResourceLoader::get_resource_type(main_scene) != "PackedScene") {
-
- current_option = -1;
- pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
- pick_main_scene->popup_centered_minsize();
+ if (!ensure_main_scene(false)) {
return;
}
}
@@ -2865,7 +2873,7 @@ bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const {
return plugin_addons.has(p_addon);
}
-void EditorNode::_remove_edited_scene() {
+void EditorNode::_remove_edited_scene(bool p_change_tab) {
int new_index = editor_data.get_edited_scene();
int old_index = new_index;
@@ -2881,18 +2889,19 @@ void EditorNode::_remove_edited_scene() {
if (editor_data.get_scene_path(old_index) != String()) {
ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
}
- _scene_tab_changed(new_index);
+
+ if (p_change_tab) _scene_tab_changed(new_index);
editor_data.remove_scene(old_index);
editor_data.get_undo_redo().clear_history(false);
_update_title();
_update_scene_tabs();
}
-void EditorNode::_remove_scene(int index) {
+void EditorNode::_remove_scene(int index, bool p_change_tab) {
if (editor_data.get_edited_scene() == index) {
//Scene to remove is current scene
- _remove_edited_scene();
+ _remove_edited_scene(p_change_tab);
} else {
//Scene to remove is not active scene
editor_data.remove_scene(index);
@@ -4157,6 +4166,45 @@ bool EditorNode::has_scenes_in_session() {
return !scenes.empty();
}
+bool EditorNode::ensure_main_scene(bool p_from_native) {
+ pick_main_scene->set_meta("from_native", p_from_native); //whether from play button or native run
+ String main_scene = GLOBAL_DEF("application/run/main_scene", "");
+
+ if (main_scene == "") {
+
+ current_option = -1;
+ pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category."));
+ pick_main_scene->popup_centered_minsize();
+ return false;
+ }
+
+ if (!FileAccess::exists(main_scene)) {
+
+ current_option = -1;
+ pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
+ pick_main_scene->popup_centered_minsize();
+ return false;
+ }
+
+ if (ResourceLoader::get_resource_type(main_scene) != "PackedScene") {
+
+ current_option = -1;
+ pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
+ pick_main_scene->popup_centered_minsize();
+ return false;
+ }
+
+ return true;
+}
+
+int EditorNode::get_current_tab() {
+ return scene_tabs->get_current_tab();
+}
+
+void EditorNode::set_current_tab(int p_tab) {
+ scene_tabs->set_current_tab(p_tab);
+}
+
void EditorNode::_update_layouts_menu() {
editor_layouts->clear();
@@ -4784,8 +4832,7 @@ void EditorNode::reload_scene(const String &p_path) {
if (scene_idx == -1) {
if (get_edited_scene()) {
- //scene is not open, so at it might be instanced, just refresh, set tab to itself and it will reload
- set_current_scene(current_tab);
+ //scene is not open, so at it might be instanced. We'll refresh the whole scene later.
editor_data.get_undo_redo().clear_history();
}
return;
@@ -4795,17 +4842,19 @@ void EditorNode::reload_scene(const String &p_path) {
editor_data.apply_changes_in_editors();
_set_scene_metadata(p_path);
}
+
//remove scene
- _remove_scene(scene_idx);
- //reload scene
+ _remove_scene(scene_idx, false);
+ //reload scene
load_scene(p_path, true, false, true, true);
+
//adjust index so tab is back a the previous position
editor_data.move_edited_scene_to_index(scene_idx);
get_undo_redo()->clear_history();
+
//recover the tab
scene_tabs->set_current_tab(current_tab);
- _scene_tab_changed(current_tab);
}
int EditorNode::plugin_init_callback_count = 0;
@@ -4995,7 +5044,7 @@ void EditorNode::_feature_profile_changed() {
main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
main_editor_buttons[EDITOR_ASSETLIB]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB));
- if (profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB)) {
+ if (profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT) || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB)) {
_editor_select(EDITOR_2D);
}
} else {
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 6e7b2b2443..f3bc95c409 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -525,8 +525,8 @@ private:
static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
void _cleanup_scene();
- void _remove_edited_scene();
- void _remove_scene(int index);
+ void _remove_edited_scene(bool p_change_tab = true);
+ void _remove_scene(int index, bool p_change_tab = true);
bool _find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags);
bool _find_and_save_edited_subresources(Object *obj, Map<RES, bool> &processed, int32_t flags);
void _save_edited_subresources(Node *scene, Map<RES, bool> &processed, int32_t flags);
@@ -644,6 +644,12 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+protected:
+ friend class FileSystemDock;
+
+ int get_current_tab();
+ void set_current_tab(int p_tab);
+
public:
bool call_build();
@@ -815,6 +821,7 @@ public:
void remove_tool_menu_item(const String &p_name);
void save_all_scenes();
+ void save_scene_list(Vector<String> p_scene_filenames);
void restart_editor();
void dim_editor(bool p_dimming);
@@ -836,6 +843,8 @@ public:
static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
static void add_build_callback(EditorBuildCallback p_callback);
+
+ bool ensure_main_scene(bool p_from_native);
};
struct EditorProgress {
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 56fc1f87a5..055e1338dd 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -48,7 +48,7 @@ Array EditorInterface::_make_mesh_previews(const Array &p_meshes, int p_preview_
meshes.push_back(p_meshes[i]);
}
- Vector<Ref<Texture> > textures = make_mesh_previews(meshes, p_preview_size);
+ Vector<Ref<Texture> > textures = make_mesh_previews(meshes, NULL, p_preview_size);
Array ret;
for (int i = 0; i < textures.size(); i++) {
ret.push_back(textures[i]);
@@ -57,7 +57,7 @@ Array EditorInterface::_make_mesh_previews(const Array &p_meshes, int p_preview_
return ret;
}
-Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh> > &p_meshes, int p_preview_size) {
+Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh> > &p_meshes, Vector<Transform> *p_transforms, int p_preview_size) {
int size = p_preview_size;
@@ -74,25 +74,14 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
RID camera = VS::get_singleton()->camera_create();
VS::get_singleton()->viewport_attach_camera(viewport, camera);
- VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
- //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()->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()->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);
- VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
-
- //sphere = VS::get_singleton()->mesh_create();
- RID mesh_instance = VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_scenario(mesh_instance, scenario);
-
EditorProgress ep("mlib", TTR("Creating Mesh Previews"), p_meshes.size());
Vector<Ref<Texture> > textures;
@@ -104,25 +93,38 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
textures.push_back(Ref<Texture>());
continue;
}
+
+ Transform mesh_xform;
+ if (p_transforms != NULL) {
+ mesh_xform = (*p_transforms)[i];
+ }
+
+ RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(), scenario);
+ VS::get_singleton()->instance_set_transform(inst, mesh_xform);
+
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.25);
- xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI * 0.25) * xform.basis;
+ xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI / 6);
+ xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI / 6) * xform.basis;
AABB rot_aabb = xform.xform(aabb);
float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
if (m == 0) {
textures.push_back(Ref<Texture>());
continue;
}
- m = 1.0 / m;
- m *= 0.5;
- xform.basis.scale(Vector3(m, m, m));
xform.origin = -xform.basis.xform(ofs); //-ofs*m;
xform.origin.z -= rot_aabb.size.z * 2;
- RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(), scenario);
- VS::get_singleton()->instance_set_transform(inst, xform);
+ xform.invert();
+ xform = mesh_xform * xform;
+
+ VS::get_singleton()->camera_set_transform(camera, xform * Transform(Basis(), Vector3(0, 0, 3)));
+ VS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0);
+
+ VS::get_singleton()->instance_set_transform(light_instance, xform * Transform().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
+ VS::get_singleton()->instance_set_transform(light_instance2, xform * Transform().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
+
ep.step(TTR("Thumbnail..."), i);
Main::iteration();
Main::iteration();
@@ -136,7 +138,6 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
textures.push_back(it);
}
- VS::get_singleton()->free(mesh_instance);
VS::get_singleton()->free(viewport);
VS::get_singleton()->free(light);
VS::get_singleton()->free(light_instance);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index ba4df35e66..c28e607c89 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -100,7 +100,7 @@ public:
Error save_scene();
void save_scene_as(const String &p_scene, bool p_with_preview = true);
- Vector<Ref<Texture> > make_mesh_previews(const Vector<Ref<Mesh> > &p_meshes, int p_preview_size);
+ Vector<Ref<Texture> > make_mesh_previews(const Vector<Ref<Mesh> > &p_meshes, Vector<Transform> *p_trnasforms, int p_preview_size);
EditorInterface();
};
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 2baad8c904..6cca0a0ffa 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -203,7 +203,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
if (has_small_texture) {
ResourceSaver::save(cache_base + "_small.png", r_small_texture);
}
- FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
+ Error err;
+ FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE, &err);
+ ERR_FAIL_COND(err != OK);
f->store_line(itos(thumbnail_size));
f->store_line(itos(has_small_texture));
f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index b73cda6008..585ea0ec69 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -101,6 +101,12 @@ void EditorRunNative::_notification(int p_what) {
void EditorRunNative::_run_native(int p_idx, int p_platform) {
+ if (!EditorNode::get_singleton()->ensure_main_scene(true)) {
+ resume_idx = p_idx;
+ resume_platform = p_platform;
+ return;
+ }
+
Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(p_platform);
ERR_FAIL_COND(eep.is_null());
@@ -144,6 +150,10 @@ void EditorRunNative::_run_native(int p_idx, int p_platform) {
eep->run(preset, p_idx, flags);
}
+void EditorRunNative::resume_run_native() {
+ _run_native(resume_idx, resume_platform);
+}
+
void EditorRunNative::_bind_methods() {
ClassDB::bind_method("_run_native", &EditorRunNative::_run_native);
@@ -198,4 +208,6 @@ EditorRunNative::EditorRunNative() {
deploy_debug_remote = false;
debug_collisions = false;
debug_navigation = false;
+ resume_idx = 0;
+ resume_platform = 0;
}
diff --git a/editor/editor_run_native.h b/editor/editor_run_native.h
index 10cca014cf..d62c982725 100644
--- a/editor/editor_run_native.h
+++ b/editor/editor_run_native.h
@@ -45,6 +45,9 @@ class EditorRunNative : public HBoxContainer {
bool debug_collisions;
bool debug_navigation;
+ int resume_idx;
+ int resume_platform;
+
void _run_native(int p_idx, int p_platform);
protected:
@@ -64,6 +67,8 @@ public:
void set_debug_navigation(bool p_debug);
bool get_debug_navigation() const;
+ void resume_run_native();
+
EditorRunNative();
};
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index c0dc231ea9..c7fac07ba2 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -318,7 +318,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/display_scale", 0);
hints["interface/editor/display_scale"] = PropertyInfo(Variant::INT, "interface/editor/display_scale", PROPERTY_HINT_ENUM, "Auto,75%,100%,125%,150%,175%,200%,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/custom_display_scale", 1.0f);
- hints["interface/editor/custom_display_scale"] = PropertyInfo(Variant::REAL, "interface/editor/custom_display_scale", PROPERTY_HINT_RANGE, "0.75,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ hints["interface/editor/custom_display_scale"] = PropertyInfo(Variant::REAL, "interface/editor/custom_display_scale", PROPERTY_HINT_RANGE, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/main_font_size", 14);
hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font_size", 14);
@@ -340,6 +340,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/dim_amount"] = PropertyInfo(Variant::REAL, "interface/editor/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/dim_transition_time", 0.08f);
hints["interface/editor/dim_transition_time"] = PropertyInfo(Variant::REAL, "interface/editor/dim_transition_time", PROPERTY_HINT_RANGE, "0,1,0.001", PROPERTY_USAGE_DEFAULT);
+ _initial_set("interface/editor/low_processor_mode_sleep_usec", 6900); // ~144 FPS
+ hints["interface/editor/low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT);
+ _initial_set("interface/editor/unfocused_low_processor_mode_sleep_usec", 50000); // 20 FPS
+ hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/separate_distraction_mode", false);
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
_initial_set("interface/editor/quit_confirmation", true);
@@ -565,7 +569,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/bone_outline_size", 2);
_initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4));
_initial_set("editors/2d/warped_mouse_panning", true);
- _initial_set("editors/2d/simple_spacebar_panning", false);
+ _initial_set("editors/2d/simple_panning", false);
_initial_set("editors/2d/scroll_to_pan", false);
_initial_set("editors/2d/pan_speed", 20);
@@ -1119,7 +1123,7 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re
Variant _EDITOR_GET(const String &p_setting) {
- ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant())
+ ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant());
return EditorSettings::get_singleton()->get(p_setting);
}
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 194a131095..e57217bb11 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -451,9 +451,11 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
} else if (dirAccess->dir_exists(p_path)) {
path = target_path + "/";
} else {
+ memdelete(dirAccess);
ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path));
ERR_FAIL();
}
+ memdelete(dirAccess);
}
_set_current_path_text(path);
@@ -1201,6 +1203,21 @@ void FileSystemDock::_update_favorites_list_after_move(const Map<String, String>
EditorSettings::get_singleton()->set_favorites(new_favorites);
}
+void FileSystemDock::_save_scenes_after_move(const Map<String, String> &p_renames) const {
+ Vector<String> remaps;
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(), p_renames, remaps);
+ Vector<String> new_filenames;
+
+ for (int i = 0; i < remaps.size(); ++i) {
+ String file = p_renames.has(remaps[i]) ? p_renames[remaps[i]] : remaps[i];
+ if (ResourceLoader::get_resource_type(file) == "PackedScene") {
+ new_filenames.push_back(file);
+ }
+ }
+
+ editor->save_scene_list(new_filenames);
+}
+
void FileSystemDock::_make_dir_confirm() {
String dir_name = make_dir_dialog_text->get_text().strip_edges();
@@ -1279,14 +1296,21 @@ void FileSystemDock::_rename_operation_confirm() {
Map<String, String> file_renames;
Map<String, String> folder_renames;
_try_move_item(to_rename, new_path, file_renames, folder_renames);
+
+ int current_tab = editor->get_current_tab();
+
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
- //Rescan everything
+ editor->set_current_tab(current_tab);
+
print_verbose("FileSystem: calling rescan.");
_rescan();
+
+ print_verbose("FileSystem: saving moved scenes.");
+ _save_scenes_after_move(file_renames);
}
void FileSystemDock::_duplicate_operation_confirm() {
@@ -1382,13 +1406,20 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
}
if (is_moved) {
+ int current_tab = editor->get_current_tab();
+
_update_dependencies_after_move(file_renames);
_update_resource_paths_after_move(file_renames);
_update_project_settings_after_move(file_renames);
_update_favorites_list_after_move(file_renames, folder_renames);
+ editor->set_current_tab(current_tab);
+
print_verbose("FileSystem: calling rescan.");
_rescan();
+
+ print_verbose("FileSystem: saving moved scenes.");
+ _save_scenes_after_move(file_renames);
}
}
@@ -2038,7 +2069,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths, bool p_display_path_dependent_options) {
// Add options for files and folders
- ERR_FAIL_COND(p_paths.empty())
+ ERR_FAIL_COND(p_paths.empty());
Vector<String> filenames;
Vector<String> foldernames;
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 978235b328..46eaf71a8a 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -202,6 +202,7 @@ private:
void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
void _update_resource_paths_after_move(const Map<String, String> &p_renames) const;
+ void _save_scenes_after_move(const Map<String, String> &p_renames) const;
void _update_favorites_list_after_move(const Map<String, String> &p_files_renames, const Map<String, String> &p_folders_renames) const;
void _update_project_settings_after_move(const Map<String, String> &p_folders_renames) const;
diff --git a/editor/icons/icon_multi_mesh_instance_2d.svg b/editor/icons/icon_multi_mesh_instance_2d.svg
new file mode 100644
index 0000000000..07202ac659
--- /dev/null
+++ b/editor/icons/icon_multi_mesh_instance_2d.svg
@@ -0,0 +1,4 @@
+<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
+<rect x="-1" y="-1" width="582" height="402" fill="none"/>
+<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.6e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35664-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.6e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.6e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35664-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2z" fill="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+</svg>
diff --git a/editor/icons/icon_project_icon_loading.svg b/editor/icons/icon_project_icon_loading.svg
new file mode 100644
index 0000000000..3802b67654
--- /dev/null
+++ b/editor/icons/icon_project_icon_loading.svg
@@ -0,0 +1 @@
+<svg height="64" viewBox="0 0 64 64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m8 0c-4.432 0-8 3.568-8 8v48c0 4.432 3.568 8 8 8h48c4.432 0 8-3.568 8-8v-48c0-4.432-3.568-8-8-8z" fill="#e0e0e0" fill-opacity=".188235"/></svg> \ No newline at end of file
diff --git a/editor/icons/icon_visual_shader.svg b/editor/icons/icon_visual_shader.svg
index e2c4f128b2..ded54276f4 100644
--- a/editor/icons/icon_visual_shader.svg
+++ b/editor/icons/icon_visual_shader.svg
@@ -1,105 +1,10 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16"
- height="16"
- version="1.1"
- viewBox="0 0 16 16"
- id="svg20"
- sodipodi:docname="icon_visual_shader.svg"
- inkscape:version="0.92.3 (2405546, 2018-03-11)">
- <metadata
- id="metadata26">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs24" />
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="640"
- inkscape:window-height="480"
- id="namedview22"
- showgrid="false"
- inkscape:zoom="14.75"
- inkscape:cx="8"
- inkscape:cy="8"
- inkscape:window-x="67"
- inkscape:window-y="27"
- inkscape:window-maximized="0"
- inkscape:current-layer="svg20" />
- <g
- id="g18"
- transform="matrix(1,0,0,0.50605327,0,0.49394673)">
- <path
- d="M 2,1 C 1.44774,1.0001 1.00006,1.4477 1,2 v 12 c 5.52e-5,0.5523 0.44774,0.9999 1,1 h 12 c 0.55226,-10e-5 0.99994,-0.4477 1,-1 V 6 L 10,1 Z m 1,2 h 6 v 3 c 0,0.554 0.44599,1 1,1 h 3 v 6 H 3 Z"
- id="path2"
- inkscape:connector-curvature="0"
- style="fill:#e0e0e0" />
- <path
- d="m 10,11 h 2 v 1 h -2 z"
- id="path4"
- inkscape:connector-curvature="0"
- style="fill:#9f70ff" />
- <path
- d="M 4,6 H 6 V 7 H 4 Z"
- id="path6"
- inkscape:connector-curvature="0"
- style="fill:#ffeb70" />
- <path
- d="m 8,8 h 4 V 9 H 8 Z"
- id="path8"
- inkscape:connector-curvature="0"
- style="fill:#9dff70" />
- <path
- d="M 7,6 H 8 V 7 H 7 Z"
- id="path10"
- inkscape:connector-curvature="0"
- style="fill:#70deff" />
- <path
- d="m 4,11 h 5 v 1 H 4 Z"
- id="path12"
- inkscape:connector-curvature="0"
- style="fill:#ff70ac" />
- <path
- d="M 4,4 H 7 V 5 H 4 Z"
- id="path14"
- inkscape:connector-curvature="0"
- style="fill:#ff7070" />
- <path
- d="M 4,8 H 7 V 9 H 4 Z"
- id="path16"
- inkscape:connector-curvature="0"
- style="fill:#70ffb9" />
- </g>
- <path
- inkscape:connector-curvature="0"
- style="fill:#e0e0e0"
- d="m 2.8642321,9 v 6 h 2 a 3,3 0 0 0 3,-3 V 9 h -2 v 3 a 1,1 0 0 1 -1,1 V 9 Z"
- id="path1394" />
- <path
- inkscape:connector-curvature="0"
- style="fill:#e0e0e0"
- d="m 10.864232,9 a 2,2 0 0 0 -1.7323999,1 2,2 0 0 0 0,2 2,2 0 0 0 1.7323999,1 H 8.8642321 v 2 h 1.9999999 a 2,2 0 0 0 1.7324,-1 2,2 0 0 0 0,-2 2,2 0 0 0 -1.7324,-1 h 2 V 9 Z"
- id="path30" />
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m2.8642 9.9954v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1-1 1v-4z" fill="#e0e0e0"/>
+<path d="m10.864 9.9954a2 2 0 0 0-1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0-1.7324-1h2v-2z" fill="#e0e0e0"/>
+<path d="m2 1c-0.55226 1e-4 -0.99994 0.4477-1 1v7h2v-6h6v3c0 0.554 0.44599 1 1 1h3v2h2v-3l-5-5z" fill="#e0e0e0"/>
+<path d="m4 6h2v1h-2z" fill="#ffeb70"/>
+<path d="m8 8h4v1h-4z" fill="#9dff70"/>
+<path d="m7 6h1v1h-1z" fill="#70deff"/>
+<path d="m4 4h3v1h-3z" fill="#ff7070"/>
+<path d="m4 8h3v1h-3z" fill="#70ffb9"/>
</svg>
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 5da731b0a0..0989a43705 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1024,7 +1024,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String
} else {
ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = ResourceLoader::load(ext_name);
+ p_materials[mat] = ResourceLoader::load(ext_name, "", true); // disable loading from the cache.
}
}
@@ -1070,13 +1070,13 @@ 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 (FileAccess::exists(ext_name)) {
+ if (p_keep_materials && FileAccess::exists(ext_name)) {
//if exists, use it
p_materials[mat] = ResourceLoader::load(ext_name);
} else {
ResourceSaver::save(ext_name, mat, ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat] = ResourceLoader::load(ext_name);
+ p_materials[mat] = ResourceLoader::load(ext_name, "", true); // disable loading from the cache.
}
}
diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp
index 35fdd32e2c..eca4e58abe 100644
--- a/editor/import/resource_importer_texture_atlas.cpp
+++ b/editor/import/resource_importer_texture_atlas.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* resource_importer_texture_atlas.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_texture_atlas.h"
#include "atlas_import_failed.xpm"
diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h
index 62be570dc6..042deacfe3 100644
--- a/editor/import/resource_importer_texture_atlas.h
+++ b/editor/import/resource_importer_texture_atlas.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* resource_importer_texture_atlas.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 RESOURCE_IMPORTER_TEXTURE_ATLAS_H
#define RESOURCE_IMPORTER_TEXTURE_ATLAS_H
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index fdf1103258..e39f2dabaa 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -119,7 +119,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->close();
memdelete(file);
- ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)")
+ ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)");
ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
}
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 8a2393ff60..8a0812973f 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -169,7 +169,7 @@ void InspectorDock::_save_resource(bool save_as) const {
uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj));
RES current_res = RES(Object::cast_to<Resource>(current_obj));
@@ -183,7 +183,7 @@ void InspectorDock::_unref_resource() const {
uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj));
RES current_res = RES(Object::cast_to<Resource>(current_obj));
current_res->set_path("");
@@ -194,7 +194,7 @@ void InspectorDock::_copy_resource() const {
uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+ ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj));
RES current_res = RES(Object::cast_to<Resource>(current_obj));
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index bfee76492b..dff6eb5c5e 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -471,7 +471,7 @@ void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) {
void AnimationNodeBlendTreeEditor::_open_in_editor(const String &p_which) {
Ref<AnimationNode> an = blend_tree->get_node(p_which);
- ERR_FAIL_COND(!an.is_valid())
+ ERR_FAIL_COND(!an.is_valid());
AnimationTreeEditor::get_singleton()->enter_editor(p_which);
}
@@ -798,7 +798,7 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
String new_name = p_text;
- ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1)
+ ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1);
if (new_name == prev_name) {
return; //nothing to do
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 951e971615..5204565c06 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -289,39 +289,24 @@ void AnimationPlayerEditor::_pause_pressed() {
//player->set_pause( pause->is_pressed() );
}
+void AnimationPlayerEditor::_animation_selected(int p_which) {
-String AnimationPlayerEditor::_get_current_animation() const {
-
+ if (updating)
+ return;
// when selecting an animation, the idea is that the only interesting behavior
// ui-wise is that it should play/blend the next one if currently playing
+ String current;
if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- return animation->get_item_text(animation->get_selected());
+ current = animation->get_item_text(animation->get_selected());
}
- return "";
-}
-
-void AnimationPlayerEditor::_animation_selected(int p_which) {
-
- if (updating)
- return;
-
- _current_animation_updated();
-}
-
-void AnimationPlayerEditor::_current_animation_updated() {
-
- String current = _get_current_animation();
-
if (current != "") {
- Ref<Animation> anim = player->get_animation(current);
player->set_assigned_animation(current);
- {
- if (!anim->is_connected("changed", this, "_current_animation_updated"))
- anim->connect("changed", this, "_current_animation_updated");
+ Ref<Animation> anim = player->get_animation(current);
+ {
track_editor->set_animation(anim);
Node *root = player->get_node(player->get_root());
@@ -784,7 +769,7 @@ void AnimationPlayerEditor::_dialog_action(String p_file) {
if (current != "") {
Ref<Animation> anim = player->get_animation(current);
- ERR_FAIL_COND(!Object::cast_to<Resource>(*anim))
+ ERR_FAIL_COND(!Object::cast_to<Resource>(*anim));
RES current_res = RES(Object::cast_to<Resource>(*anim));
@@ -1078,19 +1063,17 @@ void AnimationPlayerEditor::_list_changed() {
_update_player();
}
+void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len) {
+
+ frame->set_max(p_len);
+}
+
void AnimationPlayerEditor::_animation_key_editor_anim_step_changed(float p_len) {
if (p_len)
frame->set_step(p_len);
else
frame->set_step(0.00001);
-
- String current = _get_current_animation();
-
- if (current != "") {
- Ref<Animation> anim = player->get_animation(current);
- anim->_change_notify("step");
- }
}
void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag) {
@@ -1568,7 +1551,6 @@ void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_autoplay_pressed"), &AnimationPlayerEditor::_autoplay_pressed);
ClassDB::bind_method(D_METHOD("_pause_pressed"), &AnimationPlayerEditor::_pause_pressed);
ClassDB::bind_method(D_METHOD("_animation_selected"), &AnimationPlayerEditor::_animation_selected);
- ClassDB::bind_method(D_METHOD("_current_animation_updated"), &AnimationPlayerEditor::_current_animation_updated);
ClassDB::bind_method(D_METHOD("_animation_name_edited"), &AnimationPlayerEditor::_animation_name_edited);
ClassDB::bind_method(D_METHOD("_animation_new"), &AnimationPlayerEditor::_animation_new);
ClassDB::bind_method(D_METHOD("_animation_rename"), &AnimationPlayerEditor::_animation_rename);
@@ -1588,6 +1570,7 @@ void AnimationPlayerEditor::_bind_methods() {
//ClassDB::bind_method(D_METHOD("_editor_load_all"),&AnimationPlayerEditor::_editor_load_all);
ClassDB::bind_method(D_METHOD("_list_changed"), &AnimationPlayerEditor::_list_changed);
ClassDB::bind_method(D_METHOD("_animation_key_editor_seek"), &AnimationPlayerEditor::_animation_key_editor_seek);
+ ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_len_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_step_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_step_changed);
ClassDB::bind_method(D_METHOD("_hide_anim_editors"), &AnimationPlayerEditor::_hide_anim_editors);
ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate);
@@ -1801,6 +1784,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
add_child(track_editor);
track_editor->set_v_size_flags(SIZE_EXPAND_FILL);
track_editor->connect("timeline_changed", this, "_animation_key_editor_seek");
+ track_editor->connect("animation_len_changed", this, "_animation_key_editor_anim_len_changed");
track_editor->connect("animation_step_changed", this, "_animation_key_editor_anim_step_changed");
_update_player();
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index b1026b5b9f..dedce16bbc 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -171,9 +171,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _autoplay_pressed();
void _stop_pressed();
void _pause_pressed();
- String _get_current_animation() const;
void _animation_selected(int p_which);
- void _current_animation_updated();
void _animation_new();
void _animation_rename();
void _animation_name_edited();
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index f06b4b2828..e25e7ac7ed 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1096,7 +1096,7 @@ void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) {
String new_name = p_text;
- ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1)
+ ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1);
if (new_name == prev_name) {
return; // Nothing to do.
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 0dfb53b34a..1503258ff5 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -35,7 +35,7 @@
#include "editor_node.h"
#include "editor_settings.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) {
+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, const String &p_cost) {
title->set_text(p_title);
asset_id = p_asset_id;
@@ -44,13 +44,6 @@ void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, co
author->set_text(p_author);
author_id = p_author_id;
price->set_text(p_cost);
-
- for (int i = 0; i < 5; i++) {
- if (i < p_rating)
- stars[i]->set_texture(get_icon("Favorites", "EditorIcons"));
- else
- stars[i]->set_texture(get_icon("NonFavorite", "EditorIcons"));
- }
}
void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Texture> &p_image) {
@@ -65,9 +58,10 @@ void EditorAssetLibraryItem::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- icon->set_normal_texture(get_icon("DefaultProjectIcon", "EditorIcons"));
+ icon->set_normal_texture(get_icon("ProjectIconLoading", "EditorIcons"));
category->add_color_override("font_color", Color(0.5, 0.5, 0.5));
author->add_color_override("font_color", Color(0.5, 0.5, 0.5));
+ price->add_color_override("font_color", Color(0.5, 0.5, 0.5));
}
}
@@ -100,17 +94,19 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() {
Ref<StyleBoxEmpty> border;
border.instance();
- border->set_default_margin(MARGIN_LEFT, 5);
- border->set_default_margin(MARGIN_RIGHT, 5);
- border->set_default_margin(MARGIN_BOTTOM, 5);
- border->set_default_margin(MARGIN_TOP, 5);
+ border->set_default_margin(MARGIN_LEFT, 5 * EDSCALE);
+ border->set_default_margin(MARGIN_RIGHT, 5 * EDSCALE);
+ border->set_default_margin(MARGIN_BOTTOM, 5 * EDSCALE);
+ border->set_default_margin(MARGIN_TOP, 5 * EDSCALE);
add_style_override("panel", border);
HBoxContainer *hb = memnew(HBoxContainer);
+ // Add some spacing to visually separate the icon from the asset details
+ hb->add_constant_override("separation", 15 * EDSCALE);
add_child(hb);
icon = memnew(TextureButton);
- icon->set_custom_minimum_size(Size2(64, 64));
+ icon->set_custom_minimum_size(Size2(64, 64) * EDSCALE);
icon->set_default_cursor_shape(CURSOR_POINTING_HAND);
icon->connect("pressed", this, "_asset_clicked");
@@ -139,18 +135,11 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() {
author->connect("pressed", this, "_author_clicked");
vb->add_child(author);
- HBoxContainer *rating_hb = memnew(HBoxContainer);
- vb->add_child(rating_hb);
-
- for (int i = 0; i < 5; i++) {
- stars[i] = memnew(TextureRect);
- rating_hb->add_child(stars[i]);
- }
price = memnew(Label);
price->set_text(TTR("Free"));
vb->add_child(price);
- set_custom_minimum_size(Size2(250, 100));
+ set_custom_minimum_size(Size2(250, 100) * EDSCALE);
set_h_size_flags(SIZE_EXPAND_FILL);
set_mouse_filter(MOUSE_FILTER_PASS);
@@ -194,7 +183,6 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
break;
}
}
- //item->call("set_image",p_type,p_index,p_image);
} break;
case EditorAssetLibrary::IMAGE_QUEUE_SCREENSHOT: {
@@ -207,7 +195,6 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
break;
}
}
- //item->call("set_image",p_type,p_index,p_image);
} break;
}
}
@@ -248,13 +235,13 @@ void EditorAssetLibraryItemDescription::_preview_click(int p_id) {
}
}
-void EditorAssetLibraryItemDescription::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, int p_version, const String &p_version_string, const String &p_description, const String &p_download_url, const String &p_browse_url, const String &p_sha256_hash) {
+void EditorAssetLibraryItemDescription::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, const String &p_cost, int p_version, const String &p_version_string, const String &p_description, const String &p_download_url, const String &p_browse_url, const String &p_sha256_hash) {
asset_id = p_asset_id;
title = p_title;
download_url = p_download_url;
sha256 = p_sha256_hash;
- item->configure(p_title, p_asset_id, p_category, p_category_id, p_author, p_author_id, p_rating, p_cost);
+ item->configure(p_title, p_asset_id, p_category, p_category_id, p_author, p_author_id, p_cost);
description->clear();
description->add_text(TTR("Version:") + " " + p_version_string + "\n");
description->add_text(TTR("Contents:") + " ");
@@ -554,7 +541,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() {
hb2->add_child(retry);
hb2->add_child(install);
- set_custom_minimum_size(Size2(310, 0));
+ set_custom_minimum_size(Size2(310, 0) * EDSCALE);
download = memnew(HTTPRequest);
add_child(download);
@@ -666,7 +653,6 @@ void EditorAssetLibrary::_install_asset() {
}
const char *EditorAssetLibrary::sort_key[SORT_MAX] = {
- "rating",
"downloads",
"name",
"cost",
@@ -674,10 +660,9 @@ const char *EditorAssetLibrary::sort_key[SORT_MAX] = {
};
const char *EditorAssetLibrary::sort_text[SORT_MAX] = {
- "Rating",
"Downloads",
"Name",
- "Cost",
+ "License", // "cost" stores the SPDX license name in the Godot Asset Library
"Updated"
};
@@ -733,6 +718,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
image_data = cached_data;
file->close();
+ memdelete(file);
}
}
@@ -807,6 +793,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (file) {
file->store_line(new_etag);
file->close();
+ memdelete(file);
}
int len = p_data.size();
@@ -816,6 +803,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
file->store_32(len);
file->store_buffer(r.ptr(), len);
file->close();
+ memdelete(file);
}
break;
@@ -855,6 +843,7 @@ void EditorAssetLibrary::_update_image_queue() {
if (file) {
headers.push_back("If-None-Match: " + file->get_line());
file->close();
+ memdelete(file);
}
}
@@ -984,7 +973,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int
to = p_page_count;
hbc->add_spacer();
- hbc->add_constant_override("separation", 5);
+ hbc->add_constant_override("separation", 5 * EDSCALE);
Button *first = memnew(Button);
first->set_text(TTR("First"));
@@ -1190,8 +1179,8 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
asset_items = memnew(GridContainer);
asset_items->set_columns(2);
- asset_items->add_constant_override("hseparation", 10);
- asset_items->add_constant_override("vseparation", 10);
+ asset_items->add_constant_override("hseparation", 10 * EDSCALE);
+ asset_items->add_constant_override("vseparation", 10 * EDSCALE);
library_vb->add_child(asset_items);
@@ -1208,12 +1197,11 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
ERR_CONTINUE(!r.has("author_id"));
ERR_CONTINUE(!r.has("category_id"));
ERR_FAIL_COND(!category_map.has(r["category_id"]));
- ERR_CONTINUE(!r.has("rating"));
ERR_CONTINUE(!r.has("cost"));
EditorAssetLibraryItem *item = memnew(EditorAssetLibraryItem);
asset_items->add_child(item);
- item->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["rating"], r["cost"]);
+ item->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"]);
item->connect("asset_selected", this, "_select_asset");
item->connect("author_selected", this, "_select_author");
item->connect("category_selected", this, "_select_category");
@@ -1234,7 +1222,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
ERR_FAIL_COND(!r.has("version_string"));
ERR_FAIL_COND(!r.has("category_id"));
ERR_FAIL_COND(!category_map.has(r["category_id"]));
- ERR_FAIL_COND(!r.has("rating"));
ERR_FAIL_COND(!r.has("cost"));
ERR_FAIL_COND(!r.has("description"));
ERR_FAIL_COND(!r.has("download_url"));
@@ -1250,7 +1237,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
description->popup_centered_minsize();
description->connect("confirmed", this, "_install_asset");
- description->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["rating"], r["cost"], r["version"], r["version_string"], r["description"], r["download_url"], r["browse_url"], r["download_hash"]);
+ description->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"], r["version"], r["version_string"], r["description"], r["download_url"], r["browse_url"], r["download_hash"]);
/*item->connect("asset_selected",this,"_select_asset");
item->connect("author_selected",this,"_select_author");
item->connect("category_selected",this,"_category_selected");*/
@@ -1357,7 +1344,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
HBoxContainer *search_hb = memnew(HBoxContainer);
library_main->add_child(search_hb);
- library_main->add_constant_override("separation", 10);
+ library_main->add_constant_override("separation", 10 * EDSCALE);
search_hb->add_child(memnew(Label(TTR("Search:") + " ")));
filter = memnew(LineEdit);
@@ -1459,10 +1446,10 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
Ref<StyleBoxEmpty> border2;
border2.instance();
- border2->set_default_margin(MARGIN_LEFT, 15);
- border2->set_default_margin(MARGIN_RIGHT, 35);
- border2->set_default_margin(MARGIN_BOTTOM, 15);
- border2->set_default_margin(MARGIN_TOP, 15);
+ border2->set_default_margin(MARGIN_LEFT, 15 * EDSCALE);
+ border2->set_default_margin(MARGIN_RIGHT, 35 * EDSCALE);
+ border2->set_default_margin(MARGIN_BOTTOM, 15 * EDSCALE);
+ border2->set_default_margin(MARGIN_TOP, 15 * EDSCALE);
PanelContainer *library_vb_border = memnew(PanelContainer);
library_scroll->add_child(library_vb_border);
@@ -1474,15 +1461,14 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
library_vb->set_h_size_flags(SIZE_EXPAND_FILL);
library_vb_border->add_child(library_vb);
- //margin_panel->set_stop_mouse(false);
asset_top_page = memnew(HBoxContainer);
library_vb->add_child(asset_top_page);
asset_items = memnew(GridContainer);
asset_items->set_columns(2);
- asset_items->add_constant_override("hseparation", 10);
- asset_items->add_constant_override("vseparation", 10);
+ asset_items->add_constant_override("hseparation", 10 * EDSCALE);
+ asset_items->add_constant_override("vseparation", 10 * EDSCALE);
library_vb->add_child(asset_items);
@@ -1496,7 +1482,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
last_queue_id = 0;
- library_vb->add_constant_override("separation", 20);
+ library_vb->add_constant_override("separation", 20 * EDSCALE);
load_status = memnew(ProgressBar);
load_status->set_min(0);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index dd5f3c2077..81288ae831 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -77,7 +77,7 @@ protected:
static void _bind_methods();
public:
- void 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);
+ void 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, const String &p_cost);
EditorAssetLibraryItem();
};
@@ -120,7 +120,7 @@ protected:
static void _bind_methods();
public:
- void 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, int p_version, const String &p_version_string, const String &p_description, const String &p_download_url, const String &p_browse_url, const String &p_sha256_hash);
+ void 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, const String &p_cost, int p_version, const String &p_version_string, const String &p_description, const String &p_download_url, const String &p_browse_url, const String &p_sha256_hash);
void add_preview(int p_id, bool p_video, const String &p_url);
String get_title() { return title; }
@@ -216,7 +216,6 @@ class EditorAssetLibrary : public PanelContainer {
};
enum SortOrder {
- SORT_RATING,
SORT_DOWNLOADS,
SORT_NAME,
SORT_COST,
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 172096b1a7..0ab3d26c85 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -53,7 +53,6 @@ void AudioStreamEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
_current = _player->get_playback_position();
_indicator->update();
- _preview->update();
}
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -121,15 +120,19 @@ void AudioStreamEditor::_play() {
void AudioStreamEditor::_stop() {
_player->stop();
- _on_finished();
+ _play_button->set_icon(get_icon("MainPlay", "EditorIcons"));
+ _current = 0;
+ _indicator->update();
+ set_process(false);
}
void AudioStreamEditor::_on_finished() {
_play_button->set_icon(get_icon("MainPlay", "EditorIcons"));
- _current = 0;
- _indicator->update();
- set_process(false);
+ if (_current == _player->get_stream()->get_length()) {
+ _current = 0;
+ _indicator->update();
+ }
}
void AudioStreamEditor::_draw_indicator() {
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 92cc12d931..fbf01a9405 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1081,7 +1081,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
if (b->is_pressed() &&
(b->get_button_index() == BUTTON_MIDDLE ||
(b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) ||
- (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
+ (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) {
// Pan the viewport
panning = true;
}
@@ -1097,7 +1097,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
- if (k->get_scancode() == KEY_SPACE && (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") || drag_type != DRAG_NONE)) {
+ bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event);
+
+ if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) {
if (!panning) {
if (k->is_pressed() && !k->is_echo()) {
//Pan the viewport
@@ -1110,6 +1112,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
}
}
}
+
+ if (is_pan_key)
+ pan_pressed = k->is_pressed();
}
Ref<InputEventMouseMotion> m = p_event;
@@ -2214,7 +2219,7 @@ bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) {
void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
bool accepted = false;
- if (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") || !Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+ if (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || !pan_pressed) {
if ((accepted = _gui_input_rulers_and_guides(p_event))) {
//printf("Rulers and guides\n");
} else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) {
@@ -3280,6 +3285,7 @@ void CanvasItemEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
+ bool has_container_parents = false;
int nb_control = 0;
int nb_having_pivot = 0;
@@ -3323,6 +3329,10 @@ void CanvasItemEditor::_notification(int p_what) {
viewport->update();
}
nb_control++;
+
+ if (Object::cast_to<Container>(control->get_parent())) {
+ has_container_parents = true;
+ }
}
if (canvas_item->_edit_use_pivot()) {
@@ -3336,25 +3346,22 @@ void CanvasItemEditor::_notification(int p_what) {
// Show / Hide the layout and anchors mode buttons
if (nb_control > 0 && nb_control == selection.size()) {
presets_menu->set_visible(true);
- presets_menu->set_tooltip(TTR("Presets for the anchors and margins values of a Control node."));
anchor_mode_button->set_visible(true);
- anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their margins."));
// Set the pressed state of the node
anchor_mode_button->set_pressed(anchors_mode);
// Disable if the selected node is child of a container
- presets_menu->set_disabled(false);
- anchor_mode_button->set_disabled(false);
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
- if (!control || Object::cast_to<Container>(control->get_parent())) {
- presets_menu->set_disabled(true);
- presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
- anchor_mode_button->set_disabled(true);
- anchor_mode_button->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
- break;
- }
+ if (has_container_parents) {
+ presets_menu->set_disabled(true);
+ presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
+ anchor_mode_button->set_disabled(true);
+ anchor_mode_button->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
+ } else {
+ presets_menu->set_disabled(false);
+ presets_menu->set_tooltip(TTR("Presets for the anchors and margins values of a Control node."));
+ anchor_mode_button->set_disabled(false);
+ anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their margins."));
}
} else {
presets_menu->set_visible(false);
@@ -4778,6 +4785,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
dragged_guide_pos = Point2();
dragged_guide_index = -1;
panning = false;
+ pan_pressed = false;
bone_last_frame = 0;
@@ -5127,6 +5135,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
+ pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
singleton = this;
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index e098d261c0..ff221eb758 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -265,6 +265,7 @@ private:
bool key_rot;
bool key_scale;
bool panning;
+ bool pan_pressed;
MenuOption last_option;
@@ -383,6 +384,7 @@ private:
Ref<ShortCut> set_pivot_shortcut;
Ref<ShortCut> multiply_grid_step_shortcut;
Ref<ShortCut> divide_grid_step_shortcut;
+ Ref<ShortCut> pan_view_shortcut;
bool _is_node_locked(const Node *p_node);
bool _is_node_movable(const Node *p_node, bool p_popup_warning = false);
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 55feb40c2c..3b1d728b8b 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -593,7 +593,8 @@ struct CanvasItemPlotCurve {
color2(p_color2) {}
void operator()(Vector2 pos0, Vector2 pos1, bool in_definition) {
- ci.draw_line(pos0, pos1, in_definition ? color1 : color2);
+ // FIXME: Using a line width greater than 1 breaks curve rendering
+ ci.draw_line(pos0, pos1, in_definition ? color1 : color2, 1, true);
}
};
@@ -616,8 +617,8 @@ void CurveEditor::_draw() {
Vector2 min_edge = get_world_pos(Vector2(0, view_size.y));
Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0));
- const Color grid_color0 = Color(1.0, 1.0, 1.0, 0.15);
- const Color grid_color1 = Color(1.0, 1.0, 1.0, 0.07);
+ const Color grid_color0 = get_color("mono_color", "Editor") * Color(1, 1, 1, 0.15);
+ const Color grid_color1 = get_color("mono_color", "Editor") * Color(1, 1, 1, 0.07);
draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0);
draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0);
draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0);
@@ -674,13 +675,13 @@ void CurveEditor::_draw() {
if (i != 0) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT);
- draw_line(get_view_pos(pos), control_pos, tangent_color);
+ draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE), true);
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
}
if (i != curve.get_point_count() - 1) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_RIGHT);
- draw_line(get_view_pos(pos), control_pos, tangent_color);
+ draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE), true);
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
}
}
@@ -689,8 +690,8 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(_world_to_view);
- const Color line_color = get_color("highlight_color", "Editor");
- const Color edge_line_color = get_color("font_color", "Editor");
+ const Color line_color = get_color("font_color", "Editor");
+ const Color edge_line_color = get_color("highlight_color", "Editor");
CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color);
plot_curve_accurate(curve, 4.f / view_size.x, plot_func);
@@ -736,10 +737,10 @@ void CurveEditor::stroke_rect(Rect2 rect, Color color) {
Vector2 c(rect.position.x, rect.position.y + rect.size.y);
Vector2 d(rect.position + rect.size);
- draw_line(a, b, color);
- draw_line(b, d, color);
- draw_line(d, c, color);
- draw_line(c, a, color);
+ draw_line(a, b, color, Math::round(EDSCALE));
+ draw_line(b, d, color, Math::round(EDSCALE));
+ draw_line(d, c, color, Math::round(EDSCALE));
+ draw_line(c, a, color, Math::round(EDSCALE));
}
void CurveEditor::_bind_methods() {
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 28e57ac48a..285823d95a 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -643,7 +643,7 @@ Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const S
float max = -1000;
float min = 1000;
int from = uint64_t(i) * frame_length / w;
- int to = uint64_t(i + 1) * frame_length / w;
+ int to = (uint64_t(i) + 1) * frame_length / w;
to = MIN(to, frame_length);
from = MIN(from, frame_length - 1);
if (to == from) {
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 18586b2fe5..e582f6ded2 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -71,6 +71,8 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
if (!p_merge)
p_library->clear();
+ Map<int, MeshInstance *> mesh_instances;
+
for (int i = 0; i < p_scene->get_child_count(); i++) {
Node *child = p_scene->get_child(i);
@@ -91,6 +93,15 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
if (mesh.is_null())
continue;
+ mesh = mesh->duplicate();
+ for (int j = 0; j < mesh->get_surface_count(); ++j) {
+ Ref<Material> mat = mi->get_surface_material(j);
+
+ if (mat.is_valid()) {
+ mesh->surface_set_material(j, mat);
+ }
+ }
+
int id = p_library->find_item_by_name(mi->get_name());
if (id < 0) {
@@ -100,6 +111,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
}
p_library->set_item_mesh(id, mesh);
+ mesh_instances[id] = mi;
Vector<MeshLibrary::ShapeData> collisions;
@@ -159,14 +171,26 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
if (1) {
Vector<Ref<Mesh> > meshes;
+ Vector<Transform> transforms;
Vector<int> ids = p_library->get_item_list();
for (int i = 0; i < ids.size(); i++) {
- meshes.push_back(p_library->get_item_mesh(ids[i]));
+
+ if (mesh_instances.find(ids[i])) {
+
+ meshes.push_back(p_library->get_item_mesh(ids[i]));
+ transforms.push_back(mesh_instances[ids[i]]->get_transform());
+ }
}
- Vector<Ref<Texture> > textures = EditorInterface::get_singleton()->make_mesh_previews(meshes, EditorSettings::get_singleton()->get("editors/grid_map/preview_size"));
+ Vector<Ref<Texture> > textures = EditorInterface::get_singleton()->make_mesh_previews(meshes, &transforms, EditorSettings::get_singleton()->get("editors/grid_map/preview_size"));
+ int j = 0;
for (int i = 0; i < ids.size(); i++) {
- p_library->set_item_preview(ids[i], textures[i]);
+
+ if (mesh_instances.find(ids[i])) {
+
+ p_library->set_item_preview(ids[i], textures[j]);
+ j++;
+ }
}
}
}
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index fc0a425bfc..cae705a697 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -197,7 +197,7 @@ void MultiMeshEditor::_populate() {
float areapos = Math::random(0.0f, area_accum);
Map<float, int>::Element *E = triangle_area_map.find_closest(areapos);
- ERR_FAIL_COND(!E)
+ ERR_FAIL_COND(!E);
int index = E->get();
ERR_FAIL_INDEX(index, facecount);
diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp
index 4c354b8002..6fabdc93c6 100644
--- a/editor/plugins/particles_2d_editor_plugin.cpp
+++ b/editor/plugins/particles_2d_editor_plugin.cpp
@@ -94,7 +94,7 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) {
cpu_particles->set_z_index(particles->get_z_index());
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Convert from Particles2D"));
+ ur->create_action(TTR("Convert to CPUParticles"));
ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", particles, cpu_particles, true, false);
ur->add_do_reference(particles);
ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, particles, false, false);
diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp
index 09180edf2a..3f4f66a26d 100644
--- a/editor/plugins/particles_editor_plugin.cpp
+++ b/editor/plugins/particles_editor_plugin.cpp
@@ -67,7 +67,7 @@ bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vect
float areapos = Math::random(0.0f, area_accum);
Map<float, int>::Element *E = triangle_area_map.find_closest(areapos);
- ERR_FAIL_COND_V(!E, false)
+ ERR_FAIL_COND_V(!E, false);
int index = E->get();
ERR_FAIL_INDEX_V(index, geometry.size(), false);
@@ -312,7 +312,13 @@ void ParticlesEditor::_menu_option(int p_option) {
cpu_particles->set_visible(node->is_visible());
cpu_particles->set_pause_mode(node->get_pause_mode());
- EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, cpu_particles, false);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Convert to CPUParticles"));
+ ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, cpu_particles, true, false);
+ ur->add_do_reference(node);
+ ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, node, false, false);
+ ur->add_undo_reference(this);
+ ur->commit_action();
} break;
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 839c9483d7..6bf916cdfc 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -388,6 +388,14 @@ void ScriptEditor::_save_history() {
void ScriptEditor::_go_to_tab(int p_idx) {
+ ScriptEditorBase *current = _get_current_editor();
+ if (current) {
+ if (current->is_unsaved()) {
+
+ current->apply_code();
+ }
+ }
+
Control *c = Object::cast_to<Control>(tab_container->get_child(p_idx));
if (!c)
return;
@@ -715,6 +723,8 @@ void ScriptEditor::_resave_scripts(const String &p_str) {
se->trim_trailing_whitespace();
}
+ se->insert_final_newline();
+
if (convert_indent_on_save) {
if (use_space_indentation) {
se->convert_indent_to_spaces();
@@ -1070,6 +1080,8 @@ void ScriptEditor::_menu_option(int p_option) {
if (trim_trailing_whitespace_on_save)
current->trim_trailing_whitespace();
+ current->insert_final_newline();
+
if (convert_indent_on_save) {
if (use_space_indentation) {
current->convert_indent_to_spaces();
@@ -1089,7 +1101,10 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case FILE_SAVE_AS: {
- current->trim_trailing_whitespace();
+ if (trim_trailing_whitespace_on_save)
+ current->trim_trailing_whitespace();
+
+ current->insert_final_newline();
if (convert_indent_on_save) {
if (use_space_indentation) {
@@ -1733,7 +1748,19 @@ void ScriptEditor::_update_script_names() {
Ref<Texture> icon = se->get_icon();
String path = se->get_edited_resource()->get_path();
bool built_in = !path.is_resource_file();
- String name = built_in ? path.get_file() : se->get_name();
+ String name;
+
+ if (built_in) {
+
+ name = path.get_file();
+ String resource_name = se->get_edited_resource()->get_name();
+ if (resource_name != "") {
+ name = name.substr(0, name.find("::", 0) + 2) + resource_name;
+ }
+ } else {
+
+ name = se->get_name();
+ }
_ScriptEditorItemData sd;
sd.icon = icon;
@@ -1949,10 +1976,11 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags");
List<String> args;
+ bool has_file_flag = false;
+ String script_path = ProjectSettings::get_singleton()->globalize_path(p_resource->get_path());
if (flags.size()) {
String project_path = ProjectSettings::get_singleton()->get_resource_path();
- String script_path = ProjectSettings::get_singleton()->globalize_path(p_resource->get_path());
flags = flags.replacen("{line}", itos(p_line > 0 ? p_line : 0));
flags = flags.replacen("{col}", itos(p_col));
@@ -1974,6 +2002,9 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
} else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) {
String arg = flags.substr(from, num_chars);
+ if (arg.find("{file}") != -1) {
+ has_file_flag = true;
+ }
// do path replacement here, else there will be issues with spaces and quotes
arg = arg.replacen("{project}", project_path);
@@ -1988,6 +2019,11 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
}
}
+ // Default to passing script path if no {file} flag is specified.
+ if (!has_file_flag) {
+ args.push_back(script_path);
+ }
+
Error err = OS::get_singleton()->execute(path, args, false);
if (err == OK)
return false;
@@ -2101,6 +2137,8 @@ void ScriptEditor::save_all_scripts() {
se->trim_trailing_whitespace();
}
+ se->insert_final_newline();
+
if (!se->is_unsaved())
continue;
@@ -3408,7 +3446,8 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/list_script_names_as", PROPERTY_HINT_ENUM, "Name,Parent Directory And Name,Full Path"));
EDITOR_DEF("text_editor/open_scripts/list_script_names_as", 0);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_path", PROPERTY_HINT_GLOBAL_FILE));
- EDITOR_DEF("text_editor/external/exec_flags", "");
+ EDITOR_DEF("text_editor/external/exec_flags", "{file}");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_flags", PROPERTY_HINT_PLACEHOLDER_TEXT, "Call flags with placeholders: {project}, {file}, {col}, {line}."));
ED_SHORTCUT("script_editor/open_recent", TTR("Open Recent"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T);
ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Files"));
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 683fa881f8..fae98d6ec8 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -99,6 +99,7 @@ public:
virtual void set_executing_line(int p_line) = 0;
virtual void clear_executing_line() = 0;
virtual void trim_trailing_whitespace() = 0;
+ virtual void insert_final_newline() = 0;
virtual void convert_indent_to_spaces() = 0;
virtual void convert_indent_to_tabs() = 0;
virtual void ensure_focus() = 0;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index f66ae0465f..cea65bb9b4 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -457,6 +457,11 @@ void ScriptTextEditor::trim_trailing_whitespace() {
code_editor->trim_trailing_whitespace();
}
+void ScriptTextEditor::insert_final_newline() {
+
+ code_editor->insert_final_newline();
+}
+
void ScriptTextEditor::convert_indent_to_spaces() {
code_editor->convert_indent_to_spaces();
@@ -542,7 +547,6 @@ void ScriptTextEditor::_validate_script() {
script->set_source_code(text);
script->update_exports();
_update_member_keywords();
- //script->reload(); //will update all the variables in property editors
}
functions.clear();
@@ -553,30 +557,36 @@ void ScriptTextEditor::_validate_script() {
}
_update_connected_methods();
- code_editor->set_warning_nb(missing_connections.size() + warnings.size());
+ int warning_nb = warnings.size();
warnings_panel->clear();
- // add missing connections
- Node *base = get_tree()->get_edited_scene_root();
- if (base && missing_connections.size() > 0) {
- warnings_panel->push_table(1);
- for (List<Connection>::Element *E = missing_connections.front(); E; E = E->next()) {
- Connection connection = E->get();
-
- String base_path = base->get_name();
- String source_path = base == connection.source ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.source)));
- String target_path = base == connection.target ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.target)));
+ // Add missing connections.
+ if (GLOBAL_GET("debug/gdscript/warnings/enable").booleanize()) {
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base && missing_connections.size() > 0) {
+ warnings_panel->push_table(1);
+ for (List<Connection>::Element *E = missing_connections.front(); E; E = E->next()) {
+ Connection connection = E->get();
+
+ String base_path = base->get_name();
+ String source_path = base == connection.source ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.source)));
+ String target_path = base == connection.target ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.target)));
+
+ warnings_panel->push_cell();
+ warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor"));
+ warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'."), connection.method, connection.signal, source_path, target_path));
+ warnings_panel->pop(); // Color.
+ warnings_panel->pop(); // Cell.
+ }
+ warnings_panel->pop(); // Table.
- warnings_panel->push_cell();
- warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor"));
- warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'"), connection.method, connection.signal, source_path, target_path));
- warnings_panel->pop(); // Color
- warnings_panel->pop(); // Cell
+ warning_nb += missing_connections.size();
}
- warnings_panel->pop(); // Table
}
- // add script warnings
+ code_editor->set_warning_nb(warning_nb);
+
+ // Add script warnings.
warnings_panel->push_table(3);
for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) {
ScriptLanguage::Warning w = E->get();
@@ -586,13 +596,13 @@ void ScriptTextEditor::_validate_script() {
warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor"));
warnings_panel->add_text(TTR("Line") + " " + itos(w.line));
warnings_panel->add_text(" (" + w.string_code + "):");
- warnings_panel->pop(); // Color
- warnings_panel->pop(); // Meta goto
- warnings_panel->pop(); // Cell
+ warnings_panel->pop(); // Color.
+ warnings_panel->pop(); // Meta goto.
+ warnings_panel->pop(); // Cell.
warnings_panel->push_cell();
warnings_panel->add_text(w.message);
- warnings_panel->pop(); // Cell
+ warnings_panel->pop(); // Cell.
Dictionary ignore_meta;
ignore_meta["line"] = w.line;
@@ -600,11 +610,10 @@ void ScriptTextEditor::_validate_script() {
warnings_panel->push_cell();
warnings_panel->push_meta(ignore_meta);
warnings_panel->add_text(TTR("(ignore)"));
- warnings_panel->pop(); // Meta ignore
- warnings_panel->pop(); // Cell
- //warnings_panel->add_newline();
+ warnings_panel->pop(); // Meta ignore.
+ warnings_panel->pop(); // Cell.
}
- warnings_panel->pop(); // Table
+ warnings_panel->pop(); // Table.
line--;
bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true);
@@ -735,7 +744,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<String>
base = _find_node_for_script(base, base, script);
}
String hint;
- Error err = script->get_language()->complete_code(p_code, script->get_path().get_base_dir(), base, r_options, r_force, hint);
+ Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
if (err == OK && hint != "") {
code_editor->get_text_edit()->set_code_hint(hint);
}
@@ -766,7 +775,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
EditorNode::get_singleton()->load_resource(p_symbol);
}
- } else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path().get_base_dir(), base, result) == OK) {
+ } else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) {
_goto_line(p_row);
@@ -867,12 +876,33 @@ void ScriptTextEditor::_update_connected_methods() {
continue;
}
+ // As deleted nodes are still accessible via the undo/redo system, check if they're still on the tree.
+ Node *source = Object::cast_to<Node>(connection.source);
+ if (source && !source->is_inside_tree()) {
+ continue;
+ }
+
int line = script->get_language()->find_function(connection.method, text_edit->get_text());
if (line < 0) {
- missing_connections.push_back(connection);
- continue;
+ // There is a chance that the method is inherited from another script.
+ bool found_inherited_function = false;
+ Ref<Script> inherited_script = script->get_base_script();
+ while (!inherited_script.is_null()) {
+ line = inherited_script->get_language()->find_function(connection.method, inherited_script->get_source_code());
+ if (line != -1) {
+ found_inherited_function = true;
+ break;
+ }
+
+ inherited_script = inherited_script->get_base_script();
+ }
+
+ if (!found_inherited_function) {
+ missing_connections.push_back(connection);
+ }
+ } else {
+ text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method);
}
- text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method);
}
}
}
@@ -1447,7 +1477,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
base = _find_node_for_script(base, base, script);
}
ScriptLanguage::LookupResult result;
- if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_mouse, script->get_path().get_base_dir(), base, result) == OK) {
+ if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_mouse, script->get_path(), base, result) == OK) {
open_docs = true;
}
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index bdfdf18d45..7f5b6c065d 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -194,6 +194,7 @@ public:
virtual void set_edit_state(const Variant &p_state);
virtual void ensure_focus();
virtual void trim_trailing_whitespace();
+ virtual void insert_final_newline();
virtual void convert_indent_to_spaces();
virtual void convert_indent_to_tabs();
virtual void tag_saved_version();
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 60f1248ace..a1c0b732fa 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -4211,7 +4211,7 @@ void SpatialEditor::set_state(const Dictionary &p_state) {
Array vp = d["viewports"];
uint32_t vp_size = static_cast<uint32_t>(vp.size());
if (vp_size > VIEWPORTS_COUNT) {
- WARN_PRINT("Ignoring superfluous viewport settings from spatial editor state.")
+ WARN_PRINT("Ignoring superfluous viewport settings from spatial editor state.");
vp_size = VIEWPORTS_COUNT;
}
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index a0f3c253d1..d036d7e965 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -251,6 +251,11 @@ void TextEditor::trim_trailing_whitespace() {
code_editor->trim_trailing_whitespace();
}
+void TextEditor::insert_final_newline() {
+
+ code_editor->insert_final_newline();
+}
+
void TextEditor::convert_indent_to_spaces() {
code_editor->convert_indent_to_spaces();
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 2da7474793..e06d816177 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -130,6 +130,7 @@ public:
virtual void set_executing_line(int p_line);
virtual void clear_executing_line();
virtual void trim_trailing_whitespace();
+ virtual void insert_final_newline();
virtual void convert_indent_to_spaces();
virtual void convert_indent_to_tabs();
virtual void ensure_focus();
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 772e47ac3a..16f93b8fd3 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -299,9 +299,13 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p
Vector2 position;
int current = manual_palette->get_current();
if (current != -1) {
- position = manual_palette->get_item_metadata(current);
+ if (tool != TOOL_PASTING) {
+ position = manual_palette->get_item_metadata(current);
+ } else {
+ position = p_autotile_coord;
+ }
} else {
- // if there is no manual tile selected, that either means that
+ // If there is no manual tile selected, that either means that
// autotiling is enabled, or the given tile is not autotiling. Either
// way, the coordinate of the tile does not matter, so assigning it to
// the coordinate of the existing tile works fine.
@@ -309,7 +313,7 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p
}
if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose && prev_position == position)
- return; //check that it's actually different
+ return; // Check that it's actually different.
for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
@@ -322,15 +326,19 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p
node->_set_celld(p_pos, _create_cell_dictionary(p_value, p_flip_h, p_flip_v, p_transpose, p_autotile_coord));
+ if (tool == TOOL_PASTING)
+ return;
+
if (manual_autotile || (p_value != -1 && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE)) {
if (current != -1) {
node->set_cell_autotile_coord(p_pos.x, p_pos.y, position);
+ } else if (node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE && priority_atlastile) {
+ // BIND_CENTER is used to indicate that bitmask should not update for this tile cell.
+ node->get_tileset()->autotile_set_bitmask(p_value, Vector2(p_pos.x, p_pos.y), TileSet::BIND_CENTER);
+ node->update_cell_bitmask(p_pos.x, p_pos.y);
}
} else {
- // manually placing tiles should not update bitmasks
- if (tool != TOOL_PASTING) {
- node->update_bitmask_area(Point2(p_pos));
- }
+ node->update_bitmask_area(Point2(p_pos));
}
}
@@ -339,6 +347,11 @@ void TileMapEditor::_manual_toggled(bool p_enabled) {
_update_palette();
}
+void TileMapEditor::_priority_toggled(bool p_enabled) {
+ priority_atlastile = p_enabled;
+ _update_palette();
+}
+
void TileMapEditor::_text_entered(const String &p_text) {
canvas_item_editor_viewport->grab_focus();
@@ -385,6 +398,8 @@ void TileMapEditor::_update_palette() {
// Update the palette
Vector<int> selected = get_selected_tiles();
+ int selected_single = palette->get_current();
+ int selected_manual = manual_palette->get_current();
palette->clear();
manual_palette->clear();
manual_palette->hide();
@@ -492,12 +507,13 @@ void TileMapEditor::_update_palette() {
if (selected.get(0) != TileMap::INVALID_CELL) {
set_selected_tiles(selected);
sel_tile = selected.get(Math::rand() % selected.size());
- } else {
+ } else if (palette->get_item_count() > 0) {
palette->select(0);
}
if (sel_tile != TileMap::INVALID_CELL) {
- if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE) {
+ if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) ||
+ (!priority_atlastile && tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE)) {
const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile);
@@ -533,16 +549,19 @@ void TileMapEditor::_update_palette() {
if (manual_palette->get_item_count() > 0) {
// Only show the manual palette if at least tile exists in it
- int selected2 = manual_palette->get_current();
- if (selected2 == -1) selected2 = 0;
- manual_palette->set_current(selected2);
+ if (selected_manual == -1 || selected_single != palette->get_current())
+ selected_manual = 0;
+ if (selected_manual < manual_palette->get_item_count())
+ manual_palette->set_current(selected_manual);
manual_palette->show();
}
if (sel_tile != TileMap::INVALID_CELL && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) {
manual_button->show();
+ priority_button->hide();
} else {
manual_button->hide();
+ priority_button->show();
}
}
@@ -553,23 +572,25 @@ void TileMapEditor::_pick_tile(const Point2 &p_pos) {
if (id == TileMap::INVALID_CELL)
return;
- if (search_box->get_text().strip_edges() != "") {
-
+ if (search_box->get_text() != "") {
search_box->set_text("");
_update_palette();
}
- Vector<int> selected;
-
- selected.push_back(id);
- set_selected_tiles(selected);
-
flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y);
flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y);
transpose = node->is_cell_transposed(p_pos.x, p_pos.y);
autotile_coord = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
+ Vector<int> selected;
+ selected.push_back(id);
+ set_selected_tiles(selected);
_update_palette();
+
+ if ((manual_autotile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::AUTO_TILE) || (!priority_atlastile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::ATLAS_TILE)) {
+ manual_palette->select(manual_palette->find_metadata((Point2)autotile_coord));
+ }
+
CanvasItemEditor::get_singleton()->update_viewport();
}
@@ -686,7 +707,8 @@ void TileMapEditor::_fill_points(const PoolVector<Vector2> p_points, const Dicti
_set_cell(pr[i], ids, xf, yf, tr);
node->make_bitmask_area_dirty(pr[i]);
}
- node->update_dirty_bitmask();
+ if (!manual_autotile)
+ node->update_dirty_bitmask();
}
void TileMapEditor::_erase_points(const PoolVector<Vector2> p_points) {
@@ -744,15 +766,15 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
Rect2 r = node->get_tileset()->tile_get_region(p_cell);
if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) {
Vector2 offset;
- int selected = manual_palette->get_current();
- if ((manual_autotile || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) && selected != -1) {
- offset = manual_palette->get_item_metadata(selected);
- } else {
- if (tool != TOOL_PASTING) {
- offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell);
+ if (tool != TOOL_PASTING) {
+ int selected = manual_palette->get_current();
+ if ((manual_autotile || (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE && !priority_atlastile)) && selected != -1) {
+ offset = manual_palette->get_item_metadata(selected);
} else {
- offset = p_autotile_coord;
+ offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell);
}
+ } else {
+ offset = p_autotile_coord;
}
int spacing = node->get_tileset()->autotile_get_spacing(p_cell);
@@ -760,7 +782,8 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
r.position += (r.size + Vector2(spacing, spacing)) * offset;
}
Size2 sc = p_xform.get_scale();
- Size2 cell_size = node->get_cell_size();
+ /* For a future CheckBox to Center Texture:
+ Size2 cell_size = node->get_cell_size(); */
Rect2 rect = Rect2();
rect.position = node->map_to_world(p_point) + node->get_cell_draw_offset();
@@ -772,10 +795,11 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
if (p_transpose) {
SWAP(tile_ofs.x, tile_ofs.y);
+ /* For a future CheckBox to Center Texture:
rect.position.x += cell_size.x / 2 - rect.size.y / 2;
rect.position.y += cell_size.y / 2 - rect.size.x / 2;
} else {
- rect.position += cell_size / 2 - rect.size / 2;
+ rect.position += cell_size / 2 - rect.size / 2; */
}
if (p_flip_h) {
@@ -795,10 +819,11 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
Color modulate = node->get_tileset()->tile_get_modulate(p_cell);
modulate.a = 0.5;
- if (r.has_no_area())
+ if (r.has_no_area()) {
p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose);
- else
+ } else {
p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose);
+ }
}
void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i p_autotile_coord, const Transform2D &p_xform) {
@@ -833,7 +858,6 @@ void TileMapEditor::_update_copydata() {
TileData tcd;
tcd.cell = node->get_cell(j, i);
-
if (tcd.cell != TileMap::INVALID_CELL) {
tcd.pos = Point2i(j, i);
tcd.flip_h = node->is_cell_x_flipped(j, i);
@@ -960,7 +984,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
} else {
- // Mousebutton was released
+ // Mousebutton was released.
if (tool != TOOL_NONE) {
if (tool == TOOL_PAINTING) {
@@ -1024,7 +1048,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
- return true; // We want to keep the Pasting tool
+ return true; // We want to keep the Pasting tool.
} else if (tool == TOOL_SELECTING) {
CanvasItemEditor::get_singleton()->update_viewport();
@@ -1048,7 +1072,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
_finish_undo();
- // We want to keep the bucket-tool active
+ // So the fill preview is cleared right after the click.
+ CanvasItemEditor::get_singleton()->update_viewport();
+
+ // We want to keep the bucket-tool active.
return true;
}
@@ -1175,7 +1202,7 @@ 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
+ // 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);
Vector<int> ids = get_selected_tiles();
@@ -1196,7 +1223,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (tool == TOOL_ERASING) {
- // erase using bresenham line to prevent holes in painting if the user moves fast
+ // 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);
@@ -1321,13 +1348,13 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
if (!mouse_over) {
- // Editor shortcuts should not fire if mouse not in viewport
+ // Editor shortcuts should not fire if mouse not in viewport.
return false;
}
if (ED_IS_SHORTCUT("tile_map_editor/paint_tile", p_event)) {
// NOTE: We do not set tool = TOOL_PAINTING as this begins painting
- // immediately without pressing the left mouse button first
+ // immediately without pressing the left mouse button first.
tool = TOOL_NONE;
CanvasItemEditor::get_singleton()->update_viewport();
@@ -1409,7 +1436,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
return true;
}
- } else if (k.is_valid()) { // release event
+ } else if (k.is_valid()) { // Release event.
if (tool == TOOL_NONE) {
@@ -1425,7 +1452,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
#else
if (k->get_scancode() == KEY_CONTROL) {
#endif
- // go back to that last tool if KEY_CONTROL was released
+ // Go back to that last tool if KEY_CONTROL was released.
tool = last_tool;
CanvasItemEditor::get_singleton()->update_viewport();
@@ -1713,6 +1740,7 @@ void TileMapEditor::_icon_size_changed(float p_value) {
void TileMapEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_manual_toggled"), &TileMapEditor::_manual_toggled);
+ ClassDB::bind_method(D_METHOD("_priority_toggled"), &TileMapEditor::_priority_toggled);
ClassDB::bind_method(D_METHOD("_text_entered"), &TileMapEditor::_text_entered);
ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed);
ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input);
@@ -1816,6 +1844,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
node = NULL;
manual_autotile = false;
+ priority_atlastile = false;
manual_position = Vector2(0, 0);
canvas_item_editor_viewport = NULL;
editor = p_editor;
@@ -1846,10 +1875,15 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
add_child(tool_hb);
manual_button = memnew(CheckBox);
- manual_button->set_text("Disable Autotile");
+ manual_button->set_text(TTR("Disable Autotile"));
manual_button->connect("toggled", this, "_manual_toggled");
add_child(manual_button);
+ priority_button = memnew(CheckBox);
+ priority_button->set_text(TTR("Enable Priority"));
+ priority_button->connect("toggled", this, "_priority_toggled");
+ add_child(priority_button);
+
search_box = memnew(LineEdit);
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
search_box->connect("text_entered", this, "_text_entered");
@@ -1958,31 +1992,31 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
p->connect("id_pressed", this, "_menu_option");
rotate_left_button = memnew(ToolButton);
- rotate_left_button->set_tooltip(TTR("Rotate left"));
+ rotate_left_button->set_tooltip(TTR("Rotate Left"));
rotate_left_button->set_focus_mode(FOCUS_NONE);
rotate_left_button->connect("pressed", this, "_rotate", varray(-1));
tool_hb->add_child(rotate_left_button);
rotate_right_button = memnew(ToolButton);
- rotate_right_button->set_tooltip(TTR("Rotate right"));
+ rotate_right_button->set_tooltip(TTR("Rotate Right"));
rotate_right_button->set_focus_mode(FOCUS_NONE);
rotate_right_button->connect("pressed", this, "_rotate", varray(1));
tool_hb->add_child(rotate_right_button);
flip_horizontal_button = memnew(ToolButton);
- flip_horizontal_button->set_tooltip(TTR("Flip horizontally"));
+ flip_horizontal_button->set_tooltip(TTR("Flip Horizontally"));
flip_horizontal_button->set_focus_mode(FOCUS_NONE);
flip_horizontal_button->connect("pressed", this, "_flip_horizontal");
tool_hb->add_child(flip_horizontal_button);
flip_vertical_button = memnew(ToolButton);
- flip_vertical_button->set_tooltip(TTR("Flip vertically"));
+ flip_vertical_button->set_tooltip(TTR("Flip Vertically"));
flip_vertical_button->set_focus_mode(FOCUS_NONE);
flip_vertical_button->connect("pressed", this, "_flip_vertical");
tool_hb->add_child(flip_vertical_button);
clear_transform_button = memnew(ToolButton);
- clear_transform_button->set_tooltip(TTR("Clear transform"));
+ clear_transform_button->set_tooltip(TTR("Clear Transform"));
clear_transform_button->set_focus_mode(FOCUS_NONE);
clear_transform_button->connect("pressed", this, "_clear_transform");
tool_hb->add_child(clear_transform_button);
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index fcdada1111..3f0abd1e6e 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -74,6 +74,7 @@ class TileMapEditor : public VBoxContainer {
TileMap *node;
bool manual_autotile;
+ bool priority_atlastile;
Vector2 manual_position;
EditorNode *editor;
@@ -103,6 +104,7 @@ class TileMapEditor : public VBoxContainer {
ToolButton *clear_transform_button;
CheckBox *manual_button;
+ CheckBox *priority_button;
Tool tool;
Tool last_tool;
@@ -183,6 +185,7 @@ class TileMapEditor : public VBoxContainer {
void set_selected_tiles(Vector<int> p_tile);
void _manual_toggled(bool p_enabled);
+ void _priority_toggled(bool p_enabled);
void _text_entered(const String &p_text);
void _text_changed(const String &p_text);
void _sbox_input(const Ref<InputEvent> &p_ie);
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index a00be3c0ce..4b225fddf5 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -3104,7 +3104,6 @@ void TileSetEditor::update_workspace_tile_mode() {
_select_edited_shape_coord();
tool_editmode[EDITMODE_BITMASK]->hide();
- tool_editmode[EDITMODE_PRIORITY]->hide();
}
_on_edit_mode_changed(edit_mode);
}
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index b0baf954d2..7b521aba13 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1971,7 +1971,7 @@ ProjectManager::ProjectManager() {
l = memnew(Label);
String hash = String(VERSION_HASH);
if (hash.length() != 0)
- hash = "." + hash.left(7);
+ hash = "." + hash.left(9);
l->set_text("v" VERSION_FULL_BUILD "" + hash);
l->set_align(Label::ALIGN_CENTER);
top_hb->add_child(l);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index ce2795f37b..e8f5139cd5 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1082,7 +1082,7 @@ void SceneTreeDock::_notification(int p_what) {
bool show_create_root = bool(EDITOR_GET("interface/editors/show_scene_tree_root_selection")) && get_tree()->get_edited_scene_root() == NULL;
- if (show_create_root != create_root_dialog->is_visible_in_tree()) {
+ if (show_create_root != create_root_dialog->is_visible_in_tree() && !remote_tree->is_visible()) {
if (show_create_root) {
create_root_dialog->show();
scene_tree->hide();
@@ -2367,6 +2367,7 @@ void SceneTreeDock::hide_tab_buttons() {
void SceneTreeDock::_remote_tree_selected() {
scene_tree->hide();
+ create_root_dialog->hide();
if (remote_tree)
remote_tree->show();
edit_remote->set_pressed(true);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 5ca3448693..064bf0077a 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -51,6 +51,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
if (connect_to_script_mode) {
return; //don't do anything in this mode
}
+
TreeItem *item = Object::cast_to<TreeItem>(p_item);
ERR_FAIL_COND(!item);
@@ -220,23 +221,27 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (marked.has(p_node)) {
- item->set_text(0, String(p_node->get_name()) + " " + TTR("(Connecting From)"));
-
+ String node_name = p_node->get_name();
+ if (connecting_signal) {
+ node_name += " " + TTR("(Connecting From)");
+ }
+ item->set_text(0, node_name);
item->set_custom_color(0, accent);
}
} else if (part_of_subscene) {
- //item->set_selectable(0,marked_selectable);
if (valid_types.size() == 0) {
item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
}
-
} else if (marked.has(p_node)) {
- if (!connect_to_script_mode) {
- item->set_selectable(0, marked_selectable);
+ String node_name = p_node->get_name();
+ if (connecting_signal) {
+ node_name += " " + TTR("(Connecting From)");
}
- item->set_custom_color(0, get_color("error_color", "Editor"));
+ item->set_text(0, node_name);
+ item->set_selectable(0, marked_selectable);
+ item->set_custom_color(0, get_color("accent_color", "Editor"));
} else if (!marked_selectable && !marked_children_selectable) {
Node *node = p_node;
@@ -394,15 +399,17 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
- if (p_node != get_scene_node() && !p_node->get_owner()) {
+ if (!p_node || (p_node != get_scene_node() && !p_node->get_owner())) {
return;
}
- TreeItem *item = p_node ? _find(tree->get_root(), p_node->get_path()) : NULL;
- if (!item) {
+ TreeItem *item = _find(tree->get_root(), p_node->get_path());
+
+ if (!item) {
return;
}
+
int idx = item->get_button_by_id(0, BUTTON_VISIBILITY);
ERR_FAIL_COND(idx == -1);
@@ -1033,6 +1040,11 @@ void SceneTreeEditor::set_connect_to_script_mode(bool p_enable) {
update_tree();
}
+void SceneTreeEditor::set_connecting_signal(bool p_enable) {
+ connecting_signal = p_enable;
+ update_tree();
+}
+
void SceneTreeEditor::_bind_methods() {
ClassDB::bind_method("_tree_changed", &SceneTreeEditor::_tree_changed);
@@ -1077,6 +1089,7 @@ void SceneTreeEditor::_bind_methods() {
SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_open_instance) {
connect_to_script_mode = false;
+ connecting_signal = false;
undo_redo = NULL;
tree_dirty = true;
selected = NULL;
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 1c14da0d3a..68642910e8 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -68,6 +68,7 @@ class SceneTreeEditor : public Control {
AcceptDialog *warning;
bool connect_to_script_mode;
+ bool connecting_signal;
int blocked;
@@ -155,6 +156,7 @@ public:
void update_tree() { _update_tree(); }
void set_connect_to_script_mode(bool p_enable);
+ void set_connecting_signal(bool p_enable);
Tree *get_scene_tree() { return tree; }
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 751ae4fcf7..ffa221edaf 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -100,17 +100,25 @@ void ScriptCreateDialog::set_inheritance_base_type(const String &p_base) {
base_type = p_base;
}
-bool ScriptCreateDialog::_validate(const String &p_string) {
+bool ScriptCreateDialog::_validate_parent(const String &p_string) {
if (p_string.length() == 0)
return false;
- if (ScriptServer::get_language(language_menu->get_selected())->can_inherit_from_file() && p_string.is_quoted()) {
+ if (can_inherit_from_file && p_string.is_quoted()) {
String p = p_string.substr(1, p_string.length() - 2);
if (_validate_path(p, true) == "")
return true;
}
+ return ClassDB::class_exists(p_string) || ScriptServer::is_global_class(p_string);
+}
+
+bool ScriptCreateDialog::_validate_class(const String &p_string) {
+
+ if (p_string.length() == 0)
+ return false;
+
for (int i = 0; i < p_string.length(); i++) {
if (i == 0) {
@@ -118,7 +126,7 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
return false; // no start with number plz
}
- 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] == '-';
+ 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] == '_';
if (!valid_char)
return false;
@@ -193,7 +201,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
void ScriptCreateDialog::_class_name_changed(const String &p_name) {
- if (_validate(class_name->get_text())) {
+ if (_validate_class(class_name->get_text())) {
is_class_name_valid = true;
} else {
is_class_name_valid = false;
@@ -203,7 +211,7 @@ void ScriptCreateDialog::_class_name_changed(const String &p_name) {
void ScriptCreateDialog::_parent_name_changed(const String &p_parent) {
- if (_validate(parent_name->get_text())) {
+ if (_validate_parent(parent_name->get_text())) {
is_parent_name_valid = true;
} else {
is_parent_name_valid = false;
@@ -298,27 +306,13 @@ void ScriptCreateDialog::_load_exist() {
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;
+ has_named_classes = language->has_named_classes();
+ can_inherit_from_file = language->can_inherit_from_file();
+ supports_built_in = language->supports_builtin_mode();
+ if (!supports_built_in)
is_built_in = false;
- }
-
- if (ScriptServer::get_language(l)->can_inherit_from_file()) {
- can_inherit_from_file = true;
- } else {
- can_inherit_from_file = false;
- }
String selected_ext = "." + language->get_extension();
String path = file_path->get_text();
@@ -430,7 +424,7 @@ void ScriptCreateDialog::_file_selected(const String &p_file) {
String p = ProjectSettings::get_singleton()->localize_path(p_file);
if (is_browsing_parent) {
parent_name->set_text("\"" + p + "\"");
- _class_name_changed("\"" + p + "\"");
+ _parent_name_changed(parent_name->get_text());
} else {
file_path->set_text(p);
_path_changed(p);
@@ -445,7 +439,8 @@ void ScriptCreateDialog::_file_selected(const String &p_file) {
void ScriptCreateDialog::_create() {
- parent_name->set_text(select_class->get_selected_type());
+ parent_name->set_text(select_class->get_selected_type().split(" ")[0]);
+ _parent_name_changed(parent_name->get_text());
}
void ScriptCreateDialog::_browse_class_in_tree() {
@@ -542,14 +537,7 @@ void ScriptCreateDialog::_update_dialog() {
class_name->set_editable(false);
class_name->set_placeholder(TTR("N/A"));
class_name->set_placeholder_alpha(1);
- }
-
- /* Can script inherit from a file */
-
- if (can_inherit_from_file) {
- parent_browse_button->set_disabled(false);
- } else {
- parent_browse_button->set_disabled(true);
+ class_name->set_text("");
}
/* Is script Built-in */
@@ -572,7 +560,8 @@ void ScriptCreateDialog::_update_dialog() {
if (is_built_in) {
get_ok()->set_text(TTR("Create"));
parent_name->set_editable(true);
- parent_browse_button->set_disabled(false);
+ parent_search_button->set_disabled(false);
+ parent_browse_button->set_disabled(!can_inherit_from_file);
internal->set_visible(_can_be_built_in());
internal_label->set_visible(_can_be_built_in());
_msg_path_valid(true, TTR("Built-in script (into scene file)."));
@@ -580,7 +569,8 @@ void ScriptCreateDialog::_update_dialog() {
// New Script Created
get_ok()->set_text(TTR("Create"));
parent_name->set_editable(true);
- parent_browse_button->set_disabled(false);
+ parent_search_button->set_disabled(false);
+ parent_browse_button->set_disabled(!can_inherit_from_file);
internal->set_visible(_can_be_built_in());
internal_label->set_visible(_can_be_built_in());
if (is_path_valid) {
@@ -590,6 +580,7 @@ void ScriptCreateDialog::_update_dialog() {
// Script Loaded
get_ok()->set_text(TTR("Load"));
parent_name->set_editable(false);
+ parent_search_button->set_disabled(true);
parent_browse_button->set_disabled(true);
internal->set_disabled(!_can_be_built_in());
if (is_path_valid) {
@@ -755,7 +746,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
internal->set_h_size_flags(0);
internal->connect("pressed", this, "_built_in_pressed");
internal_label = memnew(Label(TTR("Built-in Script")));
- internal_label->set_text(TTR("Built-in Script"));
internal_label->set_align(Label::ALIGN_RIGHT);
gc->add_child(internal_label);
gc->add_child(internal);
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index c6dba78f56..61f87f5732 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -87,7 +87,8 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _path_entered(const String &p_path = String());
void _lang_changed(int l = 0);
void _built_in_pressed();
- bool _validate(const String &p_string);
+ bool _validate_parent(const String &p_string);
+ bool _validate_class(const String &p_string);
String _validate_path(const String &p_path, bool p_file_must_exist);
void _class_name_changed(const String &p_name);
void _parent_name_changed(const String &p_parent);
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 621ab039f4..c3b62810f1 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -1025,7 +1025,9 @@ void ScriptEditorDebugger::_performance_draw() {
int pi = which[i];
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);
+ // Use a darker color on light backgrounds for better visibility
+ float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55;
+ c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * value_multiplier);
c.a = 0.6;
perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x);
@@ -1045,9 +1047,8 @@ void ScriptEditorDebugger::_performance_draw() {
float h2 = E->get()[pi] / m;
h2 = (1.0 - h2) * r.size.y;
- c.a = 0.7;
if (E != perf_history.front())
- perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, 2.0);
+ perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, Math::round(EDSCALE), true);
prev = h2;
E = E->next();
from -= spacing;
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 104bac190e..67cbcf5de4 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -58,6 +58,7 @@
#include "scene/resources/concave_polygon_shape.h"
#include "scene/resources/convex_polygon_shape.h"
#include "scene/resources/cylinder_shape.h"
+#include "scene/resources/height_map_shape.h"
#include "scene/resources/plane_shape.h"
#include "scene/resources/primitive_meshes.h"
#include "scene/resources/ray_shape.h"
@@ -3637,6 +3638,14 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
handles.push_back(Vector3(0, 0, rs->get_length()));
p_gizmo->add_handles(handles, handles_material);
}
+
+ if (Object::cast_to<HeightMapShape>(*s)) {
+
+ Ref<HeightMapShape> hms = s;
+
+ Ref<ArrayMesh> mesh = hms->get_debug_mesh();
+ p_gizmo->add_mesh(mesh, false, RID(), material);
+ }
}
/////
diff --git a/main/main.cpp b/main/main.cpp
index 63ce165d80..3f01a17ea7 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -161,7 +161,7 @@ static String unescape_cmdline(const String &p_str) {
static String get_full_version_string() {
String hash = String(VERSION_HASH);
if (hash.length() != 0)
- hash = "." + hash.left(7);
+ hash = "." + hash.left(9);
return String(VERSION_FULL_BUILD) + hash;
}
@@ -375,7 +375,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
while (I) {
- I->get() = unescape_cmdline(I->get().strip_escapes());
+ I->get() = unescape_cmdline(I->get().strip_edges());
I = I->next();
}
@@ -939,7 +939,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false);
- video_mode.layered_splash = GLOBAL_DEF("display/window/per_pixel_transparency/splash", false);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
@@ -1754,7 +1753,7 @@ bool Main::start() {
scene = scenedata->instance();
ERR_EXPLAIN("Failed loading scene: " + local_game_path);
- ERR_FAIL_COND_V(!scene, false)
+ ERR_FAIL_COND_V(!scene, false);
sml->add_current_scene(scene);
#ifdef OSX_ENABLED
diff --git a/misc/scripts/fix_headers.py b/misc/scripts/fix_headers.py
index 823c9acfde..d94db22b42 100755
--- a/misc/scripts/fix_headers.py
+++ b/misc/scripts/fix_headers.py
@@ -33,7 +33,7 @@ header = """\
/*************************************************************************/
"""
-files = open("files", "rb")
+files = open("files", "r")
fname = files.readline()
@@ -67,7 +67,7 @@ while (fname != ""):
# In a second pass, we skip all consecutive comment lines starting with "/*",
# then we can append the rest (step 2).
- fileread = open(fname.strip(), "rb")
+ fileread = open(fname.strip(), "r")
line = fileread.readline()
header_done = False
@@ -92,11 +92,11 @@ while (fname != ""):
fileread.close()
# Write
- filewrite = open(fname.strip(), "wb")
+ filewrite = open(fname.strip(), "w")
filewrite.write(text)
filewrite.close()
# Next file
fname = files.readline()
-files.close() \ No newline at end of file
+files.close()
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index 16d694c238..2fe7a1b4c0 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -186,7 +186,11 @@ if env['builtin_bullet']:
thirdparty_sources = [thirdparty_dir + file for file in bullet2_src]
- env_bullet.Prepend(CPPPATH=[thirdparty_dir])
+ # Treat Bullet headers as system headers to avoid raising warnings. Not supported on MSVC.
+ if not env.msvc:
+ env_bullet.Append(CPPFLAGS=['-isystem', Dir(thirdparty_dir).path])
+ else:
+ env_bullet.Prepend(CPPPATH=[thirdparty_dir])
# if env['target'] == "debug" or env['target'] == "release_debug":
# env_bullet.Append(CPPFLAGS=['-DBT_DEBUG'])
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index be4e0b88e8..038001996d 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -267,7 +267,7 @@ RID BulletPhysicsServer::area_get_space(RID p_area) const {
void BulletPhysicsServer::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
AreaBullet *area = area_owner.get(p_area);
- ERR_FAIL_COND(!area)
+ ERR_FAIL_COND(!area);
area->set_spOv_mode(p_mode);
}
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp
index d9a82d6179..bc7fd52cf6 100644
--- a/modules/bullet/cone_twist_joint_bullet.cpp
+++ b/modules/bullet/cone_twist_joint_bullet.cpp
@@ -84,7 +84,7 @@ void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param,
break;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
break;
}
}
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index 8fed933854..0d2c46c579 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -175,7 +175,7 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
break;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
break;
}
}
@@ -256,7 +256,7 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
break;
default:
ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
break;
}
}
diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp
index 7b99d3d89f..b7e1e1a4c2 100644
--- a/modules/bullet/hinge_joint_bullet.cpp
+++ b/modules/bullet/hinge_joint_bullet.cpp
@@ -118,7 +118,7 @@ void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t
break;
default:
ERR_EXPLAIN("The HingeJoint parameter " + itos(p_param) + " is deprecated.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
break;
}
}
diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp
index 58b090006a..c9c4d1af7e 100644
--- a/modules/bullet/pin_joint_bullet.cpp
+++ b/modules/bullet/pin_joint_bullet.cpp
@@ -86,7 +86,7 @@ real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const {
return p2pConstraint->m_setting.m_impulseClamp;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
return 0;
}
}
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 3a61afa023..aa4d7d7d32 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -45,7 +45,7 @@ void CSGBrush::build_from_faces(const PoolVector<Vector3> &p_vertices, const Poo
int vc = p_vertices.size();
- ERR_FAIL_COND((vc % 3) != 0)
+ ERR_FAIL_COND((vc % 3) != 0);
PoolVector<Vector3>::Read rv = p_vertices.read();
int uvc = p_uvs.size();
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 18dfe08e85..1ff0395ba9 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -346,7 +346,7 @@ void NetworkedMultiplayerENet::poll() {
uint32_t *id = (uint32_t *)event.peer->data;
- ERR_CONTINUE(event.packet->dataLength < 8)
+ ERR_CONTINUE(event.packet->dataLength < 8);
uint32_t source = decode_uint32(&event.packet->data[0]);
int target = decode_uint32(&event.packet->data[4]);
@@ -462,7 +462,7 @@ void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) {
ERR_FAIL_COND(!active);
ERR_FAIL_COND(!is_server());
- ERR_FAIL_COND(!peer_map.has(p_peer))
+ ERR_FAIL_COND(!peer_map.has(p_peer));
if (now) {
enet_peer_disconnect_now(peer_map[p_peer], 0);
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index 8fa29580d6..a2ac61b35e 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -119,6 +119,14 @@ godot_vector2 GDAPI godot_vector2_cubic_interpolate(const godot_vector2 *p_self,
return dest;
}
+godot_vector2 GDAPI godot_vector2_move_toward(const godot_vector2 *p_self, const godot_vector2 *p_to, const godot_real p_delta) {
+ godot_vector2 dest;
+ const Vector2 *self = (const Vector2 *)p_self;
+ const Vector2 *to = (const Vector2 *)p_to;
+ *((Vector2 *)&dest) = self->move_toward(*to, p_delta);
+ return dest;
+}
+
godot_vector2 GDAPI godot_vector2_rotated(const godot_vector2 *p_self, const godot_real p_phi) {
godot_vector2 dest;
const Vector2 *self = (const Vector2 *)p_self;
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index ef86c6f7e9..894683ab38 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -124,6 +124,14 @@ godot_vector3 GDAPI godot_vector3_cubic_interpolate(const godot_vector3 *p_self,
return dest;
}
+godot_vector3 GDAPI godot_vector3_move_toward(const godot_vector3 *p_self, const godot_vector3 *p_to, const godot_real p_delta) {
+ godot_vector3 dest;
+ const Vector3 *self = (const Vector3 *)p_self;
+ const Vector3 *to = (const Vector3 *)p_to;
+ *((Vector3 *)&dest) = self->move_toward(*to, p_delta);
+ return dest;
+}
+
godot_real GDAPI godot_vector3_dot(const godot_vector3 *p_self, const godot_vector3 *p_b) {
const Vector3 *self = (const Vector3 *)p_self;
const Vector3 *b = (const Vector3 *)p_b;
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 8afe988102..52c989037e 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -26,6 +26,24 @@
["const godot_dictionary *", "p_self"],
["const godot_bool", "p_deep"]
]
+ },
+ {
+ "name": "godot_vector3_move_toward",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_to"],
+ ["const godot_real", "p_delta"]
+ ]
+ },
+ {
+ "name": "godot_vector2_move_toward",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"],
+ ["const godot_real", "p_delta"]
+ ]
}
]
},
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 9e37b8e0c6..7a5ae6afa9 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -83,6 +83,8 @@ godot_vector2 GDAPI godot_vector2_linear_interpolate(const godot_vector2 *p_self
godot_vector2 GDAPI godot_vector2_cubic_interpolate(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 GDAPI godot_vector2_move_toward(const godot_vector2 *p_self, const godot_vector2 *p_to, const godot_real p_delta);
+
godot_vector2 GDAPI godot_vector2_rotated(const godot_vector2 *p_self, const godot_real p_phi);
godot_vector2 GDAPI godot_vector2_tangent(const godot_vector2 *p_self);
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index 61f0c6c62e..70ec6422ac 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -90,6 +90,8 @@ godot_vector3 GDAPI godot_vector3_linear_interpolate(const godot_vector3 *p_self
godot_vector3 GDAPI godot_vector3_cubic_interpolate(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 GDAPI godot_vector3_move_toward(const godot_vector3 *p_self, const godot_vector3 *p_to, const godot_real p_delta);
+
godot_real GDAPI godot_vector3_dot(const godot_vector3 *p_self, const godot_vector3 *p_b);
godot_vector3 GDAPI godot_vector3_cross(const godot_vector3 *p_self, const godot_vector3 *p_b);
diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h
index 968f91ae9f..a9e83d1524 100644
--- a/modules/gdnative/include/pluginscript/godot_pluginscript.h
+++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h
@@ -136,7 +136,7 @@ typedef struct {
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);
+ godot_error (*complete_code)(godot_pluginscript_language_data *p_data, const godot_string *p_code, const godot_string *p_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);
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
index c9d92c09ed..7cb47ec623 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -159,13 +159,13 @@ String PluginScriptLanguage::make_function(const String &p_class, const String &
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) {
+Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_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_string *)&p_path,
(godot_object *)p_owner,
(godot_array *)&options,
&r_force,
diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h
index 991be0bf12..a11e916975 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.h
+++ b/modules/gdnative/pluginscript/pluginscript_language.h
@@ -81,7 +81,7 @@ public:
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 Error complete_code(const String &p_code, const String &p_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);
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index 8dbbd2e4eb..1d6f9db349 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -39,12 +39,12 @@
#define ASSERT_SCRIPT_VALID() \
{ \
ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \
- ERR_FAIL_COND(!can_instance()) \
+ ERR_FAIL_COND(!can_instance()); \
}
-#define ASSERT_SCRIPT_VALID_V(ret) \
- { \
- ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \
- ERR_FAIL_COND_V(!can_instance(), ret) \
+#define ASSERT_SCRIPT_VALID_V(ret) \
+ { \
+ ERR_EXPLAIN(__ASSERT_SCRIPT_REASON); \
+ ERR_FAIL_COND_V(!can_instance(), ret); \
}
#else
#define ASSERT_SCRIPT_VALID()
@@ -77,7 +77,7 @@ PluginScriptInstance *PluginScript::_create_instance(const Variant **p_args, int
// There is currently no way to get the constructor function name of the script.
// instance->call("__init__", p_args, p_argcount, r_error);
if (p_argcount > 0) {
- WARN_PRINT("PluginScript doesn't support arguments in the constructor")
+ WARN_PRINT("PluginScript doesn't support arguments in the constructor");
}
return instance;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 716f536e89..40b773d99f 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -458,9 +458,9 @@ public:
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_forced, String &r_call_hint);
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
- virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result);
+ virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result);
#endif
virtual String _get_indentation() const;
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index f7be0ce37c..189317b163 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1977,12 +1977,12 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
for (int i = 0; i < p_class->subclasses.size(); i++) {
StringName name = p_class->subclasses[i]->name;
-
- GDScript *subclass = p_script->subclasses[name].ptr();
+ Ref<GDScript> &subclass = p_script->subclasses[name];
+ GDScript *subclass_ptr = subclass.ptr();
// Subclass might still be parsing, just skip it
- if (!parsed_classes.has(subclass) && !parsing_classes.has(subclass)) {
- Error err = _parse_class_level(subclass, p_class->subclasses[i], p_keep_state);
+ if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) {
+ Error err = _parse_class_level(subclass_ptr, p_class->subclasses[i], p_keep_state);
if (err)
return err;
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index fa80c31984..6c77968f44 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2461,13 +2461,13 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS
r_forced = r_result.size() > 0;
}
-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) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
GDScriptParser parser;
- parser.parse(p_code, p_base_path, false, "", true);
+ parser.parse(p_code, p_path.get_base_dir(), false, p_path, true);
r_forced = false;
Set<String> options;
GDScriptCompletionContext context;
@@ -2478,7 +2478,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
if (!context._class || context._class->owner == NULL) {
context.base = p_owner;
- context.base_path = p_base_path;
+ context.base_path = p_path.get_base_dir();
}
bool is_function = false;
@@ -2884,7 +2884,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
#else
-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) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
return OK;
}
@@ -3155,7 +3155,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
return ERR_CANT_RESOLVE;
}
-Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) {
+Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) {
//before parsing, try the usual stuff
if (ClassDB::class_exists(p_symbol)) {
@@ -3197,7 +3197,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
}
GDScriptParser parser;
- parser.parse(p_code, p_base_path, false, "", true);
+ parser.parse(p_code, p_path.get_base_dir(), false, p_path, true);
if (parser.get_completion_type() == GDScriptParser::COMPLETION_NONE) {
return ERR_CANT_RESOLVE;
@@ -3209,7 +3209,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
context.block = parser.get_completion_block();
context.line = parser.get_completion_line();
context.base = p_owner;
- context.base_path = p_base_path;
+ context.base_path = p_path.get_base_dir();
if (context._class && context._class->extends_class.size() > 0) {
bool success = false;
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 5ebcddfd7c..0736f3d010 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -78,6 +78,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"inverse_lerp",
"range_lerp",
"smoothstep",
+ "move_toward",
"dectime",
"randomize",
"randi",
@@ -341,7 +342,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(0);
r_ret = Math::step_decimals((double)*p_args[0]);
ERR_EXPLAIN("GDScript method 'decimals' is deprecated and has been renamed to 'step_decimals', please update your code accordingly.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
} break;
case MATH_STEP_DECIMALS: {
VALIDATE_ARG_COUNT(1);
@@ -398,6 +399,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(2);
r_ret = Math::smoothstep((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
} break;
+ case MATH_MOVE_TOWARD: {
+ VALIDATE_ARG_COUNT(3);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ r_ret = Math::move_toward((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
+ } break;
case MATH_DECTIME: {
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(0);
@@ -1466,6 +1474,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_INVERSE_LERP:
case MATH_RANGE_LERP:
case MATH_SMOOTHSTEP:
+ case MATH_MOVE_TOWARD:
case MATH_DECTIME:
case MATH_DEG2RAD:
case MATH_RAD2DEG:
@@ -1669,6 +1678,11 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::REAL;
return mi;
} break;
+ case MATH_MOVE_TOWARD: {
+ MethodInfo mi("move_toward", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "delta"));
+ mi.return_val.type = Variant::REAL;
+ return mi;
+ } break;
case MATH_DECTIME: {
MethodInfo mi("dectime", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "amount"), PropertyInfo(Variant::REAL, "step"));
mi.return_val.type = Variant::REAL;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index c594480ff8..6ad70f2eb4 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -69,6 +69,7 @@ public:
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
MATH_SMOOTHSTEP,
+ MATH_MOVE_TOWARD,
MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RAND,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 9590009a54..ec3e72eef7 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -1995,7 +1995,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
}
}
- ERR_FAIL_V(op);
} break;
default: {
return p_node;
@@ -3497,7 +3496,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("'class_name' is only valid for the main class namespace.");
return;
}
- if (self_path.empty()) {
+ if (self_path.begins_with("res://") && self_path.find("::") != -1) {
_set_error("'class_name' not allowed in built-in scripts.");
return;
}
@@ -4025,7 +4024,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
ERR_EXPLAIN("Exporting bit flags hint requires string constants.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
break;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
@@ -4068,6 +4067,50 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
break;
}
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_RENDER") {
+
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in layers 2D render hint.");
+ return;
+ }
+ current_export.hint = PROPERTY_HINT_LAYERS_2D_RENDER;
+ break;
+ }
+
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_PHYSICS") {
+
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in layers 2D physics hint.");
+ return;
+ }
+ current_export.hint = PROPERTY_HINT_LAYERS_2D_PHYSICS;
+ break;
+ }
+
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_RENDER") {
+
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in layers 3D render hint.");
+ return;
+ }
+ current_export.hint = PROPERTY_HINT_LAYERS_3D_RENDER;
+ break;
+ }
+
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_PHYSICS") {
+
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')' in layers 3D physics hint.");
+ return;
+ }
+ current_export.hint = PROPERTY_HINT_LAYERS_3D_PHYSICS;
+ break;
+ }
+
if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) {
//enumeration
current_export.hint = PROPERTY_HINT_ENUM;
@@ -6021,7 +6064,11 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
}
GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
+#ifdef DEBUG_ENABLED
+ if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) {
+#else
if (p_node->get_datatype().has_type) {
+#endif
return p_node->get_datatype();
}
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 32a014e76d..3caa7b1d12 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -197,7 +197,7 @@ bool GridMap::get_collision_layer_bit(int p_bit) const {
void GridMap::set_theme(const Ref<MeshLibrary> &p_theme) {
ERR_EXPLAIN("GridMap.theme/set_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/set_mesh_library() instead.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
set_mesh_library(p_theme);
}
@@ -205,7 +205,7 @@ void GridMap::set_theme(const Ref<MeshLibrary> &p_theme) {
Ref<MeshLibrary> GridMap::get_theme() const {
ERR_EXPLAIN("GridMap.theme/get_theme() is deprecated and will be removed in a future version. Use GridMap.mesh_library/get_mesh_library() instead.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
return get_mesh_library();
}
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 341d57f3e4..6c3ecee272 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -20,11 +20,6 @@ if env['tools']:
'glue/cs_glue_version.gen.h'
)
-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_mono)
-
# Glue sources
if env_mono['mono_glue']:
env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED'])
diff --git a/modules/mono/build_scripts/godotsharptools_build.py b/modules/mono/build_scripts/godotsharptools_build.py
index af3a5cb5c6..17f9a990af 100644
--- a/modules/mono/build_scripts/godotsharptools_build.py
+++ b/modules/mono/build_scripts/godotsharptools_build.py
@@ -1,6 +1,5 @@
# Build GodotSharpTools solution
-
import os
from SCons.Script import Builder, Dir
@@ -53,21 +52,9 @@ def find_nuget_windows(env):
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
return hint_path
- from . import mono_reg_utils as monoreg
-
- mono_root = ''
- bits = env['bits']
+ from . mono_reg_utils import find_mono_root_dir
- 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)
+ mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits'])
if mono_root:
mono_bin_dir = os.path.join(mono_root, 'bin')
@@ -114,21 +101,9 @@ def find_msbuild_unix(filename):
def find_msbuild_windows(env):
- from . import mono_reg_utils as monoreg
+ from . mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg
- mono_root = ''
- 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)
+ mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits'])
if not mono_root:
raise RuntimeError('Cannot find mono root directory')
@@ -148,7 +123,7 @@ def find_msbuild_windows(env):
}
return (msbuild_mono, framework_path, mono_msbuild_env)
- msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
+ msbuild_tools_path = find_msbuild_tools_path_reg()
if msbuild_tools_path:
return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index 4cfa2a5b93..c549640d61 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -1,15 +1,30 @@
import imp
import os
+import os.path
import sys
import subprocess
from distutils.version import LooseVersion
-from SCons.Script import BoolVariable, Dir, Environment, Variables
+from SCons.Script import Dir, Environment
if os.name == 'nt':
from . import mono_reg_utils as monoreg
+android_arch_dirs = {
+ 'armv7': 'armeabi-v7a',
+ 'arm64v8': 'arm64-v8a',
+ 'x86': 'x86',
+ 'x86_64': 'x86_64'
+}
+
+
+def get_android_out_dir(env):
+ return os.path.join(Dir('#platform/android/java/libs').abspath,
+ 'release' if env['target'] == 'release' else 'debug',
+ android_arch_dirs[env['android_arch']])
+
+
def find_file_in_dir(directory, files, prefix='', extension=''):
if not extension.startswith('.'):
extension = '.' + extension
@@ -20,47 +35,47 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
def copy_file(src_dir, dst_dir, name):
- from shutil import copyfile
+ from shutil import copy
- src_path = os.path.join(src_dir, name)
- dst_path = os.path.join(dst_dir, name)
+ src_path = os.path.join(Dir(src_dir).abspath, name)
+ dst_dir = Dir(dst_dir).abspath
if not os.path.isdir(dst_dir):
os.mkdir(dst_dir)
- copyfile(src_path, dst_path)
+ copy(src_path, dst_dir)
def configure(env, env_mono):
- envvars = Variables()
- envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
- envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
- envvars.Update(env)
-
bits = env['bits']
+ is_android = env['platform'] == 'android'
tools_enabled = env['tools']
mono_static = env['mono_static']
copy_mono_root = env['copy_mono_root']
+ mono_prefix = env['mono_prefix']
+
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
+ if is_android and not env['android_arch'] in android_arch_dirs:
+ raise RuntimeError('This module does not support for the specified \'android_arch\': ' + env['android_arch'])
+
+ if is_android and tools_enabled:
+ # TODO: Implement this. We have to add the data directory to the apk, concretely the Api and Tools folders.
+ raise RuntimeError('This module does not currently support building for android with tools enabled')
+
+ if (os.getenv('MONO32_PREFIX') or os.getenv('MONO64_PREFIX')) and not mono_prefix:
+ print("WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the 'mono_prefix' SCons parameter instead")
+
if env['platform'] == 'windows':
- mono_root = ''
+ mono_root = mono_prefix
- 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(bits)
- else:
- if os.getenv('MONO64_PREFIX'):
- mono_root = os.getenv('MONO64_PREFIX')
- elif os.name == 'nt':
- mono_root = monoreg.find_mono_root_dir(bits)
+ if not mono_root and os.name == 'nt':
+ mono_root = monoreg.find_mono_root_dir(bits)
if not mono_root:
- raise RuntimeError('Mono installation directory not found')
+ raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter")
print('Found Mono root directory: ' + mono_root)
@@ -113,21 +128,18 @@ def configure(env, env_mono):
if not mono_dll_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
- copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll')
+ copy_file(mono_bin_path, '#bin', mono_dll_name + '.dll')
else:
is_apple = (sys.platform == 'darwin' or "osxcross" in env)
sharedlib_ext = '.dylib' if is_apple else '.so'
- mono_root = ''
+ mono_root = mono_prefix
mono_lib_path = ''
+ mono_so_name = ''
- 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 not mono_root and is_android:
+ raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter")
if not mono_root and is_apple:
# Try with some known directories under OSX
@@ -142,7 +154,8 @@ def configure(env, env_mono):
if not mono_root and mono_static:
mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
if not mono_root:
- raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually')
+ raise RuntimeError("Building with mono_static=yes, but failed to find the mono prefix with pkg-config; " + \
+ "specify one manually with the 'mono_prefix' SCons parameter")
if mono_root:
print('Found Mono root directory: ' + mono_root)
@@ -174,6 +187,8 @@ def configure(env, env_mono):
if is_apple:
env.Append(LIBS=['iconv', 'pthread'])
+ elif is_android:
+ env.Append(LIBS=['m', 'dl'])
else:
env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
@@ -183,7 +198,7 @@ def configure(env, env_mono):
if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
- copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
+ copy_file(mono_lib_path, '#bin', 'lib' + mono_so_name + sharedlib_ext)
else:
assert not mono_static
@@ -196,9 +211,6 @@ def configure(env, env_mono):
env.ParseConfig('pkg-config monosgen-2 --libs')
env_mono.ParseConfig('pkg-config monosgen-2 --cflags')
- mono_lib_path = ''
- mono_so_name = ''
-
tmpenv = Environment()
tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
@@ -213,11 +225,13 @@ def configure(env, env_mono):
if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
- copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
+ if not mono_static:
+ libs_output_dir = get_android_out_dir(env) if is_android else '#bin'
+ copy_file(mono_lib_path, libs_output_dir, 'lib' + mono_so_name + sharedlib_ext)
env.Append(LINKFLAGS='-rdynamic')
- if not tools_enabled:
+ if not tools_enabled and not is_android:
if not mono_root:
mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
@@ -241,7 +255,7 @@ def make_template_dir(env, mono_root):
template_dir_name = ''
- if platform in ['windows', 'osx', 'x11']:
+ if platform in ['windows', 'osx', 'x11', 'android']:
template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
else:
assert False
@@ -256,12 +270,13 @@ def make_template_dir(env, mono_root):
# Copy etc/mono/
- template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
- copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
+ if platform != 'android':
+ template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
+ copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
# Copy the required shared libraries
- copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform'])
+ copy_mono_shared_libs(env, mono_root, template_mono_root_dir)
def copy_mono_root_files(env, mono_root):
@@ -285,7 +300,7 @@ def copy_mono_root_files(env, mono_root):
# Copy the required shared libraries
- copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform'])
+ copy_mono_shared_libs(env, mono_root, editor_mono_root_dir)
# Copy framework assemblies
@@ -332,39 +347,55 @@ def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0'))
copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0'))
copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5'))
- copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
+ if os.path.isdir(os.path.join(mono_etc_dir, 'mconfig')):
+ copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
for file in glob(os.path.join(mono_etc_dir, '*')):
if os.path.isfile(file):
copy(file, target_mono_config_dir)
-def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform):
+def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
from shutil import copy
+ def copy_if_exists(src, dst):
+ if os.path.isfile(src):
+ copy(src, dst)
+
+ platform = env['platform']
+
if platform == 'windows':
target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin')
if not os.path.isdir(target_mono_bin_dir):
os.makedirs(target_mono_bin_dir)
- copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll'))
+ copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), target_mono_bin_dir)
else:
- target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib')
+ target_mono_lib_dir = get_android_out_dir(env) if platform == 'android' else os.path.join(target_mono_root_dir, 'lib')
if not os.path.isdir(target_mono_lib_dir):
os.makedirs(target_mono_lib_dir)
if platform == 'osx':
- copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib'))
- elif platform == 'x11':
- copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so'))
- copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so'))
+ # TODO: Make sure nothing is missing
+ copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), target_mono_lib_dir)
+ elif platform == 'x11' or platform == 'android':
+ lib_file_names = [lib_name + '.so' for lib_name in [
+ 'libmono-btls-shared', 'libmono-ee-interp', 'libmono-native', 'libMonoPosixHelper',
+ 'libmono-profiler-aot', 'libmono-profiler-coverage', 'libmono-profiler-log', 'libMonoSupportW'
+ ]]
+
+ for lib_file_name in lib_file_names:
+ copy_if_exists(os.path.join(mono_root, 'lib', lib_file_name), target_mono_lib_dir)
def configure_for_mono_version(env, mono_version):
if mono_version is None:
- raise RuntimeError('Mono JIT compiler version not found')
+ if os.getenv('MONO_VERSION'):
+ mono_version = os.getenv('MONO_VERSION')
+ else:
+ raise RuntimeError("Mono JIT compiler version not found; specify one manually with the 'MONO_VERSION' environment variable")
print('Found Mono JIT compiler version: ' + str(mono_version))
if mono_version >= LooseVersion('5.12.0'):
env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS'])
diff --git a/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff b/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff
new file mode 100644
index 0000000000..05f8dcadcc
--- /dev/null
+++ b/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff
@@ -0,0 +1,70 @@
+diff --git a/libgc/include/private/gcconfig.h b/libgc/include/private/gcconfig.h
+index e2bdf13ac3e..f962200ba4e 100644
+--- a/libgc/include/private/gcconfig.h
++++ b/libgc/include/private/gcconfig.h
+@@ -2255,6 +2255,14 @@
+ # define GETPAGESIZE() getpagesize()
+ # endif
+
++#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
++ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
++ || defined(ARM32) || defined(I386) /* but not x32 */)
++ /* tkill() exists only on arm32/mips(32)/x86. */
++ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
++# define USE_TKILL_ON_ANDROID
++#endif
++
+ # if defined(SUNOS5) || defined(DRSNX) || defined(UTS4)
+ /* OS has SVR4 generic features. Probably others also qualify. */
+ # define SVR4
+diff --git a/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c
+index f93ce26b562..4a49a6d578c 100644
+--- a/libgc/pthread_stop_world.c
++++ b/libgc/pthread_stop_world.c
+@@ -336,7 +336,7 @@ void GC_push_all_stacks()
+ pthread_t GC_stopping_thread;
+ int GC_stopping_pid;
+
+-#ifdef HOST_ANDROID
++#ifdef USE_TKILL_ON_ANDROID
+ static
+ int android_thread_kill(pid_t tid, int sig)
+ {
+diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
+index ad9b8823f8f..3542b32b540 100644
+--- a/mono/metadata/threads.c
++++ b/mono/metadata/threads.c
+@@ -77,8 +77,12 @@ mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle);
+ #include <zircon/syscalls.h>
+ #endif
+
+-#if defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64)
+-#define USE_TKILL_ON_ANDROID 1
++#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
++ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
++ || defined(ARM32) || defined(I386) /* but not x32 */)
++ /* tkill() exists only on arm32/mips(32)/x86. */
++ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
++# define USE_TKILL_ON_ANDROID
+ #endif
+
+ #ifdef HOST_ANDROID
+diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c
+index 3e4bf93de5f..79c9f731fe7 100644
+--- a/mono/utils/mono-threads-posix.c
++++ b/mono/utils/mono-threads-posix.c
+@@ -31,8 +31,12 @@
+
+ #include <errno.h>
+
+-#if defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64)
+-#define USE_TKILL_ON_ANDROID 1
++#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
++ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
++ || defined(ARM32) || defined(I386) /* but not x32 */)
++ /* tkill() exists only on arm32/mips(32)/x86. */
++ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
++# define USE_TKILL_ON_ANDROID
+ #endif
+
+ #ifdef USE_TKILL_ON_ANDROID
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 3b2e96765e..9adf4ee6e5 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -8,6 +8,16 @@ def configure(env):
env.use_ptrcall = True
env.add_module_version_string('mono')
+ from SCons.Script import BoolVariable, PathVariable, Variables
+
+ envvars = Variables()
+ envvars.Add(PathVariable('mono_prefix', 'Path to the mono installation directory for the target platform and architecture', '', PathVariable.PathAccept))
+ envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
+ envvars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
+ envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
+ envvars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False))
+ envvars.Update(env)
+
def get_doc_classes():
return [
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index e735e0f741..4a1fb8e5ed 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -380,7 +380,6 @@ public:
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/editor/GodotSharpTools/Editor/GodotSharpExport.cs b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
index e45dd2025b..44a43f0ddd 100644
--- a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
+++ b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
namespace GodotSharpTools.Editor
@@ -62,7 +63,7 @@ namespace GodotSharpTools.Editor
{
// OSX export templates are contained in a zip, so we place
// our custom template inside it and let Godot do the rest.
- return !featureSet.Contains("OSX");
+ return !featureSet.Any(f => new[] {"OSX", "Android"}.Contains(f));
}
[MethodImpl(MethodImplOptions.InternalCall)]
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index ae5b939b26..126178125f 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -125,11 +125,21 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug
bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name,
project_dll_src_path, &scripts_assembly, /* refonly: */ true);
- ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name);
+ ERR_EXPLAIN("Cannot load assembly (refonly): " + project_dll_name);
ERR_FAIL_COND(!load_success);
Vector<String> search_dirs;
- GDMonoAssembly::fill_search_dirs(search_dirs, build_config);
+ String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+ String android_bcl_dir = templates_dir.plus_file("android-bcl");
+
+ String custom_lib_dir;
+
+ if (p_features.find("Android") && DirAccess::exists(android_bcl_dir)) {
+ custom_lib_dir = android_bcl_dir;
+ }
+
+ GDMonoAssembly::fill_search_dirs(search_dirs, build_config, custom_lib_dir);
+
Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies);
ERR_FAIL_COND(depend_error != OK);
}
@@ -152,7 +162,7 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug
int i = 0;
for (const Set<String>::Element *E = p_features.front(); E; E = E->next()) {
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get());
- mono_array_set(features, MonoString *, i, boxed);
+ mono_array_setref(features, i, boxed);
i++;
}
@@ -234,8 +244,10 @@ Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, c
r_dependencies.insert(ref_name, ref_assembly->get_path());
Error err = _get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
- if (err != OK)
- return err;
+ if (err != OK) {
+ ERR_EXPLAIN("Cannot load one of the dependencies for the assembly: " + ref_name);
+ ERR_FAIL_V(err);
+ }
}
return OK;
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index 8fb8730b88..2d8c63fe7f 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -210,6 +210,11 @@ namespace Godot
return a < b ? a : b;
}
+ public static real_t MoveToward(real_t from, real_t to, real_t delta)
+ {
+ return Abs(to - from) <= delta ? to : from + Sign(to - from) * delta;
+ }
+
public static int NearestPo2(int value)
{
value--;
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index bb1950e1a8..a7f26283a7 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -186,6 +186,14 @@ namespace Godot
return res;
}
+ public Vector2 MoveToward(Vector2 to, real_t delta)
+ {
+ var v = this;
+ var vd = to - v;
+ var len = vd.Length();
+ return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ }
+
public Vector2 Normalized()
{
var v = this;
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index 283cb6341a..16803ae55c 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -190,6 +190,14 @@ namespace Godot
);
}
+ public Vector3 MoveToward(Vector3 to, real_t delta)
+ {
+ var v = this;
+ var vd = to - v;
+ var len = vd.Length();
+ return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ }
+
public Axis MaxAxis()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 7385014a53..75b2dfce9a 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -166,7 +166,7 @@ MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
int i = 0;
for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
- mono_array_set(result, MonoString *, i, boxed);
+ mono_array_setref(result, i, boxed);
i++;
}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 19e49d29f9..7699e0d0cd 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -251,17 +251,19 @@ void GDMono::initialize() {
String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir();
#ifdef TOOLS_ENABLED
- if (DirAccess::exists(bundled_assembly_rootdir) && DirAccess::exists(bundled_config_dir)) {
+ if (DirAccess::exists(bundled_assembly_rootdir)) {
assembly_rootdir = bundled_assembly_rootdir;
+ }
+
+ if (DirAccess::exists(bundled_config_dir)) {
config_dir = bundled_config_dir;
}
#ifdef WINDOWS_ENABLED
if (assembly_rootdir.empty() || config_dir.empty()) {
+ ERR_PRINT("Cannot find Mono in the registry");
// Assertion: if they are not set, then they weren't found in the registry
CRASH_COND(mono_reg_info.assembly_dir.length() > 0 || mono_reg_info.config_dir.length() > 0);
-
- ERR_PRINT("Cannot find Mono in the registry");
}
#endif // WINDOWS_ENABLED
@@ -807,6 +809,8 @@ Error GDMono::_unload_scripts_domain() {
mono_gc_collect(mono_gc_max_generation());
+ GDMonoUtils::clear_godot_api_cache();
+
_domain_assemblies_cleanup(mono_domain_get_id(scripts_domain));
core_api_assembly = NULL;
@@ -926,6 +930,7 @@ Error GDMono::reload_scripts_domain() {
Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
CRASH_COND(p_domain == NULL);
+ CRASH_COND(p_domain == SCRIPTS_DOMAIN); // Should use _unload_scripts_domain() instead
String domain_name = mono_domain_get_friendly_name(p_domain);
@@ -1078,8 +1083,6 @@ GDMono::~GDMono() {
}
assemblies.clear();
- GDMonoUtils::clear_cache();
-
print_verbose("Mono: Runtime cleanup...");
mono_jit_cleanup(root_domain);
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 8fec28b186..f1f0015ac9 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -46,11 +46,17 @@ bool GDMonoAssembly::in_preload = false;
Vector<String> GDMonoAssembly::search_dirs;
-void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config) {
+void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) {
- const char *rootdir = mono_assembly_getrootdir();
- if (rootdir) {
- String framework_dir = String::utf8(rootdir).plus_file("mono").plus_file("4.5");
+ String framework_dir;
+
+ if (!p_custom_bcl_dir.empty()) {
+ framework_dir = p_custom_bcl_dir;
+ } else if (mono_assembly_getrootdir()) {
+ framework_dir = String::utf8(mono_assembly_getrootdir()).plus_file("mono").plus_file("4.5");
+ }
+
+ if (!framework_dir.empty()) {
r_search_dirs.push_back(framework_dir);
r_search_dirs.push_back(framework_dir.plus_file("Facades"));
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 32432af37d..39749dfc1d 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -122,7 +122,7 @@ public:
GDMonoClass *get_object_derived_class(const StringName &p_class);
- static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String());
+ static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String());
static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly);
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index c462b8f71d..87157ed233 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -1019,7 +1019,7 @@ MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) {
for (int i = 0; i < p_array.size(); i++) {
MonoString *boxed = mono_string_from_godot(r[i]);
- mono_array_set(ret, MonoString *, i, boxed);
+ mono_array_setref(ret, i, boxed);
}
return ret;
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index f290c6c8ac..968b316a3e 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -109,7 +109,7 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
for (int i = 0; i < params_count; i++) {
MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object(p_params[i], param_types[i]);
- mono_array_set(params, MonoObject *, i, boxed_param);
+ mono_array_setref(params, i, boxed_param);
}
MonoException *exc = NULL;
diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp
index 5842e26241..f1da00638f 100644
--- a/modules/mono/mono_gd/gd_mono_property.cpp
+++ b/modules/mono/mono_gd/gd_mono_property.cpp
@@ -142,7 +142,7 @@ bool GDMonoProperty::has_setter() {
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
MonoMethod *prop_method = mono_property_get_set_method(mono_property);
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
- mono_array_set(params, MonoObject *, 0, p_value);
+ mono_array_setref(params, 0, p_value);
MonoException *exc = NULL;
GDMonoUtils::runtime_invoke_array(prop_method, p_object, params, &exc);
if (exc) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 413c8cba85..1b32f1126e 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -50,6 +50,7 @@ MonoCache mono_cache;
#define CACHE_AND_CHECK(m_var, m_val) \
{ \
+ CRASH_COND(m_var != NULL); \
m_var = m_val; \
if (!m_var) { \
ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \
@@ -65,7 +66,9 @@ MonoCache mono_cache;
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
#define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.property_##m_class##_##m_property, m_val)
-void MonoCache::clear_members() {
+void MonoCache::clear_corlib_cache() {
+
+ corlib_cache_updated = false;
class_MonoObject = NULL;
class_bool = NULL;
@@ -93,6 +96,11 @@ void MonoCache::clear_members() {
#endif
class_KeyNotFoundException = NULL;
+}
+
+void MonoCache::clear_godot_api_cache() {
+
+ godot_api_cache_updated = false;
rawclass_Dictionary = NULL;
@@ -176,12 +184,6 @@ void MonoCache::clear_members() {
task_scheduler_handle = Ref<MonoGCHandle>();
}
-void MonoCache::cleanup() {
-
- corlib_cache_updated = false;
- godot_api_cache_updated = false;
-}
-
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
#define GODOT_API_NS_CLAS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class))
@@ -281,13 +283,10 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
-
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info, (GenericIDictionaryIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, (MakeGenericArrayType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericArrayType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, (MakeGenericDictionaryType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericDictionaryType", 2));
@@ -310,11 +309,6 @@ void update_godot_api_cache() {
mono_cache.godot_api_cache_updated = true;
}
-void clear_cache() {
- mono_cache.cleanup();
- mono_cache.clear_members();
-}
-
MonoObject *unmanaged_get_managed(Object *unmanaged) {
if (!unmanaged)
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index ee239be959..00e1ffdd31 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -218,14 +218,12 @@ struct MonoCache {
bool corlib_cache_updated;
bool godot_api_cache_updated;
- void clear_members();
- void cleanup();
+ void clear_corlib_cache();
+ void clear_godot_api_cache();
MonoCache() {
- corlib_cache_updated = false;
- godot_api_cache_updated = false;
-
- clear_members();
+ clear_corlib_cache();
+ clear_godot_api_cache();
}
};
@@ -233,7 +231,13 @@ extern MonoCache mono_cache;
void update_corlib_cache();
void update_godot_api_cache();
-void clear_cache();
+
+inline void clear_corlib_cache() {
+ mono_cache.clear_corlib_cache();
+}
+inline void clear_godot_api_cache() {
+ mono_cache.clear_godot_api_cache();
+}
_FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) {
p_hash ^= p_with_hash + 0x9e3779b9 + (p_hash << 6) + (p_hash >> 2);
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 5d37e8212f..0e1739b754 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -95,7 +95,7 @@ Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_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);
+ mono_array_setref(signal_args, i, boxed);
}
MonoException *exc = NULL;
diff --git a/modules/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp
index fda82295de..70d0f770d8 100644
--- a/modules/opus/audio_stream_opus.cpp
+++ b/modules/opus/audio_stream_opus.cpp
@@ -313,7 +313,7 @@ int AudioStreamPlaybackOpus::mix(int16_t *p_buffer, int p_frames) {
bool ok = op_pcm_seek(opus_file, (loop_restart_time * osrate) + pre_skip) == 0;
if (!ok) {
playing = false;
- ERR_PRINT("loop restart time rejected")
+ ERR_PRINT("Loop restart time rejected");
}
frames_mixed = (loop_restart_time * osrate) + pre_skip;
diff --git a/modules/recast/navigation_mesh_editor_plugin.cpp b/modules/recast/navigation_mesh_editor_plugin.cpp
index eadc11fcee..9f30806925 100644
--- a/modules/recast/navigation_mesh_editor_plugin.cpp
+++ b/modules/recast/navigation_mesh_editor_plugin.cpp
@@ -67,9 +67,7 @@ void NavigationMeshEditor::_bake_pressed() {
EditorNavigationMeshGenerator::get_singleton()->clear(node->get_navigation_mesh());
EditorNavigationMeshGenerator::get_singleton()->bake(node->get_navigation_mesh(), node);
- if (node) {
- node->update_gizmo();
- }
+ node->update_gizmo();
}
void NavigationMeshEditor::_clear_pressed() {
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index bd84a28c84..a9340b1498 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -122,13 +122,13 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
}
if (idxG == -1) {
- ERR_PRINT("TinyEXR: G channel not found.")
+ ERR_PRINT("TinyEXR: G channel not found.");
// @todo { free exr_image }
return ERR_FILE_CORRUPT;
}
if (idxB == -1) {
- ERR_PRINT("TinyEXR: B channel not found.")
+ ERR_PRINT("TinyEXR: B channel not found.");
// @todo { free exr_image }
return ERR_FILE_CORRUPT;
}
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 74d5f29c02..21e8a38c16 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -102,114 +102,117 @@
</constant>
<constant name="MATH_RANGE_LERP" value="28" enum="BuiltinFunc">
</constant>
- <constant name="MATH_DECTIME" value="29" enum="BuiltinFunc">
+ <constant name="MATH_MOVE_TOWARD" value="29" enum="BuiltinFunc">
+ Moves the number toward a value, based on the third input.
+ </constant>
+ <constant name="MATH_DECTIME" value="30" enum="BuiltinFunc">
Return the result of 'value' decreased by 'step' * 'amount'.
</constant>
- <constant name="MATH_RANDOMIZE" value="30" enum="BuiltinFunc">
+ <constant name="MATH_RANDOMIZE" value="31" enum="BuiltinFunc">
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="31" enum="BuiltinFunc">
+ <constant name="MATH_RAND" value="32" enum="BuiltinFunc">
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="32" enum="BuiltinFunc">
+ <constant name="MATH_RANDF" value="33" enum="BuiltinFunc">
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="33" enum="BuiltinFunc">
+ <constant name="MATH_RANDOM" value="34" enum="BuiltinFunc">
Return a random floating-point value between the two inputs.
</constant>
- <constant name="MATH_SEED" value="34" enum="BuiltinFunc">
+ <constant name="MATH_SEED" value="35" enum="BuiltinFunc">
Set the seed for the random number generator.
</constant>
- <constant name="MATH_RANDSEED" value="35" enum="BuiltinFunc">
+ <constant name="MATH_RANDSEED" value="36" enum="BuiltinFunc">
Return a random value from the given seed, along with the new seed.
</constant>
- <constant name="MATH_DEG2RAD" value="36" enum="BuiltinFunc">
+ <constant name="MATH_DEG2RAD" value="37" enum="BuiltinFunc">
Convert the input from degrees to radians.
</constant>
- <constant name="MATH_RAD2DEG" value="37" enum="BuiltinFunc">
+ <constant name="MATH_RAD2DEG" value="38" enum="BuiltinFunc">
Convert the input from radians to degrees.
</constant>
- <constant name="MATH_LINEAR2DB" value="38" enum="BuiltinFunc">
+ <constant name="MATH_LINEAR2DB" value="39" enum="BuiltinFunc">
Convert the input from linear volume to decibel volume.
</constant>
- <constant name="MATH_DB2LINEAR" value="39" enum="BuiltinFunc">
+ <constant name="MATH_DB2LINEAR" value="40" enum="BuiltinFunc">
Convert the input from decibel volume to linear volume.
</constant>
- <constant name="MATH_POLAR2CARTESIAN" value="40" enum="BuiltinFunc">
+ <constant name="MATH_POLAR2CARTESIAN" value="41" enum="BuiltinFunc">
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" enum="BuiltinFunc">
+ <constant name="MATH_CARTESIAN2POLAR" value="42" enum="BuiltinFunc">
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" enum="BuiltinFunc">
+ <constant name="MATH_WRAP" value="43" enum="BuiltinFunc">
</constant>
- <constant name="MATH_WRAPF" value="43" enum="BuiltinFunc">
+ <constant name="MATH_WRAPF" value="44" enum="BuiltinFunc">
</constant>
- <constant name="LOGIC_MAX" value="44" enum="BuiltinFunc">
+ <constant name="LOGIC_MAX" value="45" enum="BuiltinFunc">
Return the greater of the two numbers, also known as their maximum.
</constant>
- <constant name="LOGIC_MIN" value="45" enum="BuiltinFunc">
+ <constant name="LOGIC_MIN" value="46" enum="BuiltinFunc">
Return the lesser of the two numbers, also known as their minimum.
</constant>
- <constant name="LOGIC_CLAMP" value="46" enum="BuiltinFunc">
+ <constant name="LOGIC_CLAMP" value="47" enum="BuiltinFunc">
Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to [code]min(max(input, range_low), range_high)[/code].
</constant>
- <constant name="LOGIC_NEAREST_PO2" value="47" enum="BuiltinFunc">
+ <constant name="LOGIC_NEAREST_PO2" value="48" enum="BuiltinFunc">
Return the nearest power of 2 to the input.
</constant>
- <constant name="OBJ_WEAKREF" value="48" enum="BuiltinFunc">
+ <constant name="OBJ_WEAKREF" value="49" enum="BuiltinFunc">
Create a [WeakRef] from the input.
</constant>
- <constant name="FUNC_FUNCREF" value="49" enum="BuiltinFunc">
+ <constant name="FUNC_FUNCREF" value="50" enum="BuiltinFunc">
Create a [FuncRef] from the input.
</constant>
- <constant name="TYPE_CONVERT" value="50" enum="BuiltinFunc">
+ <constant name="TYPE_CONVERT" value="51" enum="BuiltinFunc">
Convert between types.
</constant>
- <constant name="TYPE_OF" value="51" enum="BuiltinFunc">
+ <constant name="TYPE_OF" value="52" enum="BuiltinFunc">
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="52" enum="BuiltinFunc">
+ <constant name="TYPE_EXISTS" value="53" enum="BuiltinFunc">
Checks if a type is registered in the [ClassDB].
</constant>
- <constant name="TEXT_CHAR" value="53" enum="BuiltinFunc">
+ <constant name="TEXT_CHAR" value="54" enum="BuiltinFunc">
Return a character with the given ascii value.
</constant>
- <constant name="TEXT_STR" value="54" enum="BuiltinFunc">
+ <constant name="TEXT_STR" value="55" enum="BuiltinFunc">
Convert the input to a string.
</constant>
- <constant name="TEXT_PRINT" value="55" enum="BuiltinFunc">
+ <constant name="TEXT_PRINT" value="56" enum="BuiltinFunc">
Print the given string to the output window.
</constant>
- <constant name="TEXT_PRINTERR" value="56" enum="BuiltinFunc">
+ <constant name="TEXT_PRINTERR" value="57" enum="BuiltinFunc">
Print the given string to the standard error output.
</constant>
- <constant name="TEXT_PRINTRAW" value="57" enum="BuiltinFunc">
+ <constant name="TEXT_PRINTRAW" value="58" enum="BuiltinFunc">
Print the given string to the standard output, without adding a newline.
</constant>
- <constant name="VAR_TO_STR" value="58" enum="BuiltinFunc">
+ <constant name="VAR_TO_STR" value="59" enum="BuiltinFunc">
Serialize a [Variant] to a string.
</constant>
- <constant name="STR_TO_VAR" value="59" enum="BuiltinFunc">
+ <constant name="STR_TO_VAR" value="60" enum="BuiltinFunc">
Deserialize a [Variant] from a string serialized using [code]VAR_TO_STR[/code].
</constant>
- <constant name="VAR_TO_BYTES" value="60" enum="BuiltinFunc">
+ <constant name="VAR_TO_BYTES" value="61" enum="BuiltinFunc">
Serialize a [Variant] to a [PoolByteArray].
</constant>
- <constant name="BYTES_TO_VAR" value="61" enum="BuiltinFunc">
+ <constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc">
Deserialize a [Variant] from a [PoolByteArray] serialized using [code]VAR_TO_BYTES[/code].
</constant>
- <constant name="COLORN" value="62" enum="BuiltinFunc">
+ <constant name="COLORN" value="63" enum="BuiltinFunc">
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="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc">
+ <constant name="MATH_SMOOTHSTEP" value="64" enum="BuiltinFunc">
Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [code]MATH_LERP[/code], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula:
[codeblock]
var t = clamp((weight - from) / (to - from), 0.0, 1.0)
return t * t * (3.0 - 2.0 * t)
[/codeblock]
</constant>
- <constant name="FUNC_MAX" value="64" enum="BuiltinFunc">
+ <constant name="FUNC_MAX" value="65" enum="BuiltinFunc">
The maximum value the [member function] property can have.
</constant>
</constants>
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index d207656705..75b79f8929 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -68,6 +68,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"lerp",
"inverse_lerp",
"range_lerp",
+ "move_toward",
"dectime",
"randomize",
"randi",
@@ -206,6 +207,7 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case MATH_LERP:
case MATH_INVERSE_LERP:
case MATH_SMOOTHSTEP:
+ case MATH_MOVE_TOWARD:
case MATH_DECTIME:
case MATH_WRAP:
case MATH_WRAPF:
@@ -347,6 +349,14 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
else
return PropertyInfo(Variant::REAL, "weight");
} break;
+ case MATH_MOVE_TOWARD: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "from");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::REAL, "to");
+ else
+ return PropertyInfo(Variant::REAL, "delta");
+ } break;
case MATH_DECTIME: {
if (p_idx == 0)
return PropertyInfo(Variant::REAL, "value");
@@ -580,6 +590,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_INVERSE_LERP:
case MATH_RANGE_LERP:
case MATH_SMOOTHSTEP:
+ case MATH_MOVE_TOWARD:
case MATH_DECTIME: {
t = Variant::REAL;
@@ -916,6 +927,13 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(2);
*r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
} break;
+ case VisualScriptBuiltinFunc::MATH_MOVE_TOWARD: {
+
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
+ } break;
case VisualScriptBuiltinFunc::MATH_DECTIME: {
VALIDATE_ARG_NUM(0);
@@ -1363,6 +1381,7 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_LERP);
BIND_ENUM_CONSTANT(MATH_INVERSE_LERP);
BIND_ENUM_CONSTANT(MATH_RANGE_LERP);
+ BIND_ENUM_CONSTANT(MATH_MOVE_TOWARD);
BIND_ENUM_CONSTANT(MATH_DECTIME);
BIND_ENUM_CONSTANT(MATH_RANDOMIZE);
BIND_ENUM_CONSTANT(MATH_RAND);
@@ -1453,6 +1472,7 @@ void register_visual_script_builtin_func_node() {
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/smoothstep", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SMOOTHSTEP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/move_toward", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_MOVE_TOWARD>);
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>);
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index 50854c16b1..3e452cd94f 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -67,6 +67,7 @@ public:
MATH_LERP,
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
+ MATH_MOVE_TOWARD,
MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RAND,
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index aad6e95845..f84f2c90cd 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -2111,6 +2111,9 @@ void VisualScriptEditor::clear_executing_line() {
void VisualScriptEditor::trim_trailing_whitespace() {
}
+void VisualScriptEditor::insert_final_newline() {
+}
+
void VisualScriptEditor::convert_indent_to_spaces() {
}
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index 3d3a49f672..6072e77342 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -266,6 +266,7 @@ public:
virtual void set_executing_line(int p_line);
virtual void clear_executing_line();
virtual void trim_trailing_whitespace();
+ virtual void insert_final_newline();
virtual void convert_indent_to_spaces();
virtual void convert_indent_to_tabs();
virtual void ensure_focus();
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 692705e411..e652abbe6a 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -143,8 +143,7 @@ int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_buffer, int p_frames) {
bool ok = ov_time_seek(&vf, loop_restart_time) == 0;
if (!ok) {
playing = false;
- //ERR_EXPLAIN("loop restart time rejected");
- ERR_PRINT("loop restart time rejected")
+ ERR_PRINT("Loop restart time rejected");
}
frames_mixed = stream_srate * loop_restart_time;
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index 6485c95360..3670edc9ea 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -413,10 +413,11 @@ void VideoStreamPlaybackWebm::delete_pointers() {
if (audio_frame)
memdelete(audio_frame);
- for (int i = 0; i < video_frames_capacity; ++i)
- memdelete(video_frames[i]);
- if (video_frames)
+ if (video_frames) {
+ for (int i = 0; i < video_frames_capacity; ++i)
+ memdelete(video_frames[i]);
memfree(video_frames);
+ }
if (video)
memdelete(video);
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index b987b3aebd..30267aa968 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -790,7 +790,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
if (tname == "manifest" && attrname == "versionName") {
if (attr_value == 0xFFFFFFFF) {
- WARN_PRINT("Version name in a resource, should be plaintext")
+ WARN_PRINT("Version name in a resource, should be plain text");
} else
string_table.write[attr_value] = version_name;
}
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index ba405ab7ae..7ca83320d0 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -914,7 +914,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
};
DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
+ ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
print_line("Unzipping...");
FileAccess *src_f = NULL;
diff --git a/platform/iphone/icloud.mm b/platform/iphone/icloud.mm
index e32618e8f6..c60db3d661 100644
--- a/platform/iphone/icloud.mm
+++ b/platform/iphone/icloud.mm
@@ -138,7 +138,7 @@ Variant nsobject_to_variant(NSObject *object) {
//this is a type that icloud supports...but how did you submit it in the first place?
//I guess this is a type that *might* show up, if you were, say, trying to make your game
//compatible with existing cloud data written by another engine's version of your game
- WARN_PRINT("NSDate unsupported, returning null Variant")
+ WARN_PRINT("NSDate unsupported, returning null Variant");
return Variant();
} else if ([object isKindOfClass:[NSNull class]] or object == nil) {
return Variant();
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index c69e6f0cb8..e7981bf576 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -795,6 +795,47 @@ const char *OS_JavaScript::get_audio_driver_name(int p_driver) const {
return "JavaScript";
}
+// Clipboard
+extern "C" EMSCRIPTEN_KEEPALIVE void update_clipboard(const char *p_text) {
+ // Only call set_clipboard from OS (sets local clipboard)
+ OS::get_singleton()->OS::set_clipboard(p_text);
+}
+
+void OS_JavaScript::set_clipboard(const String &p_text) {
+ OS::set_clipboard(p_text);
+ /* clang-format off */
+ int err = EM_ASM_INT({
+ var text = UTF8ToString($0);
+ if (!navigator.clipboard || !navigator.clipboard.writeText)
+ return 1;
+ navigator.clipboard.writeText(text).catch(e => {
+ // Setting OS clipboard is only possible from an input callback.
+ console.error("Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:", e);
+ });
+ return 0;
+ }, p_text.utf8().get_data());
+ /* clang-format on */
+ ERR_EXPLAIN("Clipboard API is not supported.");
+ ERR_FAIL_COND(err);
+}
+
+String OS_JavaScript::get_clipboard() const {
+ /* clang-format off */
+ EM_ASM({
+ try {
+ navigator.clipboard.readText().then(function (result) {
+ ccall('update_clipboard', 'void', ['string'], [result]);
+ }).catch(function (e) {
+ // Fail graciously.
+ });
+ } catch (e) {
+ // Fail graciously.
+ }
+ });
+ /* clang-format on */
+ return this->OS::get_clipboard();
+}
+
// Lifecycle
int OS_JavaScript::get_current_video_driver() const {
return video_driver_index;
@@ -939,6 +980,11 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
(['mouseover', 'mouseleave', 'focus', 'blur']).forEach(function(event, index) {
Module.canvas.addEventListener(event, send_notification.bind(null, notifications[index]));
});
+ // Clipboard
+ const update_clipboard = cwrap('update_clipboard', null, ['string']);
+ window.addEventListener('paste', function(evt) {
+ update_clipboard(evt.clipboardData.getData('text'));
+ }, true);
},
MainLoop::NOTIFICATION_WM_MOUSE_ENTER,
MainLoop::NOTIFICATION_WM_MOUSE_EXIT,
@@ -1098,7 +1144,7 @@ void OS_JavaScript::set_icon(const Ref<Image> &p_icon) {
Ref<Image> icon = p_icon;
if (icon->is_compressed()) {
icon = icon->duplicate();
- ERR_FAIL_COND(icon->decompress() != OK)
+ ERR_FAIL_COND(icon->decompress() != OK);
}
if (icon->get_format() != Image::FORMAT_RGBA8) {
if (icon == p_icon)
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index a0c7c31f2d..27b23a4673 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -133,6 +133,9 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void set_clipboard(const String &p_text);
+ virtual String get_clipboard() const;
+
virtual MainLoop *get_main_loop() const;
void run_async();
bool main_loop_iterate();
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 212966af11..eed230ba89 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -60,6 +60,7 @@ public:
unsigned int osx_state;
bool pressed;
bool echo;
+ bool raw;
uint32_t scancode;
uint32_t unicode;
};
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 113c6636f0..bdc17c7124 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -392,7 +392,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
@interface GodotContentView : NSView <NSTextInputClient> {
NSTrackingArea *trackingArea;
NSMutableAttributedString *markedText;
- bool imeMode;
+ bool imeInputEventInProgress;
}
- (void)cancelComposition;
- (BOOL)wantsUpdateLayer;
@@ -418,7 +418,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
- (id)init {
self = [super init];
trackingArea = nil;
- imeMode = false;
+ imeInputEventInProgress = false;
[self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
markedText = [[NSMutableAttributedString alloc] init];
@@ -452,7 +452,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[markedText initWithString:aString];
}
if (OS_OSX::singleton->im_active) {
- imeMode = true;
+ imeInputEventInProgress = true;
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
@@ -467,7 +467,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (void)unmarkText {
- imeMode = false;
+ imeInputEventInProgress = false;
[[markedText mutableString] setString:@""];
if (OS_OSX::singleton->im_active) {
OS_OSX::singleton->im_text = String();
@@ -540,6 +540,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
ke.osx_state = [event modifierFlags];
ke.pressed = true;
ke.echo = false;
+ ke.raw = false; // IME input event
ke.scancode = 0;
ke.unicode = codepoint;
@@ -1001,7 +1002,7 @@ static const _KeyCodeMap _keycodes[55] = {
{ '/', KEY_SLASH }
};
-static int remapKey(unsigned int key) {
+static int remapKey(unsigned int key, unsigned int state) {
if (isNumpadKey(key))
return translateKey(key);
@@ -1023,7 +1024,7 @@ static int remapKey(unsigned int key) {
OSStatus err = UCKeyTranslate(keyboardLayout,
key,
kUCKeyActionDisplay,
- 0,
+ (state >> 8) & 0xFF,
LMGetKbdType(),
kUCKeyTranslateNoDeadKeysBit,
&keysDown,
@@ -1045,29 +1046,52 @@ static int remapKey(unsigned int key) {
- (void)keyDown:(NSEvent *)event {
- //disable raw input in IME mode
- if (!imeMode) {
- OS_OSX::KeyEvent ke;
+ // Ignore all input if IME input is in progress
+ if (!imeInputEventInProgress) {
+ NSString *characters = [event characters];
+ NSUInteger length = [characters length];
- ke.osx_state = [event modifierFlags];
- ke.pressed = true;
- ke.echo = [event isARepeat];
- ke.scancode = remapKey([event keyCode]);
- ke.unicode = 0;
+ if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) {
+ // Fallback unicode character handler used if IME is not active
+ for (NSUInteger i = 0; i < length; i++) {
+ OS_OSX::KeyEvent ke;
- push_to_key_event_buffer(ke);
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = true;
+ ke.echo = [event isARepeat];
+ ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+ ke.raw = true;
+ ke.unicode = [characters characterAtIndex:i];
+
+ push_to_key_event_buffer(ke);
+ }
+ } else {
+ OS_OSX::KeyEvent ke;
+
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = true;
+ ke.echo = [event isARepeat];
+ ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+ ke.raw = false;
+ ke.unicode = 0;
+
+ push_to_key_event_buffer(ke);
+ }
}
- if (OS_OSX::singleton->im_active == true)
+ // Pass events to IME handler
+ if (OS_OSX::singleton->im_active)
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
- (void)flagsChanged:(NSEvent *)event {
- if (!imeMode) {
+ // Ignore all input if IME input is in progress
+ if (!imeInputEventInProgress) {
OS_OSX::KeyEvent ke;
ke.echo = false;
+ ke.raw = true;
int key = [event keyCode];
int mod = [event modifierFlags];
@@ -1105,7 +1129,7 @@ static int remapKey(unsigned int key) {
}
ke.osx_state = mod;
- ke.scancode = remapKey(key);
+ ke.scancode = remapKey(key, mod);
ke.unicode = 0;
push_to_key_event_buffer(ke);
@@ -1114,17 +1138,37 @@ static int remapKey(unsigned int key) {
- (void)keyUp:(NSEvent *)event {
- if (!imeMode) {
+ // Ignore all input if IME input is in progress
+ if (!imeInputEventInProgress) {
+ NSString *characters = [event characters];
+ NSUInteger length = [characters length];
- OS_OSX::KeyEvent ke;
+ // Fallback unicode character handler used if IME is not active
+ if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) {
+ for (NSUInteger i = 0; i < length; i++) {
+ OS_OSX::KeyEvent ke;
- ke.osx_state = [event modifierFlags];
- ke.pressed = false;
- ke.echo = false;
- ke.scancode = remapKey([event keyCode]);
- ke.unicode = 0;
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = false;
+ ke.echo = [event isARepeat];
+ ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+ ke.raw = true;
+ ke.unicode = [characters characterAtIndex:i];
- push_to_key_event_buffer(ke);
+ push_to_key_event_buffer(ke);
+ }
+ } else {
+ OS_OSX::KeyEvent ke;
+
+ ke.osx_state = [event modifierFlags];
+ ke.pressed = false;
+ ke.echo = [event isARepeat];
+ ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+ ke.raw = true;
+ ke.unicode = 0;
+
+ push_to_key_event_buffer(ke);
+ }
}
}
@@ -1507,7 +1551,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
restore_rect = Rect2(get_window_position(), get_window_size());
- if (p_desired.layered_splash) {
+ if (p_desired.layered) {
set_window_per_pixel_transparency_enabled(true);
}
return OK;
@@ -2612,30 +2656,44 @@ void OS_OSX::process_key_events() {
const KeyEvent &ke = key_event_buffer[i];
- if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
+ if (ke.raw) {
+ // Non IME input - no composite characters, pass events as is
k.instance();
get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
- k->set_scancode(0);
+ k->set_scancode(ke.scancode);
k->set_unicode(ke.unicode);
push_input(k);
- }
- if (ke.scancode != 0) {
- k.instance();
+ } else {
+ // IME input
+ if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
+ k.instance();
- get_key_modifier_state(ke.osx_state, k);
- k->set_pressed(ke.pressed);
- k->set_echo(ke.echo);
- k->set_scancode(ke.scancode);
+ get_key_modifier_state(ke.osx_state, k);
+ k->set_pressed(ke.pressed);
+ k->set_echo(ke.echo);
+ k->set_scancode(0);
+ k->set_unicode(ke.unicode);
- if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
- k->set_unicode(key_event_buffer[i + 1].unicode);
+ push_input(k);
}
+ if (ke.scancode != 0) {
+ k.instance();
- push_input(k);
+ get_key_modifier_state(ke.osx_state, k);
+ k->set_pressed(ke.pressed);
+ k->set_echo(ke.echo);
+ k->set_scancode(ke.scancode);
+
+ if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
+ k->set_unicode(key_event_buffer[i + 1].unicode);
+ }
+
+ push_input(k);
+ }
}
}
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 08c2eb6aaf..a5648d8d9d 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -145,12 +145,12 @@ def configure(env):
env.ParseConfig('pkg-config libpng --cflags --libs')
if not env['builtin_bullet']:
- # We need at least version 2.88
+ # We need at least version 2.89
import subprocess
bullet_version = subprocess.check_output(['pkg-config', 'bullet', '--modversion']).strip()
- if str(bullet_version) < "2.88":
+ if str(bullet_version) < "2.89":
# Abort as system bullet was requested but too old
- print("Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(bullet_version, "2.88"))
+ print("Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(bullet_version, "2.89"))
sys.exit(255)
env.ParseConfig('pkg-config bullet --cflags --libs')
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index cdcad33f6d..ec43a4c26f 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -241,7 +241,6 @@ void AppxPackager::make_block_map() {
tmp_file->close();
memdelete(tmp_file);
- tmp_file = NULL;
}
String AppxPackager::content_type(String p_extension) {
@@ -291,7 +290,6 @@ void AppxPackager::make_content_types() {
tmp_file->close();
memdelete(tmp_file);
- tmp_file = NULL;
}
Vector<uint8_t> AppxPackager::make_file_header(FileMeta p_file_meta) {
@@ -606,7 +604,6 @@ void AppxPackager::finish() {
blockmap_file->close();
memdelete(blockmap_file);
- blockmap_file = NULL;
// Add content types
EditorNode::progress_task_step("export", "Setting content types...", 5);
@@ -622,7 +619,6 @@ void AppxPackager::finish() {
types_file->close();
memdelete(types_file);
- types_file = NULL;
// Pre-process central directory before signing
for (int i = 0; i < file_metadata.size(); i++) {
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index f2dca10d55..1fa8957f15 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -21,7 +21,7 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Godot Engine"
- VALUE "FileDescription", VERSION_NAME " Editor"
+ VALUE "FileDescription", VERSION_NAME
VALUE "FileVersion", VERSION_NUMBER
VALUE "ProductName", VERSION_NAME
VALUE "Licence", "MIT"
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 6df2ad4821..4cd637a4b2 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1381,7 +1381,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
SetFocus(hWnd); // Sets Keyboard Focus To
}
- if (p_desired.layered_splash) {
+ if (p_desired.layered) {
set_window_per_pixel_transparency_enabled(true);
}
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 933ee6b72e..a502308eee 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -219,12 +219,12 @@ def configure(env):
env.ParseConfig('pkg-config libpng --cflags --libs')
if not env['builtin_bullet']:
- # We need at least version 2.88
+ # We need at least version 2.89
import subprocess
bullet_version = subprocess.check_output(['pkg-config', 'bullet', '--modversion']).strip()
- if str(bullet_version) < "2.88":
+ if str(bullet_version) < "2.89":
# Abort as system bullet was requested but too old
- print("Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(bullet_version, "2.88"))
+ print("Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(bullet_version, "2.89"))
sys.exit(255)
env.ParseConfig('pkg-config bullet --cflags --libs')
diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp
index c4dd8fe0e0..3e9e8033e8 100644
--- a/platform/x11/joypad_linux.cpp
+++ b/platform/x11/joypad_linux.cpp
@@ -444,10 +444,10 @@ InputDefault::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int
jx.min = -1;
if (p_value < 0) {
jx.value = (float)-p_value / min;
+ } else {
+ jx.value = (float)p_value / max;
}
- jx.value = (float)p_value / max;
- }
- if (min == 0) {
+ } else if (min == 0) {
jx.min = 0;
jx.value = 0.0f + (float)p_value / max;
}
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index f034b2389b..510f3d6114 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -593,7 +593,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
power_manager = memnew(PowerX11);
- if (p_desired.layered_splash) {
+ if (p_desired.layered) {
set_window_per_pixel_transparency_enabled(true);
}
@@ -1017,12 +1017,12 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
XFree(xsh);
}
- if (!p_enabled && !get_borderless_window()) {
- // put decorations back if the window wasn't suppoesed to be borderless
+ if (!p_enabled) {
+ // put back or remove decorations according to the last set borderless state
Hints hints;
Atom property;
hints.flags = 2;
- hints.decorations = 1;
+ hints.decorations = current_videomode.borderless_window ? 0 : 1;
property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
}
@@ -1531,7 +1531,7 @@ bool OS_X11::is_window_always_on_top() const {
void OS_X11::set_borderless_window(bool p_borderless) {
- if (current_videomode.borderless_window == p_borderless)
+ if (get_borderless_window() == p_borderless)
return;
if (!p_borderless && layered_window)
@@ -1551,7 +1551,24 @@ void OS_X11::set_borderless_window(bool p_borderless) {
}
bool OS_X11::get_borderless_window() {
- return current_videomode.borderless_window;
+
+ bool borderless = current_videomode.borderless_window;
+ Atom prop = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ if (prop != None) {
+
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = NULL;
+ if (XGetWindowProperty(x11_display, x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
+ if (data && (format == 32) && (len >= 5)) {
+ borderless = !((Hints *)data)->decorations;
+ }
+ XFree(data);
+ }
+ }
+ return borderless;
}
void OS_X11::request_attention() {
@@ -2378,7 +2395,7 @@ void OS_X11::process_xevents() {
Vector<String> files = String((char *)p.data).split("\n", false);
for (int i = 0; i < files.size(); i++) {
- files.write[i] = files[i].replace("file://", "").http_unescape().strip_escapes();
+ files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges();
}
main_loop->drop_files(files);
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 25ad6bd5c9..5bf70e12b7 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -646,6 +646,7 @@ void AnimatedSprite::_reset_timeout() {
void AnimatedSprite::set_animation(const StringName &p_animation) {
ERR_EXPLAIN(vformat("There is no animation with name '%s'.", p_animation));
+ ERR_FAIL_COND(frames == NULL);
ERR_FAIL_COND(frames->get_animation_names().find(p_animation) == -1);
if (animation == p_animation)
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 11846654c5..aa14491577 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -44,15 +44,16 @@ void Camera2D::_update_scroll() {
return;
}
+ if (!viewport)
+ return;
+
if (current) {
ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
Transform2D xform = get_camera_transform();
- if (viewport) {
- viewport->set_canvas_transform(xform);
- }
+ viewport->set_canvas_transform(xform);
Size2 screen_size = viewport->get_visible_rect().size;
Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2());
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index ff27e0a29a..2b1009a2d1 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -545,6 +545,8 @@ void CPUParticles2D::_particles_process(float p_delta) {
velocity_xform[2] = Vector2();
}
+ float system_phase = time / lifetime;
+
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];
@@ -552,21 +554,26 @@ void CPUParticles2D::_particles_process(float p_delta) {
if (!emitting && !p.active)
continue;
- float restart_time = (float(i) / float(pcount)) * lifetime;
float local_delta = p_delta;
+ // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
+ // While we use time in tests later on, for randomness we use the phase as done in the
+ // original shader code, and we later multiply by lifetime to get the time.
+ float restart_phase = float(i) / float(pcount);
+
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
- if (restart_time >= time) {
+ if (restart_phase >= system_phase) {
seed -= uint32_t(1);
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_time += randomness_ratio * random * 1.0 / float(pcount);
+ restart_phase += randomness_ratio * random * 1.0 / float(pcount);
}
- restart_time *= (1.0 - explosiveness_ratio);
+ restart_phase *= (1.0 - explosiveness_ratio);
+ float restart_time = restart_phase * lifetime;
bool restart = false;
if (time > prev_time) {
@@ -748,7 +755,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector2();
//apply tangential acceleration;
Vector2 yx = Vector2(diff.y, diff.x);
- force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
+ force += yx.length() > 0.0 ? (yx * Vector2(-1.0, 1.0)).normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector2();
//apply attractor forces
p.velocity += force * local_delta;
//orbit velocity
@@ -1174,15 +1181,16 @@ void CPUParticles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
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", "");
+ // No visibility_rect property contrarily to Particles2D, it's updated automatically.
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_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 23d2586331..81343a4604 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -116,7 +116,7 @@ private:
const Particle *particles;
bool operator()(int p_a, int p_b) const {
- return particles[p_a].time < particles[p_b].time;
+ return particles[p_a].time > particles[p_b].time;
}
};
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index ba06b3ebff..5ba184b324 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -105,6 +105,7 @@ void Line2D::set_point_position(int i, Vector2 pos) {
}
Vector2 Line2D::get_point_position(int i) const {
+ ERR_FAIL_INDEX_V(i, _points.size(), Vector2());
return _points.get(i);
}
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index b382ca7b33..bcd4bca940 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -50,6 +50,8 @@ void MeshInstance2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &MeshInstance2D::set_normal_map);
ClassDB::bind_method(D_METHOD("get_normal_map"), &MeshInstance2D::get_normal_map);
+ ADD_SIGNAL(MethodInfo("texture_changed"));
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
new file mode 100644
index 0000000000..ca75302163
--- /dev/null
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* multimesh_instance_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 "multimesh_instance_2d.h"
+
+void MultiMeshInstance2D::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_DRAW) {
+ if (multimesh.is_valid()) {
+ draw_multimesh(multimesh, texture, normal_map);
+ }
+ }
+}
+
+void MultiMeshInstance2D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance2D::set_multimesh);
+ ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance2D::get_multimesh);
+
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &MultiMeshInstance2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &MultiMeshInstance2D::get_texture);
+
+ ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &MultiMeshInstance2D::set_normal_map);
+ ClassDB::bind_method(D_METHOD("get_normal_map"), &MultiMeshInstance2D::get_normal_map);
+
+ ADD_SIGNAL(MethodInfo("texture_changed"));
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
+}
+
+void MultiMeshInstance2D::set_multimesh(const Ref<MultiMesh> &p_multimesh) {
+
+ multimesh = p_multimesh;
+ update();
+}
+
+Ref<MultiMesh> MultiMeshInstance2D::get_multimesh() const {
+
+ return multimesh;
+}
+
+void MultiMeshInstance2D::set_texture(const Ref<Texture> &p_texture) {
+
+ if (p_texture == texture)
+ return;
+ texture = p_texture;
+ update();
+ emit_signal("texture_changed");
+ _change_notify("texture");
+}
+
+Ref<Texture> MultiMeshInstance2D::get_texture() const {
+
+ return texture;
+}
+
+void MultiMeshInstance2D::set_normal_map(const Ref<Texture> &p_texture) {
+
+ normal_map = p_texture;
+ update();
+}
+
+Ref<Texture> MultiMeshInstance2D::get_normal_map() const {
+
+ return normal_map;
+}
+
+Rect2 MultiMeshInstance2D::_edit_get_rect() const {
+
+ if (multimesh.is_valid()) {
+ AABB aabb = multimesh->get_aabb();
+ return Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
+ }
+
+ return Node2D::_edit_get_rect();
+}
+
+MultiMeshInstance2D::MultiMeshInstance2D() {
+}
+
+MultiMeshInstance2D::~MultiMeshInstance2D() {
+}
diff --git a/scene/2d/multimesh_instance_2d.h b/scene/2d/multimesh_instance_2d.h
new file mode 100644
index 0000000000..3795497183
--- /dev/null
+++ b/scene/2d/multimesh_instance_2d.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* multimesh_instance_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MULTIMESH_INSTANCE_2D_H
+#define MULTIMESH_INSTANCE_2D_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/resources/multimesh.h"
+
+class MultiMeshInstance2D : public Node2D {
+ GDCLASS(MultiMeshInstance2D, Node2D);
+
+ Ref<MultiMesh> multimesh;
+
+ Ref<Texture> texture;
+ Ref<Texture> normal_map;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_multimesh(const Ref<MultiMesh> &p_multimesh);
+ Ref<MultiMesh> get_multimesh() const;
+
+ void set_texture(const Ref<Texture> &p_texture);
+ Ref<Texture> get_texture() const;
+
+ void set_normal_map(const Ref<Texture> &p_texture);
+ Ref<Texture> get_normal_map() const;
+
+ virtual Rect2 _edit_get_rect() const;
+
+ MultiMeshInstance2D();
+ ~MultiMeshInstance2D();
+};
+
+#endif // MULTIMESH_INSTANCE_2D_H
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 578c9aa5f9..2bd9e5e2a2 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -203,8 +203,8 @@ void StaticBody2D::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -217,8 +217,8 @@ void StaticBody2D::set_friction(real_t p_friction) {
real_t StaticBody2D::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -233,8 +233,8 @@ void StaticBody2D::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -247,8 +247,8 @@ void StaticBody2D::set_bounce(real_t p_bounce) {
real_t StaticBody2D::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
@@ -630,8 +630,8 @@ void RigidBody2D::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -643,8 +643,8 @@ void RigidBody2D::set_friction(real_t p_friction) {
}
real_t RigidBody2D::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -659,8 +659,8 @@ void RigidBody2D::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -672,8 +672,8 @@ void RigidBody2D::set_bounce(real_t p_bounce) {
}
real_t RigidBody2D::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index bed6f8a816..8bccf117fd 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -35,13 +35,15 @@
void Position2D::_draw_cross() {
- draw_line(Point2(-10, 0), Point2(+10, 0), Color(1, 0.5, 0.5));
- draw_line(Point2(0, -10), Point2(0, +10), Color(0.5, 1, 0.5));
+ float extents = get_gizmo_extents();
+ draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(1, 0.5, 0.5));
+ draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.5, 1, 0.5));
}
Rect2 Position2D::_edit_get_rect() const {
- return Rect2(Point2(-10, -10), Size2(20, 20));
+ float extents = get_gizmo_extents();
+ return Rect2(Point2(-extents, -extents), Size2(extents * 2, extents * 2));
}
bool Position2D::_edit_use_rect() const {
@@ -66,5 +68,31 @@ void Position2D::_notification(int p_what) {
}
}
+void Position2D::set_gizmo_extents(float p_extents) {
+ if (p_extents == DEFAULT_GIZMO_EXTENTS) {
+ set_meta("_gizmo_extents_", Variant());
+ } else {
+ set_meta("_gizmo_extents_", p_extents);
+ }
+
+ update();
+}
+
+float Position2D::get_gizmo_extents() const {
+ if (has_meta("_gizmo_extents_")) {
+ return get_meta("_gizmo_extents_");
+ } else {
+ return DEFAULT_GIZMO_EXTENTS;
+ }
+}
+
+void Position2D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_set_gizmo_extents", "extents"), &Position2D::set_gizmo_extents);
+ ClassDB::bind_method(D_METHOD("_get_gizmo_extents"), &Position2D::get_gizmo_extents);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "gizmo_extents", PROPERTY_HINT_RANGE, "0,1000,0.1,or_greater", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_gizmo_extents", "_get_gizmo_extents");
+}
+
Position2D::Position2D() {
}
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index c95315fea3..dc9cc2df15 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -37,14 +37,21 @@ class Position2D : public Node2D {
GDCLASS(Position2D, Node2D)
+ const float DEFAULT_GIZMO_EXTENTS = 10.0;
+
void _draw_cross();
protected:
void _notification(int p_what);
+ static void _bind_methods();
public:
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
+
+ void set_gizmo_extents(float p_extents);
+ float get_gizmo_extents() const;
+
Position2D();
};
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 86be8762d4..b3b6f3175d 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -220,8 +220,8 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const
xform.elements[1].y = -xform.elements[1].y;
offset.y = s.y - offset.y;
}
-
- offset += cell_size / 2 - s / 2;
+ /* For a future CheckBox to Center Texture:
+ offset += cell_size / 2 - s / 2; */
xform.elements[2] += offset;
}
@@ -372,10 +372,11 @@ void TileMap::update_dirty_quadrants() {
if (c.transpose) {
SWAP(tile_ofs.x, tile_ofs.y);
+ /* For a future CheckBox to Center Texture:
rect.position.x += cell_size.x / 2 - rect.size.y / 2;
rect.position.y += cell_size.y / 2 - rect.size.x / 2;
} else {
- rect.position += cell_size / 2 - rect.size / 2;
+ rect.position += cell_size / 2 - rect.size / 2; */
}
if (c.flip_h) {
@@ -868,8 +869,17 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) {
_make_quadrant_dirty(Q);
} else if (tile_set->tile_get_tile_mode(id) == TileSet::SINGLE_TILE) {
+
E->get().autotile_coord_x = 0;
E->get().autotile_coord_y = 0;
+ } else if (tile_set->tile_get_tile_mode(id) == TileSet::ATLAS_TILE) {
+
+ if (tile_set->autotile_get_bitmask(id, Vector2(p_x, p_y)) == TileSet::BIND_CENTER) {
+ Vector2 coord = tile_set->atlastile_get_subtile_by_priority(id, this, Vector2(p_x, p_y));
+
+ E->get().autotile_coord_x = (int)coord.x;
+ E->get().autotile_coord_y = (int)coord.y;
+ }
}
}
}
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index 4e88948ce2..95eec41fb2 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -390,7 +390,7 @@ String ARVRController::get_configuration_warning() const {
};
ARVRController::ARVRController() {
- controller_id = 0;
+ controller_id = 1;
is_active = true;
button_states = 0;
};
@@ -530,7 +530,7 @@ Ref<Mesh> ARVRAnchor::get_mesh() const {
}
ARVRAnchor::ARVRAnchor() {
- anchor_id = 0;
+ anchor_id = 1;
is_active = true;
};
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 29002c6701..a00f2173c0 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -106,9 +106,15 @@ void Camera::_notification(int p_what) {
case NOTIFICATION_ENTER_WORLD: {
- bool first_camera = get_viewport()->_camera_add(this);
- if (!get_tree()->is_node_being_edited(this) && (current || first_camera))
- make_current();
+ // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD
+ // and Spatial will handle it first, including clearing its reference to the Viewport,
+ // therefore making it impossible to subclasses to access it
+ viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+
+ bool first_camera = viewport->_camera_add(this);
+ if (current || first_camera)
+ viewport->_camera_set(this);
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -130,17 +136,20 @@ void Camera::_notification(int p_what) {
}
}
- get_viewport()->_camera_remove(this);
+ if (viewport) {
+ viewport->_camera_remove(this);
+ viewport = NULL;
+ }
} break;
case NOTIFICATION_BECAME_CURRENT: {
- if (get_world().is_valid()) {
- get_world()->_register_camera(this);
+ if (viewport) {
+ viewport->find_world()->_register_camera(this);
}
} break;
case NOTIFICATION_LOST_CURRENT: {
- if (get_world().is_valid()) {
- get_world()->_remove_camera(this);
+ if (viewport) {
+ viewport->find_world()->_remove_camera(this);
}
} break;
}
@@ -255,8 +264,6 @@ bool Camera::is_current() const {
return get_viewport()->get_camera() == this;
} else
return current;
-
- return false;
}
bool Camera::_can_gizmo_scale() const {
@@ -694,6 +701,7 @@ Camera::Camera() {
near = 0;
far = 0;
current = false;
+ viewport = NULL;
force_change = false;
mode = PROJECTION_PERSPECTIVE;
set_perspective(70.0, 0.05, 100.0);
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index cbcefbb0ae..1cd729199d 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -64,6 +64,7 @@ public:
private:
bool force_change;
bool current;
+ Viewport *viewport;
Projection mode;
diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp
index 3190e1e0b2..219ea56681 100644
--- a/scene/3d/collision_shape.cpp
+++ b/scene/3d/collision_shape.cpp
@@ -228,7 +228,9 @@ void CollisionShape::_update_debug_shape() {
void CollisionShape::_shape_changed() {
// If this is a heightfield shape our center may have changed
- _update_in_shape_owner(true);
+ if (parent) {
+ _update_in_shape_owner(true);
+ }
if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) {
debug_shape_dirty = true;
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index 138c446fea..a81071492b 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -515,6 +515,8 @@ void CPUParticles::_particles_process(float p_delta) {
velocity_xform = emission_xform.basis;
}
+ float system_phase = time / lifetime;
+
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];
@@ -522,21 +524,26 @@ void CPUParticles::_particles_process(float p_delta) {
if (!emitting && !p.active)
continue;
- float restart_time = (float(i) / float(pcount)) * lifetime;
float local_delta = p_delta;
+ // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
+ // While we use time in tests later on, for randomness we use the phase as done in the
+ // original shader code, and we later multiply by lifetime to get the time.
+ float restart_phase = float(i) / float(pcount);
+
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
- if (restart_time >= time) {
+ if (restart_phase >= system_phase) {
seed -= uint32_t(1);
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_time += randomness_ratio * random * 1.0 / float(pcount);
+ restart_phase += randomness_ratio * random * 1.0 / float(pcount);
}
- restart_time *= (1.0 - explosiveness_ratio);
+ restart_phase *= (1.0 - explosiveness_ratio);
+ float restart_time = restart_phase * lifetime;
bool restart = false;
if (time > prev_time) {
@@ -754,8 +761,9 @@ void CPUParticles::_particles_process(float p_delta) {
//apply tangential acceleration;
if (flags[FLAG_DISABLE_Z]) {
- Vector3 yx = Vector3(diff.y, 0, diff.x);
- force += yx.length() > 0.0 ? (yx * Vector3(-1.0, 0, 1.0)) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
+ Vector2 yx = Vector2(diff.y, diff.x);
+ Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized();
+ force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
} else {
Vector3 crossDiff = diff.normalized().cross(gravity.normalized());
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 57af951110..3624e04434 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -192,8 +192,8 @@ void StaticBody::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -206,8 +206,8 @@ void StaticBody::set_friction(real_t p_friction) {
real_t StaticBody::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -222,8 +222,8 @@ void StaticBody::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -236,8 +236,8 @@ void StaticBody::set_bounce(real_t p_bounce) {
real_t StaticBody::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
@@ -636,8 +636,8 @@ void RigidBody::set_friction(real_t p_friction) {
return;
}
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
@@ -649,8 +649,8 @@ void RigidBody::set_friction(real_t p_friction) {
}
real_t RigidBody::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 1;
@@ -665,8 +665,8 @@ void RigidBody::set_bounce(real_t p_bounce) {
return;
}
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
@@ -677,8 +677,8 @@ void RigidBody::set_bounce(real_t p_bounce) {
physics_material_override->set_bounce(p_bounce);
}
real_t RigidBody::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
- WARN_DEPRECATED
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.");
+ WARN_DEPRECATED;
if (physics_material_override.is_null()) {
return 0;
}
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index 0e7d9be505..3b924e0454 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -89,6 +89,7 @@ class GeometryInstance : public VisualInstance {
public:
enum Flags {
FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT,
+ FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
FLAG_MAX = VS::INSTANCE_FLAG_MAX,
};
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index e9b38ae990..20a09696e1 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -1049,7 +1049,7 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node
return CONNECTION_ERROR_NO_INPUT;
}
- if (!nodes.has(p_input_node)) {
+ if (p_input_node == p_output_node) {
return CONNECTION_ERROR_SAME_NODE;
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 8247728b9d..54f0fdc26a 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -316,7 +316,7 @@ String AnimationNode::get_caption() const {
void AnimationNode::add_input(const String &p_name) {
//root nodes can't add inputs
- ERR_FAIL_COND(Object::cast_to<AnimationRootNode>(this) != NULL)
+ ERR_FAIL_COND(Object::cast_to<AnimationRootNode>(this) != NULL);
Input input;
ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
input.name = p_name;
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 3cc90c2ad6..5c3e123ac3 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -404,7 +404,7 @@ void AnimationTreePlayer::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
ERR_EXPLAIN("AnimationTreePlayer has been deprecated. Use AnimationTree instead.");
- WARN_DEPRECATED
+ WARN_DEPRECATED;
if (!processing) {
//make sure that a previous process state was not saved
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index e8692d56d2..6463ee5ad5 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -159,9 +159,7 @@ void GraphNode::_resort() {
fit_child_in_rect(c, r);
cache_y.push_back(vofs + size.y * 0.5);
- if (vofs > 0)
- vofs += sep;
- vofs += size.y;
+ vofs += size.y + sep;
}
update();
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 406c8e4f48..91b76839d7 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -749,9 +749,21 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
search_string = "";
}
- search_string += String::chr(k->get_unicode());
- for (int i = 0; i < items.size(); i++) {
- if (items[i].text.begins_with(search_string)) {
+ if (String::chr(k->get_unicode()) != search_string)
+ search_string += String::chr(k->get_unicode());
+
+ for (int i = current + 1; i <= items.size(); i++) {
+ if (i == items.size()) {
+ if (current == 0)
+ break;
+ else
+ i = 0;
+ }
+
+ if (i == current)
+ break;
+
+ if (items[i].text.findn(search_string) == 0) {
set_current(i);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
@@ -1248,7 +1260,7 @@ int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Rect2 rc = items[i].rect_cache;
if (i % current_columns == current_columns - 1) {
- rc.size.width = get_size().width; //not right but works
+ rc.size.width = get_size().width - rc.position.x; //make sure you can still select the last item when clicking past the column
}
if (rc.has_point(pos)) {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 1f778bc516..da6bff8ab8 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -44,7 +44,7 @@
static bool _is_text_char(CharType c) {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+ return !is_symbol(c);
}
void LineEdit::_gui_input(Ref<InputEvent> p_event) {
@@ -539,7 +539,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (handled) {
accept_event();
- } else if (!k->get_alt() && !k->get_command()) {
+ } else if (!k->get_command()) {
if (k->get_unicode() >= 32 && k->get_scancode() != KEY_DELETE) {
if (editable) {
@@ -923,7 +923,8 @@ void LineEdit::cut_text() {
void LineEdit::paste_text() {
- String paste_buffer = OS::get_singleton()->get_clipboard();
+ // Strip escape characters like \n and \t as they can't be displayed on LineEdit.
+ String paste_buffer = OS::get_singleton()->get_clipboard().strip_escapes();
if (paste_buffer != "") {
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 694065497a..7027fceb84 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -354,6 +354,7 @@ OptionButton::OptionButton() {
add_child(popup);
popup->set_pass_on_modal_close_click(false);
popup->set_notify_transform(true);
+ popup->set_allow_search(true);
popup->connect("id_pressed", this, "_selected");
popup->connect("id_focused", this, "_focused");
popup->connect("popup_hide", this, "set_pressed", varray(false));
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 984307530d..2cac345dae 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -31,6 +31,7 @@
#include "popup_menu.h"
#include "core/os/input.h"
#include "core/os/keyboard.h"
+#include "core/os/os.h"
#include "core/print_string.h"
#include "core/translation.h"
@@ -380,6 +381,43 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
}
}
+
+ Ref<InputEventKey> k = p_event;
+
+ if (allow_search && k.is_valid() && k->get_unicode()) {
+
+ uint64_t now = OS::get_singleton()->get_ticks_msec();
+ uint64_t diff = now - search_time_msec;
+ uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000));
+ search_time_msec = now;
+
+ if (diff > max_interval) {
+ search_string = "";
+ }
+
+ if (String::chr(k->get_unicode()) != search_string)
+ search_string += String::chr(k->get_unicode());
+
+ for (int i = mouse_over + 1; i <= items.size(); i++) {
+ if (i == items.size()) {
+ if (mouse_over <= 0)
+ break;
+ else
+ i = 0;
+ }
+
+ if (i == mouse_over)
+ break;
+
+ if (items[i].text.findn(search_string) == 0) {
+ mouse_over = i;
+ emit_signal("id_focused", i);
+ update();
+ accept_event();
+ break;
+ }
+ }
+ }
}
bool PopupMenu::has_point(const Point2 &p_point) const {
@@ -1289,6 +1327,16 @@ float PopupMenu::get_submenu_popup_delay() const {
return submenu_timer->get_wait_time();
}
+void PopupMenu::set_allow_search(bool p_allow) {
+
+ allow_search = p_allow;
+}
+
+bool PopupMenu::get_allow_search() const {
+
+ return allow_search;
+}
+
void PopupMenu::set_hide_on_window_lose_focus(bool p_enabled) {
hide_on_window_lose_focus = p_enabled;
@@ -1407,6 +1455,9 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_on_window_lose_focus", "enable"), &PopupMenu::set_hide_on_window_lose_focus);
ClassDB::bind_method(D_METHOD("is_hide_on_window_lose_focus"), &PopupMenu::is_hide_on_window_lose_focus);
+ ClassDB::bind_method(D_METHOD("set_allow_search", "allow"), &PopupMenu::set_allow_search);
+ ClassDB::bind_method(D_METHOD("get_allow_search"), &PopupMenu::get_allow_search);
+
ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
@@ -1414,6 +1465,7 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "submenu_popup_delay"), "set_submenu_popup_delay", "get_submenu_popup_delay");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "id")));
@@ -1435,6 +1487,10 @@ PopupMenu::PopupMenu() {
initial_button_mask = 0;
during_grabbed_click = false;
+ allow_search = false;
+ search_time_msec = 0;
+ search_string = "";
+
set_focus_mode(FOCUS_ALL);
set_as_toplevel(true);
set_hide_on_item_selection(true);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 687006d58d..babdd21281 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -112,6 +112,10 @@ class PopupMenu : public Popup {
void _ref_shortcut(Ref<ShortCut> p_sc);
void _unref_shortcut(Ref<ShortCut> p_sc);
+ bool allow_search;
+ uint64_t search_time_msec;
+ String search_string;
+
protected:
virtual bool has_point(const Point2 &p_point) const;
@@ -206,6 +210,9 @@ public:
void set_submenu_popup_delay(float p_time);
float get_submenu_popup_delay() const;
+ void set_allow_search(bool p_allow);
+ bool get_allow_search() const;
+
virtual void popup(const Rect2 &p_bounds = Rect2());
void set_hide_on_window_lose_focus(bool p_enabled);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index da452e3f10..c6b6d29384 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -592,7 +592,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
//assign actual widths
for (int i = 0; i < table->columns.size(); i++) {
table->columns.write[i].width = table->columns[i].min_width;
- if (table->columns[i].expand)
+ if (table->columns[i].expand && total_ratio > 0)
table->columns.write[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
table->total_width += table->columns[i].width + hseparation;
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 3117d8c59f..6b40ecfc6b 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -50,7 +50,7 @@ inline bool _is_symbol(CharType c) {
static bool _is_text_char(CharType c) {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+ return !is_symbol(c);
}
static bool _is_whitespace(CharType c) {
@@ -4682,6 +4682,8 @@ bool TextEdit::has_keyword_color(String p_keyword) const {
}
Color TextEdit::get_keyword_color(String p_keyword) const {
+
+ ERR_FAIL_COND_V(!keywords.has(p_keyword), Color());
return keywords[p_keyword];
}
@@ -6342,14 +6344,14 @@ int TextEdit::get_info_gutter_width() const {
return info_gutter_width;
}
-void TextEdit::set_hiding_enabled(int p_enabled) {
+void TextEdit::set_hiding_enabled(bool p_enabled) {
if (!p_enabled)
unhide_all_lines();
hiding_enabled = p_enabled;
update();
}
-int TextEdit::is_hiding_enabled() const {
+bool TextEdit::is_hiding_enabled() const {
return hiding_enabled;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 68e590f1e6..0c26602d2b 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -697,8 +697,8 @@ public:
void set_info_gutter_width(int p_gutter_width);
int get_info_gutter_width() const;
- void set_hiding_enabled(int p_enabled);
- int is_hiding_enabled() const;
+ void set_hiding_enabled(bool p_enabled);
+ bool is_hiding_enabled() const;
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index e5313061da..451241af40 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -318,7 +318,7 @@ void TreeItem::set_custom_draw(int p_column, Object *p_object, const StringName
void TreeItem::set_collapsed(bool p_collapsed) {
- if (collapsed == p_collapsed)
+ if (collapsed == p_collapsed || !tree)
return;
collapsed = p_collapsed;
TreeItem *ci = tree->selected_item;
@@ -344,8 +344,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
}
_changed_notify();
- if (tree)
- tree->emit_signal("item_collapsed", this);
+ tree->emit_signal("item_collapsed", this);
}
bool TreeItem::is_collapsed() {
@@ -389,7 +388,7 @@ TreeItem *TreeItem::get_children() {
return children;
}
-TreeItem *TreeItem::get_prev_visible() {
+TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
TreeItem *current = this;
@@ -398,8 +397,20 @@ TreeItem *TreeItem::get_prev_visible() {
if (!prev) {
current = current->parent;
- if (!current || (current == tree->root && tree->hide_root))
+ if (current == tree->root && tree->hide_root) {
return NULL;
+ } else if (!current) {
+ if (p_wrap) {
+ current = this;
+ TreeItem *temp = this->get_next_visible();
+ while (temp) {
+ current = temp;
+ temp = temp->get_next_visible();
+ }
+ } else {
+ return NULL;
+ }
+ }
} else {
current = prev;
@@ -415,7 +426,7 @@ TreeItem *TreeItem::get_prev_visible() {
return current;
}
-TreeItem *TreeItem::get_next_visible() {
+TreeItem *TreeItem::get_next_visible(bool p_wrap) {
TreeItem *current = this;
@@ -433,10 +444,14 @@ TreeItem *TreeItem::get_next_visible() {
current = current->parent;
}
- if (current == NULL)
- return NULL;
- else
+ if (!current) {
+ if (p_wrap)
+ return tree->root;
+ else
+ return NULL;
+ } else {
current = current->next;
+ }
}
return current;
@@ -740,8 +755,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent);
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
- ClassDB::bind_method(D_METHOD("get_next_visible"), &TreeItem::get_next_visible);
- ClassDB::bind_method(D_METHOD("get_prev_visible"), &TreeItem::get_prev_visible);
+ ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
@@ -3491,6 +3506,7 @@ void Tree::scroll_to_item(TreeItem *p_item) {
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
+ TreeItem *from = p_at;
while (p_at) {
for (int i = 0; i < columns.size(); i++) {
@@ -3502,9 +3518,12 @@ TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_c
}
if (p_backwards)
- p_at = p_at->get_prev_visible();
+ p_at = p_at->get_prev_visible(true);
else
- p_at = p_at->get_next_visible();
+ p_at = p_at->get_next_visible(true);
+
+ if ((p_at) == from)
+ break;
}
return NULL;
@@ -3512,10 +3531,14 @@ TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_c
TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_selectable) {
- if (!root)
+ TreeItem *from = get_selected();
+
+ if (!from)
+ from = root;
+ if (!from)
return NULL;
- return _search_item_text(root, p_find, r_col, p_selectable);
+ return _search_item_text(from->get_next_visible(true), p_find, r_col, p_selectable);
}
void Tree::_do_incr_search(const String &p_add) {
@@ -3524,7 +3547,7 @@ void Tree::_do_incr_search(const String &p_add) {
uint64_t diff = time - last_keypress;
if (diff > uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000)))
incr_search = p_add;
- else
+ else if (incr_search != p_add)
incr_search += p_add;
last_keypress = time;
@@ -3697,6 +3720,10 @@ String Tree::get_tooltip(const Point2 &p_pos) const {
const TreeItem::Cell &c = it->cells[col];
int col_width = get_column_width(col);
+
+ for (int i = 0; i < col; i++)
+ pos.x -= get_column_width(i);
+
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture> b = c.buttons[j].texture;
Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 26d64baafb..45d451eb72 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -238,8 +238,8 @@ public:
TreeItem *get_parent();
TreeItem *get_children();
- TreeItem *get_prev_visible();
- TreeItem *get_next_visible();
+ TreeItem *get_prev_visible(bool p_wrap = false);
+ TreeItem *get_next_visible(bool p_wrap = false);
void remove_child(TreeItem *p_item);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 2f23c11748..ee23b24b3c 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1165,7 +1165,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
ERR_FAIL_NULL(p_child);
if (p_child == this) {
- ERR_EXPLAIN("Can't add child '" + p_child->get_name() + "' to itself.")
+ ERR_EXPLAIN("Can't add child '" + p_child->get_name() + "' to itself.");
ERR_FAIL_COND(p_child == this); // adding to itself!
}
@@ -1199,7 +1199,7 @@ void Node::add_child_below_node(Node *p_node, Node *p_child, bool p_legible_uniq
if (is_a_parent_of(p_node)) {
move_child(p_child, p_node->get_position_in_parent() + 1);
} else {
- WARN_PRINTS("Cannot move under node " + p_node->get_name() + " as " + p_child->get_name() + " does not share a parent.")
+ WARN_PRINTS("Cannot move under node " + p_node->get_name() + " as " + p_child->get_name() + " does not share a parent.");
}
}
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 65cda73a23..7f0cebd492 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1244,7 +1244,7 @@ void SceneTree::_update_root_rect() {
root->update_canvas_items(); //force them to update just in case
if (use_font_oversampling) {
- WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'.")
+ WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'.");
}
} break;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index b5e5022e63..c02873cdeb 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -886,7 +886,7 @@ void Viewport::_camera_set(Camera *p_camera) {
if (camera == p_camera)
return;
- if (camera && find_world().is_valid()) {
+ if (camera) {
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
}
camera = p_camera;
@@ -895,7 +895,7 @@ void Viewport::_camera_set(Camera *p_camera) {
else
VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
- if (camera && find_world().is_valid()) {
+ if (camera) {
camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
}
@@ -914,9 +914,7 @@ void Viewport::_camera_remove(Camera *p_camera) {
cameras.erase(p_camera);
if (camera == p_camera) {
- if (camera && find_world().is_valid()) {
- camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
- }
+ camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
camera = NULL;
}
}
@@ -1013,7 +1011,7 @@ void Viewport::_propagate_enter_world(Node *p_node) {
Viewport *v = Object::cast_to<Viewport>(p_node);
if (v) {
- if (v->world.is_valid())
+ if (v->world.is_valid() || v->own_world.is_valid())
return;
}
}
@@ -1050,7 +1048,7 @@ void Viewport::_propagate_exit_world(Node *p_node) {
Viewport *v = Object::cast_to<Viewport>(p_node);
if (v) {
- if (v->world.is_valid())
+ if (v->world.is_valid() || v->own_world.is_valid())
return;
}
}
@@ -1070,23 +1068,11 @@ void Viewport::set_world(const Ref<World> &p_world) {
if (is_inside_tree())
_propagate_exit_world(this);
-#ifndef _3D_DISABLED
- if (find_world().is_valid() && camera)
- camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
-#endif
-
world = p_world;
if (is_inside_tree())
_propagate_enter_world(this);
-#ifndef _3D_DISABLED
- if (find_world().is_valid() && camera)
- camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
-#endif
-
- //propagate exit
-
if (is_inside_tree()) {
VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
}
@@ -2722,11 +2708,6 @@ void Viewport::set_use_own_world(bool p_world) {
if (is_inside_tree())
_propagate_exit_world(this);
-#ifndef _3D_DISABLED
- if (find_world().is_valid() && camera)
- camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
-#endif
-
if (!p_world)
own_world = Ref<World>();
else
@@ -2735,13 +2716,6 @@ void Viewport::set_use_own_world(bool p_world) {
if (is_inside_tree())
_propagate_enter_world(this);
-#ifndef _3D_DISABLED
- if (find_world().is_valid() && camera)
- camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
-#endif
-
- //propagate exit
-
if (is_inside_tree()) {
VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
}
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 5440c88fa8..5e4cf9c2ee 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -48,6 +48,7 @@
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/line_2d.h"
#include "scene/2d/mesh_instance_2d.h"
+#include "scene/2d/multimesh_instance_2d.h"
#include "scene/2d/navigation_2d.h"
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
@@ -144,7 +145,6 @@
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/mesh_data_tool.h"
-#include "scene/resources/mesh_library.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/particles_material.h"
#include "scene/resources/physics_material.h"
@@ -209,6 +209,7 @@
#include "scene/3d/visibility_notifier.h"
#include "scene/animation/skeleton_ik.h"
#include "scene/resources/environment.h"
+#include "scene/resources/mesh_library.h"
#endif
static Ref<ResourceFormatSaverText> resource_saver_text;
@@ -468,7 +469,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
#endif
- ClassDB::register_class<MeshLibrary>();
+
AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel())));
ClassDB::register_class<Shader>();
@@ -543,6 +544,7 @@ void register_scene_types() {
ClassDB::register_class<Position2D>();
ClassDB::register_class<Line2D>();
ClassDB::register_class<MeshInstance2D>();
+ ClassDB::register_class<MultiMeshInstance2D>();
ClassDB::register_virtual_class<CollisionObject2D>();
ClassDB::register_virtual_class<PhysicsBody2D>();
ClassDB::register_class<StaticBody2D>();
@@ -587,9 +589,13 @@ void register_scene_types() {
SceneTree::add_idle_callback(ParticlesMaterial::flush_changes);
ParticlesMaterial::init_shaders();
-#ifndef _3D_DISABLED
ClassDB::register_virtual_class<Mesh>();
ClassDB::register_class<ArrayMesh>();
+ ClassDB::register_class<MultiMesh>();
+ ClassDB::register_class<SurfaceTool>();
+ ClassDB::register_class<MeshDataTool>();
+
+#ifndef _3D_DISABLED
ClassDB::register_virtual_class<PrimitiveMesh>();
ClassDB::register_class<CapsuleMesh>();
ClassDB::register_class<CubeMesh>();
@@ -603,7 +609,6 @@ void register_scene_types() {
SceneTree::add_idle_callback(SpatialMaterial::flush_changes);
SpatialMaterial::init_shaders();
- ClassDB::register_class<MultiMesh>();
ClassDB::register_class<MeshLibrary>();
OS::get_singleton()->yield(); //may take time to init
@@ -619,9 +624,6 @@ void register_scene_types() {
ClassDB::register_class<ConvexPolygonShape>();
ClassDB::register_class<ConcavePolygonShape>();
- ClassDB::register_class<SurfaceTool>();
- ClassDB::register_class<MeshDataTool>();
-
OS::get_singleton()->yield(); //may take time to init
ClassDB::register_class<SpatialVelocityTracker>();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 6ab78326b2..e4da659b0d 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -93,7 +93,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
TransformTrack *tt = static_cast<TransformTrack *>(tracks[track]);
PoolVector<float> values = p_value;
int vcount = values.size();
- ERR_FAIL_COND_V(vcount % 12, false); // shuld be multiple of 11
+ ERR_FAIL_COND_V(vcount % 12, false); // should be multiple of 11
PoolVector<float>::Read r = values.read();
@@ -1298,6 +1298,78 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const {
ERR_FAIL_V(-1);
}
+void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) {
+
+ ERR_FAIL_INDEX(p_track, tracks.size());
+ Track *t = tracks[p_track];
+
+ switch (t->type) {
+
+ case TYPE_TRANSFORM: {
+
+ TransformTrack *tt = static_cast<TransformTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
+ TKey<TransformKey> key = tt->transforms[p_key_idx];
+ key.time = p_time;
+ tt->transforms.remove(p_key_idx);
+ _insert(p_time, tt->transforms, key);
+ return;
+ }
+ case TYPE_VALUE: {
+
+ ValueTrack *vt = static_cast<ValueTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, vt->values.size());
+ TKey<Variant> key = vt->values[p_key_idx];
+ key.time = p_time;
+ vt->values.remove(p_key_idx);
+ _insert(p_time, vt->values, key);
+ return;
+ }
+ case TYPE_METHOD: {
+
+ MethodTrack *mt = static_cast<MethodTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, mt->methods.size());
+ MethodKey key = mt->methods[p_key_idx];
+ key.time = p_time;
+ mt->methods.remove(p_key_idx);
+ _insert(p_time, mt->methods, key);
+ return;
+ }
+ case TYPE_BEZIER: {
+
+ BezierTrack *bt = static_cast<BezierTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, bt->values.size());
+ TKey<BezierKey> key = bt->values[p_key_idx];
+ key.time = p_time;
+ bt->values.remove(p_key_idx);
+ _insert(p_time, bt->values, key);
+ return;
+ }
+ case TYPE_AUDIO: {
+
+ AudioTrack *at = static_cast<AudioTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, at->values.size());
+ TKey<AudioKey> key = at->values[p_key_idx];
+ key.time = p_time;
+ at->values.remove(p_key_idx);
+ _insert(p_time, at->values, key);
+ return;
+ }
+ case TYPE_ANIMATION: {
+
+ AnimationTrack *at = static_cast<AnimationTrack *>(t);
+ ERR_FAIL_INDEX(p_key_idx, at->values.size());
+ TKey<StringName> key = at->values[p_key_idx];
+ key.time = p_time;
+ at->values.remove(p_key_idx);
+ _insert(p_time, at->values, key);
+ return;
+ }
+ }
+
+ ERR_FAIL();
+}
+
float Animation::track_get_key_transition(int p_track, int p_key_idx) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
@@ -2691,6 +2763,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_remove_key_at_position", "idx", "position"), &Animation::track_remove_key_at_position);
ClassDB::bind_method(D_METHOD("track_set_key_value", "idx", "key", "value"), &Animation::track_set_key_value);
ClassDB::bind_method(D_METHOD("track_set_key_transition", "idx", "key_idx", "transition"), &Animation::track_set_key_transition);
+ ClassDB::bind_method(D_METHOD("track_set_key_time", "idx", "key_idx", "time"), &Animation::track_set_key_time);
ClassDB::bind_method(D_METHOD("track_get_key_transition", "idx", "key_idx"), &Animation::track_get_key_transition);
ClassDB::bind_method(D_METHOD("track_get_key_count", "idx"), &Animation::track_get_key_count);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 36ebaa25d5..59f2ae24c7 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -305,6 +305,7 @@ public:
void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1);
void track_set_key_transition(int p_track, int p_key_idx, float p_transition);
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
+ void track_set_key_time(int p_track, int p_key_idx, float p_time);
int track_find_key(int p_track, float p_time, bool p_exact = false) const;
void track_remove_key(int p_track, int p_idx);
void track_remove_key_at_position(int p_track, float p_pos);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index bdb6c78782..e8359e3dfe 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -582,14 +582,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// GraphNode
- Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png, 6, 24, 6, 5, 16, 24, 16, 5);
- Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png, 6, 24, 6, 5, 16, 24, 16, 5);
- Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png, 6, 24, 6, 5, 16, 24, 16, 5);
- Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png, 6, 24, 6, 5, 16, 24, 16, 5);
+ Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png, 6, 24, 6, 5, 16, 24, 16, 6);
+ Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png, 6, 24, 6, 5, 16, 24, 16, 6);
+ Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png, 6, 24, 6, 5, 16, 24, 16, 6);
+ Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png, 6, 24, 6, 5, 16, 24, 16, 6);
Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png, 4, 4, 4, 4, 6, 4, 4, 4);
Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png, 4, 4, 4, 4, 6, 4, 4, 4);
- Ref<StyleBoxTexture> graph_bpoint = make_stylebox(graph_node_breakpoint_png, 6, 24, 6, 5, 16, 24, 16, 5);
- Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png, 6, 24, 6, 5, 16, 24, 16, 5);
+ Ref<StyleBoxTexture> graph_bpoint = make_stylebox(graph_node_breakpoint_png, 6, 24, 6, 5, 16, 24, 16, 6);
+ Ref<StyleBoxTexture> graph_position = make_stylebox(graph_node_position_png, 6, 24, 6, 5, 16, 24, 16, 6);
//graphsb->set_expand_margin_size(MARGIN_LEFT,10);
//graphsb->set_expand_margin_size(MARGIN_RIGHT,10);
diff --git a/scene/resources/height_map_shape.cpp b/scene/resources/height_map_shape.cpp
index 8cd271dab0..f763700d52 100644
--- a/scene/resources/height_map_shape.cpp
+++ b/scene/resources/height_map_shape.cpp
@@ -85,6 +85,7 @@ void HeightMapShape::_update_shape() {
d["min_height"] = min_height;
d["max_height"] = max_height;
PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
+ Shape::_update_shape();
}
void HeightMapShape::set_map_width(int p_new) {
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 67639858ce..6443b44bb6 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -489,6 +489,7 @@ void Mesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count);
ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays);
ClassDB::bind_method(D_METHOD("surface_get_blend_shape_arrays", "surf_idx"), &Mesh::surface_get_blend_shape_arrays);
+ ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material"), &Mesh::surface_set_material);
ClassDB::bind_method(D_METHOD("surface_get_material", "surf_idx"), &Mesh::surface_get_material);
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
@@ -1305,7 +1306,6 @@ void ArrayMesh::_bind_methods() {
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);
ClassDB::bind_method(D_METHOD("surface_get_primitive_type", "surf_idx"), &ArrayMesh::surface_get_primitive_type);
- ClassDB::bind_method(D_METHOD("surface_set_material", "surf_idx", "material"), &ArrayMesh::surface_set_material);
ClassDB::bind_method(D_METHOD("surface_find_by_name", "name"), &ArrayMesh::surface_find_by_name);
ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name);
ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 1457d283bd..b38791b9a6 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -128,6 +128,7 @@ public:
virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0;
virtual uint32_t surface_get_format(int p_idx) const = 0;
virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) = 0;
virtual Ref<Material> surface_get_material(int p_idx) const = 0;
virtual int get_blend_shape_count() const = 0;
virtual StringName get_blend_shape_name(int p_index) const = 0;
@@ -215,8 +216,8 @@ public:
PrimitiveType surface_get_primitive_type(int p_idx) const;
bool surface_is_alpha_sorting_enabled(int p_idx) const;
- void surface_set_material(int p_idx, const Ref<Material> &p_material);
- Ref<Material> surface_get_material(int p_idx) const;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material);
+ virtual Ref<Material> surface_get_material(int p_idx) const;
int surface_find_by_name(const String &p_name) const;
void surface_set_name(int p_idx, const String &p_name);
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 2c6f30f429..99286668ce 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -92,8 +92,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
if (i > 0) {
- ERR_EXPLAIN(vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name]))
- ERR_FAIL_COND_V(n.parent == -1, NULL)
+ ERR_EXPLAIN(vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name]));
+ ERR_FAIL_COND_V(n.parent == -1, NULL);
NODE_FROM_ID(nparent, n.parent);
#ifdef DEBUG_ENABLED
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index ef67e6ea80..758475b75e 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -1186,6 +1186,7 @@ void ParticlesMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY);
BIND_ENUM_CONSTANT(FLAG_ROTATE_Y);
+ BIND_ENUM_CONSTANT(FLAG_DISABLE_Z);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index db58fe7823..04d13c8869 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -157,6 +157,12 @@ Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
return primitive_type;
}
+void PrimitiveMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
+ ERR_FAIL_INDEX(p_idx, 1);
+
+ set_material(p_material);
+}
+
Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, NULL);
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 88a26801b7..0045a48736 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -72,6 +72,7 @@ public:
virtual Array surface_get_blend_shape_arrays(int p_surface) const;
virtual uint32_t surface_get_format(int p_idx) const;
virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material);
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;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 6e7bb27e74..0921c0dae9 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -1712,15 +1712,15 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
Vector<StringName> groups = state->get_node_groups(i);
String header = "[node";
- header += " name=\"" + String(name) + "\"";
+ header += " name=\"" + String(name).c_escape() + "\"";
if (type != StringName()) {
header += " type=\"" + String(type) + "\"";
}
if (path != NodePath()) {
- header += " parent=\"" + String(path.simplified()) + "\"";
+ header += " parent=\"" + String(path.simplified()).c_escape() + "\"";
}
if (owner != NodePath() && owner != NodePath(".")) {
- header += " owner=\"" + String(owner.simplified()) + "\"";
+ header += " owner=\"" + String(owner.simplified()).c_escape() + "\"";
}
if (index >= 0) {
header += " index=\"" + itos(index) + "\"";
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 92172912c2..503949fd60 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -232,7 +232,7 @@ Image::Format ImageTexture::get_format() const {
#ifndef DISABLE_DEPRECATED
Error ImageTexture::load(const String &p_path) {
- WARN_DEPRECATED
+ WARN_DEPRECATED;
Ref<Image> img;
img.instance();
Error err = img->load(p_path);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 5b5968c10f..d09fac47f0 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -319,6 +319,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/spacing", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/occluder_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/navpoly_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
}
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset"));
@@ -646,6 +647,36 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask,
}
}
+Vector2 TileSet::atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node, const Vector2 &p_tile_location) {
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2());
+ //First try to forward selection to script
+ if (get_script_instance() != NULL) {
+ if (get_script_instance()->has_method("_forward_atlas_subtile_selection")) {
+ Variant ret = get_script_instance()->call("_forward_atlas_subtile_selection", p_id, p_tilemap_node, p_tile_location);
+ if (ret.get_type() == Variant::VECTOR2) {
+ return ret;
+ }
+ }
+ }
+
+ Vector2 coord = tile_get_region(p_id).size / autotile_get_size(p_id);
+
+ List<Vector2> coords;
+ for (int x = 0; x < coord.x; x++) {
+ for (int y = 0; y < coord.y; y++) {
+ for (int i = 0; i < autotile_get_subtile_priority(p_id, Vector2(x, y)); i++) {
+ coords.push_back(Vector2(x, y));
+ }
+ }
+ }
+ if (coords.size() == 0) {
+ return autotile_get_icon_coordinate(p_id);
+ } else {
+ return coords[Math::random(0, (int)coords.size())];
+ }
+}
+
void TileSet::tile_set_name(int p_id, const String &p_name) {
ERR_FAIL_COND(!tile_map.has(p_id));
@@ -1141,6 +1172,7 @@ void TileSet::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
+ BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_atlas_subtile_selection", PropertyInfo(Variant::INT, "atlastile_id"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
BIND_ENUM_CONSTANT(BITMASK_2X2);
BIND_ENUM_CONSTANT(BITMASK_3X3_MINIMAL);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index fb84cee218..5fc22b9fc6 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -195,6 +195,7 @@ public:
uint32_t autotile_get_bitmask(int p_id, Vector2 p_coord);
const Map<Vector2, uint32_t> &autotile_get_bitmask_map(int p_id);
Vector2 autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, const Node *p_tilemap_node = NULL, const Vector2 &p_tile_location = Vector2());
+ Vector2 atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node = NULL, const Vector2 &p_tile_location = Vector2());
void tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape);
Ref<Shape2D> tile_get_shape(int p_id, int p_shape_id) const;
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 9b2e410985..dd595d9ff8 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -297,7 +297,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
if (MAX(0, from_port_type - 2) != (MAX(0, to_port_type - 2))) {
ERR_EXPLAIN("Incompatible port types (scalar/vec/bool with transform");
- ERR_FAIL_V(ERR_INVALID_PARAMETER)
+ ERR_FAIL_V(ERR_INVALID_PARAMETER);
return ERR_INVALID_PARAMETER;
}
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
index 8e15e9288f..f5ac0afefa 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* audio_effect_spectrum_analyzer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_effect_spectrum_analyzer.h"
#include "servers/audio_server.h"
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h
index 0534426da3..4f4c3c8a58 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.h
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* audio_effect_spectrum_analyzer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_EFFECT_SPECTRUM_ANALYZER_H
#define AUDIO_EFFECT_SPECTRUM_ANALYZER_H
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index f4a66b5643..49af63e82a 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -1,3 +1,33 @@
+/*************************************************************************/
+/* audio_stream_generator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
#include "audio_stream_generator.h"
void AudioStreamGenerator::set_mix_rate(float p_mix_rate) {
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 2082682907..c3490ddaa5 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -1,5 +1,35 @@
-#ifndef AUDIO_STREAM_USER_FED_H
-#define AUDIO_STREAM_USER_FED_H
+/*************************************************************************/
+/* audio_stream_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AUDIO_STREAM_GENERATOR_H
+#define AUDIO_STREAM_GENERATOR_H
#include "core/ring_buffer.h"
#include "servers/audio/audio_stream.h"
@@ -63,4 +93,4 @@ public:
AudioStreamGeneratorPlayback();
};
-#endif // AUDIO_STREAM_USER_FED_H
+#endif // AUDIO_STREAM_GENERATOR_H
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 954b0fa3ea..acdaa6e6df 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -92,7 +92,7 @@ normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vecto
bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
- ERR_FAIL_COND_V(!space, false;)
+ ERR_FAIL_COND_V(!space, false);
rA = A->get_transform().basis_xform(anchor_A);
rB = B ? B->get_transform().basis_xform(anchor_B) : anchor_B;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 732c08fdea..3e1e8f9734 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -26,7 +26,7 @@ comments.
## bullet
- Upstream: https://github.com/bulletphysics/bullet3
-- Version: 2.88
+- Version: git (5ec8339, 2019)
- License: zlib
Files extracted from upstream source:
diff --git a/thirdparty/bullet/Bullet3Common/b3Quaternion.h b/thirdparty/bullet/Bullet3Common/b3Quaternion.h
index 9bd5ff7d90..4fdd72dcc4 100644
--- a/thirdparty/bullet/Bullet3Common/b3Quaternion.h
+++ b/thirdparty/bullet/Bullet3Common/b3Quaternion.h
@@ -92,8 +92,11 @@ public:
/**@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)
+ void setRotation(const b3Vector3& axis1, const b3Scalar& _angle)
{
+ b3Vector3 axis = axis1;
+ axis.safeNormalize();
+
b3Scalar d = axis.length();
b3Assert(d != b3Scalar(0.0));
if (d < B3_EPSILON)
diff --git a/thirdparty/bullet/Bullet3Common/b3Vector3.h b/thirdparty/bullet/Bullet3Common/b3Vector3.h
index 56e6c13311..a70d68d6e1 100644
--- a/thirdparty/bullet/Bullet3Common/b3Vector3.h
+++ b/thirdparty/bullet/Bullet3Common/b3Vector3.h
@@ -36,7 +36,7 @@ subject to the following restrictions:
#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_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#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))
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
index 37156fd589..166cb04c0b 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -37,7 +37,7 @@ static DBVT_INLINE int indexof(const btDbvtNode* node)
static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume& a,
const btDbvtVolume& b)
{
-#if (DBVT_MERGE_IMPL == DBVT_IMPL_SSE)
+#ifdef BT_USE_SSE
ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
btDbvtVolume* ptr = (btDbvtVolume*)locals;
btDbvtVolume& res = *ptr;
@@ -80,6 +80,7 @@ static DBVT_INLINE void deletenode(btDbvt* pdbvt,
static void recursedeletenode(btDbvt* pdbvt,
btDbvtNode* node)
{
+ if (node == 0) return;
if (!node->isleaf())
{
recursedeletenode(pdbvt, node->childs[0]);
@@ -298,7 +299,7 @@ static int split(btDbvtNode** leaves,
static btDbvtVolume bounds(btDbvtNode** leaves,
int count)
{
-#if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
+#ifdef BT_USE_SSE
ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
btDbvtVolume* ptr = (btDbvtVolume*)locals;
btDbvtVolume& volume = *ptr;
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
index 166cf771fe..b7fe0a1f34 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -123,11 +123,11 @@ protected:
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
{
+ m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
+
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
- m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
-
//validate();
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
index 98a02d0c45..b48d9301d7 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -43,6 +43,7 @@ btCollisionObject::btCollisionObject()
m_userObjectPointer(0),
m_userIndex2(-1),
m_userIndex(-1),
+ m_userIndex3(-1),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
index 56b3d89e56..85dc488c8c 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -101,6 +101,8 @@ protected:
int m_userIndex;
+ int m_userIndex3;
+
///time of impact calculation
btScalar m_hitFraction;
@@ -526,6 +528,11 @@ public:
return m_userIndex2;
}
+ int getUserIndex3() const
+ {
+ return m_userIndex3;
+ }
+
///users can point to their objects, userPointer is not used by Bullet
void setUserPointer(void* userPointer)
{
@@ -543,6 +550,11 @@ public:
m_userIndex2 = index;
}
+ void setUserIndex3(int index)
+ {
+ m_userIndex3 = index;
+ }
+
int getUpdateRevisionInternal() const
{
return m_updateRevision;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
index b30ce03164..71184f36ac 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -19,10 +19,10 @@ subject to the following restrictions:
#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/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
@@ -414,7 +414,9 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, co
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
}
- else if (collisionShape->getShapeType()==TERRAIN_SHAPE_PROXYTYPE)
+ else if (((resultCallback.m_flags&btTriangleRaycastCallback::kF_DisableHeightfieldAccelerator)==0)
+ && collisionShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE
+ )
{
///optimized version for btHeightfieldTerrainShape
btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
@@ -422,7 +424,7 @@ void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, co
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),heightField,colObjWorldTransform);
+ BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), heightField, colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
index 65b669e1c0..9694f4ddb3 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
@@ -27,7 +27,7 @@ btConvexPolyhedron::~btConvexPolyhedron()
{
}
-inline bool IsAlmostZero(const btVector3& v)
+inline bool IsAlmostZero1(const btVector3& v)
{
if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
return true;
@@ -122,8 +122,8 @@ void btConvexPolyhedron::initialize()
for (int p = 0; p < m_uniqueEdges.size(); p++)
{
- if (IsAlmostZero(m_uniqueEdges[p] - edge) ||
- IsAlmostZero(m_uniqueEdges[p] + edge))
+ if (IsAlmostZero1(m_uniqueEdges[p] - edge) ||
+ IsAlmostZero1(m_uniqueEdges[p] + edge))
{
found = true;
break;
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 4adf27e6bb..34ec2d8c45 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -71,9 +71,10 @@ void btHeightfieldTerrainShape::initialize(
m_flipQuadEdges = flipQuadEdges;
m_useDiamondSubdivision = false;
m_useZigzagSubdivision = false;
+ m_flipTriangleWinding = false;
m_upAxis = upAxis;
m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
- m_vboundsGrid = NULL;
+
m_vboundsChunkSize = 0;
m_vboundsGridWidth = 0;
m_vboundsGridLength = 0;
@@ -335,30 +336,37 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
for (int x = startX; x < endX; x++)
{
btVector3 vertices[3];
+ int indices[3] = { 0, 1, 2 };
+ if (m_flipTriangleWinding)
+ {
+ indices[0] = 2;
+ indices[2] = 0;
+ }
+
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]);
+ getVertex(x, j, vertices[indices[0]]);
+ getVertex(x, j + 1, vertices[indices[1]]);
+ getVertex(x + 1, j + 1, vertices[indices[2]]);
callback->processTriangle(vertices, x, j);
//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]);
+ getVertex(x + 1, j + 1, vertices[indices[1]]);
+ getVertex(x + 1, j, vertices[indices[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]);
+ getVertex(x, j, vertices[indices[0]]);
+ getVertex(x, j + 1, vertices[indices[1]]);
+ getVertex(x + 1, j, vertices[indices[2]]);
callback->processTriangle(vertices, x, j);
//second triangle
- getVertex(x + 1, j, vertices[0]);
+ getVertex(x + 1, j, vertices[indices[0]]);
//getVertex(x,j+1,vertices[1]);
- getVertex(x + 1, j + 1, vertices[2]);
+ getVertex(x + 1, j + 1, vertices[indices[2]]);
callback->processTriangle(vertices, x, j);
}
}
@@ -381,39 +389,42 @@ const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
return m_localScaling;
}
-
-
-struct GridRaycastState
+namespace
{
- int x; // Next quad coords
- int z;
- int prev_x; // Previous quad coords
- int prev_z;
- btScalar param; // Exit param for previous quad
- btScalar prevParam; // Enter param for previous quad
- btScalar maxDistanceFlat;
- btScalar maxDistance3d;
-};
-
+ struct GridRaycastState
+ {
+ int x; // Next quad coords
+ int z;
+ int prev_x; // Previous quad coords
+ int prev_z;
+ btScalar param; // Exit param for previous quad
+ btScalar prevParam; // Enter param for previous quad
+ btScalar maxDistanceFlat;
+ btScalar maxDistance3d;
+ };
+}
// TODO Does it really need to take 3D vectors?
/// Iterates through a virtual 2D grid of unit-sized square cells,
/// and executes an action on each cell intersecting the given segment, ordered from begin to end.
/// Initially inspired by http://www.cse.yorku.ca/~amana/research/grid.pdf
template <typename Action_T>
-void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector3 &endPos)
+void gridRaycast(Action_T& quadAction, const btVector3& beginPos, const btVector3& endPos, int indices[3])
{
GridRaycastState rs;
rs.maxDistance3d = beginPos.distance(endPos);
if (rs.maxDistance3d < 0.0001)
+ {
// Consider the ray is too small to hit anything
return;
+ }
+
- btScalar rayDirectionFlatX = endPos[0] - beginPos[0];
- btScalar rayDirectionFlatZ = endPos[2] - beginPos[2];
+ btScalar rayDirectionFlatX = endPos[indices[0]] - beginPos[indices[0]];
+ btScalar rayDirectionFlatZ = endPos[indices[2]] - beginPos[indices[2]];
rs.maxDistanceFlat = btSqrt(rayDirectionFlatX * rayDirectionFlatX + rayDirectionFlatZ * rayDirectionFlatZ);
- if(rs.maxDistanceFlat < 0.0001)
+ if (rs.maxDistanceFlat < 0.0001)
{
// Consider the ray vertical
rayDirectionFlatX = 0;
@@ -433,34 +444,46 @@ void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector
const btScalar paramDeltaZ = ziStep != 0 ? 1.f / btFabs(rayDirectionFlatZ) : infinite;
// pos = param * dir
- btScalar paramCrossX; // At which value of `param` we will cross a x-axis lane?
- btScalar paramCrossZ; // At which value of `param` we will cross a z-axis lane?
+ btScalar paramCrossX; // At which value of `param` we will cross a x-axis lane?
+ btScalar paramCrossZ; // At which value of `param` we will cross a z-axis lane?
// paramCrossX and paramCrossZ are initialized as being the first cross
// X initialization
if (xiStep != 0)
{
if (xiStep == 1)
- paramCrossX = (ceil(beginPos[0]) - beginPos[0]) * paramDeltaX;
+ {
+ paramCrossX = (ceil(beginPos[indices[0]]) - beginPos[indices[0]]) * paramDeltaX;
+ }
else
- paramCrossX = (beginPos[0] - floor(beginPos[0])) * paramDeltaX;
+ {
+ paramCrossX = (beginPos[indices[0]] - floor(beginPos[indices[0]])) * paramDeltaX;
+ }
}
else
- paramCrossX = infinite; // Will never cross on X
+ {
+ paramCrossX = infinite; // Will never cross on X
+ }
// Z initialization
if (ziStep != 0)
{
if (ziStep == 1)
- paramCrossZ = (ceil(beginPos[2]) - beginPos[2]) * paramDeltaZ;
+ {
+ paramCrossZ = (ceil(beginPos[indices[2]]) - beginPos[indices[2]]) * paramDeltaZ;
+ }
else
- paramCrossZ = (beginPos[2] - floor(beginPos[2])) * paramDeltaZ;
+ {
+ paramCrossZ = (beginPos[indices[2]] - floor(beginPos[indices[2]])) * paramDeltaZ;
+ }
}
else
- paramCrossZ = infinite; // Will never cross on Z
+ {
+ paramCrossZ = infinite; // Will never cross on Z
+ }
- rs.x = static_cast<int>(floor(beginPos[0]));
- rs.z = static_cast<int>(floor(beginPos[2]));
+ rs.x = static_cast<int>(floor(beginPos[indices[0]]));
+ rs.z = static_cast<int>(floor(beginPos[indices[2]]));
// Workaround cases where the ray starts at an integer position
if (paramCrossX == 0.0)
@@ -469,7 +492,9 @@ void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector
// If going backwards, we should ignore the position we would get by the above flooring,
// because the ray is not heading in that direction
if (xiStep == -1)
+ {
rs.x -= 1;
+ }
}
if (paramCrossZ == 0.0)
@@ -513,14 +538,15 @@ void gridRaycast(Action_T &quadAction, const btVector3 &beginPos, const btVector
break;
}
else
+ {
quadAction(rs);
+ }
}
}
-
struct ProcessTrianglesAction
{
- const btHeightfieldTerrainShape *shape;
+ const btHeightfieldTerrainShape* shape;
bool flipQuadEdges;
bool useDiamondSubdivision;
int width;
@@ -529,11 +555,15 @@ struct ProcessTrianglesAction
void exec(int x, int z) const
{
- if(x < 0 || z < 0 || x >= width || z >= length)
+ if (x < 0 || z < 0 || x >= width || z >= length)
+ {
return;
+ }
btVector3 vertices[3];
+ // TODO Since this is for raycasts, we could greatly benefit from an early exit on the first hit
+
// Check quad
if (flipQuadEdges || (useDiamondSubdivision && (((z + x) & 1) > 0)))
{
@@ -565,16 +595,15 @@ struct ProcessTrianglesAction
}
}
- void operator ()(const GridRaycastState &bs) const
+ void operator()(const GridRaycastState& bs) const
{
exec(bs.prev_x, bs.prev_z);
}
};
-
struct ProcessVBoundsAction
{
- const btHeightfieldTerrainShape::Range *vbounds;
+ const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& vbounds;
int width;
int length;
int chunkSize;
@@ -583,15 +612,23 @@ struct ProcessVBoundsAction
btVector3 rayEnd;
btVector3 rayDir;
+ int* m_indices;
ProcessTrianglesAction processTriangles;
- void operator ()(const GridRaycastState &rs) const
+ ProcessVBoundsAction(const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& bnd, int* indices)
+ : vbounds(bnd),
+ m_indices(indices)
+ {
+ }
+ void operator()(const GridRaycastState& rs) const
{
int x = rs.prev_x;
int z = rs.prev_z;
- if(x < 0 || z < 0 || x >= width || z >= length)
+ if (x < 0 || z < 0 || x >= width || z >= length)
+ {
return;
+ }
const btHeightfieldTerrainShape::Range chunk = vbounds[x + z * width];
@@ -608,10 +645,14 @@ struct ProcessVBoundsAction
// We did enter the flat projection of the AABB,
// but we have to check if we intersect it on the vertical axis
- if (enterPos[1] > chunk.max && exitPos[1] > chunk.max)
+ if (enterPos[1] > chunk.max && exitPos[m_indices[1]] > chunk.max)
+ {
return;
- if (enterPos[1] < chunk.min && exitPos[1] < chunk.min)
+ }
+ if (enterPos[1] < chunk.min && exitPos[m_indices[1]] < chunk.min)
+ {
return;
+ }
}
else
{
@@ -621,13 +662,12 @@ struct ProcessVBoundsAction
exitPos = rayEnd;
}
- gridRaycast(processTriangles, enterPos, exitPos);
+ gridRaycast(processTriangles, enterPos, exitPos, m_indices);
// Note: it could be possible to have more than one grid at different levels,
// to do this there would be a branch using a pointer to another ProcessVBoundsAction
}
};
-
// TODO How do I interrupt the ray when there is a hit? `callback` does not return any result
/// Performs a raycast using a hierarchical Bresenham algorithm.
/// Does not allocate any memory by itself.
@@ -648,10 +688,16 @@ void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, con
processTriangles.length = m_heightStickLength - 1;
// TODO Transform vectors to account for m_upAxis
- int iBeginX = static_cast<int>(floor(beginPos[0]));
- int iBeginZ = static_cast<int>(floor(beginPos[2]));
- int iEndX = static_cast<int>(floor(endPos[0]));
- int iEndZ = static_cast<int>(floor(endPos[2]));
+ int indices[3] = { 0, 1, 2 };
+ if (m_upAxis == 2)
+ {
+ indices[1] = 2;
+ indices[2] = 1;
+ }
+ int iBeginX = static_cast<int>(floor(beginPos[indices[0]]));
+ int iBeginZ = static_cast<int>(floor(beginPos[indices[2]]));
+ int iEndX = static_cast<int>(floor(endPos[indices[0]]));
+ int iEndZ = static_cast<int>(floor(endPos[indices[2]]));
if (iBeginX == iEndX && iBeginZ == iEndZ)
{
@@ -662,36 +708,36 @@ void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, con
return;
}
- if (m_vboundsGrid == NULL)
+
+
+ if (m_vboundsGrid.size()==0)
{
// Process all quads intersecting the flat projection of the ray
- gridRaycast(processTriangles, beginPos, endPos);
+ gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
}
else
{
btVector3 rayDiff = endPos - beginPos;
- btScalar flatDistance2 = rayDiff[0] * rayDiff[0] + rayDiff[2] * rayDiff[2];
+ btScalar flatDistance2 = rayDiff[indices[0]] * rayDiff[indices[0]] + rayDiff[indices[2]] * rayDiff[indices[2]];
if (flatDistance2 < m_vboundsChunkSize * m_vboundsChunkSize)
{
// Don't use chunks, the ray is too short in the plane
- gridRaycast(processTriangles, beginPos, endPos);
+ gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
}
- ProcessVBoundsAction processVBounds;
+ ProcessVBoundsAction processVBounds(m_vboundsGrid, &indices[0]);
processVBounds.width = m_vboundsGridWidth;
processVBounds.length = m_vboundsGridLength;
- processVBounds.vbounds = m_vboundsGrid;
processVBounds.rayBegin = beginPos;
processVBounds.rayEnd = endPos;
processVBounds.rayDir = rayDiff.normalized();
processVBounds.processTriangles = processTriangles;
processVBounds.chunkSize = m_vboundsChunkSize;
// The ray is long, run raycast on a higher-level grid
- gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize);
+ gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize, indices);
}
}
-
/// Builds a grid data structure storing the min and max heights of the terrain in chunks.
/// if chunkSize is zero, that accelerator is removed.
/// If you modify the heights, you need to rebuild this accelerator.
@@ -708,11 +754,15 @@ void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
int nChunksZ = m_heightStickLength / chunkSize;
if (m_heightStickWidth % chunkSize > 0)
- ++nChunksX; // In case terrain size isn't dividable by chunk size
+ {
+ ++nChunksX; // In case terrain size isn't dividable by chunk size
+ }
if (m_heightStickLength % chunkSize > 0)
+ {
++nChunksZ;
+ }
- if(m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
+ if (m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
{
clearAccelerator();
m_vboundsGridWidth = nChunksX;
@@ -720,13 +770,13 @@ void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
}
if (nChunksX == 0 || nChunksZ == 0)
+ {
return;
+ }
- // TODO What is the recommended way to allocate this?
// This data structure is only reallocated if the required size changed
- if (m_vboundsGrid == NULL)
- m_vboundsGrid = new Range[nChunksX * nChunksZ];
-
+ m_vboundsGrid.resize(nChunksX * nChunksZ);
+
// Compute min and max height for all chunks
for (int cz = 0; cz < nChunksZ; ++cz)
{
@@ -760,19 +810,27 @@ void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
for (int z = z0; z < z0 + chunkSize + 1; ++z)
{
if (z >= m_heightStickLength)
+ {
continue;
+ }
for (int x = x0; x < x0 + chunkSize + 1; ++x)
{
if (x >= m_heightStickWidth)
+ {
continue;
+ }
btScalar height = getRawHeightFieldValue(x, z);
if (height < r.min)
+ {
r.min = height;
+ }
else if (height > r.max)
+ {
r.max = height;
+ }
}
}
@@ -781,15 +839,7 @@ void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
}
}
-
void btHeightfieldTerrainShape::clearAccelerator()
{
- if (m_vboundsGrid)
- {
- // TODO What is the recommended way to deallocate this?
- delete[] m_vboundsGrid;
- m_vboundsGrid = 0;
- }
-}
-
-
+ m_vboundsGrid.clear();
+} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index e23b548cb2..43e1d25e3d 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -17,7 +17,7 @@ subject to the following restrictions:
#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
#include "btConcaveShape.h"
-
+#include "LinearMath/btAlignedObjectArray.h"
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
/**
@@ -73,7 +73,8 @@ ATTRIBUTE_ALIGNED16(class)
btHeightfieldTerrainShape : public btConcaveShape
{
public:
- struct Range {
+ struct Range
+ {
btScalar min;
btScalar max;
};
@@ -102,13 +103,13 @@ protected:
bool m_flipQuadEdges;
bool m_useDiamondSubdivision;
bool m_useZigzagSubdivision;
-
+ bool m_flipTriangleWinding;
int m_upAxis;
btVector3 m_localScaling;
// Accelerator
- Range *m_vboundsGrid;
+ btAlignedObjectArray<Range> m_vboundsGrid;
int m_vboundsGridWidth;
int m_vboundsGridLength;
int m_vboundsChunkSize;
@@ -157,6 +158,10 @@ public:
///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; }
+ void setFlipTriangleWinding(bool flipTriangleWinding)
+ {
+ m_flipTriangleWinding = flipTriangleWinding;
+ }
virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
@@ -166,16 +171,20 @@ public:
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
-
- void getVertex(int x,int y,btVector3& vertex) const;
- void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const;
+ void getVertex(int x, int y, btVector3& vertex) const;
+
+ void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget) const;
- void buildAccelerator(int chunkSize=16);
+ void buildAccelerator(int chunkSize = 16);
void clearAccelerator();
+ int getUpAxis() const
+ {
+ return m_upAxis;
+ }
//debugging
virtual const char* getName() const { return "HEIGHTFIELD"; }
};
-#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
index 54888c6757..8f78c234b4 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
@@ -28,28 +28,7 @@ subject to the following restrictions:
#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;
- }
-};
+#include "gim_pair.h" //for GIM_PAIR
///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
struct GIM_BVH_DATA
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
index 3d8ab9f520..73e3db1010 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
@@ -18,7 +18,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
/*
-Author: Francisco Len Nßjera
+Author: Francisco Leon Najera
Concave-Concave Collision
*/
@@ -590,14 +590,16 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrappe
}
btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
- const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap();
+ const btCollisionObjectWrapper* prevObj;
if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
{
+ prevObj = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&ob0);
}
else
{
+ prevObj = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&ob0);
}
@@ -610,7 +612,15 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrappe
{
shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
}
- m_resultOut->setBody0Wrap(prevObj0);
+
+ if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(prevObj);
+ }
+ else
+ {
+ m_resultOut->setBody1Wrap(prevObj);
+ }
}
shape0->unlockChildShapes();
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
index 5b85e87041..eb33ce05e2 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
@@ -1,5 +1,5 @@
/*! \file btGImpactShape.h
-\author Francisco Len Nßjera
+\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
index 0522007e4f..afc591dac0 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
@@ -37,28 +37,7 @@ email: projectileman@yahoo.com
#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;
- }
-};
+#include "gim_pair.h"
//! A pairset array
class gim_pair_set : public gim_array<GIM_PAIR>
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h
new file mode 100644
index 0000000000..56c185a5dc
--- /dev/null
+++ b/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h
@@ -0,0 +1,28 @@
+#ifndef GIM_PAIR_H
+#define GIM_PAIR_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;
+ }
+};
+
+#endif //GIM_PAIR_H
+
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
index 76f54699c5..77b19be599 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
@@ -23,11 +23,11 @@ class btMinkowskiSumShape;
#include "LinearMath/btIDebugDraw.h"
#ifdef BT_USE_DOUBLE_PRECISION
-#define MAX_ITERATIONS 64
-#define MAX_EPSILON (SIMD_EPSILON * 10)
+#define MAX_CONVEX_CAST_ITERATIONS 64
+#define MAX_CONVEX_CAST_EPSILON (SIMD_EPSILON * 10)
#else
-#define MAX_ITERATIONS 32
-#define MAX_EPSILON btScalar(0.0001)
+#define MAX_CONVEX_CAST_ITERATIONS 32
+#define MAX_CONVEX_CAST_EPSILON btScalar(0.0001)
#endif
///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
@@ -58,8 +58,8 @@ public:
: m_fraction(btScalar(BT_LARGE_FLOAT)),
m_debugDrawer(0),
m_allowedPenetration(btScalar(0)),
- m_subSimplexCastMaxIterations(MAX_ITERATIONS),
- m_subSimplexCastEpsilon(MAX_EPSILON)
+ m_subSimplexCastMaxIterations(MAX_CONVEX_CAST_ITERATIONS),
+ m_subSimplexCastEpsilon(MAX_CONVEX_CAST_EPSILON)
{
}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
index 803f6e0671..4339b2ea75 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -1,4 +1,4 @@
-/*
+/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
index 2b2dfabec2..2d0df718a2 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
@@ -37,6 +37,7 @@ public:
///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_DisableHeightfieldAccelerator = 1 << 4, //don't use the heightfield raycast accelerator. See https://github.com/bulletphysics/bullet3/pull/2062
kF_Terminator = 0xFFFFFFFF
};
unsigned int m_flags;
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
index b51dfaad3c..2a5efc6495 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
@@ -22,6 +22,8 @@ subject to the following restrictions:
#include <string.h> //for memset
+#include <cmath>
+
const int kNoMerge = -1;
bool btBatchedConstraints::s_debugDrawBatches = false;
@@ -520,7 +522,7 @@ static void writeGrainSizes(btBatchedConstraints* bc)
{
const Range& phase = bc->m_phases[iPhase];
int numBatches = phase.end - phase.begin;
- float grainSize = floor((0.25f * numBatches / float(numThreads)) + 0.0f);
+ float grainSize = std::floor((0.25f * numBatches / float(numThreads)) + 0.0f);
bc->m_phaseGrainSize[iPhase] = btMax(1, int(grainSize));
}
}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
index 10678b2a61..ac046aa6ea 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
@@ -19,6 +19,7 @@ Written by: Marcus Hennix
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btMinMax.h"
+#include <cmath>
#include <new>
//#define CONETWIST_USE_OBSOLETE_SOLVER true
@@ -842,7 +843,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
- swingLimit = sqrt(swingLimit2);
+ swingLimit = std::sqrt(swingLimit2);
}
// test!
@@ -887,7 +888,7 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc
btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
- swingLimit = sqrt(swingLimit2);
+ swingLimit = std::sqrt(swingLimit2);
}
// convert into point in constraint space:
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
index 808433477c..68a4a07a1d 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
@@ -35,6 +35,7 @@ enum btConstraintSolverType
BT_MLCP_SOLVER = 2,
BT_NNCG_SOLVER = 4,
BT_MULTIBODY_SOLVER = 8,
+ BT_BLOCK_SOLVER = 16,
};
class btConstraintSolver
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
index 89f8db8b1a..63d7c98e16 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -64,6 +64,7 @@ struct btContactSolverInfoData
btScalar m_restitutionVelocityThreshold;
bool m_jointFeedbackInWorldSpace;
bool m_jointFeedbackInJointFrame;
+ int m_reportSolverAnalytics;
};
struct btContactSolverInfo : public btContactSolverInfoData
@@ -98,6 +99,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_restitutionVelocityThreshold = 0.2f; //if the relative velocity is below this threshold, there is zero restitution
m_jointFeedbackInWorldSpace = false;
m_jointFeedbackInJointFrame = false;
+ m_reportSolverAnalytics = 0;
}
};
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
index 49c8d9bbf7..9a3b39e6f8 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
@@ -32,7 +32,7 @@ Cons:
/*
2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Le?n
+btGeneric6DofConstraint Refactored by Francisco Leon
email: projectileman@yahoo.com
http://gimpact.sf.net
*/
@@ -40,6 +40,7 @@ http://gimpact.sf.net
#include "btGeneric6DofSpring2Constraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
+#include <cmath>
#include <new>
btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder)
@@ -310,9 +311,9 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
case RO_XYZ:
{
//Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
- //The two planes are non-homologous, so this is a Tait–Bryan angle formalism and not a proper Euler
+ //The two planes are non-homologous, so this is a Tait-Bryan angle formalism and not a proper Euler
//Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
- //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait–Bryan angles)
+ //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait-Bryan angles)
// x' = Nperp = N.cross(axis2)
// y' = N = axis2.cross(axis0)
// z' = z
@@ -845,7 +846,7 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
if (m_rbA.getInvMass() == 0) m = mB; else
if (m_rbB.getInvMass() == 0) m = mA; else
m = mA*mB / (mA + mB);
- btScalar angularfreq = sqrt(ks / m);
+ btScalar angularfreq = btSqrt(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)
@@ -865,7 +866,7 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
// vel + f / m * (rotational ? -1 : 1)
// so in theory this should be set here for m_constraintError
// (with m_constraintError we set a desired velocity for the affected body(es))
- // however in practice any value is fine as long as it is greater then the "proper" velocity,
+ // however in practice any value is fine as long as it is greater than the "proper" velocity,
// because the m_lowerLimit and the m_upperLimit will determinate the strength of the final pulling force
// so it is much simpler (and more robust) just to simply use inf (with the proper sign)
// (Even with our best intent the "new" velocity is only an estimation. If we underestimate
@@ -1085,7 +1086,7 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr
btScalar target = targetOrg + SIMD_PI;
if (1)
{
- btScalar m = target - SIMD_2_PI * floor(target / SIMD_2_PI);
+ btScalar m = target - SIMD_2_PI * std::floor(target / SIMD_2_PI);
// handle boundary cases resulted from floating-point cut off:
{
if (m >= SIMD_2_PI)
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
index bc3ee6d210..00e24364e0 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
@@ -294,7 +294,7 @@ protected:
bool m_hasStaticBody;
int m_flags;
- btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&)
+ btGeneric6DofSpring2Constraint& operator=(const btGeneric6DofSpring2Constraint&)
{
btAssert(0);
return *this;
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
index def3227b43..d3b71e4583 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -394,6 +394,18 @@ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstr
return gResolveSingleConstraintRowLowerLimit_scalar_reference;
}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarSplitPenetrationImpulseGeneric()
+{
+ return gResolveSplitPenetrationImpulse_scalar_reference;
+}
+
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2SplitPenetrationImpulseGeneric()
+{
+ return gResolveSplitPenetrationImpulse_sse2;
+}
+
+
+
#ifdef USE_SIMD
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
{
@@ -421,6 +433,11 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2()
return m_btSeed2;
}
+unsigned long btSequentialImpulseConstraintSolver::btRand2a(unsigned long& seed)
+{
+ seed = (1664525L * seed + 1013904223L) & 0xffffffff;
+ return seed;
+}
//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
int btSequentialImpulseConstraintSolver::btRandInt2(int n)
{
@@ -454,42 +471,44 @@ int btSequentialImpulseConstraintSolver::btRandInt2(int n)
return (int)(r % un);
}
-void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
+int btSequentialImpulseConstraintSolver::btRandInt2a(int n, unsigned long& seed)
{
- 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);
+ // seems good; xor-fold and modulus
+ const unsigned long un = static_cast<unsigned long>(n);
+ unsigned long r = btSequentialImpulseConstraintSolver::btRand2a(seed);
- 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
+ // note: probably more aggressive than it needs to be -- might be
+ // able to get away without one or two of the innermost branches.
+ if (un <= 0x00010000UL)
{
- solverBody->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);
+ 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);
}
-btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
+{
+ btSISolverSingleIterationData::initSolverBody(solverBody, collisionObject, timeStep);
+}
+
+btScalar btSequentialImpulseConstraintSolver::restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
{
//printf("rel_vel =%f\n", rel_vel);
if (btFabs(rel_vel) < velocityThreshold)
@@ -498,6 +517,10 @@ btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel,
btScalar rest = restitution * -rel_vel;
return rest;
}
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+{
+ return btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, restitution, velocityThreshold);
+}
void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
{
@@ -513,13 +536,13 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb
}
}
-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)
+void btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -605,30 +628,47 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
}
}
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+}
+
+btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ btSolverConstraint& solverConstraint = tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
+
btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+ 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)
+
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity, btScalar cfmSlip)
{
btVector3 normalAxis(0, 0, 0);
solverConstraint.m_contactNormal1 = normalAxis;
solverConstraint.m_contactNormal2 = -normalAxis;
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -677,15 +717,250 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSol
}
}
+
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity, btScalar cfmSlip)
+
+{
+ setupTorsionalFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis1, solverBodyIdA, solverBodyIdB,
+ cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation,
+ desiredVelocity, cfmSlip);
+
+}
+
+btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ btSolverConstraint& solverConstraint = tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupTorsionalFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
+
+
btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
return solverConstraint;
}
+int btSISolverSingleIterationData::getOrInitSolverBody(btCollisionObject & body, btScalar timeStep)
+{
+#if BT_THREADSAFE
+ int solverBodyId = -1;
+ bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+ if (isRigidBodyType && !body.isStaticOrKinematicObject())
+ {
+ // dynamic body
+ // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+ solverBodyId = body.getCompanionId();
+ if (solverBodyId < 0)
+ {
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ body.setCompanionId(solverBodyId);
+ }
+ }
+ else if (isRigidBodyType && body.isKinematicObject())
+ {
+ //
+ // NOTE: must test for kinematic before static because some kinematic objects also
+ // identify as "static"
+ //
+ // Kinematic bodies can be in multiple islands at once, so it is a
+ // race condition to write to them, so we use an alternate method
+ // to record the solverBodyId
+ int uniqueId = body.getWorldArrayIndex();
+ const int INVALID_SOLVER_BODY_ID = -1;
+ if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
+ {
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+ }
+ solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+ // if no table entry yet,
+ if (solverBodyId == INVALID_SOLVER_BODY_ID)
+ {
+ // create a table entry for this body
+ solverBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
+ }
+ }
+ else
+ {
+ bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
+ // Incorrectly set collision object flags can degrade performance in various ways.
+ if (!isMultiBodyType)
+ {
+ btAssert(body.isStaticOrKinematicObject());
+ }
+ //it could be a multibody link collider
+ // all fixed bodies (inf mass) get mapped to a single solver id
+ if (m_fixedBodyId < 0)
+ {
+ m_fixedBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody, 0, timeStep);
+ }
+ solverBodyId = m_fixedBodyId;
+ }
+ btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
+ return solverBodyId;
+#else // BT_THREADSAFE
+
+ int solverBodyIdA = -1;
+
+ if (body.getCompanionId() >= 0)
+ {
+ //body has already been converted
+ solverBodyIdA = body.getCompanionId();
+ btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
+ }
+ else
+ {
+ btRigidBody* rb = btRigidBody::upcast(&body);
+ //convert both active and kinematic objects (for their velocity)
+ if (rb && (rb->getInvMass() || rb->isKinematicObject()))
+ {
+ solverBodyIdA = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody, &body, timeStep);
+ body.setCompanionId(solverBodyIdA);
+ }
+ else
+ {
+ if (m_fixedBodyId < 0)
+ {
+ m_fixedBodyId = m_tmpSolverBodyPool.size();
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody, 0, timeStep);
+ }
+ return m_fixedBodyId;
+ // return 0;//assume first one is a fixed solver body
+ }
+ }
+
+ return solverBodyIdA;
+#endif // BT_THREADSAFE
+}
+void btSISolverSingleIterationData::initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep)
+{
+ btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
+
+ solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+ if (rb)
+ {
+ solverBody->m_worldTransform = rb->getWorldTransform();
+ solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
+ solverBody->m_originalBody = rb;
+ solverBody->m_angularFactor = rb->getAngularFactor();
+ solverBody->m_linearFactor = rb->getLinearFactor();
+ solverBody->m_linearVelocity = rb->getLinearVelocity();
+ solverBody->m_angularVelocity = rb->getAngularVelocity();
+ solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
+ solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
+ }
+ else
+ {
+ solverBody->m_worldTransform.setIdentity();
+ solverBody->internalSetInvMass(btVector3(0, 0, 0));
+ solverBody->m_originalBody = 0;
+ solverBody->m_angularFactor.setValue(1, 1, 1);
+ solverBody->m_linearFactor.setValue(1, 1, 1);
+ solverBody->m_linearVelocity.setValue(0, 0, 0);
+ solverBody->m_angularVelocity.setValue(0, 0, 0);
+ solverBody->m_externalForceImpulse.setValue(0, 0, 0);
+ solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
+ }
+}
+
+int btSISolverSingleIterationData::getSolverBody(btCollisionObject& body) const
+{
+#if BT_THREADSAFE
+ int solverBodyId = -1;
+ bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+ if (isRigidBodyType && !body.isStaticOrKinematicObject())
+ {
+ // dynamic body
+ // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+ solverBodyId = body.getCompanionId();
+ btAssert(solverBodyId >= 0);
+ }
+ else if (isRigidBodyType && body.isKinematicObject())
+ {
+ //
+ // NOTE: must test for kinematic before static because some kinematic objects also
+ // identify as "static"
+ //
+ // Kinematic bodies can be in multiple islands at once, so it is a
+ // race condition to write to them, so we use an alternate method
+ // to record the solverBodyId
+ int uniqueId = body.getWorldArrayIndex();
+ const int INVALID_SOLVER_BODY_ID = -1;
+ if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
+ {
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+ }
+ solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+ btAssert(solverBodyId != INVALID_SOLVER_BODY_ID);
+ }
+ else
+ {
+ bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
+ // Incorrectly set collision object flags can degrade performance in various ways.
+ if (!isMultiBodyType)
+ {
+ btAssert(body.isStaticOrKinematicObject());
+ }
+ btAssert(m_fixedBodyId >= 0);
+ solverBodyId = m_fixedBodyId;
+ }
+ btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
+ return solverBodyId;
+#else // BT_THREADSAFE
+ int solverBodyIdA = -1;
+
+ if (body.getCompanionId() >= 0)
+ {
+ //body has already been converted
+ solverBodyIdA = body.getCompanionId();
+ btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
+ }
+ else
+ {
+ btRigidBody* rb = btRigidBody::upcast(&body);
+ //convert both active and kinematic objects (for their velocity)
+ if (rb && (rb->getInvMass() || rb->isKinematicObject()))
+ {
+ btAssert(0);
+ }
+ else
+ {
+ if (m_fixedBodyId < 0)
+ {
+ btAssert(0);
+ }
+ return m_fixedBodyId;
+ // return 0;//assume first one is a fixed solver body
+ }
+ }
+
+ return solverBodyIdA;
+#endif // BT_THREADSAFE
+}
+
int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
{
#if BT_THREADSAFE
@@ -789,17 +1064,20 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
}
#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)
+
+
+void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISolverSingleIterationData& siData,
+ 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];
+ btSolverBody* bodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
btRigidBody* rb0 = bodyA->m_originalBody;
btRigidBody* rb1 = bodyB->m_originalBody;
@@ -906,7 +1184,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
solverConstraint.m_friction = cp.m_combinedFriction;
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ restitution = btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
if (restitution <= btScalar(0.))
{
restitution = 0.f;
@@ -920,7 +1198,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
if (rb0)
bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() , -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
}
else
{
@@ -974,25 +1252,59 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
}
}
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ btScalar& relaxation,
+ const btVector3& rel_pos1, const btVector3& rel_pos2)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations
+ );
+
+
+ setupContactConstraintInternal(siData, solverConstraint,
+ solverBodyIdA, solverBodyIdB,
+ cp, infoGlobal,
+ relaxation,
+ rel_pos1, rel_pos2);
+}
+
+
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
+ btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
{
- btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody* bodyA = &tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &tmpSolverBodyPool[solverBodyIdB];
btRigidBody* rb0 = bodyA->m_originalBody;
btRigidBody* rb1 = bodyB->m_originalBody;
{
- btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+ btSolverConstraint& frictionConstraint1 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass() , frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
+ bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass(), frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass() , -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse);
+ bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse);
}
else
{
@@ -1002,7 +1314,7 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverC
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
+ btSolverConstraint& frictionConstraint2 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
@@ -1018,21 +1330,31 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverC
}
}
-void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+{
+ setFrictionConstraintImpulseInternal(m_tmpSolverBodyPool, m_tmpSolverContactFrictionConstraintPool,
+ solverConstraint,
+ solverBodyIdA, solverBodyIdB,
+ cp, infoGlobal);
+
+}
+void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
{
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);
+ int solverBodyIdA = siData.getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = siData.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];
+ btSolverBody* solverBodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
///avoid collision response between two static objects
if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
@@ -1049,8 +1371,8 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
btVector3 rel_pos2;
btScalar relaxation;
- int frictionIndex = m_tmpSolverContactConstraintPool.size();
- btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+ int frictionIndex = siData.m_tmpSolverContactConstraintPool.size();
+ btSolverConstraint& solverConstraint = siData.m_tmpSolverContactConstraintPool.expandNonInitializing();
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -1071,16 +1393,20 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
btVector3 vel = vel1 - vel2;
btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+ setupContactConstraintInternal(siData, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
/////setup the friction constraints
- solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+ solverConstraint.m_frictionIndex = siData.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);
+
+ btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
+ siData.m_tmpSolverContactRollingFrictionConstraintPool,
+ cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+
btVector3 axis0, axis1;
btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
axis0.normalize();
@@ -1091,11 +1417,17 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
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);
+ {
+ btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
+ siData.m_tmpSolverContactRollingFrictionConstraintPool, 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);
+ {
+ btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
+ siData.m_tmpSolverContactRollingFrictionConstraintPool, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+ }
}
}
@@ -1124,7 +1456,8 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
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);
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
@@ -1132,7 +1465,8 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
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);
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
}
else
@@ -1141,13 +1475,15 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
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);
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ 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);
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ 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))
@@ -1158,16 +1494,44 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
}
else
{
- addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
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);
+ {
+ btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+ }
}
- setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+ btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(
+ siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
+ solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
}
}
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ btSequentialImpulseConstraintSolver::convertContactInternal(siData, manifold, infoGlobal);
+}
+
void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
int i;
@@ -1181,22 +1545,24 @@ void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold**
}
}
-void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
+ int& maxOverrideNumSolverIterations,
+ btSolverConstraint* currentConstraintRow,
+ btTypedConstraint* constraint,
+ const btTypedConstraint::btConstraintInfo1& info1,
+ int solverBodyIdA,
+ int solverBodyIdB,
+ const btContactSolverInfo& infoGlobal)
{
const btRigidBody& rbA = constraint->getRigidBodyA();
const btRigidBody& rbB = constraint->getRigidBodyB();
- const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+ const btSolverBody* bodyAPtr = &tmpSolverBodyPool[solverBodyIdA];
+ const btSolverBody* bodyBPtr = &tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
- m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+ if (overrideNumSolverIterations > maxOverrideNumSolverIterations)
+ maxOverrideNumSolverIterations = overrideNumSolverIterations;
for (int j = 0; j < info1.m_numConstraintRows; j++)
{
@@ -1236,7 +1602,7 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
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
+ ///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;
@@ -1313,7 +1679,16 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre
}
}
-void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
+ btTypedConstraint* constraint,
+ const btTypedConstraint::btConstraintInfo1& info1,
+ int solverBodyIdA,
+ int solverBodyIdB,
+ const btContactSolverInfo& infoGlobal)
+{
+}
+
+void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertJoints");
for (int j = 0; j < numConstraints; j++)
@@ -1325,11 +1700,11 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons
int totalNumRows = 0;
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+ siData.m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
for (int i = 0; i < numConstraints; i++)
{
- btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
btJointFeedback* fb = constraints[i]->getJointFeedback();
if (fb)
{
@@ -1350,34 +1725,58 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons
}
totalNumRows += info1.m_numConstraintRows;
}
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+ siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
int currentRow = 0;
for (int i = 0; i < numConstraints; i++)
{
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ const btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
btAssert(currentRow < totalNumRows);
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+ btSolverConstraint* currentConstraintRow = &siData.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);
+ int solverBodyIdA = siData.getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
+ int solverBodyIdB = siData.getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
- convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
+ convertJointInternal(siData.m_tmpSolverBodyPool, siData.m_maxOverrideNumSolverIterations,
+ currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
}
currentRow += info1.m_numConstraintRows;
}
}
-void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ convertJointsInternal(siData, constraints, numConstraints, infoGlobal);
+}
+
+
+void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertBodies");
for (int i = 0; i < numBodies; i++)
@@ -1385,23 +1784,23 @@ void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodi
bodies[i]->setCompanionId(-1);
}
#if BT_THREADSAFE
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+ siData.m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
#endif // BT_THREADSAFE
- m_tmpSolverBodyPool.reserve(numBodies + 1);
- m_tmpSolverBodyPool.resize(0);
+ siData.m_tmpSolverBodyPool.reserve(numBodies + 1);
+ siData.m_tmpSolverBodyPool.resize(0);
//btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
//initSolverBody(&fixedBody,0);
for (int i = 0; i < numBodies; i++)
{
- int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+ int bodyId = siData.getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(bodies[i]);
if (body && body->getInvMass())
{
- btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+ btSolverBody& solverBody = siData.m_tmpSolverBodyPool[bodyId];
btVector3 gyroForce(0, 0, 0);
if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
{
@@ -1422,6 +1821,29 @@ void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodi
}
}
+
+void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ convertBodiesInternal(siData, bodies, numBodies, infoGlobal);
+}
+
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
m_fixedBodyId = -1;
@@ -1545,14 +1967,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
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 btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveSingleIteration");
btScalar leastSquaresResidual = 0.f;
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+ int numNonContactPool = siData.m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = siData.m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = siData.m_tmpSolverContactFrictionConstraintPool.size();
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
@@ -1560,10 +1982,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
{
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;
+ int tmp = siData.m_orderNonContactConstraintPool[j];
+ int swapi = btRandInt2a(j + 1, siData.m_seed);
+ siData.m_orderNonContactConstraintPool[j] = siData.m_orderNonContactConstraintPool[swapi];
+ siData.m_orderNonContactConstraintPool[swapi] = tmp;
}
//contact/friction constraints are not solved more than
@@ -1571,30 +1993,30 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
{
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;
+ int tmp = siData.m_orderTmpConstraintPool[j];
+ int swapi = btRandInt2a(j + 1, siData.m_seed);
+ siData.m_orderTmpConstraintPool[j] = siData.m_orderTmpConstraintPool[swapi];
+ siData.m_orderTmpConstraintPool[swapi] = tmp;
}
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;
+ int tmp = siData.m_orderFrictionConstraintPool[j];
+ int swapi = btRandInt2a(j + 1, siData.m_seed);
+ siData.m_orderFrictionConstraintPool[j] = siData.m_orderFrictionConstraintPool[swapi];
+ siData.m_orderFrictionConstraintPool[swapi] = tmp;
}
}
}
}
///solve all joint constraints
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+ for (int j = 0; j < siData.m_tmpSolverNonContactConstraintPool.size(); j++)
{
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+ btSolverConstraint& constraint = siData.m_tmpSolverNonContactConstraintPool[siData.m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
{
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+ btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -1605,10 +2027,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
{
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];
+ int bodyAid = siData.getSolverBody(constraints[j]->getRigidBodyA());
+ int bodyBid = siData.getSolverBody(constraints[j]->getRigidBodyB());
+ btSolverBody& bodyA = siData.m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = siData.m_tmpSolverBodyPool[bodyBid];
constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
}
}
@@ -1616,7 +2038,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
///solve all contact constraints
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
for (int c = 0; c < numPoolConstraints; c++)
@@ -1624,8 +2046,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
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);
+ const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[c]];
+ btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
totalImpulse = solveManifold.m_appliedImpulse;
@@ -1634,28 +2056,28 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
if (applyFriction)
{
{
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
+ btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.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);
+ btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
+ btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.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);
+ btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -1665,40 +2087,40 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
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 numPoolConstraints = siData.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);
+ const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
+ btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
///solve all friction constraints
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ int numFrictionPoolConstraints = siData.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;
+ btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = siData.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);
+ btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
}
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ int numRollingFrictionPoolConstraints = siData.m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
{
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ btSolverConstraint& rollingFrictionConstraint = siData.m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = siData.m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse > btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
@@ -1708,7 +2130,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -1716,8 +2138,56 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
return leastSquaresResidual;
}
+
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ btScalar leastSquaresResidual = btSequentialImpulseConstraintSolver::solveSingleIterationInternal(siData,
+ iteration, constraints, numConstraints, infoGlobal);
+ return leastSquaresResidual;
+}
+
void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ solveGroupCacheFriendlySplitImpulseIterationsInternal(siData,
+ bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+}
+void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
int iteration;
if (infoGlobal.m_splitImpulse)
@@ -1727,13 +2197,13 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
btScalar leastSquaresResidual = 0.f;
{
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
int j;
for (j = 0; j < numPoolConstraints; j++)
{
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = siData.m_resolveSplitPenetrationImpulse(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -1760,7 +2230,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
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--)
+ //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
{
m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
@@ -1769,6 +2239,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
#ifdef VERBOSE_RESIDUAL_PRINTF
printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
#endif
+ m_analyticsData.m_numSolverCalls++;
+ m_analyticsData.m_numIterationsUsed = iteration+1;
+ m_analyticsData.m_islandId = -2;
+ if (numBodies>0)
+ m_analyticsData.m_islandId = bodies[0]->getCompanionId();
+ m_analyticsData.m_numBodies = numBodies;
+ m_analyticsData.m_numContactManifolds = numManifolds;
+ m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
break;
}
}
@@ -1776,31 +2254,42 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
return 0.f;
}
-void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+ const btSolverConstraint& solveManifold = 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;
+ pt->m_appliedImpulseLateral1 = 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;
+ pt->m_appliedImpulseLateral2 = tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
}
//do a callback here?
}
}
+void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+ writeBackContactsInternal(m_tmpSolverContactConstraintPool, m_tmpSolverContactFrictionConstraintPool, iBegin, iEnd, infoGlobal);
+
+}
+
void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
+ writeBackJointsInternal(m_tmpSolverNonContactConstraintPool, iBegin, iEnd, infoGlobal);
+}
+
+void btSequentialImpulseConstraintSolver::writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+ const btSolverConstraint& solverConstr = tmpSolverNonContactConstraintPool[j];
btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
btJointFeedback* fb = constr->getJointFeedback();
if (fb)
@@ -1821,53 +2310,79 @@ void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd,
void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
+ writeBackBodiesInternal(m_tmpSolverBodyPool, iBegin, iEnd, infoGlobal);
+}
+void btSequentialImpulseConstraintSolver::writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
for (int i = iBegin; i < iEnd; i++)
{
- btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+ btRigidBody* body = tmpSolverBodyPool[i].m_originalBody;
if (body)
{
if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
else
- m_tmpSolverBodyPool[i].writebackVelocity();
+ tmpSolverBodyPool[i].writebackVelocity();
- m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- m_tmpSolverBodyPool[i].m_linearVelocity +
- m_tmpSolverBodyPool[i].m_externalForceImpulse);
+ tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
+ tmpSolverBodyPool[i].m_linearVelocity +
+ tmpSolverBodyPool[i].m_externalForceImpulse);
- m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- m_tmpSolverBodyPool[i].m_angularVelocity +
- m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
+ tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
+ tmpSolverBodyPool[i].m_angularVelocity +
+ tmpSolverBodyPool[i].m_externalTorqueImpulse);
if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
+ tmpSolverBodyPool[i].m_originalBody->setWorldTransform(tmpSolverBodyPool[i].m_worldTransform);
- m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
+ tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
}
}
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveGroupCacheFriendlyFinish");
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
+ writeBackContactsInternal(siData.m_tmpSolverContactConstraintPool, siData.m_tmpSolverContactFrictionConstraintPool, 0, siData.m_tmpSolverContactConstraintPool.size(), infoGlobal);
}
- writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
- writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
+ writeBackJointsInternal(siData.m_tmpSolverNonContactConstraintPool, 0, siData.m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
+ writeBackBodiesInternal(siData.m_tmpSolverBodyPool, 0, siData.m_tmpSolverBodyPool.size(), infoGlobal);
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+ siData.m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ siData.m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ siData.m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverBodyPool.resizeNoInitialize(0);
+ siData.m_tmpSolverBodyPool.resizeNoInitialize(0);
return 0.f;
}
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+ btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
+ m_tmpSolverContactConstraintPool,
+ m_tmpSolverNonContactConstraintPool,
+ m_tmpSolverContactFrictionConstraintPool,
+ m_tmpSolverContactRollingFrictionConstraintPool,
+ m_orderTmpConstraintPool,
+ m_orderNonContactConstraintPool,
+ m_orderFrictionConstraintPool,
+ m_tmpConstraintSizesPool,
+ m_resolveSingleConstraintRowGeneric,
+ m_resolveSingleConstraintRowLowerLimit,
+ m_resolveSplitPenetrationImpulse,
+ m_kinematicBodyUniqueIdToSolverBodyTable,
+ m_btSeed2,
+ m_fixedBodyId,
+ m_maxOverrideNumSolverIterations);
+
+ return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(siData, bodies, numBodies, infoGlobal);
+}
+
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
{
@@ -1886,4 +2401,4 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
void btSequentialImpulseConstraintSolver::reset()
{
m_btSeed2 = 0;
-}
+} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
index 70db83b063..2b88e25be7 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -29,10 +29,91 @@ class btCollisionObject;
typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
+struct btSISolverSingleIterationData
+{
+ btAlignedObjectArray<btSolverBody>& m_tmpSolverBodyPool;
+ btConstraintArray& m_tmpSolverContactConstraintPool;
+ btConstraintArray& m_tmpSolverNonContactConstraintPool;
+ btConstraintArray& m_tmpSolverContactFrictionConstraintPool;
+ btConstraintArray& m_tmpSolverContactRollingFrictionConstraintPool;
+
+ btAlignedObjectArray<int>& m_orderTmpConstraintPool;
+ btAlignedObjectArray<int>& m_orderNonContactConstraintPool;
+ btAlignedObjectArray<int>& m_orderFrictionConstraintPool;
+ btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& m_tmpConstraintSizesPool;
+ unsigned long& m_seed;
+
+ btSingleConstraintRowSolver& m_resolveSingleConstraintRowGeneric;
+ btSingleConstraintRowSolver& m_resolveSingleConstraintRowLowerLimit;
+ btSingleConstraintRowSolver& m_resolveSplitPenetrationImpulse;
+ btAlignedObjectArray<int>& m_kinematicBodyUniqueIdToSolverBodyTable;
+ int& m_fixedBodyId;
+ int& m_maxOverrideNumSolverIterations;
+ int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
+ static void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
+ int getSolverBody(btCollisionObject& body) const;
+
+
+ btSISolverSingleIterationData(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
+ btConstraintArray& tmpSolverContactConstraintPool,
+ btConstraintArray& tmpSolverNonContactConstraintPool,
+ btConstraintArray& tmpSolverContactFrictionConstraintPool,
+ btConstraintArray& tmpSolverContactRollingFrictionConstraintPool,
+ btAlignedObjectArray<int>& orderTmpConstraintPool,
+ btAlignedObjectArray<int>& orderNonContactConstraintPool,
+ btAlignedObjectArray<int>& orderFrictionConstraintPool,
+ btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& tmpConstraintSizesPool,
+ btSingleConstraintRowSolver& resolveSingleConstraintRowGeneric,
+ btSingleConstraintRowSolver& resolveSingleConstraintRowLowerLimit,
+ btSingleConstraintRowSolver& resolveSplitPenetrationImpulse,
+ btAlignedObjectArray<int>& kinematicBodyUniqueIdToSolverBodyTable,
+ unsigned long& seed,
+ int& fixedBodyId,
+ int& maxOverrideNumSolverIterations
+ )
+ :m_tmpSolverBodyPool(tmpSolverBodyPool),
+ m_tmpSolverContactConstraintPool(tmpSolverContactConstraintPool),
+ m_tmpSolverNonContactConstraintPool(tmpSolverNonContactConstraintPool),
+ m_tmpSolverContactFrictionConstraintPool(tmpSolverContactFrictionConstraintPool),
+ m_tmpSolverContactRollingFrictionConstraintPool(tmpSolverContactRollingFrictionConstraintPool),
+ m_orderTmpConstraintPool(orderTmpConstraintPool),
+ m_orderNonContactConstraintPool(orderNonContactConstraintPool),
+ m_orderFrictionConstraintPool(orderFrictionConstraintPool),
+ m_tmpConstraintSizesPool(tmpConstraintSizesPool),
+ m_seed(seed),
+ m_resolveSingleConstraintRowGeneric(resolveSingleConstraintRowGeneric),
+ m_resolveSingleConstraintRowLowerLimit(resolveSingleConstraintRowLowerLimit),
+ m_resolveSplitPenetrationImpulse(resolveSplitPenetrationImpulse),
+ m_kinematicBodyUniqueIdToSolverBodyTable(kinematicBodyUniqueIdToSolverBodyTable),
+ m_fixedBodyId(fixedBodyId),
+ m_maxOverrideNumSolverIterations(maxOverrideNumSolverIterations)
+ {
+ }
+};
+
+struct btSolverAnalyticsData
+{
+ btSolverAnalyticsData()
+ {
+ m_numSolverCalls = 0;
+ m_numIterationsUsed = -1;
+ m_remainingLeastSquaresResidual = -1;
+ m_islandId = -2;
+ }
+ int m_islandId;
+ int m_numBodies;
+ int m_numContactManifolds;
+ int m_numSolverCalls;
+ int m_numIterationsUsed;
+ double m_remainingLeastSquaresResidual;
+};
+
///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;
@@ -64,26 +145,26 @@ protected:
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.);
+ 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.);
+ 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);
+ 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);
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
unsigned long m_btSeed2;
@@ -97,6 +178,7 @@ protected:
virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
+
virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
@@ -122,7 +204,8 @@ protected:
return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
}
-protected:
+public:
+
void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
@@ -130,6 +213,7 @@ 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);
virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
@@ -141,13 +225,52 @@ public:
virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+ static btScalar solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
+ static void convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+ static void convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
+ static void convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
+ static void setupContactConstraintInternal(btSISolverSingleIterationData& siData, btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation,
+ const btVector3& rel_pos1, const btVector3& rel_pos2);
+ static btScalar restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
+ static btSolverConstraint& addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.);
+ static void setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+ btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity, btScalar cfmSlip);
+ static void setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip);
+ static btSolverConstraint& addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
+ static void setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
+
+ btSolverConstraint& solverConstraint,
+ int solverBodyIdA, int solverBodyIdB,
+ btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
+ static void convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
+ int& maxOverrideNumSolverIterations,
+ btSolverConstraint* currentConstraintRow,
+ btTypedConstraint* constraint,
+ const btTypedConstraint::btConstraintInfo1& info1,
+ int solverBodyIdA,
+ int solverBodyIdB,
+ const btContactSolverInfo& infoGlobal);
+
+ static btScalar solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+ static void writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+
+ static void writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ static void writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+ static void solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+
///clear internal cached data and reset random seed
virtual void reset();
unsigned long btRand2();
-
int btRandInt2(int n);
+ static unsigned long btRand2a(unsigned long& seed);
+ static int btRandInt2a(int n, unsigned long& seed);
+
void setRandSeed(unsigned long seed)
{
m_btSeed2 = seed;
@@ -179,15 +302,22 @@ public:
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();
+ static btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
+ static btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
+ static 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();
+ static btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+ static btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+ static btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
+
+ static btSingleConstraintRowSolver getScalarSplitPenetrationImpulseGeneric();
+ static btSingleConstraintRowSolver getSSE2SplitPenetrationImpulseGeneric();
+
+ btSolverAnalyticsData m_analyticsData;
};
#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
index 17287aa82a..5353fe009e 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
@@ -65,7 +65,7 @@ inline int getIslandId(const btPersistentManifold* lhs)
return islandId;
}
-SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
+SIMD_FORCE_INLINE int btGetConstraintIslandId1(const btTypedConstraint* lhs)
{
const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
@@ -452,7 +452,7 @@ void btSimulationIslandManagerMt::addConstraintsToIslands(btAlignedObjectArray<b
btTypedConstraint* constraint = constraints[i];
if (constraint->isEnabled())
{
- int islandId = btGetConstraintIslandId(constraint);
+ int islandId = btGetConstraintIslandId1(constraint);
// if island is not sleeping,
if (Island* island = getIsland(islandId))
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
index 53fc48d4b9..3e210d7520 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -106,6 +106,7 @@ btMultiBody::btMultiBody(int n_links,
m_fixedBase(fixedBase),
m_awake(true),
m_canSleep(canSleep),
+ m_canWakeup(true),
m_sleepTimer(0),
m_userObjectPointer(0),
m_userIndex2(-1),
@@ -343,6 +344,7 @@ void btMultiBody::finalizeMultiDof()
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)
+ m_matrixBuf.resize(m_links.size() + 1);
for (int i = 0; i < m_vectorBuf.size(); i++)
{
m_vectorBuf[i].setValue(0, 0, 0);
@@ -350,9 +352,9 @@ void btMultiBody::finalizeMultiDof()
updateLinksDofOffsets();
}
-int btMultiBody::getParent(int i) const
+int btMultiBody::getParent(int link_num) const
{
- return m_links[i].m_parent;
+ return m_links[link_num].m_parent;
}
btScalar btMultiBody::getLinkMass(int i) const
@@ -1882,6 +1884,8 @@ void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
return;
}
+
+
// motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
btScalar motion = 0;
{
@@ -1900,8 +1904,11 @@ void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
else
{
m_sleepTimer = 0;
- if (!m_awake)
- wakeUp();
+ if (m_canWakeup)
+ {
+ if (!m_awake)
+ wakeUp();
+ }
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
index e5c0f1806b..c0b0d003be 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
@@ -65,7 +65,7 @@ public:
virtual ~btMultiBody();
//note: fixed link collision with parent is always disabled
- void setupFixed(int linkIndex,
+ void setupFixed(int i, //linkIndex
btScalar mass,
const btVector3 &inertia,
int parent,
@@ -83,7 +83,7 @@ public:
const btVector3 &thisPivotToThisComOffset,
bool disableParentCollision);
- void setupRevolute(int linkIndex, // 0 to num_links-1
+ void setupRevolute(int i, // 0 to num_links-1
btScalar mass,
const btVector3 &inertia,
int parentIndex,
@@ -93,7 +93,7 @@ public:
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
+ void setupSpherical(int i, // linkIndex, 0 to num_links-1
btScalar mass,
const btVector3 &inertia,
int parent,
@@ -182,7 +182,10 @@ public:
// get/set pos/vel/rot/omega for the base link
//
- const btVector3 &getBasePos() const { return m_basePos; } // in world frame
+ 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]);
@@ -274,15 +277,15 @@ public:
//
// 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;
+ btVector3 localPosToWorld(int i, const btVector3 &local_pos) const;
+ btVector3 localDirToWorld(int i, const btVector3 &local_dir) const;
+ btVector3 worldPosToLocal(int i, const btVector3 &world_pos) const;
+ btVector3 worldDirToLocal(int i, const btVector3 &world_dir) const;
//
// transform a frame in local coordinate to a frame in world coordinate
//
- btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const;
+ btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
//
// calculate kinetic energy and angular momentum
@@ -451,7 +454,10 @@ public:
//
void setCanSleep(bool canSleep)
{
- m_canSleep = canSleep;
+ if (m_canWakeup)
+ {
+ m_canSleep = canSleep;
+ }
}
bool getCanSleep() const
@@ -459,6 +465,15 @@ public:
return m_canSleep;
}
+ bool getCanWakeup() const
+ {
+ return m_canWakeup;
+ }
+
+ void setCanWakeup(bool canWakeup)
+ {
+ m_canWakeup = canWakeup;
+ }
bool isAwake() const { return m_awake; }
void wakeUp();
void goToSleep();
@@ -469,6 +484,11 @@ public:
return m_fixedBase;
}
+ void setFixedBase(bool fixedBase)
+ {
+ m_fixedBase = fixedBase;
+ }
+
int getCompanionId() const
{
return m_companionId;
@@ -556,11 +576,11 @@ public:
{
return m_internalNeedsJointFeedback;
}
- void forwardKinematics(btAlignedObjectArray<btQuaternion> & scratch_q, btAlignedObjectArray<btVector3> & scratch_m);
+ void forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local, btAlignedObjectArray<btVector3> & local_origin);
void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
- void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & scratch_q, btAlignedObjectArray<btVector3> & scratch_m);
+ void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
virtual int calculateSerializeBufferSize() const;
@@ -688,6 +708,7 @@ private:
// Sleep parameters.
bool m_awake;
bool m_canSleep;
+ bool m_canWakeup;
btScalar m_sleepTimer;
void *m_userObjectPointer;
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index e97bd71cc4..23e163f0e8 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -70,6 +70,30 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
//solve featherstone frictional contact
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
{
+ for (int j1 = 0; j1 < this->m_multiBodySpinningFrictionContactConstraints.size(); j1++)
+ {
+ if (iteration < infoGlobal.m_numIterations)
+ {
+ int index = j1;
+
+ btMultiBodySolverConstraint& frictionConstraint = m_multiBodySpinningFrictionContactConstraints[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 = btMax(leastSquaredResidual, residual * residual);
+
+ if (frictionConstraint.m_multiBodyA)
+ frictionConstraint.m_multiBodyA->setPosUpdated(false);
+ if (frictionConstraint.m_multiBodyB)
+ frictionConstraint.m_multiBodyB->setPosUpdated(false);
+ }
+ }
+ }
+
for (int j1 = 0; j1 < this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
{
if (iteration < infoGlobal.m_numIterations)
@@ -78,18 +102,29 @@ btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btColl
btMultiBodySolverConstraint& frictionConstraint = m_multiBodyTorsionalFrictionContactConstraints[index];
btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+ j1++;
+ int index2 = j1;
+ btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyTorsionalFrictionContactConstraints[index2];
//adjust friction limits here
- if (totalImpulse > btScalar(0))
+ if (totalImpulse > btScalar(0) && frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
{
frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
+ frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
+ frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
+
+ btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
if (frictionConstraint.m_multiBodyA)
frictionConstraint.m_multiBodyA->setPosUpdated(false);
if (frictionConstraint.m_multiBodyB)
frictionConstraint.m_multiBodyB->setPosUpdated(false);
+
+ if (frictionConstraintB.m_multiBodyA)
+ frictionConstraintB.m_multiBodyA->setPosUpdated(false);
+ if (frictionConstraintB.m_multiBodyB)
+ frictionConstraintB.m_multiBodyB->setPosUpdated(false);
}
}
}
@@ -164,6 +199,7 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionOb
m_multiBodyNormalContactConstraints.resize(0);
m_multiBodyFrictionContactConstraints.resize(0);
m_multiBodyTorsionalFrictionContactConstraints.resize(0);
+ m_multiBodySpinningFrictionContactConstraints.resize(0);
m_data.m_jacobians.resize(0);
m_data.m_deltaVelocitiesUnitImpulse.resize(0);
@@ -1169,6 +1205,43 @@ btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalF
return solverConstraint;
}
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodySpinningFrictionConstraint(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_multiBodySpinningFrictionContactConstraints.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());
@@ -1258,7 +1331,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
{
if (cp.m_combinedSpinningFriction > 0)
{
- addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodySpinningFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
}
if (cp.m_combinedRollingFriction > 0)
{
@@ -1267,11 +1340,8 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
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);
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
}
rollingFriction--;
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
index f39f2879fc..abf5718839 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
@@ -34,6 +34,7 @@ protected:
btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints;
+ btMultiBodyConstraintArray m_multiBodySpinningFrictionContactConstraints;
btMultiBodyJacobianData m_data;
@@ -54,6 +55,10 @@ protected:
btScalar combinedTorsionalFriction,
btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+ btMultiBodySolverConstraint& addMultiBodySpinningFrictionConstraint(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,
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
index 1557987bc3..1131e5378c 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
@@ -207,6 +207,7 @@ public:
}
};
+
struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
{
btContactSolverInfo* m_solverInfo;
@@ -224,6 +225,8 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
btAlignedObjectArray<btTypedConstraint*> m_constraints;
btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+ btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
+
MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
btDispatcher* dispatcher)
: m_solverInfo(NULL),
@@ -235,7 +238,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
{
}
- MultiBodyInplaceSolverIslandCallback& operator=(MultiBodyInplaceSolverIslandCallback& other)
+ MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
{
btAssert(0);
(void)other;
@@ -244,6 +247,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
{
+ m_islandAnalyticsData.clear();
btAssert(solverInfo);
m_solverInfo = solverInfo;
@@ -270,6 +274,11 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
{
///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_solverInfo->m_reportSolverAnalytics&1)
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
}
else
{
@@ -335,7 +344,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
{
- processConstraints();
+ processConstraints(islandId);
}
else
{
@@ -344,7 +353,7 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
}
}
}
- void processConstraints()
+ void processConstraints(int islandId=-1)
{
btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
@@ -354,6 +363,11 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
//printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
m_bodies.resize(0);
m_manifolds.resize(0);
m_constraints.resize(0);
@@ -361,6 +375,11 @@ struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::
}
};
+void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
+{
+ islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
+}
+
btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
m_multiBodyConstraintSolver(constraintSolver)
@@ -717,13 +736,17 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
m_scratch_v.resize(bod->getNumLinks() + 1);
m_scratch_m.resize(bod->getNumLinks() + 1);
+ if (bod->internalNeedsJointFeedback())
{
if (!bod->isUsingRK4Integration())
{
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
+ if (bod->internalNeedsJointFeedback())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
}
}
}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
index 641238f3bb..e36c2f7aad 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
@@ -109,5 +109,7 @@ public:
virtual void serialize(btSerializer* serializer);
virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
virtual void setConstraintSolver(btConstraintSolver* solver);
+ virtual void getAnalyticsData(btAlignedObjectArray<struct btSolverAnalyticsData>& m_islandAnalyticsData) const;
+
};
#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
index f91c001f12..bc909990c2 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
@@ -36,6 +36,10 @@ public:
btMultiBody* m_multiBody;
int m_link;
+ virtual ~btMultiBodyLinkCollider()
+ {
+
+ }
btMultiBodyLinkCollider(btMultiBody* multiBody, int link)
: m_multiBody(multiBody),
m_link(link)
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
index 338e8af0ab..f2186a93e9 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
@@ -22,9 +22,9 @@ subject to the following restrictions:
#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
-static bool interleaveContactAndFriction = false;
+static bool interleaveContactAndFriction1 = false;
-struct btJointNode
+struct btJointNode1
{
int jointIndex; // pointer to enclosing dxJoint object
int otherBodyIndex; // *other* body this joint is connected to
@@ -241,7 +241,7 @@ void btMultiBodyMLCPConstraintSolver::createMLCPFast(const btContactSolverInfo&
void btMultiBodyMLCPConstraintSolver::createMLCPFastRigidBody(const btContactSolverInfo& infoGlobal)
{
- int numContactRows = interleaveContactAndFriction ? 3 : 1;
+ int numContactRows = interleaveContactAndFriction1 ? 3 : 1;
int numConstraintRows = m_allConstraintPtrArray.size();
@@ -301,7 +301,7 @@ void btMultiBodyMLCPConstraintSolver::createMLCPFastRigidBody(const btContactSol
BT_PROFILE("bodyJointNodeArray.resize");
bodyJointNodeArray.resize(numBodies, -1);
}
- btAlignedObjectArray<btJointNode> jointNodeArray;
+ btAlignedObjectArray<btJointNode1> jointNodeArray;
{
BT_PROFILE("jointNodeArray.reserve");
jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
@@ -729,7 +729,7 @@ btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlySetup(
int firstContactConstraintOffset = dindex;
// The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
- if (interleaveContactAndFriction)
+ if (interleaveContactAndFriction1)
{
for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
{
@@ -785,7 +785,7 @@ btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlySetup(
firstContactConstraintOffset = dindex;
// The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
- if (interleaveContactAndFriction)
+ if (interleaveContactAndFriction1)
{
for (int i = 0; i < m_multiBodyNormalContactConstraints.size(); ++i)
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
index 6be36ba142..77fdb86bb9 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
@@ -156,7 +156,7 @@ protected:
btTypedConstraint** constraints,
int numConstraints,
const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer) BT_OVERRIDE;
+ btIDebugDraw* debugDrawer) ;
public:
BT_DECLARE_ALIGNED_ALLOCATOR()
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
index 3f215e56bb..ac2fc46ab0 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "btMLCPSolverInterface.h"
#include "btLemkeAlgorithm.h"
-///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
+///The btLemkeSolver is based on "Fast Implementation of Lemke's Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
class btLemkeSolver : public btMLCPSolverInterface
@@ -67,7 +67,7 @@ public:
btMatrixXu A1;
btMatrixXu B(n, n);
{
- BT_PROFILE("inverse(slow)");
+ //BT_PROFILE("inverse(slow)");
A1.resize(A.rows(), A.cols());
for (int row = 0; row < A.rows(); row++)
{
@@ -174,7 +174,7 @@ public:
y1.resize(n, 1);
btLemkeAlgorithm lemke(M, qq, m_debugLevel);
{
- BT_PROFILE("lemke.solve");
+ //BT_PROFILE("lemke.solve");
lemke.setSystem(M, qq);
z1 = lemke.solve(m_maxLoops);
}
diff --git a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
index f150b5ae4c..9326b0d098 100644
--- a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
@@ -349,7 +349,7 @@ int MultiBodyTree::finalize()
const int &num_bodies = m_init_cache->numBodies();
const int &num_dofs = m_init_cache->numDoFs();
- if (num_dofs <= 0)
+ if (num_dofs < 0)
{
bt_id_error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
//return -1;
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
index befbc2e2a4..ec9a562295 100644
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
+++ b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
@@ -479,9 +479,17 @@ int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx
//todo: review
RigidBody &body = m_body_list[m_body_spherical_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));
+ mat33 T;
+
+ T = transformX(q(body.m_q_index)) *
+ transformY(q(body.m_q_index + 1)) *
+ transformZ(q(body.m_q_index + 2));
+ body.m_body_T_parent = T * body.m_body_T_parent_ref;
+
+ body.m_parent_pos_parent_body(0)=0;
+ body.m_parent_pos_parent_body(1)=0;
+ body.m_parent_pos_parent_body(2)=0;
+
body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
if (type >= POSITION_VELOCITY)
@@ -832,6 +840,25 @@ int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool
body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
}
+
+ for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+ {
+ //todo: review
+ RigidBody &body = m_body_list[m_body_spherical_list[i]];
+
+ mat33 T;
+
+ T = transformX(q(body.m_q_index)) *
+ transformY(q(body.m_q_index + 1)) *
+ transformZ(q(body.m_q_index + 2));
+ body.m_body_T_parent = T * body.m_body_T_parent_ref;
+
+ body.m_parent_pos_parent_body(0)=0;
+ body.m_parent_pos_parent_body(1)=0;
+ body.m_parent_pos_parent_body(2)=0;
+
+ 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--)
{
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
index 58796a88d0..7463bdc019 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
@@ -518,7 +518,7 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10º) = 0.98480
+ // cos(10°) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -604,7 +604,7 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10º) = 0.98480
+ // cos(10°) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
index 02f4ed1631..a03f6dc570 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
@@ -45,14 +45,14 @@ subject to the following restrictions:
int btGetNumHardwareThreads()
{
- return btMin<int>(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency());
+ return btMax(1u, btMin(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency()));
}
#else
int btGetNumHardwareThreads()
{
- return btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN));
+ return btMax(1, btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN)));
}
#endif
@@ -304,8 +304,8 @@ void btThreadSupportPosix::stopThreads()
checkPThreadFunction(sem_post(threadStatus.startSemaphore));
checkPThreadFunction(sem_wait(m_mainSemaphore));
- destroySem(threadStatus.startSemaphore);
checkPThreadFunction(pthread_join(threadStatus.thread, 0));
+ destroySem(threadStatus.startSemaphore);
}
destroySem(m_mainSemaphore);
m_activeThreadStatus.clear();
diff --git a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h b/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
index b4671bc19f..b3d5d64b58 100644
--- a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
+++ b/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
@@ -38,13 +38,6 @@ subject to the following restrictions:
#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>
@@ -209,7 +202,7 @@ public:
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
{
- const BT_REGISTER int curSize = size();
+ const int curSize = size();
if (newsize < curSize)
{
@@ -236,7 +229,7 @@ public:
}
SIMD_FORCE_INLINE T& expandNonInitializing()
{
- const BT_REGISTER int sz = size();
+ const int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
@@ -248,7 +241,7 @@ public:
SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
{
- const BT_REGISTER int sz = size();
+ const int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
@@ -263,7 +256,7 @@ public:
SIMD_FORCE_INLINE void push_back(const T& _Val)
{
- const BT_REGISTER int sz = size();
+ const int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
diff --git a/thirdparty/bullet/LinearMath/btMatrixX.h b/thirdparty/bullet/LinearMath/btMatrixX.h
index 9df9e49469..388c57c2d7 100644
--- a/thirdparty/bullet/LinearMath/btMatrixX.h
+++ b/thirdparty/bullet/LinearMath/btMatrixX.h
@@ -263,7 +263,10 @@ struct btMatrixX
{
{
BT_PROFILE("storage=0");
- btSetZero(&m_storage[0], m_storage.size());
+ if (m_storage.size())
+ {
+ 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;
@@ -281,7 +284,7 @@ struct btMatrixX
}
}
- void printMatrix(const char* msg)
+ void printMatrix(const char* msg) const
{
printf("%s ---------------------\n", msg);
for (int i = 0; i < rows(); i++)
diff --git a/thirdparty/bullet/LinearMath/btScalar.h b/thirdparty/bullet/LinearMath/btScalar.h
index c198bd4b35..ba49d6700b 100644
--- a/thirdparty/bullet/LinearMath/btScalar.h
+++ b/thirdparty/bullet/LinearMath/btScalar.h
@@ -124,7 +124,7 @@ inline int btGetVersion()
#ifdef BT_DEBUG
#ifdef _MSC_VER
#include <stdio.h>
- #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
+ #define btAssert(x) { if(!(x)){printf("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
#else//_MSC_VER
#include <assert.h>
#define btAssert assert
@@ -152,7 +152,7 @@ inline int btGetVersion()
#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);}}
+ #define btAssert(x) {if(!(x)){printf("Assert " __FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
#else
#define btAssert assert
#endif
diff --git a/thirdparty/bullet/LinearMath/btVector3.h b/thirdparty/bullet/LinearMath/btVector3.h
index 61fd8d1e46..d65ed9808d 100644
--- a/thirdparty/bullet/LinearMath/btVector3.h
+++ b/thirdparty/bullet/LinearMath/btVector3.h
@@ -36,7 +36,7 @@ subject to the following restrictions:
#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_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#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))
diff --git a/thirdparty/bullet/btBulletCollisionAll.cpp b/thirdparty/bullet/btBulletCollisionAll.cpp
new file mode 100644
index 0000000000..2851fb3b73
--- /dev/null
+++ b/thirdparty/bullet/btBulletCollisionAll.cpp
@@ -0,0 +1,96 @@
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp"
+#include "BulletCollision/BroadphaseCollision/btDbvt.cpp"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp"
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.cpp"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp"
+#include "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp"
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp"
+#include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.cpp"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.cpp"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btUnionFind.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp"
+#include "BulletCollision/CollisionDispatch/btGhostObject.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"
+#include "BulletCollision/CollisionShapes/btBox2dShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp"
+#include "BulletCollision/CollisionShapes/btShapeHull.cpp"
+#include "BulletCollision/CollisionShapes/btBoxShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexShape.cpp"
+#include "BulletCollision/CollisionShapes/btSphereShape.cpp"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.cpp"
+#include "BulletCollision/CollisionShapes/btCylinderShape.cpp"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp"
+#include "BulletCollision/CollisionShapes/btCollisionShape.cpp"
+#include "BulletCollision/CollisionShapes/btEmptyShape.cpp"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.cpp"
+#include "BulletCollision/CollisionShapes/btCompoundShape.cpp"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleBuffer.cpp"
+#include "BulletCollision/CollisionShapes/btConcaveShape.cpp"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.cpp"
+#include "BulletCollision/CollisionShapes/btConeShape.cpp"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp"
+#include "BulletCollision/CollisionShapes/btConvex2dShape.cpp"
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.cpp"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.cpp"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.cpp"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp"
+#include "BulletCollision/CollisionShapes/btMiniSDF.cpp"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.cpp"
+#include "BulletCollision/Gimpact/btContactProcessing.cpp"
+#include "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp"
+#include "BulletCollision/Gimpact/btTriangleShapeEx.cpp"
+#include "BulletCollision/Gimpact/gim_memory.cpp"
+#include "BulletCollision/Gimpact/btGImpactBvh.cpp"
+#include "BulletCollision/Gimpact/btGImpactShape.cpp"
+#include "BulletCollision/Gimpact/gim_box_set.cpp"
+#include "BulletCollision/Gimpact/gim_tri_collision.cpp"
+#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp"
+#include "BulletCollision/Gimpact/btGenericPoolAllocator.cpp"
+#include "BulletCollision/Gimpact/gim_contact.cpp"
diff --git a/thirdparty/bullet/btBulletDynamicsAll.cpp b/thirdparty/bullet/btBulletDynamicsAll.cpp
new file mode 100644
index 0000000000..a8069e30ae
--- /dev/null
+++ b/thirdparty/bullet/btBulletDynamicsAll.cpp
@@ -0,0 +1,42 @@
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp"
+#include "BulletDynamics/Dynamics/btRigidBody.cpp"
+#include "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp"
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp"
+#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp"
+#include "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGearConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp"
+#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp"
+#include "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp"
+#include "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp"
+#include "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBody.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp"
+#include "BulletDynamics/Vehicle/btRaycastVehicle.cpp"
+#include "BulletDynamics/Vehicle/btWheelInfo.cpp"
+#include "BulletDynamics/Character/btKinematicCharacterController.cpp"
+
diff --git a/thirdparty/bullet/btLinearMathAll.cpp b/thirdparty/bullet/btLinearMathAll.cpp
new file mode 100644
index 0000000000..808f412803
--- /dev/null
+++ b/thirdparty/bullet/btLinearMathAll.cpp
@@ -0,0 +1,14 @@
+#include "LinearMath/btAlignedAllocator.cpp"
+#include "LinearMath/btGeometryUtil.cpp"
+#include "LinearMath/btSerializer.cpp"
+#include "LinearMath/btVector3.cpp"
+#include "LinearMath/btConvexHull.cpp"
+#include "LinearMath/btPolarDecomposition.cpp"
+#include "LinearMath/btSerializer64.cpp"
+#include "LinearMath/btConvexHullComputer.cpp"
+#include "LinearMath/btQuickprof.cpp"
+#include "LinearMath/btThreads.cpp"
+#include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
+#include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
+#include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
+