summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/config/engine.cpp2
-rw-r--r--core/version.h6
-rw-r--r--doc/classes/EditorSettings.xml3
-rw-r--r--doc/classes/Engine.xml3
-rw-r--r--doc/classes/TileMap.xml2
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp748
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.h41
-rw-r--r--editor/editor_about.cpp10
-rw-r--r--editor/editor_plugin_settings.cpp6
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/gui/editor_bottom_panel.cpp9
-rw-r--r--editor/import/3d/resource_importer_scene.cpp9
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.h2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h2
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h2
-rw-r--r--editor/plugins/gizmos/collision_object_3d_gizmo_plugin.cpp6
-rw-r--r--editor/plugins/gizmos/collision_polygon_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp6
-rw-r--r--editor/plugins/gizmos/physics_bone_3d_gizmo_plugin.cpp3
-rw-r--r--editor/plugins/gizmos/ray_cast_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gizmos/shape_cast_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gizmos/spring_arm_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gizmos/vehicle_body_3d_gizmo_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp5
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp3
-rw-r--r--editor/plugins/navigation_obstacle_3d_editor_plugin.h2
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp62
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.h4
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp1
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.h3
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.h2
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp7
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp1
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp9
-rw-r--r--editor/project_manager.cpp9
-rw-r--r--main/main.cpp23
-rw-r--r--main/main.h1
-rw-r--r--methods.py13
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml11
-rw-r--r--modules/gdscript/gdscript_parser.cpp21
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out10
-rw-r--r--modules/gdscript/tests/scripts/parser/features/annotations.gd31
-rw-r--r--modules/gdscript/tests/scripts/parser/features/annotations.out36
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_enum.gd19
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_enum.out18
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_variable.gd35
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_variable.out35
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd12
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out9
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info.gd2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd2
-rw-r--r--modules/gdscript/tests/scripts/utils.notest.gd25
-rw-r--r--modules/gltf/extensions/physics/gltf_document_extension_physics.cpp3
-rw-r--r--modules/gltf/extensions/physics/gltf_physics_body.cpp7
-rw-r--r--modules/gltf/extensions/physics/gltf_physics_body.h2
-rw-r--r--modules/gltf/extensions/physics/gltf_physics_shape.cpp2
-rw-r--r--modules/gltf/extensions/physics/gltf_physics_shape.h2
-rw-r--r--modules/mono/.editorconfig71
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs122
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs166
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic1T.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic2T.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/NestedClass.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs8
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs12
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllReadOnly_ScriptProperties.generated.cs40
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllWriteOnly_ScriptProperties.generated.cs24
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs840
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptPropertyDefVal.generated.cs240
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs924
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs244
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/MixedReadOnlyWriteOnly_ScriptProperties.generated.cs64
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllReadOnly.cs8
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllWriteOnly.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Bar.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedFields.cs122
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs162
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Foo.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.GD0003.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MixedReadOnlyWriteOnly.cs12
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MoreExportedFields.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ScriptBoilerplate.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GlobalClassAnalyzer.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs4
-rw-r--r--modules/mono/editor/bindings_generator.cpp67
-rw-r--r--modules/mono/glue/GodotSharp/.editorconfig19
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Compat.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/AlcReloadCfg.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/CustomGCHandle.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs35
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs9
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharpEditor/Compat.cs3
-rw-r--r--modules/navigation/2d/nav_mesh_generator_2d.cpp2
-rw-r--r--modules/navigation/3d/nav_mesh_generator_3d.cpp2
-rw-r--r--modules/navigation/nav_agent.h1
-rw-r--r--scene/2d/SCsub3
-rw-r--r--scene/2d/audio_stream_player_2d.cpp2
-rw-r--r--scene/2d/joint_2d.cpp564
-rw-r--r--scene/2d/joint_2d.h167
-rw-r--r--scene/2d/physics/SCsub8
-rw-r--r--scene/2d/physics/animatable_body_2d.cpp111
-rw-r--r--scene/2d/physics/animatable_body_2d.h61
-rw-r--r--scene/2d/physics/area_2d.cpp (renamed from scene/2d/area_2d.cpp)0
-rw-r--r--scene/2d/physics/area_2d.h (renamed from scene/2d/area_2d.h)2
-rw-r--r--scene/2d/physics/character_body_2d.cpp755
-rw-r--r--scene/2d/physics/character_body_2d.h173
-rw-r--r--scene/2d/physics/collision_object_2d.cpp (renamed from scene/2d/collision_object_2d.cpp)0
-rw-r--r--scene/2d/physics/collision_object_2d.h (renamed from scene/2d/collision_object_2d.h)0
-rw-r--r--scene/2d/physics/collision_polygon_2d.cpp (renamed from scene/2d/collision_polygon_2d.cpp)4
-rw-r--r--scene/2d/physics/collision_polygon_2d.h (renamed from scene/2d/collision_polygon_2d.h)0
-rw-r--r--scene/2d/physics/collision_shape_2d.cpp (renamed from scene/2d/collision_shape_2d.cpp)4
-rw-r--r--scene/2d/physics/collision_shape_2d.h (renamed from scene/2d/collision_shape_2d.h)0
-rw-r--r--scene/2d/physics/joints/SCsub5
-rw-r--r--scene/2d/physics/joints/damped_spring_joint_2d.cpp128
-rw-r--r--scene/2d/physics/joints/damped_spring_joint_2d.h67
-rw-r--r--scene/2d/physics/joints/groove_joint_2d.cpp92
-rw-r--r--scene/2d/physics/joints/groove_joint_2d.h59
-rw-r--r--scene/2d/physics/joints/joint_2d.cpp254
-rw-r--r--scene/2d/physics/joints/joint_2d.h84
-rw-r--r--scene/2d/physics/joints/pin_joint_2d.cpp177
-rw-r--r--scene/2d/physics/joints/pin_joint_2d.h71
-rw-r--r--scene/2d/physics/kinematic_collision_2d.cpp120
-rw-r--r--scene/2d/physics/kinematic_collision_2d.h67
-rw-r--r--scene/2d/physics/physical_bone_2d.cpp (renamed from scene/2d/physical_bone_2d.cpp)2
-rw-r--r--scene/2d/physics/physical_bone_2d.h (renamed from scene/2d/physical_bone_2d.h)2
-rw-r--r--scene/2d/physics/physics_body_2d.cpp180
-rw-r--r--scene/2d/physics/physics_body_2d.h63
-rw-r--r--scene/2d/physics/ray_cast_2d.cpp (renamed from scene/2d/ray_cast_2d.cpp)2
-rw-r--r--scene/2d/physics/ray_cast_2d.h (renamed from scene/2d/ray_cast_2d.h)0
-rw-r--r--scene/2d/physics/rigid_body_2d.cpp817
-rw-r--r--scene/2d/physics/rigid_body_2d.h249
-rw-r--r--scene/2d/physics/shape_cast_2d.cpp (renamed from scene/2d/shape_cast_2d.cpp)4
-rw-r--r--scene/2d/physics/shape_cast_2d.h (renamed from scene/2d/shape_cast_2d.h)0
-rw-r--r--scene/2d/physics/static_body_2d.cpp96
-rw-r--r--scene/2d/physics/static_body_2d.h64
-rw-r--r--scene/2d/physics_body_2d.cpp1923
-rw-r--r--scene/2d/physics_body_2d.h493
-rw-r--r--scene/2d/tile_map_layer.cpp13
-rw-r--r--scene/3d/SCsub3
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/camera_3d.cpp1
-rw-r--r--scene/3d/joint_3d.h301
-rw-r--r--scene/3d/mesh_instance_3d.cpp5
-rw-r--r--scene/3d/navigation_obstacle_3d.cpp2
-rw-r--r--scene/3d/physics/SCsub8
-rw-r--r--scene/3d/physics/animatable_body_3d.cpp128
-rw-r--r--scene/3d/physics/animatable_body_3d.h67
-rw-r--r--scene/3d/physics/area_3d.cpp (renamed from scene/3d/area_3d.cpp)0
-rw-r--r--scene/3d/physics/area_3d.h (renamed from scene/3d/area_3d.h)2
-rw-r--r--scene/3d/physics/character_body_3d.cpp939
-rw-r--r--scene/3d/physics/character_body_3d.h190
-rw-r--r--scene/3d/physics/collision_object_3d.cpp (renamed from scene/3d/collision_object_3d.cpp)0
-rw-r--r--scene/3d/physics/collision_object_3d.h (renamed from scene/3d/collision_object_3d.h)0
-rw-r--r--scene/3d/physics/collision_polygon_3d.cpp (renamed from scene/3d/collision_polygon_3d.cpp)2
-rw-r--r--scene/3d/physics/collision_polygon_3d.h (renamed from scene/3d/collision_polygon_3d.h)0
-rw-r--r--scene/3d/physics/collision_shape_3d.cpp (renamed from scene/3d/collision_shape_3d.cpp)7
-rw-r--r--scene/3d/physics/collision_shape_3d.h (renamed from scene/3d/collision_shape_3d.h)0
-rw-r--r--scene/3d/physics/joints/SCsub5
-rw-r--r--scene/3d/physics/joints/cone_twist_joint_3d.cpp97
-rw-r--r--scene/3d/physics/joints/cone_twist_joint_3d.h63
-rw-r--r--scene/3d/physics/joints/generic_6dof_joint_3d.cpp (renamed from scene/3d/joint_3d.cpp)559
-rw-r--r--scene/3d/physics/joints/generic_6dof_joint_3d.h112
-rw-r--r--scene/3d/physics/joints/hinge_joint_3d.cpp135
-rw-r--r--scene/3d/physics/joints/hinge_joint_3d.h77
-rw-r--r--scene/3d/physics/joints/joint_3d.cpp241
-rw-r--r--scene/3d/physics/joints/joint_3d.h85
-rw-r--r--scene/3d/physics/joints/pin_joint_3d.cpp80
-rw-r--r--scene/3d/physics/joints/pin_joint_3d.h60
-rw-r--r--scene/3d/physics/joints/slider_joint_3d.cpp149
-rw-r--r--scene/3d/physics/joints/slider_joint_3d.h82
-rw-r--r--scene/3d/physics/kinematic_collision_3d.cpp134
-rw-r--r--scene/3d/physics/kinematic_collision_3d.h68
-rw-r--r--scene/3d/physics/physical_bone_3d.cpp1346
-rw-r--r--scene/3d/physics/physical_bone_3d.h306
-rw-r--r--scene/3d/physics/physics_body_3d.cpp228
-rw-r--r--scene/3d/physics/physics_body_3d.h72
-rw-r--r--scene/3d/physics/ray_cast_3d.cpp (renamed from scene/3d/ray_cast_3d.cpp)71
-rw-r--r--scene/3d/physics/ray_cast_3d.h (renamed from scene/3d/ray_cast_3d.h)4
-rw-r--r--scene/3d/physics/rigid_body_3d.cpp825
-rw-r--r--scene/3d/physics/rigid_body_3d.h248
-rw-r--r--scene/3d/physics/shape_cast_3d.cpp (renamed from scene/3d/shape_cast_3d.cpp)67
-rw-r--r--scene/3d/physics/shape_cast_3d.h (renamed from scene/3d/shape_cast_3d.h)4
-rw-r--r--scene/3d/physics/spring_arm_3d.cpp (renamed from scene/3d/spring_arm_3d.cpp)0
-rw-r--r--scene/3d/physics/spring_arm_3d.h (renamed from scene/3d/spring_arm_3d.h)0
-rw-r--r--scene/3d/physics/static_body_3d.cpp96
-rw-r--r--scene/3d/physics/static_body_3d.h64
-rw-r--r--scene/3d/physics/vehicle_body_3d.cpp (renamed from scene/3d/vehicle_body_3d.cpp)0
-rw-r--r--scene/3d/physics/vehicle_body_3d.h (renamed from scene/3d/vehicle_body_3d.h)3
-rw-r--r--scene/3d/physics_body_3d.cpp3503
-rw-r--r--scene/3d/physics_body_3d.h797
-rw-r--r--scene/3d/skeleton_3d.cpp3
-rw-r--r--scene/3d/soft_body_3d.cpp2
-rw-r--r--scene/main/node.cpp11
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/register_scene_types.cpp53
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d.cpp6
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp2
-rw-r--r--scene/resources/world_2d.h1
-rw-r--r--scu_builders.py4
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_device_driver.h2
-rw-r--r--tests/scene/test_viewport.h4
243 files changed, 12402 insertions, 10640 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 2bb8837849..d714ec42c2 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -114,6 +114,8 @@ Dictionary Engine::get_version_info() const {
String hash = String(VERSION_HASH);
dict["hash"] = hash.is_empty() ? String("unknown") : hash;
+ dict["timestamp"] = VERSION_TIMESTAMP;
+
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
if ((int)dict["patch"] != 0) {
stringver += "." + String(dict["patch"]);
diff --git a/core/version.h b/core/version.h
index abb81312ac..18a97cadf0 100644
--- a/core/version.h
+++ b/core/version.h
@@ -33,6 +33,8 @@
#include "core/version_generated.gen.h"
+#include <stdint.h>
+
// Copied from typedefs.h to stay lean.
#ifndef _STR
#define _STR(m_x) #m_x
@@ -77,4 +79,8 @@
// Git commit hash, generated at build time in `core/version_hash.gen.cpp`.
extern const char *const VERSION_HASH;
+// Git commit date UNIX timestamp (in seconds), generated at build time in `core/version_hash.gen.cpp`.
+// Set to 0 if unknown.
+extern const uint64_t VERSION_TIMESTAMP;
+
#endif // VERSION_H
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 0e4dcacc56..dd0522e091 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -429,6 +429,9 @@
<member name="editors/panning/warped_mouse_panning" type="bool" setter="" getter="">
If [code]true[/code], warps the mouse around the 2D viewport while panning in the 2D editor. This makes it possible to pan over a large area without having to exit panning and adjust the mouse cursor.
</member>
+ <member name="editors/polygon_editor/auto_bake_delay" type="float" setter="" getter="">
+ The delay in seconds until more complex and performance costly polygon editors commit their outlines, e.g. the 2D navigation polygon editor rebakes the navigation mesh polygons. A negative value stops the auto bake.
+ </member>
<member name="editors/polygon_editor/point_grab_radius" type="int" setter="" getter="">
The radius in which points can be selected in the [Polygon2D] and [CollisionPolygon2D] editors (in pixels). Higher values make it easier to select points quickly, but can make it more difficult to select the expected point when several points are located close to each other.
</member>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index f9c9b72ed7..4c8859baf2 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -180,6 +180,7 @@
- [code]status[/code] - Status (such as "beta", "rc1", "rc2", "stable", etc.) as a String;
- [code]build[/code] - Build name (e.g. "custom_build") as a String;
- [code]hash[/code] - Full Git commit hash as a String;
+ - [code]timestamp[/code] - Holds the Git commit date UNIX timestamp in seconds as an int, or [code]0[/code] if unavailable;
- [code]string[/code] - [code]major[/code], [code]minor[/code], [code]patch[/code], [code]status[/code], and [code]build[/code] in a single String.
The [code]hex[/code] value is encoded as follows, from left to right: one byte for the major, one byte for the minor, one byte for the patch version. For example, "3.1.12" would be [code]0x03010C[/code].
[b]Note:[/b] The [code]hex[/code] value is still an [int] internally, and printing it will give you its decimal representation, which is not particularly meaningful. Use hexadecimal literals for quick version comparisons from code:
@@ -261,7 +262,7 @@
func _enter_tree():
# Depending on when the node is added to the tree,
# prints either "true" or "false".
- print(Engine.is_in_physics_frame())
+ print(Engine.is_in_physics_frame())
func _process(delta):
print(Engine.is_in_physics_frame()) # Prints false
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index daa0eec230..5731c10651 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Node for 2D tile-based maps. Tilemaps use a [TileSet] which contain a list of tiles which are used to create grid-based maps. A TileMap may have several layers, layouting tiles on top of each other.
- For performance reasons, all TileMap updates are batched at the end of a frame. Notably, this means that scene tiles from a [TileSetScenesCollectionSource] may be initialized after their parent.
+ For performance reasons, all TileMap updates are batched at the end of a frame. Notably, this means that scene tiles from a [TileSetScenesCollectionSource] may be initialized after their parent. This is only queued when inside the scene tree.
To force an update earlier on, call [method update_internals].
</description>
<tutorials>
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index e74ea910a0..381d022a55 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -530,7 +530,7 @@ static const D3D12_RESOURCE_DIMENSION RD_TEXTURE_TYPE_TO_D3D12_RESOURCE_DIMENSIO
D3D12_RESOURCE_DIMENSION_TEXTURE2D,
};
-void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_resource, uint32_t p_subresource, uint32_t p_num_planes, D3D12_RESOURCE_STATES p_new_state, ID3D12Resource *p_resource_override) {
+void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_resource, uint32_t p_subresource, uint32_t p_num_planes, D3D12_RESOURCE_STATES p_new_state) {
DEV_ASSERT(p_subresource != UINT32_MAX); // We don't support an "all-resources" command here.
#ifdef DEBUG_COUNT_BARRIERS
@@ -538,9 +538,16 @@ void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_reso
#endif
ResourceInfo::States *res_states = p_resource->states_ptr;
- D3D12_RESOURCE_STATES *curr_state = &res_states->subresource_states[p_subresource];
- ID3D12Resource *res_to_transition = p_resource_override ? p_resource_override : p_resource->resource;
+ if (p_new_state == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) {
+ if (unlikely(!res_states->xfamily_fallback.subresources_dirty.is_empty())) {
+ uint32_t subres_qword = p_subresource / 64;
+ uint64_t subres_mask = (uint64_t(1) << (p_subresource % 64));
+ res_states->xfamily_fallback.subresources_dirty[subres_qword] |= subres_mask;
+ }
+ }
+
+ D3D12_RESOURCE_STATES *curr_state = &res_states->subresource_states[p_subresource];
// Transitions can be considered redundant if the current state has all the bits of the new state.
// This check does not apply to the common state however, which must resort to checking if the state is the same (0).
@@ -553,7 +560,7 @@ void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_reso
if (res_barriers.size() < res_barriers_count + 1) {
res_barriers.resize(res_barriers_count + 1);
}
- res_barriers[res_barriers_count] = CD3DX12_RESOURCE_BARRIER::UAV(res_to_transition);
+ res_barriers[res_barriers_count] = CD3DX12_RESOURCE_BARRIER::UAV(p_resource->resource);
res_barriers_count++;
res_states->last_batch_with_uav_barrier = res_barriers_batch;
}
@@ -563,7 +570,7 @@ void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_reso
if (res_barriers_requests.has(res_states)) {
BarrierRequest &br = res_barriers_requests.get(res_states);
- DEV_ASSERT(br.dx_resource == res_to_transition);
+ DEV_ASSERT(br.dx_resource == p_resource->resource);
DEV_ASSERT(br.subres_mask_qwords == STEPIFY(res_states->subresource_states.size(), 64) / 64);
DEV_ASSERT(br.planes == p_num_planes);
@@ -681,7 +688,7 @@ void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_reso
}
} else {
BarrierRequest &br = res_barriers_requests[res_states];
- br.dx_resource = res_to_transition;
+ br.dx_resource = p_resource->resource;
br.subres_mask_qwords = STEPIFY(p_resource->states_ptr->subresource_states.size(), 64) / 64;
CRASH_COND(p_resource->states_ptr->subresource_states.size() > BarrierRequest::MAX_SUBRESOURCES);
br.planes = p_num_planes;
@@ -697,10 +704,6 @@ void RenderingDeviceDriverD3D12::_resource_transition_batch(ResourceInfo *p_reso
}
}
- if (p_new_state == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) {
- res_states->last_batch_transitioned_to_uav = res_barriers_batch;
- }
-
#ifdef DEBUG_COUNT_BARRIERS
frame_barriers_cpu_time += OS::get_singleton()->get_ticks_usec() - start;
#endif
@@ -1135,19 +1138,13 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
// If views of different families are wanted, special setup is needed for proper sharing among them.
// Two options here:
- // 1. If ID3DDevice10 is present and driver reports relaxed casting is, leverage its new extended resource creation API (via D3D12MA).
- // 2. Otherwise, fall back to an approach based on abusing aliasing, hoping for the best. [[CROSS_FAMILY_ALIASING]]
- if (p_format.shareable_formats.size()) {
- if (format_capabilities.relaxed_casting_supported) {
- ComPtr<ID3D12Device10> device_10;
- device->QueryInterface(device_10.GetAddressOf());
- if (device_10) {
- relaxed_casting_available = true;
- relaxed_casting_formats = ALLOCA_ARRAY(DXGI_FORMAT, p_format.shareable_formats.size());
- relaxed_casting_formats[0] = RD_TO_D3D12_FORMAT[p_format.format].general_format;
- relaxed_casting_format_count++;
- }
- }
+ // 1. If the driver reports relaxed casting is, leverage its new extended resource creation API (via D3D12MA).
+ // 2. Otherwise, fall back to an approach based on having multiple versions of the resource and copying as needed. [[CROSS_FAMILY_FALLBACK]]
+ if (p_format.shareable_formats.size() && format_capabilities.relaxed_casting_supported) {
+ relaxed_casting_available = true;
+ relaxed_casting_formats = ALLOCA_ARRAY(DXGI_FORMAT, p_format.shareable_formats.size());
+ relaxed_casting_formats[0] = RD_TO_D3D12_FORMAT[p_format.format].general_format;
+ relaxed_casting_format_count++;
}
HashMap<DataFormat, D3D12_RESOURCE_FLAGS> aliases_forbidden_flags;
@@ -1168,9 +1165,6 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
}
if (cross_family_sharing && !relaxed_casting_available) {
- // At least guarantee the same layout among aliases.
- resource_desc.Layout = D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE;
-
// Per https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_layout.
if (p_format.texture_type == TEXTURE_TYPE_1D) {
ERR_FAIL_V_MSG(TextureID(), "This texture's views require aliasing, but that's not supported for a 1D texture.");
@@ -1221,9 +1215,6 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
// Create.
D3D12MA::ALLOCATION_DESC allocation_desc = {};
- if (cross_family_sharing && !relaxed_casting_available) {
- allocation_desc.Flags = D3D12MA::ALLOCATION_FLAG_CAN_ALIAS;
- }
allocation_desc.HeapType = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? D3D12_HEAP_TYPE_READBACK : D3D12_HEAP_TYPE_DEFAULT;
if ((resource_desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))) {
allocation_desc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;
@@ -1343,53 +1334,6 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = main_uav_desc;
uav_desc.Format = RD_TO_D3D12_FORMAT[p_view.format].general_format;
- // Create aliases if needed. [[CROSS_FAMILY_ALIASING]]
-
- using AliasEntry = Pair<DXGI_FORMAT, ID3D12Resource *>;
- AliasEntry *aliases = nullptr;
- uint32_t alias_count = 0;
- if (cross_family_sharing && !relaxed_casting_available) {
- aliases = ALLOCA_ARRAY(AliasEntry, p_format.shareable_formats.size());
-
- for (int i = 0; i < p_format.shareable_formats.size(); i++) {
- DataFormat curr_format = p_format.shareable_formats[i];
-
- DXGI_FORMAT format_family = RD_TO_D3D12_FORMAT[curr_format].family;
- if (format_family == RD_TO_D3D12_FORMAT[p_format.format].family) {
- continue;
- }
-
- D3D12_RESOURCE_DESC alias_resource_desc = *(D3D12_RESOURCE_DESC *)&resource_desc;
- alias_resource_desc.Format = format_family;
- clear_value.Format = format_family;
- if ((alias_resource_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)) {
- if (!texture_get_usages_supported_by_format(curr_format, false).has_flag(TEXTURE_USAGE_STORAGE_BIT)) {
- alias_resource_desc.Flags &= ~D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- }
- }
- ID3D12Resource *alias = nullptr;
- HRESULT res = allocator->CreateAliasingResource(
- allocation.Get(),
- 0,
- &alias_resource_desc,
- initial_state,
- (alias_resource_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ? clear_value_ptr : nullptr,
- IID_PPV_ARGS(&alias));
- if (!SUCCEEDED(res)) {
- for (uint32_t j = 0; j < alias_count; j++) {
- aliases[j].second->Release();
- }
- ERR_FAIL_V_MSG(TextureID(), "CreateAliasingResource failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
- }
- aliases[alias_count] = AliasEntry(format_family, alias);
- alias_count++;
-
- if (curr_format == p_view.format) {
- texture = alias;
- }
- }
- }
-
// Bookkeep.
TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);
@@ -1409,12 +1353,8 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
tex_info->mipmaps = resource_desc.MipLevels;
tex_info->view_descs.srv = srv_desc;
tex_info->view_descs.uav = uav_desc;
- tex_info->main_texture = main_texture.Get();
- tex_info->aliasing_hack.main_uav_desc = main_uav_desc;
- if (alias_count) {
- for (uint32_t i = 0; i < alias_count; i++) {
- tex_info->aliasing_hack.owner_info.aliases.insert(aliases[i].first, aliases[i].second);
- }
+ if ((p_format.usage_bits & (TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_COLOR_ATTACHMENT_BIT))) {
+ textures_pending_clear.add(&tex_info->pending_clear);
}
return TextureID(tex_info);
@@ -1425,75 +1365,59 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create_from_extension(uint64_
}
RDD::TextureID RenderingDeviceDriverD3D12::texture_create_shared(TextureID p_original_texture, const TextureView &p_view) {
- const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_V(!owner_tex_info->owner_info.allocation, TextureID());
-#endif
-
- ID3D12Resource *texture = nullptr;
- if (owner_tex_info->aliasing_hack.owner_info.aliases.is_empty()) {
- texture = owner_tex_info->resource;
- } else {
- texture = owner_tex_info->main_texture;
- for (const KeyValue<DXGI_FORMAT, ComPtr<ID3D12Resource>> &E : owner_tex_info->aliasing_hack.owner_info.aliases) {
- if (E.key == RD_TO_D3D12_FORMAT[p_view.format].family) {
- texture = E.value.Get();
- break;
- }
- }
- }
-
- // Describe views.
-
- D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = owner_tex_info->view_descs.srv;
- {
- srv_desc.Format = RD_TO_D3D12_FORMAT[p_view.format].general_format;
- srv_desc.Shader4ComponentMapping = _compute_component_mapping(p_view);
- }
-
- D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = owner_tex_info->view_descs.uav;
- {
- uav_desc.Format = RD_TO_D3D12_FORMAT[p_view.format].general_format;
- }
-
- // Bookkeep.
-
- TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);
- tex_info->resource = texture;
- tex_info->states_ptr = owner_tex_info->states_ptr;
- tex_info->format = p_view.format;
- tex_info->desc = owner_tex_info->desc;
- tex_info->base_layer = owner_tex_info->base_layer;
- tex_info->layers = owner_tex_info->layers;
- tex_info->base_mip = owner_tex_info->base_mip;
- tex_info->mipmaps = owner_tex_info->mipmaps;
- tex_info->view_descs.srv = srv_desc;
- tex_info->view_descs.uav = uav_desc;
- tex_info->main_texture = owner_tex_info->main_texture;
- tex_info->aliasing_hack.main_uav_desc = owner_tex_info->aliasing_hack.main_uav_desc;
-
- return TextureID(tex_info);
+ return _texture_create_shared_from_slice(p_original_texture, p_view, (TextureSliceType)-1, 0, 0, 0, 0);
}
RDD::TextureID RenderingDeviceDriverD3D12::texture_create_shared_from_slice(TextureID p_original_texture, const TextureView &p_view, TextureSliceType p_slice_type, uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {
- const TextureInfo *owner_tex_info = (const TextureInfo *)p_original_texture.id;
+ return _texture_create_shared_from_slice(p_original_texture, p_view, p_slice_type, p_layer, p_layers, p_mipmap, p_mipmaps);
+}
+
+RDD::TextureID RenderingDeviceDriverD3D12::_texture_create_shared_from_slice(TextureID p_original_texture, const TextureView &p_view, TextureSliceType p_slice_type, uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {
+ TextureInfo *owner_tex_info = (TextureInfo *)p_original_texture.id;
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V(!owner_tex_info->owner_info.allocation, TextureID());
#endif
- // Find appropriate resource instance.
+ ComPtr<ID3D12Resource> new_texture;
+ ComPtr<D3D12MA::Allocation> new_allocation;
+ ID3D12Resource *resource = nullptr;
+ CD3DX12_RESOURCE_DESC new_tex_resource_desc = owner_tex_info->desc;
+ bool cross_family = RD_TO_D3D12_FORMAT[p_view.format].family != RD_TO_D3D12_FORMAT[owner_tex_info->format].family;
+ if (cross_family && !format_capabilities.relaxed_casting_supported) {
+ // [[CROSS_FAMILY_FALLBACK]].
+ // We have to create a new texture of the alternative format.
- ID3D12Resource *texture = nullptr;
- if (owner_tex_info->aliasing_hack.owner_info.aliases.is_empty()) {
- texture = owner_tex_info->resource;
- } else {
- texture = owner_tex_info->main_texture;
- for (const KeyValue<DXGI_FORMAT, ComPtr<ID3D12Resource>> &E : owner_tex_info->aliasing_hack.owner_info.aliases) {
- if (E.key == RD_TO_D3D12_FORMAT[p_view.format].family) {
- texture = E.value.Get();
- break;
+ D3D12MA::ALLOCATION_DESC allocation_desc = {};
+ allocation_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+ allocation_desc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES;
+
+ if (p_slice_type != -1) {
+#ifdef DEV_ENABLED
+ // Actual slicing is not contemplated. If ever needed, let's at least realize.
+ if (p_slice_type != -1) {
+ uint32_t new_texture_subresorce_count = owner_tex_info->mipmaps * owner_tex_info->layers;
+ uint32_t slice_subresorce_count = p_mipmaps * p_layers;
+ DEV_ASSERT(new_texture_subresorce_count == slice_subresorce_count);
}
+#endif
+ new_tex_resource_desc.DepthOrArraySize = p_layers;
+ new_tex_resource_desc.MipLevels = p_mipmaps;
}
+ new_tex_resource_desc.Format = RD_TO_D3D12_FORMAT[p_view.format].family;
+ new_tex_resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; // Alternative formats can only be used as SRVs.
+
+ HRESULT res = allocator->CreateResource(
+ &allocation_desc,
+ &new_tex_resource_desc,
+ D3D12_RESOURCE_STATE_COPY_DEST,
+ nullptr,
+ new_allocation.GetAddressOf(),
+ IID_PPV_ARGS(new_texture.GetAddressOf()));
+ ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), TextureID(), vformat("D3D12MA::CreateResource failed with error 0x%08ux.", (uint64_t)res));
+
+ resource = new_texture.Get();
+ } else {
+ resource = owner_tex_info->resource;
}
// Describe views.
@@ -1509,103 +1433,169 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create_shared_from_slice(Text
uav_desc.Format = RD_TO_D3D12_FORMAT[p_view.format].general_format;
}
- // Complete description with slicing.
- // (Leveraging aliasing in members of the union as much as possible.)
-
- srv_desc.Texture1D.MostDetailedMip = p_mipmap;
- srv_desc.Texture1D.MipLevels = 1;
-
- uav_desc.Texture1D.MipSlice = p_mipmap;
-
- switch (p_slice_type) {
- case TEXTURE_SLICE_2D: {
- if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D && p_layer == 0) {
- DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2D);
- } else if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS && p_layer == 0) {
- DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_UNKNOWN);
- } else if ((srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY || (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D && p_layer)) || srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) {
- srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ if (p_slice_type != -1) {
+ // Complete description with slicing.
+
+ switch (p_slice_type) {
+ case TEXTURE_SLICE_2D: {
+ if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D && p_layer == 0) {
+ srv_desc.Texture2D.MostDetailedMip = p_mipmap;
+ srv_desc.Texture2D.MipLevels = p_mipmaps;
+
+ DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2D);
+ uav_desc.Texture1D.MipSlice = p_mipmap;
+ } else if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS && p_layer == 0) {
+ DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_UNKNOWN);
+ } else if ((srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY || (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2D && p_layer)) || srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) {
+ srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ srv_desc.Texture2DArray.MostDetailedMip = p_mipmap;
+ srv_desc.Texture2DArray.MipLevels = p_mipmaps;
+ srv_desc.Texture2DArray.FirstArraySlice = p_layer;
+ srv_desc.Texture2DArray.ArraySize = 1;
+ srv_desc.Texture2DArray.PlaneSlice = 0;
+ srv_desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
+
+ uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+ uav_desc.Texture2DArray.MipSlice = p_mipmap;
+ uav_desc.Texture2DArray.FirstArraySlice = p_layer;
+ uav_desc.Texture2DArray.ArraySize = 1;
+ uav_desc.Texture2DArray.PlaneSlice = 0;
+ } else if ((srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY || (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS && p_layer))) {
+ srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ srv_desc.Texture2DMSArray.FirstArraySlice = p_layer;
+ srv_desc.Texture2DMSArray.ArraySize = 1;
+
+ uav_desc.ViewDimension = D3D12_UAV_DIMENSION_UNKNOWN;
+ } else {
+ DEV_ASSERT(false);
+ }
+ } break;
+ case TEXTURE_SLICE_CUBEMAP: {
+ if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || p_layer == 0) {
+ srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
+ srv_desc.TextureCube.MostDetailedMip = p_mipmap;
+ srv_desc.TextureCube.MipLevels = p_mipmaps;
+
+ DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY);
+ uav_desc.Texture2DArray.MipSlice = p_mipmap;
+ uav_desc.Texture2DArray.FirstArraySlice = p_layer;
+ uav_desc.Texture2DArray.ArraySize = 6;
+ uav_desc.Texture2DArray.PlaneSlice = 0;
+ } else if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY || p_layer != 0) {
+ srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
+ srv_desc.TextureCubeArray.MostDetailedMip = p_mipmap;
+ srv_desc.TextureCubeArray.MipLevels = p_mipmaps;
+ srv_desc.TextureCubeArray.First2DArrayFace = p_layer;
+ srv_desc.TextureCubeArray.NumCubes = 1;
+ srv_desc.TextureCubeArray.ResourceMinLODClamp = 0.0f;
+
+ DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY);
+ uav_desc.Texture2DArray.MipSlice = p_mipmap;
+ uav_desc.Texture2DArray.FirstArraySlice = p_layer;
+ uav_desc.Texture2DArray.ArraySize = 6;
+ uav_desc.Texture2DArray.PlaneSlice = 0;
+ } else {
+ DEV_ASSERT(false);
+ }
+ } break;
+ case TEXTURE_SLICE_3D: {
+ DEV_ASSERT(srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE3D);
+ srv_desc.Texture3D.MostDetailedMip = p_mipmap;
+ srv_desc.Texture3D.MipLevels = p_mipmaps;
+
+ DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE3D);
+ uav_desc.Texture3D.MipSlice = p_mipmap;
+ uav_desc.Texture3D.WSize = -1;
+ } break;
+ case TEXTURE_SLICE_2D_ARRAY: {
+ DEV_ASSERT(srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY);
+ srv_desc.Texture2DArray.MostDetailedMip = p_mipmap;
+ srv_desc.Texture2DArray.MipLevels = p_mipmaps;
srv_desc.Texture2DArray.FirstArraySlice = p_layer;
- srv_desc.Texture2DArray.ArraySize = 1;
- srv_desc.Texture2DArray.PlaneSlice = 0;
- srv_desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
-
- uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
- uav_desc.Texture2DArray.FirstArraySlice = p_layer;
- uav_desc.Texture2DArray.ArraySize = 1;
- uav_desc.Texture2DArray.PlaneSlice = 0;
- } else if ((srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY || (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DMS && p_layer))) {
- srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
- srv_desc.Texture2DMSArray.FirstArraySlice = p_layer;
- srv_desc.Texture2DMSArray.ArraySize = 1;
-
- uav_desc.ViewDimension = D3D12_UAV_DIMENSION_UNKNOWN;
- } else {
- DEV_ASSERT(false);
- }
- } break;
- case TEXTURE_SLICE_CUBEMAP: {
- if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || p_layer == 0) {
- srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
- srv_desc.TextureCube.MostDetailedMip = p_mipmap;
- srv_desc.TextureCube.MipLevels = 1;
-
- DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY);
- uav_desc.Texture2DArray.MipSlice = p_mipmap;
- uav_desc.Texture2DArray.FirstArraySlice = 0;
- uav_desc.Texture2DArray.ArraySize = 6;
- uav_desc.Texture2DArray.PlaneSlice = 0;
- } else if (srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY || p_layer != 0) {
- srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
- srv_desc.TextureCubeArray.MostDetailedMip = p_mipmap;
- srv_desc.TextureCubeArray.MipLevels = 1;
- srv_desc.TextureCubeArray.First2DArrayFace = p_layer;
- srv_desc.TextureCubeArray.NumCubes = 1;
- srv_desc.TextureCubeArray.ResourceMinLODClamp = 0.0f;
+ srv_desc.Texture2DArray.ArraySize = p_layers;
DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY);
uav_desc.Texture2DArray.MipSlice = p_mipmap;
uav_desc.Texture2DArray.FirstArraySlice = p_layer;
- uav_desc.Texture2DArray.ArraySize = 6;
- uav_desc.Texture2DArray.PlaneSlice = 0;
- } else {
- DEV_ASSERT(false);
- }
- } break;
- case TEXTURE_SLICE_3D: {
- DEV_ASSERT(srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE3D);
-
- DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE3D);
- uav_desc.Texture3D.WSize = -1;
- } break;
- case TEXTURE_SLICE_2D_ARRAY: {
- DEV_ASSERT(srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURE2DARRAY);
- srv_desc.Texture2DArray.FirstArraySlice = p_layer;
- srv_desc.Texture2DArray.ArraySize = p_layers;
-
- DEV_ASSERT(uav_desc.ViewDimension == D3D12_UAV_DIMENSION_TEXTURE2DARRAY);
- uav_desc.Texture2DArray.FirstArraySlice = p_layer;
- uav_desc.Texture2DArray.ArraySize = p_layers;
- } break;
- default:
- break;
+ uav_desc.Texture2DArray.ArraySize = p_layers;
+ } break;
+ default:
+ break;
+ }
}
// Bookkeep.
TextureInfo *tex_info = VersatileResource::allocate<TextureInfo>(resources_allocator);
- tex_info->resource = texture;
- tex_info->states_ptr = owner_tex_info->states_ptr;
+ tex_info->resource = resource;
+ if (new_texture.Get()) {
+ // [[CROSS_FAMILY_FALLBACK]].
+
+ DEV_ASSERT(cross_family && !format_capabilities.relaxed_casting_supported);
+
+ uint32_t new_texture_subresorce_count = owner_tex_info->mipmaps * owner_tex_info->layers;
+#ifdef DEV_ENABLED
+ // Actual slicing is not contemplated. If ever needed, let's at least realize.
+ if (p_slice_type != -1) {
+ uint32_t slice_subresorce_count = p_mipmaps * p_layers;
+ DEV_ASSERT(new_texture_subresorce_count == slice_subresorce_count);
+ }
+#endif
+
+ tex_info->owner_info.resource = new_texture;
+ tex_info->owner_info.allocation = new_allocation;
+ tex_info->owner_info.states.subresource_states.resize(new_texture_subresorce_count);
+ for (uint32_t i = 0; i < tex_info->owner_info.states.subresource_states.size(); i++) {
+ tex_info->owner_info.states.subresource_states[i] = D3D12_RESOURCE_STATE_COPY_DEST;
+ }
+ tex_info->states_ptr = &tex_info->owner_info.states;
+
+ ResourceInfo::States::CrossFamillyFallback &xfamily = owner_tex_info->owner_info.states.xfamily_fallback;
+ if (xfamily.subresources_dirty.is_empty()) {
+ uint32_t items_required = STEPIFY(new_texture_subresorce_count, sizeof(uint64_t)) / sizeof(uint64_t);
+ xfamily.subresources_dirty.resize(items_required);
+ memset(xfamily.subresources_dirty.ptr(), 255, sizeof(uint64_t) * xfamily.subresources_dirty.size());
+
+ // Create buffer for non-direct copy if it's a format not supporting reinterpret-copy.
+ DEV_ASSERT(!xfamily.interim_buffer.Get());
+ if (owner_tex_info->format == DATA_FORMAT_R16_UINT && p_view.format == DATA_FORMAT_R4G4B4A4_UNORM_PACK16) {
+ uint32_t row_pitch = STEPIFY(owner_tex_info->desc.Width * sizeof(uint16_t), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+ uint32_t buffer_size = sizeof(uint16_t) * row_pitch * owner_tex_info->desc.Height * owner_tex_info->desc.Depth();
+ CD3DX12_RESOURCE_DESC resource_desc = CD3DX12_RESOURCE_DESC::Buffer(STEPIFY(buffer_size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT));
+ resource_desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
+
+ D3D12MA::ALLOCATION_DESC allocation_desc = {};
+ allocation_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+
+ HRESULT res = allocator->CreateResource(
+ &allocation_desc,
+ &resource_desc,
+ D3D12_RESOURCE_STATE_COPY_SOURCE, // Makes the code that makes the copy easier.
+ nullptr,
+ xfamily.interim_buffer_alloc.GetAddressOf(),
+ IID_PPV_ARGS(xfamily.interim_buffer.GetAddressOf()));
+ ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), TextureID(), "D3D12MA::CreateResource failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
+ }
+ }
+ } else {
+ tex_info->states_ptr = owner_tex_info->states_ptr;
+ }
tex_info->format = p_view.format;
- tex_info->desc = owner_tex_info->desc;
- tex_info->base_layer = p_layer;
- tex_info->layers = p_layers;
- tex_info->base_mip = p_mipmap;
- tex_info->mipmaps = p_mipmaps;
+ tex_info->desc = new_tex_resource_desc;
+ if (p_slice_type == -1) {
+ tex_info->base_layer = owner_tex_info->base_layer;
+ tex_info->layers = owner_tex_info->layers;
+ tex_info->base_mip = owner_tex_info->base_mip;
+ tex_info->mipmaps = owner_tex_info->mipmaps;
+ } else {
+ tex_info->base_layer = p_layer;
+ tex_info->layers = p_layers;
+ tex_info->base_mip = p_mipmap;
+ tex_info->mipmaps = p_mipmaps;
+ }
tex_info->view_descs.srv = srv_desc;
tex_info->view_descs.uav = uav_desc;
- tex_info->main_texture = owner_tex_info->main_texture;
- tex_info->aliasing_hack.main_uav_desc = owner_tex_info->aliasing_hack.main_uav_desc;
+ tex_info->main_texture = owner_tex_info;
return TextureID(tex_info);
}
@@ -2352,6 +2342,14 @@ D3D12_RENDER_TARGET_VIEW_DESC RenderingDeviceDriverD3D12::_make_rtv_for_texture(
rtv_desc.Texture3D.FirstWSlice = 0;
rtv_desc.Texture3D.WSize = -1;
} break;
+ case D3D12_SRV_DIMENSION_TEXTURECUBE:
+ case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: {
+ rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtv_desc.Texture2DArray.MipSlice = (p_add_bases ? p_texture_info->base_mip : 0) + p_mipmap_offset;
+ rtv_desc.Texture2DArray.FirstArraySlice = (p_add_bases ? p_texture_info->base_layer : 0) + p_layer_offset;
+ rtv_desc.Texture2DArray.ArraySize = p_layers == UINT32_MAX ? p_texture_info->layers : p_layers;
+ rtv_desc.Texture2DArray.PlaneSlice = 0;
+ } break;
default: {
DEV_ASSERT(false);
}
@@ -2360,6 +2358,36 @@ D3D12_RENDER_TARGET_VIEW_DESC RenderingDeviceDriverD3D12::_make_rtv_for_texture(
return rtv_desc;
}
+D3D12_UNORDERED_ACCESS_VIEW_DESC RenderingDeviceDriverD3D12::_make_ranged_uav_for_texture(const TextureInfo *p_texture_info, uint32_t p_mipmap_offset, uint32_t p_layer_offset, uint32_t p_layers, bool p_add_bases) {
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = p_texture_info->view_descs.uav;
+
+ uint32_t mip = (p_add_bases ? p_texture_info->base_mip : 0) + p_mipmap_offset;
+ switch (p_texture_info->view_descs.uav.ViewDimension) {
+ case D3D12_UAV_DIMENSION_TEXTURE1D: {
+ uav_desc.Texture1DArray.MipSlice = mip;
+ } break;
+ case D3D12_UAV_DIMENSION_TEXTURE1DARRAY: {
+ uav_desc.Texture1DArray.MipSlice = mip;
+ uav_desc.Texture1DArray.FirstArraySlice = mip;
+ uav_desc.Texture1DArray.ArraySize = p_layers;
+ } break;
+ case D3D12_UAV_DIMENSION_TEXTURE2D: {
+ uav_desc.Texture2D.MipSlice = mip;
+ } break;
+ case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: {
+ uav_desc.Texture2DArray.MipSlice = mip;
+ uav_desc.Texture2DArray.FirstArraySlice = (p_add_bases ? p_texture_info->base_layer : 0) + p_layer_offset;
+ uav_desc.Texture2DArray.ArraySize = p_layers;
+ } break;
+ case D3D12_UAV_DIMENSION_TEXTURE3D: {
+ uav_desc.Texture3D.MipSlice = mip;
+ uav_desc.Texture3D.WSize >>= p_mipmap_offset;
+ } break;
+ }
+
+ return uav_desc;
+}
+
D3D12_DEPTH_STENCIL_VIEW_DESC RenderingDeviceDriverD3D12::_make_dsv_for_texture(const TextureInfo *p_texture_info) {
D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
dsv_desc.Format = RD_TO_D3D12_FORMAT[p_texture_info->format].dsv_format;
@@ -3779,6 +3807,21 @@ void RenderingDeviceDriverD3D12::uniform_set_free(UniformSetID p_uniform_set) {
// ----- COMMANDS -----
void RenderingDeviceDriverD3D12::command_uniform_set_prepare_for_use(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) {
+ // Perform pending blackouts.
+ {
+ SelfList<TextureInfo> *E = textures_pending_clear.first();
+ while (E) {
+ TextureSubresourceRange subresources;
+ subresources.layer_count = E->self()->layers;
+ subresources.mipmap_count = E->self()->mipmaps;
+ command_clear_color_texture(p_cmd_buffer, TextureID(E->self()), TEXTURE_LAYOUT_GENERAL, Color(), subresources);
+
+ SelfList<TextureInfo> *next = E->next();
+ E->remove_from_list();
+ E = next;
+ }
+ }
+
const UniformSetInfo *uniform_set_info = (const UniformSetInfo *)p_uniform_set.id;
const ShaderInfo *shader_info_in = (const ShaderInfo *)p_shader.id;
const ShaderInfo::UniformSet &shader_set = shader_info_in->sets[p_set_index];
@@ -3825,13 +3868,6 @@ void RenderingDeviceDriverD3D12::command_uniform_set_prepare_for_use(CommandBuff
}
DEV_ASSERT((wanted_state == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) == (bool)(wanted_state & D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
-
- if (wanted_state == D3D12_RESOURCE_STATE_UNORDERED_ACCESS || wanted_state == D3D12_RESOURCE_STATE_RENDER_TARGET) {
- if (!sr.is_buffer) {
- TextureInfo *tex_info = (TextureInfo *)sr.resource;
- CRASH_COND_MSG(tex_info->resource != tex_info->main_texture, "The texture format used for UAV or RTV must be the main one.");
- }
- }
}
}
#endif
@@ -3911,7 +3947,35 @@ void RenderingDeviceDriverD3D12::command_uniform_set_prepare_for_use(CommandBuff
for (uint32_t i = 0; i < tex_info->layers; i++) {
for (uint32_t j = 0; j < tex_info->mipmaps; j++) {
uint32_t subresource = D3D12CalcSubresource(tex_info->base_mip + j, tex_info->base_layer + i, 0, tex_info->desc.MipLevels, tex_info->desc.ArraySize());
- _resource_transition_batch(tex_info, subresource, planes, wanted_state, tex_info->main_texture);
+
+ if ((wanted_state & D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE)) {
+ // [[CROSS_FAMILY_FALLBACK]].
+ if (tex_info->owner_info.resource && tex_info->main_texture && tex_info->main_texture != tex_info) {
+ uint32_t subres_qword = subresource / 64;
+ uint64_t subres_mask = (uint64_t(1) << (subresource % 64));
+ if ((tex_info->main_texture->states_ptr->xfamily_fallback.subresources_dirty[subres_qword] & subres_mask)) {
+ // Prepare for copying the write-to texture to this one, if out-of-date.
+ _resource_transition_batch(tex_info->main_texture, subresource, planes, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ _resource_transition_batch(tex_info, subresource, planes, D3D12_RESOURCE_STATE_COPY_DEST);
+
+ CommandBufferInfo::FamilyFallbackCopy ffc;
+ ffc.texture = tex_info;
+ ffc.subresource = subresource;
+ ffc.mipmap = j;
+ ffc.dst_wanted_state = wanted_state;
+
+ CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;
+ cmd_buf_info->family_fallback_copies.resize(cmd_buf_info->family_fallback_copies.size() + 1);
+ cmd_buf_info->family_fallback_copies[cmd_buf_info->family_fallback_copy_count] = ffc;
+ cmd_buf_info->family_fallback_copy_count++;
+
+ tex_info->main_texture->states_ptr->xfamily_fallback.subresources_dirty[subres_qword] &= ~subres_mask;
+ }
+ continue;
+ }
+ }
+
+ _resource_transition_batch(tex_info, subresource, planes, wanted_state);
}
}
}
@@ -3920,7 +3984,56 @@ void RenderingDeviceDriverD3D12::command_uniform_set_prepare_for_use(CommandBuff
}
if (p_set_index == shader_info_in->sets.size() - 1) {
- const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id;
+ CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;
+ _resource_transitions_flush(cmd_buf_info->cmd_list.Get());
+
+ // [[CROSS_FAMILY_FALLBACK]].
+ for (uint32_t i = 0; i < cmd_buf_info->family_fallback_copy_count; i++) {
+ const CommandBufferInfo::FamilyFallbackCopy &ffc = cmd_buf_info->family_fallback_copies[i];
+
+ D3D12_TEXTURE_COPY_LOCATION dst_tex = {};
+ dst_tex.pResource = ffc.texture->resource;
+ dst_tex.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst_tex.SubresourceIndex = ffc.subresource;
+
+ D3D12_TEXTURE_COPY_LOCATION src_tex = {};
+ src_tex.pResource = ffc.texture->main_texture->resource;
+ src_tex.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ src_tex.SubresourceIndex = ffc.subresource;
+
+ const ResourceInfo::States::CrossFamillyFallback &xfamily = ffc.texture->main_texture->owner_info.states.xfamily_fallback;
+ if (xfamily.interim_buffer.Get()) {
+ // Must copy via a buffer due to reinterpret-copy known not to be available for these data types.
+ D3D12_TEXTURE_COPY_LOCATION buf_loc = {};
+ buf_loc.pResource = xfamily.interim_buffer.Get();
+ buf_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ buf_loc.PlacedFootprint.Offset = 0;
+ buf_loc.PlacedFootprint.Footprint.Format = ffc.texture->main_texture->desc.Format;
+ buf_loc.PlacedFootprint.Footprint.Width = MAX(1u, ffc.texture->main_texture->desc.Width >> ffc.mipmap);
+ buf_loc.PlacedFootprint.Footprint.Height = MAX(1u, ffc.texture->main_texture->desc.Height >> ffc.mipmap);
+ buf_loc.PlacedFootprint.Footprint.Depth = MAX(1u, (uint32_t)ffc.texture->main_texture->desc.Depth() >> ffc.mipmap);
+ buf_loc.PlacedFootprint.Footprint.RowPitch = STEPIFY(buf_loc.PlacedFootprint.Footprint.Width * sizeof(uint16_t), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+
+ D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(xfamily.interim_buffer.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
+ cmd_buf_info->cmd_list->ResourceBarrier(1, &barrier);
+
+ cmd_buf_info->cmd_list->CopyTextureRegion(&buf_loc, 0, 0, 0, &src_tex, nullptr);
+
+ barrier = CD3DX12_RESOURCE_BARRIER::Transition(xfamily.interim_buffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ cmd_buf_info->cmd_list->ResourceBarrier(1, &barrier);
+
+ buf_loc.PlacedFootprint.Footprint.Format = ffc.texture->desc.Format;
+ cmd_buf_info->cmd_list->CopyTextureRegion(&dst_tex, 0, 0, 0, &buf_loc, nullptr);
+ } else {
+ // Direct copy is possible.
+ cmd_buf_info->cmd_list->CopyTextureRegion(&dst_tex, 0, 0, 0, &src_tex, nullptr);
+ }
+
+ // Set the specific SRV state we wanted from the beginning to the alternative version of the texture.
+ _resource_transition_batch(ffc.texture, ffc.subresource, 1, ffc.dst_wanted_state);
+ }
+ cmd_buf_info->family_fallback_copy_count = 0;
+
_resource_transitions_flush(cmd_buf_info->cmd_list.Get());
}
}
@@ -4234,17 +4347,17 @@ void RenderingDeviceDriverD3D12::command_clear_buffer(CommandBufferID p_cmd_buff
frames[frame_idx].desc_heap_walkers.aux.advance();
}
-void RenderingDeviceDriverD3D12::command_copy_buffer(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, BufferID p_dst_buffer, VectorView<BufferCopyRegion> p_regions) {
+void RenderingDeviceDriverD3D12::command_copy_buffer(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, BufferID p_buf_locfer, VectorView<BufferCopyRegion> p_regions) {
const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id;
BufferInfo *src_buf_info = (BufferInfo *)p_src_buffer.id;
- BufferInfo *dst_buf_info = (BufferInfo *)p_dst_buffer.id;
+ BufferInfo *buf_loc_info = (BufferInfo *)p_buf_locfer.id;
_resource_transition_batch(src_buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_SOURCE);
- _resource_transition_batch(dst_buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_DEST);
+ _resource_transition_batch(buf_loc_info, 0, 1, D3D12_RESOURCE_STATE_COPY_DEST);
_resource_transitions_flush(cmd_buf_info->cmd_list.Get());
for (uint32_t i = 0; i < p_regions.size(); i++) {
- cmd_buf_info->cmd_list->CopyBufferRegion(dst_buf_info->resource, p_regions[i].dst_offset, src_buf_info->resource, p_regions[i].src_offset, p_regions[i].size);
+ cmd_buf_info->cmd_list->CopyBufferRegion(buf_loc_info->resource, p_regions[i].dst_offset, src_buf_info->resource, p_regions[i].src_offset, p_regions[i].size);
}
}
@@ -4312,12 +4425,29 @@ void RenderingDeviceDriverD3D12::command_resolve_texture(CommandBufferID p_cmd_b
void RenderingDeviceDriverD3D12::command_clear_color_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, const Color &p_color, const TextureSubresourceRange &p_subresources) {
const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id;
TextureInfo *tex_info = (TextureInfo *)p_texture.id;
+ if (tex_info->main_texture) {
+ tex_info = tex_info->main_texture;
+ }
+
+ auto _transition_subresources = [&](D3D12_RESOURCE_STATES p_new_state) {
+ for (uint32_t i = 0; i < p_subresources.layer_count; i++) {
+ for (uint32_t j = 0; j < p_subresources.mipmap_count; j++) {
+ UINT subresource = D3D12CalcSubresource(
+ p_subresources.base_mipmap + j,
+ p_subresources.base_layer + i,
+ 0,
+ tex_info->desc.MipLevels,
+ tex_info->desc.ArraySize());
+ _resource_transition_batch(tex_info, subresource, 1, p_new_state);
+ }
+ }
+ _resource_transitions_flush(cmd_buf_info->cmd_list.Get());
+ };
- ID3D12Resource *res_to_clear = tex_info->main_texture ? tex_info->main_texture : tex_info->resource;
if ((tex_info->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)) {
// Clear via RTV.
- if (frames[frame_idx].desc_heap_walkers.rtv.is_at_eof()) {
+ if (frames[frame_idx].desc_heap_walkers.rtv.get_free_handles() < p_subresources.mipmap_count) {
if (!frames[frame_idx].desc_heaps_exhausted_reported.rtv) {
frames[frame_idx].desc_heaps_exhausted_reported.rtv = true;
ERR_FAIL_MSG(
@@ -4328,37 +4458,29 @@ void RenderingDeviceDriverD3D12::command_clear_color_texture(CommandBufferID p_c
}
}
- D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = _make_rtv_for_texture(tex_info, p_subresources.base_mipmap, p_subresources.base_layer, p_subresources.layer_count, false);
- rtv_desc.Format = tex_info->aliasing_hack.main_uav_desc.Format;
+ _transition_subresources(D3D12_RESOURCE_STATE_RENDER_TARGET);
- for (uint32_t i = 0; i < p_subresources.layer_count; i++) {
- for (uint32_t j = 0; j < p_subresources.mipmap_count; j++) {
- UINT subresource = D3D12CalcSubresource(
- p_subresources.base_mipmap + j,
- p_subresources.base_layer + i,
- 0,
- tex_info->desc.MipLevels,
- tex_info->desc.ArraySize());
- _resource_transition_batch(tex_info, subresource, 1, D3D12_RESOURCE_STATE_RENDER_TARGET, tex_info->main_texture);
- }
- }
- _resource_transitions_flush(cmd_buf_info->cmd_list.Get());
+ for (uint32_t i = 0; i < p_subresources.mipmap_count; i++) {
+ D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = _make_rtv_for_texture(tex_info, p_subresources.base_mipmap + i, p_subresources.base_layer, p_subresources.layer_count, false);
+ rtv_desc.Format = tex_info->view_descs.uav.Format;
+ device->CreateRenderTargetView(
+ tex_info->resource,
+ &rtv_desc,
+ frames[frame_idx].desc_heap_walkers.rtv.get_curr_cpu_handle());
- device->CreateRenderTargetView(
- res_to_clear,
- &rtv_desc,
- frames[frame_idx].desc_heap_walkers.rtv.get_curr_cpu_handle());
- cmd_buf_info->cmd_list->ClearRenderTargetView(
- frames[frame_idx].desc_heap_walkers.rtv.get_curr_cpu_handle(),
- p_color.components,
- 0,
- nullptr);
- frames[frame_idx].desc_heap_walkers.rtv.advance();
+ cmd_buf_info->cmd_list->ClearRenderTargetView(
+ frames[frame_idx].desc_heap_walkers.rtv.get_curr_cpu_handle(),
+ p_color.components,
+ 0,
+ nullptr);
+
+ frames[frame_idx].desc_heap_walkers.rtv.advance();
+ }
} else {
// Clear via UAV.
_command_check_descriptor_sets(p_cmd_buffer);
- if (frames[frame_idx].desc_heap_walkers.resources.is_at_eof()) {
+ if (frames[frame_idx].desc_heap_walkers.resources.get_free_handles() < p_subresources.mipmap_count) {
if (!frames[frame_idx].desc_heaps_exhausted_reported.resources) {
frames[frame_idx].desc_heaps_exhausted_reported.resources = true;
ERR_FAIL_MSG(
@@ -4368,7 +4490,7 @@ void RenderingDeviceDriverD3D12::command_clear_color_texture(CommandBufferID p_c
return;
}
}
- if (frames[frame_idx].desc_heap_walkers.aux.is_at_eof()) {
+ if (frames[frame_idx].desc_heap_walkers.aux.get_free_handles() < p_subresources.mipmap_count) {
if (!frames[frame_idx].desc_heaps_exhausted_reported.aux) {
frames[frame_idx].desc_heaps_exhausted_reported.aux = true;
ERR_FAIL_MSG(
@@ -4379,47 +4501,38 @@ void RenderingDeviceDriverD3D12::command_clear_color_texture(CommandBufferID p_c
}
}
- for (uint32_t i = 0; i < p_subresources.layer_count; i++) {
- for (uint32_t j = 0; j < p_subresources.mipmap_count; j++) {
- UINT subresource = D3D12CalcSubresource(
- p_subresources.base_mipmap + j,
- p_subresources.base_layer + i,
- 0,
- tex_info->desc.MipLevels,
- tex_info->desc.ArraySize());
- _resource_transition_batch(tex_info, subresource, 1, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, tex_info->main_texture);
- }
- }
- _resource_transitions_flush(cmd_buf_info->cmd_list.Get());
-
- device->CreateUnorderedAccessView(
- res_to_clear,
- nullptr,
- &tex_info->aliasing_hack.main_uav_desc,
- frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle());
-
- device->CopyDescriptorsSimple(
- 1,
- frames[frame_idx].desc_heap_walkers.resources.get_curr_cpu_handle(),
- frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle(),
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
-
- UINT values[4] = {
- (UINT)p_color.get_r8(),
- (UINT)p_color.get_g8(),
- (UINT)p_color.get_b8(),
- (UINT)p_color.get_a8(),
- };
- cmd_buf_info->cmd_list->ClearUnorderedAccessViewUint(
- frames[frame_idx].desc_heap_walkers.resources.get_curr_gpu_handle(),
- frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle(),
- res_to_clear,
- values,
- 0,
- nullptr);
+ _transition_subresources(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+
+ for (uint32_t i = 0; i < p_subresources.mipmap_count; i++) {
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = _make_ranged_uav_for_texture(tex_info, p_subresources.base_mipmap + i, p_subresources.base_layer, p_subresources.layer_count, false);
+ device->CreateUnorderedAccessView(
+ tex_info->resource,
+ nullptr,
+ &uav_desc,
+ frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle());
+ device->CopyDescriptorsSimple(
+ 1,
+ frames[frame_idx].desc_heap_walkers.resources.get_curr_cpu_handle(),
+ frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle(),
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ UINT values[4] = {
+ (UINT)p_color.get_r8(),
+ (UINT)p_color.get_g8(),
+ (UINT)p_color.get_b8(),
+ (UINT)p_color.get_a8(),
+ };
+ cmd_buf_info->cmd_list->ClearUnorderedAccessViewUint(
+ frames[frame_idx].desc_heap_walkers.resources.get_curr_gpu_handle(),
+ frames[frame_idx].desc_heap_walkers.aux.get_curr_cpu_handle(),
+ tex_info->resource,
+ values,
+ 0,
+ nullptr);
- frames[frame_idx].desc_heap_walkers.resources.advance();
- frames[frame_idx].desc_heap_walkers.aux.advance();
+ frames[frame_idx].desc_heap_walkers.resources.advance();
+ frames[frame_idx].desc_heap_walkers.aux.advance();
+ }
}
}
@@ -4429,7 +4542,7 @@ void RenderingDeviceDriverD3D12::command_copy_buffer_to_texture(CommandBufferID
TextureInfo *tex_info = (TextureInfo *)p_dst_texture.id;
if (buf_info->flags.is_for_upload) {
- _resource_transition_batch(buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_SOURCE, nullptr);
+ _resource_transition_batch(buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_SOURCE);
}
uint32_t pixel_size = get_image_format_pixel_size(tex_info->format);
@@ -4465,7 +4578,7 @@ void RenderingDeviceDriverD3D12::command_copy_buffer_to_texture(CommandBufferID
tex_info->desc.ArraySize());
CD3DX12_TEXTURE_COPY_LOCATION copy_dst(tex_info->resource, dst_subresource);
- _resource_transition_batch(tex_info, dst_subresource, 1, D3D12_RESOURCE_STATE_COPY_DEST, tex_info->main_texture);
+ _resource_transition_batch(tex_info, dst_subresource, 1, D3D12_RESOURCE_STATE_COPY_DEST);
}
_resource_transitions_flush(cmd_buf_info->cmd_list.Get());
@@ -4490,12 +4603,12 @@ void RenderingDeviceDriverD3D12::command_copy_buffer_to_texture(CommandBufferID
}
}
-void RenderingDeviceDriverD3D12::command_copy_texture_to_buffer(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, BufferID p_dst_buffer, VectorView<BufferTextureCopyRegion> p_regions) {
+void RenderingDeviceDriverD3D12::command_copy_texture_to_buffer(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, BufferID p_buf_locfer, VectorView<BufferTextureCopyRegion> p_regions) {
const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)p_cmd_buffer.id;
TextureInfo *tex_info = (TextureInfo *)p_src_texture.id;
- BufferInfo *buf_info = (BufferInfo *)p_dst_buffer.id;
+ BufferInfo *buf_info = (BufferInfo *)p_buf_locfer.id;
- _resource_transition_batch(buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_DEST, nullptr);
+ _resource_transition_batch(buf_info, 0, 1, D3D12_RESOURCE_STATE_COPY_DEST);
uint32_t block_w = 0, block_h = 0;
get_compressed_image_format_block_dimensions(tex_info->format, block_w, block_h);
@@ -4509,7 +4622,7 @@ void RenderingDeviceDriverD3D12::command_copy_texture_to_buffer(CommandBufferID
tex_info->desc.MipLevels,
tex_info->desc.ArraySize());
- _resource_transition_batch(tex_info, src_subresource, 1, D3D12_RESOURCE_STATE_COPY_SOURCE, tex_info->main_texture);
+ _resource_transition_batch(tex_info, src_subresource, 1, D3D12_RESOURCE_STATE_COPY_SOURCE);
}
_resource_transitions_flush(cmd_buf_info->cmd_list.Get());
@@ -4657,7 +4770,7 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
0,
p_texture_info->desc.MipLevels,
p_texture_info->desc.ArraySize());
- _resource_transition_batch(p_texture_info, subresource, planes, p_states, nullptr);
+ _resource_transition_batch(p_texture_info, subresource, planes, p_states);
}
}
};
@@ -6125,7 +6238,15 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
}
if (format_capabilities.relaxed_casting_supported) {
+#if 0
print_verbose("- Relaxed casting supported");
+#else
+ // Certain configurations (Windows 11 with an updated Nvida driver) crash when using relaxed casting.
+ // Therefore, we disable it temporarily until we can assure that it's reliable.
+ // There are fallbacks in place that work in every case, if less efficient.
+ format_capabilities.relaxed_casting_supported = false;
+ print_verbose("- Relaxed casting supported (but disabled for now)");
+#endif
} else {
print_verbose("- Relaxed casting not supported");
}
@@ -6171,6 +6292,7 @@ Error RenderingDeviceDriverD3D12::_initialize_allocator() {
D3D12MA::ALLOCATOR_DESC allocator_desc = {};
allocator_desc.pDevice = device.Get();
allocator_desc.pAdapter = adapter.Get();
+ allocator_desc.Flags = D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED;
HRESULT res = D3D12MA::CreateAllocator(&allocator_desc, &allocator);
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12MA::CreateAllocator failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h
index 06d5cb65c4..852cb9db0e 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.h
+++ b/drivers/d3d12/rendering_device_driver_d3d12.h
@@ -33,6 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/paged_allocator.h"
+#include "core/templates/self_list.h"
#include "servers/rendering/rendering_device_driver.h"
#if defined(__GNUC__) && !defined(__clang__)
@@ -215,17 +216,21 @@ private:
struct States {
// As many subresources as mipmaps * layers; planes (for depth-stencil) are tracked together.
TightLocalVector<D3D12_RESOURCE_STATES> subresource_states; // Used only if not a view.
- uint32_t last_batch_transitioned_to_uav = 0;
uint32_t last_batch_with_uav_barrier = 0;
+ struct CrossFamillyFallback {
+ TightLocalVector<uint64_t> subresources_dirty;
+ ComPtr<ID3D12Resource> interim_buffer;
+ ComPtr<D3D12MA::Allocation> interim_buffer_alloc;
+ } xfamily_fallback; // [[CROSS_FAMILY_FALLBACK]].
};
- ID3D12Resource *resource = nullptr; // Non-null even if a view.
+ ID3D12Resource *resource = nullptr; // Non-null even if not owned.
struct {
ComPtr<ID3D12Resource> resource;
ComPtr<D3D12MA::Allocation> allocation;
States states;
- } owner_info; // All empty if a view.
- States *states_ptr = nullptr; // Own or from another if a view.
+ } owner_info; // All empty if the resource is not owned.
+ States *states_ptr = nullptr; // Own or from another if it doesn't own the D3D12 resource.
};
struct BarrierRequest {
@@ -257,7 +262,7 @@ private:
uint64_t frame_barriers_cpu_time = 0;
#endif
- void _resource_transition_batch(ResourceInfo *p_resource, uint32_t p_subresource, uint32_t p_num_planes, D3D12_RESOURCE_STATES p_new_state, ID3D12Resource *p_resource_override = nullptr);
+ void _resource_transition_batch(ResourceInfo *p_resource, uint32_t p_subresource, uint32_t p_num_planes, D3D12_RESOURCE_STATES p_new_state);
void _resource_transitions_flush(ID3D12GraphicsCommandList *p_cmd_list);
/*****************/
@@ -298,16 +303,12 @@ private:
D3D12_UNORDERED_ACCESS_VIEW_DESC uav;
} view_descs = {};
- ID3D12Resource *main_texture = nullptr;
- struct {
- D3D12_UNORDERED_ACCESS_VIEW_DESC main_uav_desc;
- struct {
- HashMap<DXGI_FORMAT, ComPtr<ID3D12Resource>> aliases; // Key is the DXGI format family.
- } owner_info = {};
- } aliasing_hack = {}; // [[CROSS_FAMILY_ALIASING]]
+ TextureInfo *main_texture = nullptr;
UINT mapped_subresource = UINT_MAX;
+ SelfList<TextureInfo> pending_clear{ this };
};
+ SelfList<TextureInfo>::List textures_pending_clear;
HashMap<DXGI_FORMAT, uint32_t> format_sample_counts_mask_cache;
@@ -331,6 +332,10 @@ public:
virtual void texture_unmap(TextureID p_texture) override final;
virtual BitField<TextureUsageBits> texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) override final;
+private:
+ TextureID _texture_create_shared_from_slice(TextureID p_original_texture, const TextureView &p_view, TextureSliceType p_slice_type, uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps);
+
+public:
/*****************/
/**** SAMPLER ****/
/*****************/
@@ -459,6 +464,16 @@ private:
RenderPassState render_pass_state;
bool descriptor_heaps_set = false;
+
+ // [[CROSS_FAMILY_FALLBACK]].
+ struct FamilyFallbackCopy {
+ TextureInfo *texture = nullptr;
+ uint32_t subresource = 0;
+ uint32_t mipmap = 0;
+ D3D12_RESOURCE_STATES dst_wanted_state = {};
+ };
+ LocalVector<FamilyFallbackCopy> family_fallback_copies;
+ uint32_t family_fallback_copy_count = 0;
};
public:
@@ -513,6 +528,7 @@ private:
};
D3D12_RENDER_TARGET_VIEW_DESC _make_rtv_for_texture(const TextureInfo *p_texture_info, uint32_t p_mipmap_offset, uint32_t p_layer_offset, uint32_t p_layers, bool p_add_bases = true);
+ D3D12_UNORDERED_ACCESS_VIEW_DESC _make_ranged_uav_for_texture(const TextureInfo *p_texture_info, uint32_t p_mipmap_offset, uint32_t p_layer_offset, uint32_t p_layers, bool p_add_bases = true);
D3D12_DEPTH_STENCIL_VIEW_DESC _make_dsv_for_texture(const TextureInfo *p_texture_info);
FramebufferID _framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height, bool p_is_screen);
@@ -758,6 +774,7 @@ public:
virtual void command_resolve_texture(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, uint32_t p_src_layer, uint32_t p_src_mipmap, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, uint32_t p_dst_layer, uint32_t p_dst_mipmap) override final;
virtual void command_clear_color_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, const Color &p_color, const TextureSubresourceRange &p_subresources) override final;
+public:
virtual void command_copy_buffer_to_texture(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, VectorView<BufferTextureCopyRegion> p_regions) override final;
virtual void command_copy_texture_to_buffer(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, BufferID p_dst_buffer, VectorView<BufferTextureCopyRegion> p_regions) override final;
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index b4ef0f8c4a..e594d53d69 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -33,6 +33,7 @@
#include "core/authors.gen.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
+#include "core/os/time.h"
#include "core/version.h"
#include "editor/editor_string_names.h"
#include "editor/themes/editor_scale.h"
@@ -206,7 +207,14 @@ EditorAbout::EditorAbout() {
// Set the text to copy in metadata as it slightly differs from the button's text.
version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash);
version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- version_btn->set_tooltip_text(TTR("Click to copy."));
+ String build_date;
+ if (VERSION_TIMESTAMP > 0) {
+ build_date = Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC";
+ } else {
+ build_date = TTR("(unknown)");
+ }
+ version_btn->set_tooltip_text(vformat(TTR("Git commit date: %s\nClick to copy the version number."), build_date));
+
version_btn->connect("pressed", callable_mp(this, &EditorAbout::_version_button_pressed));
version_info_vbc->add_child(version_btn);
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 7d0024b1da..2920cf19c0 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -143,7 +143,11 @@ void EditorPluginSettings::_plugin_activity_changed() {
ti->set_checked(COLUMN_STATUS, is_enabled);
updating = false;
}
- ti->set_custom_color(COLUMN_NAME, is_enabled ? Color() : get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
+ if (is_enabled) {
+ ti->clear_custom_color(COLUMN_NAME);
+ } else {
+ ti->set_custom_color(COLUMN_NAME, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
+ }
}
void EditorPluginSettings::_create_clicked() {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 199fa3f6c9..d76f55564b 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -756,6 +756,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Polygon editor
_initial_set("editors/polygon_editor/point_grab_radius", has_touchscreen_ui ? 32 : 8);
_initial_set("editors/polygon_editor/show_previous_outline", true);
+ EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/polygon_editor/auto_bake_delay", 1.5, "-1.0,10.0,0.01");
// Animation
_initial_set("editors/animation/autorename_animation_tracks", true);
diff --git a/editor/gui/editor_bottom_panel.cpp b/editor/gui/editor_bottom_panel.cpp
index 1cf9daa545..ab7e05b915 100644
--- a/editor/gui/editor_bottom_panel.cpp
+++ b/editor/gui/editor_bottom_panel.cpp
@@ -30,6 +30,7 @@
#include "editor_bottom_panel.h"
+#include "core/os/time.h"
#include "core/version.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_about.h"
@@ -253,7 +254,13 @@ EditorBottomPanel::EditorBottomPanel() {
// Fade out the version label to be less prominent, but still readable.
version_btn->set_self_modulate(Color(1, 1, 1, 0.65));
version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- version_btn->set_tooltip_text(TTR("Click to copy."));
+ String build_date;
+ if (VERSION_TIMESTAMP > 0) {
+ build_date = Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC";
+ } else {
+ build_date = TTR("(unknown)");
+ }
+ version_btn->set_tooltip_text(vformat(TTR("Git commit date: %s\nClick to copy the version information."), build_date));
version_btn->connect("pressed", callable_mp(this, &EditorBottomPanel::_version_button_pressed));
version_info_vbox->add_child(version_btn);
diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp
index 38977d11e0..ca128968de 100644
--- a/editor/import/3d/resource_importer_scene.cpp
+++ b/editor/import/3d/resource_importer_scene.cpp
@@ -37,14 +37,15 @@
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/import/3d/scene_import_settings.h"
-#include "scene/3d/area_3d.h"
-#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/occluder_instance_3d.h"
-#include "scene/3d/physics_body_3d.h"
-#include "scene/3d/vehicle_body_3d.h"
+#include "scene/3d/physics/area_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
+#include "scene/3d/physics/vehicle_body_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/3d/box_shape_3d.h"
#include "scene/resources/3d/importer_mesh.h"
diff --git a/editor/plugins/cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index a6457e38a7..64db19d85e 100644
--- a/editor/plugins/cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -33,8 +33,8 @@
#include "canvas_item_editor_plugin.h"
#include "editor/editor_node.h"
#include "editor/editor_undo_redo_manager.h"
-#include "scene/2d/ray_cast_2d.h"
-#include "scene/2d/shape_cast_2d.h"
+#include "scene/2d/physics/ray_cast_2d.h"
+#include "scene/2d/physics/shape_cast_2d.h"
void Cast2DEditor::_notification(int p_what) {
switch (p_what) {
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h
index 070a01f651..61e6cc3dda 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -32,7 +32,7 @@
#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
#include "editor/plugins/abstract_polygon_2d_editor.h"
-#include "scene/2d/collision_polygon_2d.h"
+#include "scene/2d/physics/collision_polygon_2d.h"
class CollisionPolygon2DEditor : public AbstractPolygon2DEditor {
GDCLASS(CollisionPolygon2DEditor, AbstractPolygon2DEditor);
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index d58f5d511f..0e454799d6 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -32,7 +32,7 @@
#define COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/2d/collision_shape_2d.h"
+#include "scene/2d/physics/collision_shape_2d.h"
class CanvasItemEditor;
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index 5077827ce8..ffcf53af66 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -32,8 +32,8 @@
#define CPU_PARTICLES_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/2d/collision_polygon_2d.h"
#include "scene/2d/cpu_particles_2d.h"
+#include "scene/2d/physics/collision_polygon_2d.h"
#include "scene/gui/box_container.h"
class CheckBox;
diff --git a/editor/plugins/gizmos/collision_object_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_object_3d_gizmo_plugin.cpp
index 63f2883ed7..caac143f23 100644
--- a/editor/plugins/gizmos/collision_object_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/collision_object_3d_gizmo_plugin.cpp
@@ -32,9 +32,9 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/collision_object_3d.h"
-#include "scene/3d/collision_polygon_3d.h"
-#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/physics/collision_object_3d.h"
+#include "scene/3d/physics/collision_polygon_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
#include "scene/resources/surface_tool.h"
CollisionObject3DGizmoPlugin::CollisionObject3DGizmoPlugin() {
diff --git a/editor/plugins/gizmos/collision_polygon_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_polygon_3d_gizmo_plugin.cpp
index 50c10be11d..7d19e8f677 100644
--- a/editor/plugins/gizmos/collision_polygon_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/collision_polygon_3d_gizmo_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/collision_polygon_3d.h"
+#include "scene/3d/physics/collision_polygon_3d.h"
CollisionPolygon3DGizmoPlugin::CollisionPolygon3DGizmoPlugin() {
const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
index 3cf9164460..9d4c08ed57 100644
--- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
@@ -36,7 +36,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
#include "scene/resources/3d/box_shape_3d.h"
#include "scene/resources/3d/capsule_shape_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
diff --git a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
index 3a8a0cff96..c15ddef933 100644
--- a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
@@ -33,7 +33,11 @@
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/joint_3d.h"
+#include "scene/3d/physics/joints/cone_twist_joint_3d.h"
+#include "scene/3d/physics/joints/generic_6dof_joint_3d.h"
+#include "scene/3d/physics/joints/hinge_joint_3d.h"
+#include "scene/3d/physics/joints/pin_joint_3d.h"
+#include "scene/3d/physics/joints/slider_joint_3d.h"
#define BODY_A_RADIUS 0.25
#define BODY_B_RADIUS 0.27
diff --git a/editor/plugins/gizmos/physics_bone_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/physics_bone_3d_gizmo_plugin.cpp
index d1511a5f76..b15f9bec3f 100644
--- a/editor/plugins/gizmos/physics_bone_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/physics_bone_3d_gizmo_plugin.cpp
@@ -33,7 +33,8 @@
#include "editor/editor_settings.h"
#include "editor/plugins/gizmos/joint_3d_gizmo_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physical_bone_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
PhysicalBone3DGizmoPlugin::PhysicalBone3DGizmoPlugin() {
create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
diff --git a/editor/plugins/gizmos/ray_cast_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/ray_cast_3d_gizmo_plugin.cpp
index eb9e54fe1d..d783c4e4a7 100644
--- a/editor/plugins/gizmos/ray_cast_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/ray_cast_3d_gizmo_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/ray_cast_3d.h"
+#include "scene/3d/physics/ray_cast_3d.h"
RayCast3DGizmoPlugin::RayCast3DGizmoPlugin() {
const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
diff --git a/editor/plugins/gizmos/shape_cast_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/shape_cast_3d_gizmo_plugin.cpp
index 23a224fc01..909f5b5f9a 100644
--- a/editor/plugins/gizmos/shape_cast_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/shape_cast_3d_gizmo_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/shape_cast_3d.h"
+#include "scene/3d/physics/shape_cast_3d.h"
ShapeCast3DGizmoPlugin::ShapeCast3DGizmoPlugin() {
const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
diff --git a/editor/plugins/gizmos/spring_arm_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/spring_arm_3d_gizmo_plugin.cpp
index 69acac5a89..85e2c86947 100644
--- a/editor/plugins/gizmos/spring_arm_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/spring_arm_3d_gizmo_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/spring_arm_3d.h"
+#include "scene/3d/physics/spring_arm_3d.h"
#include "scene/resources/3d/shape_3d.h"
void SpringArm3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
diff --git a/editor/plugins/gizmos/vehicle_body_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/vehicle_body_3d_gizmo_plugin.cpp
index ef6cd88868..69e87a55c0 100644
--- a/editor/plugins/gizmos/vehicle_body_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/vehicle_body_3d_gizmo_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/vehicle_body_3d.h"
+#include "scene/3d/physics/vehicle_body_3d.h"
VehicleWheel3DGizmoPlugin::VehicleWheel3DGizmoPlugin() {
Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index 237a005ab7..f202179eff 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -32,8 +32,8 @@
#define GPU_PARTICLES_2D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/2d/collision_polygon_2d.h"
#include "scene/2d/gpu_particles_2d.h"
+#include "scene/2d/physics/collision_polygon_2d.h"
#include "scene/gui/box_container.h"
#include "scene/gui/spin_box.h"
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 061b839ee3..d62eddeeea 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -35,9 +35,10 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/themes/editor_scale.h"
-#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/navigation_region_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
#include "scene/gui/box_container.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 4e45714174..8bfd3d0957 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -40,7 +40,8 @@
#include "main/main.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
#include "scene/gui/menu_button.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
diff --git a/editor/plugins/navigation_obstacle_3d_editor_plugin.h b/editor/plugins/navigation_obstacle_3d_editor_plugin.h
index 175fc75612..74094dc86f 100644
--- a/editor/plugins/navigation_obstacle_3d_editor_plugin.h
+++ b/editor/plugins/navigation_obstacle_3d_editor_plugin.h
@@ -32,8 +32,8 @@
#define NAVIGATION_OBSTACLE_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/physics/collision_polygon_3d.h"
#include "scene/gui/box_container.h"
#include "scene/resources/immediate_mesh.h"
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index 48335f3b94..04133072be 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "navigation_polygon_editor_plugin.h"
#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/2d/navigation_region_2d.h"
#include "scene/gui/dialogs.h"
@@ -50,6 +51,13 @@ Node2D *NavigationPolygonEditor::_get_node() const {
void NavigationPolygonEditor::_set_node(Node *p_polygon) {
node = Object::cast_to<NavigationRegion2D>(p_polygon);
+ if (node) {
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (navpoly.is_valid() && navpoly->get_outline_count() > 0 && navpoly->get_polygon_count() == 0) {
+ // We have outlines drawn / added by the user but no polygons were created for this navmesh yet so let's bake once immediately.
+ _rebake_timer_timeout();
+ }
+ }
}
int NavigationPolygonEditor::_get_polygon_count() const {
@@ -73,6 +81,10 @@ Variant NavigationPolygonEditor::_get_polygon(int p_idx) const {
void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
Ref<NavigationPolygon> navpoly = _ensure_navpoly();
navpoly->set_outline(p_idx, p_polygon);
+
+ if (rebake_timer && _rebake_timer_delay >= 0.0) {
+ rebake_timer->start();
+ }
}
void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) {
@@ -80,6 +92,10 @@ void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_method(navpoly.ptr(), "add_outline", p_polygon);
undo_redo->add_undo_method(navpoly.ptr(), "remove_outline", navpoly->get_outline_count());
+
+ if (rebake_timer && _rebake_timer_delay >= 0.0) {
+ rebake_timer->start();
+ }
}
void NavigationPolygonEditor::_action_remove_polygon(int p_idx) {
@@ -87,6 +103,10 @@ void NavigationPolygonEditor::_action_remove_polygon(int p_idx) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_method(navpoly.ptr(), "remove_outline", p_idx);
undo_redo->add_undo_method(navpoly.ptr(), "add_outline_at_index", navpoly->get_outline(p_idx), p_idx);
+
+ if (rebake_timer && _rebake_timer_delay >= 0.0) {
+ rebake_timer->start();
+ }
}
void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
@@ -94,6 +114,10 @@ void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_pr
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_method(navpoly.ptr(), "set_outline", p_idx, p_polygon);
undo_redo->add_undo_method(navpoly.ptr(), "set_outline", p_idx, p_previous);
+
+ if (rebake_timer && _rebake_timer_delay >= 0.0) {
+ rebake_timer->start();
+ }
}
bool NavigationPolygonEditor::_has_resource() const {
@@ -136,6 +160,15 @@ NavigationPolygonEditor::NavigationPolygonEditor() {
bake_info = memnew(Label);
bake_hbox->add_child(bake_info);
+ rebake_timer = memnew(Timer);
+ add_child(rebake_timer);
+ rebake_timer->set_one_shot(true);
+ _rebake_timer_delay = EDITOR_GET("editors/polygon_editor/auto_bake_delay");
+ if (_rebake_timer_delay >= 0.0) {
+ rebake_timer->set_wait_time(_rebake_timer_delay);
+ }
+ rebake_timer->connect("timeout", callable_mp(this, &NavigationPolygonEditor::_rebake_timer_timeout));
+
err_dialog = memnew(AcceptDialog);
add_child(err_dialog);
node = nullptr;
@@ -147,15 +180,26 @@ void NavigationPolygonEditor::_notification(int p_what) {
button_bake->set_icon(get_theme_icon(SNAME("Bake"), SNAME("EditorIcons")));
button_reset->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
} break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ if (rebake_timer) {
+ _rebake_timer_delay = EDITOR_GET("editors/polygon_editor/auto_bake_delay");
+ if (_rebake_timer_delay >= 0.0) {
+ rebake_timer->set_wait_time(_rebake_timer_delay);
+ }
+ }
+ } break;
}
}
void NavigationPolygonEditor::_bake_pressed() {
+ if (rebake_timer) {
+ rebake_timer->stop();
+ }
button_bake->set_pressed(false);
ERR_FAIL_NULL(node);
Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
- if (!navigation_polygon.is_valid()) {
+ if (navigation_polygon.is_null()) {
err_dialog->set_text(TTR("A NavigationPolygon resource must be set or created for this node to work."));
err_dialog->popup_centered();
return;
@@ -167,6 +211,9 @@ void NavigationPolygonEditor::_bake_pressed() {
}
void NavigationPolygonEditor::_clear_pressed() {
+ if (rebake_timer) {
+ rebake_timer->stop();
+ }
if (node) {
if (node->get_navigation_polygon().is_valid()) {
node->get_navigation_polygon()->clear();
@@ -193,6 +240,19 @@ void NavigationPolygonEditor::_update_polygon_editing_state() {
}
}
+void NavigationPolygonEditor::_rebake_timer_timeout() {
+ if (!node) {
+ return;
+ }
+ Ref<NavigationPolygon> navigation_polygon = node->get_navigation_polygon();
+ if (!navigation_polygon.is_valid()) {
+ return;
+ }
+
+ node->bake_navigation_polygon(true);
+ node->queue_redraw();
+}
+
NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin() :
AbstractPolygon2DEditorPlugin(memnew(NavigationPolygonEditor), "NavigationRegion2D") {
}
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
index f1d0cd8751..bf2474bc55 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -56,6 +56,10 @@ class NavigationPolygonEditor : public AbstractPolygon2DEditor {
Button *button_reset = nullptr;
Label *bake_info = nullptr;
+ Timer *rebake_timer = nullptr;
+ float _rebake_timer_delay = 1.5;
+ void _rebake_timer_timeout();
+
void _bake_pressed();
void _clear_pressed();
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 26e33f5796..aa0069979c 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -78,11 +78,11 @@
#include "editor/plugins/node_3d_editor_gizmos.h"
#include "editor/scene_tree_dock.h"
#include "scene/3d/camera_3d.h"
-#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/decal.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
#include "scene/gui/center_container.h"
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index 37092f924e..b7c12ab5c0 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_node.h"
#include "editor/editor_string_names.h"
#include "editor/plugins/node_3d_editor_plugin.h"
+#include "scene/3d/physics/physical_bone_3d.h"
#include "scene/gui/separator.h"
void PhysicalBone3DEditor::_bind_methods() {
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h
index c9799d3faa..5c49e641a5 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.h
+++ b/editor/plugins/physical_bone_3d_editor_plugin.h
@@ -32,10 +32,11 @@
#define PHYSICAL_BONE_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/3d/physics_body_3d.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
+class PhysicalBone3D;
+
class PhysicalBone3DEditor : public Object {
GDCLASS(PhysicalBone3DEditor, Object);
diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h
index 6407e33f48..85cfd807e4 100644
--- a/editor/plugins/polygon_3d_editor_plugin.h
+++ b/editor/plugins/polygon_3d_editor_plugin.h
@@ -32,8 +32,8 @@
#define POLYGON_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/physics/collision_polygon_3d.h"
#include "scene/gui/box_container.h"
#include "scene/resources/immediate_mesh.h"
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 701e848be1..ffc59a3429 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -40,10 +40,11 @@
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/themes/editor_scale.h"
-#include "scene/3d/collision_shape_3d.h"
-#include "scene/3d/joint_3d.h"
#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/joints/joint_3d.h"
+#include "scene/3d/physics/physical_bone_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/3d/capsule_shape_3d.h"
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index 3e98f3d64f..de81264f13 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -38,9 +38,9 @@
#include "editor/gui/editor_zoom_widget.h"
#include "editor/scene_tree_dock.h"
#include "editor/themes/editor_scale.h"
-#include "scene/2d/collision_polygon_2d.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/mesh_instance_2d.h"
+#include "scene/2d/physics/collision_polygon_2d.h"
#include "scene/2d/polygon_2d.h"
#include "scene/gui/box_container.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 80490c9388..5845ddbb6e 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -641,6 +641,7 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event)
undo_redo->add_undo_method(base_control, "queue_redraw");
undo_redo->commit_action(false);
emit_signal(SNAME("polygons_changed"));
+ drag_type = DRAG_TYPE_NONE;
} else {
drag_type = DRAG_TYPE_PAN;
drag_last_pos = mb->get_position();
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index e7bf812a6c..fb31ace2e0 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -69,9 +69,6 @@ void TilesEditorUtils::_thread_func(void *ud) {
}
void TilesEditorUtils::_thread() {
- CallQueue queue;
- MessageQueue::set_thread_singleton_override(&queue);
-
pattern_thread_exited.clear();
while (!pattern_thread_exit.is_set()) {
pattern_preview_sem.wait();
@@ -131,8 +128,6 @@ void TilesEditorUtils::_thread() {
// Add the viewport at the last moment to avoid rendering too early.
callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(viewport, false, Node::INTERNAL_MODE_DISABLED);
- MessageQueue::get_singleton()->flush();
-
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorUtils *>(this), &TilesEditorUtils::_preview_frame_started), Object::CONNECT_ONE_SHOT);
pattern_preview_done.wait();
@@ -145,11 +140,7 @@ void TilesEditorUtils::_thread() {
viewport->queue_free();
}
}
-
- MessageQueue::get_singleton()->flush();
}
-
- MessageQueue::get_singleton()->flush();
pattern_thread_exited.set();
}
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 6f7d571792..4187bf5a32 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -38,6 +38,7 @@
#include "core/io/stream_peer_tls.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
+#include "core/os/time.h"
#include "core/version.h"
#include "editor/editor_about.h"
#include "editor/editor_settings.h"
@@ -1350,7 +1351,13 @@ ProjectManager::ProjectManager() {
// Fade the version label to be less prominent, but still readable.
version_btn->set_self_modulate(Color(1, 1, 1, 0.6));
version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- version_btn->set_tooltip_text(TTR("Click to copy the version information."));
+ String build_date;
+ if (VERSION_TIMESTAMP > 0) {
+ build_date = Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC";
+ } else {
+ build_date = TTR("(unknown)");
+ }
+ version_btn->set_tooltip_text(vformat(TTR("Git commit date: %s\nClick to copy the version information."), build_date));
version_btn->connect("pressed", callable_mp(this, &ProjectManager::_version_button_pressed));
footer_bar->add_child(version_btn);
}
diff --git a/main/main.cpp b/main/main.cpp
index c520ebecd3..91ccbe6766 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -393,6 +393,23 @@ void finalize_theme_db() {
#define MAIN_PRINT(m_txt)
#endif
+void Main::print_header(bool p_rich) {
+ if (VERSION_TIMESTAMP > 0) {
+ // Version timestamp available.
+ if (p_rich) {
+ print_line_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - \u001b[4m" + String(VERSION_WEBSITE));
+ } else {
+ print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - " + String(VERSION_WEBSITE));
+ }
+ } else {
+ if (p_rich) {
+ print_line_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " - \u001b[4m" + String(VERSION_WEBSITE));
+ } else {
+ print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+ }
+ }
+}
+
/**
* Prints a copyright notice in the command-line help with colored text. A newline is
* automatically added at the end.
@@ -463,7 +480,7 @@ void Main::print_help_option(const char *p_option, const char *p_description, CL
}
void Main::print_help(const char *p_binary) {
- print_line("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " - \u001b[4m" + String(VERSION_WEBSITE) + "\u001b[0m");
+ print_header(true);
print_help_copyright("Free and open source software under the terms of the MIT license.");
print_help_copyright("(c) 2014-present Godot Engine contributors. (c) 2007-present Juan Linietsky, Ariel Manzur.");
@@ -2468,8 +2485,8 @@ Error Main::setup2() {
Thread::make_main_thread(); // Make whatever thread call this the main thread.
set_current_thread_safe_for_nodes(true);
- // Print engine name and version
- Engine::get_singleton()->print_header(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+ // Don't use rich formatting to prevent ANSI escape codes from being written to log files.
+ print_header(false);
#ifdef TOOLS_ENABLED
if (editor || project_manager || cmdline_tool) {
diff --git a/main/main.h b/main/main.h
index 09cc0feae6..062af73d57 100644
--- a/main/main.h
+++ b/main/main.h
@@ -46,6 +46,7 @@ class Main {
CLI_OPTION_AVAILABILITY_HIDDEN,
};
+ static void print_header(bool p_rich);
static void print_help_copyright(const char *p_notice);
static void print_help_title(const char *p_title);
static void print_help_option(const char *p_option, const char *p_description, CLIOptionAvailability p_availability = CLI_OPTION_AVAILABILITY_TEMPLATE_RELEASE);
diff --git a/methods.py b/methods.py
index 69d8df1d72..c85e6825da 100644
--- a/methods.py
+++ b/methods.py
@@ -209,6 +209,18 @@ def get_version_info(module_version_string="", silent=False):
githash = head
version_info["git_hash"] = githash
+ # Fallback to 0 as a timestamp (will be treated as "unknown" in the engine).
+ version_info["git_timestamp"] = 0
+
+ # Get the UNIX timestamp of the build commit.
+ if os.path.exists(".git"):
+ try:
+ version_info["git_timestamp"] = subprocess.check_output(
+ ["git", "log", "-1", "--pretty=format:%ct", githash]
+ ).decode("utf-8")
+ except (subprocess.CalledProcessError, OSError):
+ # `git` not found in PATH.
+ pass
return version_info
@@ -246,6 +258,7 @@ def generate_version_header(module_version_string=""):
"""/* THIS FILE IS GENERATED DO NOT EDIT */
#include "core/version.h"
const char *const VERSION_HASH = "{git_hash}";
+const uint64_t VERSION_TIMESTAMP = {git_timestamp};
""".format(
**version_info
)
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 4b009f1866..7ececce613 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -597,6 +597,17 @@
[/codeblock]
</description>
</annotation>
+ <annotation name="@export_storage">
+ <return type="void" />
+ <description>
+ Export a property with [constant PROPERTY_USAGE_STORAGE] flag. The property is not displayed in the editor, but it is serialized and stored in the scene or resource file. This can be useful for [annotation @tool] scripts. Also the property value is copied when [method Resource.duplicate] or [method Node.duplicate] is called, unlike non-exported variables.
+ [codeblock]
+ var a # Not stored in the file, not displayed in the editor.
+ @export_storage var b # Stored in the file, not displayed in the editor.
+ @export var c: int # Stored in the file, displayed in the editor.
+ [/codeblock]
+ </description>
+ </annotation>
<annotation name="@export_subgroup">
<return type="void" />
<param index="0" name="name" type="String" />
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index f63b2ce0ee..4d4eadf0fa 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -101,6 +101,7 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
// Export annotations.
register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
+ register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::NIL>, varray(), true);
register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>);
@@ -4085,11 +4086,11 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
}
hint_string += arg_string;
}
-
variable->export_info.hint_string = hint_string;
// This is called after the analyzer is done finding the type, so this should be set here.
DataType export_type = variable->get_datatype();
+ bool use_default_variable_type_check = true;
if (p_annotation->name == SNAME("@export_range")) {
if (export_type.builtin_type == Variant::INT) {
@@ -4121,11 +4122,9 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
return true;
}
- }
+ } else if (p_annotation->name == SNAME("@export")) {
+ use_default_variable_type_check = false;
- // WARNING: Do not merge with the previous `else if`! Otherwise `else` (default variable type check)
- // will not work for the above annotations. `@export` and `@export_enum` validate the type separately.
- if (p_annotation->name == SNAME("@export")) {
if (variable->datatype_specifier == nullptr && variable->initializer == nullptr) {
push_error(R"(Cannot use simple "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation);
return false;
@@ -4243,6 +4242,8 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
variable->export_info.type = Variant::ARRAY;
}
} else if (p_annotation->name == SNAME("@export_enum")) {
+ use_default_variable_type_check = false;
+
Variant::Type enum_type = Variant::INT;
if (export_type.kind == DataType::BUILTIN && export_type.builtin_type == Variant::STRING) {
@@ -4260,7 +4261,15 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
push_error(vformat(R"("@export_enum" annotation requires a variable of type "int" or "String" but type "%s" was given instead.)", export_type.to_string()), variable);
return false;
}
- } else {
+ } else if (p_annotation->name == SNAME("@export_storage")) {
+ use_default_variable_type_check = false; // Can be applied to a variable of any type.
+
+ // Save the info because the compiler uses export info for overwriting member info.
+ variable->export_info = export_type.to_property_info(variable->identifier->name);
+ variable->export_info.usage |= PROPERTY_USAGE_STORAGE;
+ }
+
+ if (use_default_variable_type_check) {
// Validate variable type with export.
if (!export_type.is_variant() && (export_type.kind != DataType::BUILTIN || export_type.builtin_type != t_type)) {
// Allow float/int conversion.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd
index dafd2ec0c8..39f490c4b3 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd
@@ -4,14 +4,13 @@ enum MyEnum {A, B, C}
const Utils = preload("../../utils.notest.gd")
-@export var x1 = MyEnum
-@export var x2 = MyEnum.A
-@export var x3 := MyEnum
-@export var x4 := MyEnum.A
-@export var x5: MyEnum
+@export var test_1 = MyEnum
+@export var test_2 = MyEnum.A
+@export var test_3 := MyEnum
+@export var test_4 := MyEnum.A
+@export var test_5: MyEnum
func test():
for property in get_property_list():
- if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
- print(Utils.get_property_signature(property))
- print(" ", Utils.get_property_additional_info(property))
+ if str(property.name).begins_with("test_"):
+ Utils.print_property_extended_info(property)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
index f1a13f1045..505af5f1f3 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
@@ -1,11 +1,11 @@
GDTEST_OK
-@export var x1: Dictionary
+var test_1: Dictionary
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
-@export var x2: TestExportEnumAsDictionary.MyEnum
+var test_2: TestExportEnumAsDictionary.MyEnum
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
-@export var x3: Dictionary
+var test_3: Dictionary
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
-@export var x4: TestExportEnumAsDictionary.MyEnum
+var test_4: TestExportEnumAsDictionary.MyEnum
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
-@export var x5: TestExportEnumAsDictionary.MyEnum
+var test_5: TestExportEnumAsDictionary.MyEnum
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
diff --git a/modules/gdscript/tests/scripts/parser/features/annotations.gd b/modules/gdscript/tests/scripts/parser/features/annotations.gd
index 13c89a0a09..7a7d6d953e 100644
--- a/modules/gdscript/tests/scripts/parser/features/annotations.gd
+++ b/modules/gdscript/tests/scripts/parser/features/annotations.gd
@@ -1,48 +1,49 @@
extends Node
-@export_enum("A", "B", "C") var a0
-@export_enum("A", "B", "C",) var a1
+const Utils = preload("../../utils.notest.gd")
+
+@export_enum("A", "B", "C") var test_1
+@export_enum("A", "B", "C",) var test_2
@export_enum(
"A",
"B",
"C"
-) var a2
+) var test_3
@export_enum(
"A",
"B",
"C",
-) var a3
+) var test_4
@export
-var a4: int
+var test_5: int
@export()
-var a5: int
+var test_6: int
-@export() var a6: int
-@warning_ignore("onready_with_export") @onready @export var a7: int
-@warning_ignore("onready_with_export") @onready() @export() var a8: int
+@export() var test_7: int = 42
+@warning_ignore("onready_with_export") @onready @export var test_8: int = 42
+@warning_ignore("onready_with_export") @onready() @export() var test_9: int = 42
@warning_ignore("onready_with_export")
@onready
@export
-var a9: int
+var test_10: int = 42
@warning_ignore("onready_with_export")
@onready()
@export()
-var a10: int
+var test_11: int = 42
@warning_ignore("onready_with_export")
@onready()
@export()
-var a11: int
-
+var test_12: int = 42
func test():
for property in get_property_list():
- if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
- print(property)
+ if str(property.name).begins_with("test_"):
+ Utils.print_property_extended_info(property, self)
diff --git a/modules/gdscript/tests/scripts/parser/features/annotations.out b/modules/gdscript/tests/scripts/parser/features/annotations.out
index 3af0436c53..2ba9dd7496 100644
--- a/modules/gdscript/tests/scripts/parser/features/annotations.out
+++ b/modules/gdscript/tests/scripts/parser/features/annotations.out
@@ -1,13 +1,25 @@
GDTEST_OK
-{ "name": "a0", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 }
-{ "name": "a1", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 }
-{ "name": "a2", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 }
-{ "name": "a3", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 }
-{ "name": "a4", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a5", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a6", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a7", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a8", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a9", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a10", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "a11", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
+var test_1: int = null
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+var test_2: int = null
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+var test_3: int = null
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+var test_4: int = null
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+var test_5: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_6: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_7: int = 42
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_8: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_9: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_10: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_11: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_12: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.gd b/modules/gdscript/tests/scripts/parser/features/export_enum.gd
index 9b2c22dea1..4f2a43f4fe 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_enum.gd
+++ b/modules/gdscript/tests/scripts/parser/features/export_enum.gd
@@ -1,15 +1,16 @@
-@export_enum("Red", "Green", "Blue") var untyped
+const Utils = preload("../../utils.notest.gd")
-@export_enum("Red", "Green", "Blue") var weak_int = 0
-@export_enum("Red", "Green", "Blue") var weak_string = ""
+@export_enum("Red", "Green", "Blue") var test_untyped
-@export_enum("Red", "Green", "Blue") var hard_int: int
-@export_enum("Red", "Green", "Blue") var hard_string: String
+@export_enum("Red", "Green", "Blue") var test_weak_int = 0
+@export_enum("Red", "Green", "Blue") var test_weak_string = ""
-@export_enum("Red:10", "Green:20", "Blue:30") var with_values
+@export_enum("Red", "Green", "Blue") var test_hard_int: int
+@export_enum("Red", "Green", "Blue") var test_hard_string: String
+
+@export_enum("Red:10", "Green:20", "Blue:30") var test_with_values
func test():
for property in get_property_list():
- if property.name in ["untyped", "weak_int", "weak_string", "hard_int",
- "hard_string", "with_values"]:
- prints(property.name, property.type, property.hint_string)
+ if str(property.name).begins_with("test_"):
+ Utils.print_property_extended_info(property, self)
diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.out b/modules/gdscript/tests/scripts/parser/features/export_enum.out
index 330b7eaf01..43f5e197ad 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_enum.out
+++ b/modules/gdscript/tests/scripts/parser/features/export_enum.out
@@ -1,7 +1,13 @@
GDTEST_OK
-untyped 2 Red,Green,Blue
-weak_int 2 Red,Green,Blue
-weak_string 4 Red,Green,Blue
-hard_int 2 Red,Green,Blue
-hard_string 4 Red,Green,Blue
-with_values 2 Red:10,Green:20,Blue:30
+var test_untyped: int = null
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+var test_weak_int: int = 0
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+var test_weak_string: String = ""
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+var test_hard_int: int = 0
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+var test_hard_string: String = ""
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+var test_with_values: int = null
+ hint=ENUM hint_string="Red:10,Green:20,Blue:30" usage=DEFAULT|SCRIPT_VARIABLE
diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.gd b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
index c9d05a7e68..2a218774de 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_variable.gd
+++ b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
@@ -1,23 +1,22 @@
extends Node
-@export var example = 99
-@export_range(0, 100) var example_range = 100
-@export_range(0, 100, 1) var example_range_step = 101
-@export_range(0, 100, 1, "or_greater") var example_range_step_or_greater = 102
+const Utils = preload("../../utils.notest.gd")
-@export var color: Color
-@export_color_no_alpha var color_no_alpha: Color
-@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var nodepath := ^"hello"
-@export var node: Node
-@export var node_array: Array[Node]
+@export var test_weak_int = 1
+@export var test_hard_int: int = 2
+@export_storage var test_storage_untyped
+@export_storage var test_storage_weak_int = 3 # Property info still `Variant`, unlike `@export`.
+@export_storage var test_storage_hard_int: int = 4
+@export_range(0, 100) var test_range = 100
+@export_range(0, 100, 1) var test_range_step = 101
+@export_range(0, 100, 1, "or_greater") var test_range_step_or_greater = 102
+@export var test_color: Color
+@export_color_no_alpha var test_color_no_alpha: Color
+@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var test_node_path := ^"hello"
+@export var test_node: Node
+@export var test_node_array: Array[Node]
func test():
- print(example)
- print(example_range)
- print(example_range_step)
- print(example_range_step_or_greater)
- print(color)
- print(color_no_alpha)
- print(nodepath)
- print(node)
- print(var_to_str(node_array))
+ for property in get_property_list():
+ if str(property.name).begins_with("test_"):
+ Utils.print_property_extended_info(property, self)
diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.out b/modules/gdscript/tests/scripts/parser/features/export_variable.out
index 5430c975f4..baadcd4ee8 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_variable.out
+++ b/modules/gdscript/tests/scripts/parser/features/export_variable.out
@@ -1,10 +1,27 @@
GDTEST_OK
-99
-100
-101
-102
-(0, 0, 0, 1)
-(0, 0, 0, 1)
-hello
-<null>
-Array[Node]([])
+var test_weak_int: int = 1
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_hard_int: int = 2
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+var test_storage_untyped: Variant = null
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT
+var test_storage_weak_int: Variant = 3
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT
+var test_storage_hard_int: int = 4
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE
+var test_range: int = 100
+ hint=RANGE hint_string="0,100" usage=DEFAULT|SCRIPT_VARIABLE
+var test_range_step: int = 101
+ hint=RANGE hint_string="0,100,1" usage=DEFAULT|SCRIPT_VARIABLE
+var test_range_step_or_greater: int = 102
+ hint=RANGE hint_string="0,100,1,or_greater" usage=DEFAULT|SCRIPT_VARIABLE
+var test_color: Color = Color(0, 0, 0, 1)
+ hint=NONE hint_string="Color" usage=DEFAULT|SCRIPT_VARIABLE
+var test_color_no_alpha: Color = Color(0, 0, 0, 1)
+ hint=COLOR_NO_ALPHA hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+var test_node_path: NodePath = NodePath("hello")
+ hint=NODE_PATH_VALID_TYPES hint_string="Sprite2D,Sprite3D,Control,Node" usage=DEFAULT|SCRIPT_VARIABLE
+var test_node: Node = null
+ hint=NODE_TYPE hint_string="Node" usage=DEFAULT|SCRIPT_VARIABLE
+var test_node_array: Array = Array[Node]([])
+ hint=TYPE_STRING hint_string="24/34:Node" usage=DEFAULT|SCRIPT_VARIABLE
diff --git a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd
index e46f24cc5f..0133d7fcfc 100644
--- a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd
@@ -1,17 +1,17 @@
-extends RefCounted # TODO: Fix standalone annotations parsing.
+const Utils = preload("../../utils.notest.gd")
# GH-73843
@export_group("Resource")
# GH-78252
-@export var prop_1: int
-@export_category("prop_1")
-@export var prop_2: int
+@export var test_1: int
+@export_category("test_1")
+@export var test_2: int
func test():
var resource := Resource.new()
prints("Not shadowed:", resource.get_class())
for property in get_property_list():
- if property.name in ["prop_1", "prop_2"]:
- print(property)
+ if str(property.name).begins_with("test_"):
+ Utils.print_property_extended_info(property, self)
diff --git a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
index 96ae84e986..9387ec50d7 100644
--- a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
+++ b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
@@ -1,5 +1,8 @@
GDTEST_OK
Not shadowed: Resource
-{ "name": "prop_1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
-{ "name": "prop_1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 }
-{ "name": "prop_2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 }
+var test_1: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+@export_category("test_1")
+ hint=NONE hint_string="" usage=CATEGORY
+var test_2: int = 0
+ hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.gd b/modules/gdscript/tests/scripts/runtime/features/member_info.gd
index 805ea42455..6fe9647b4d 100644
--- a/modules/gdscript/tests/scripts/runtime/features/member_info.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info.gd
@@ -60,7 +60,7 @@ func test():
var script: Script = get_script()
for property in script.get_property_list():
if str(property.name).begins_with("test_"):
- print(Utils.get_property_signature(property, true))
+ print(Utils.get_property_signature(property, null, true))
for property in get_property_list():
if str(property.name).begins_with("test_"):
print(Utils.get_property_signature(property))
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.out b/modules/gdscript/tests/scripts/runtime/features/member_info.out
index 3a91507da9..7c826ac05a 100644
--- a/modules/gdscript/tests/scripts/runtime/features/member_info.out
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info.out
@@ -6,13 +6,13 @@ static var test_static_var_hard_int: int
var test_var_untyped: Variant
var test_var_weak_null: Variant
var test_var_weak_int: Variant
-@export var test_var_weak_int_exported: int
+var test_var_weak_int_exported: int
var test_var_weak_variant_type: Variant
-@export var test_var_weak_variant_type_exported: Variant.Type
+var test_var_weak_variant_type_exported: Variant.Type
var test_var_hard_variant: Variant
var test_var_hard_int: int
var test_var_hard_variant_type: Variant.Type
-@export var test_var_hard_variant_type_exported: Variant.Type
+var test_var_hard_variant_type_exported: Variant.Type
var test_var_hard_node_process_mode: Node.ProcessMode
var test_var_hard_my_enum: TestMemberInfo.MyEnum
var test_var_hard_array: Array
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
index d0cbeeab85..563c6ce569 100644
--- a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
@@ -30,7 +30,7 @@ func test():
var b := B.new()
for property in (B as GDScript).get_property_list():
if str(property.name).begins_with("test_"):
- print(Utils.get_property_signature(property, true))
+ print(Utils.get_property_signature(property, null, true))
print("---")
for property in b.get_property_list():
if str(property.name).begins_with("test_"):
diff --git a/modules/gdscript/tests/scripts/utils.notest.gd b/modules/gdscript/tests/scripts/utils.notest.gd
index 781843b8e2..31818c9d01 100644
--- a/modules/gdscript/tests/scripts/utils.notest.gd
+++ b/modules/gdscript/tests/scripts/utils.notest.gd
@@ -20,24 +20,32 @@ static func get_type(property: Dictionary, is_return: bool = false) -> String:
return type_string(property.type)
-static func get_property_signature(property: Dictionary, is_static: bool = false) -> String:
+static func get_property_signature(property: Dictionary, base: Object = null, is_static: bool = false) -> String:
+ if property.usage & PROPERTY_USAGE_CATEGORY:
+ return '@export_category("%s")' % str(property.name).c_escape()
+ if property.usage & PROPERTY_USAGE_GROUP:
+ return '@export_group("%s")' % str(property.name).c_escape()
+ if property.usage & PROPERTY_USAGE_SUBGROUP:
+ return '@export_subgroup("%s")' % str(property.name).c_escape()
+
var result: String = ""
if not (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
printerr("Missing `PROPERTY_USAGE_SCRIPT_VARIABLE` flag.")
- if property.usage & PROPERTY_USAGE_DEFAULT:
- result += "@export "
if is_static:
result += "static "
result += "var " + property.name + ": " + get_type(property)
+ if is_instance_valid(base):
+ result += " = " + var_to_str(base.get(property.name))
return result
-static func get_property_additional_info(property: Dictionary) -> String:
- return 'hint=%s hint_string="%s" usage=%s' % [
+static func print_property_extended_info(property: Dictionary, base: Object = null, is_static: bool = false) -> void:
+ print(get_property_signature(property, base, is_static))
+ print(' hint=%s hint_string="%s" usage=%s' % [
get_property_hint_name(property.hint).trim_prefix("PROPERTY_HINT_"),
str(property.hint_string).c_escape(),
get_property_usage_string(property.usage).replace("PROPERTY_USAGE_", ""),
- ]
+ ])
static func get_method_signature(method: Dictionary, is_signal: bool = false) -> String:
@@ -153,7 +161,6 @@ static func get_property_usage_string(usage: int) -> String:
return "PROPERTY_USAGE_NONE"
const FLAGS: Array[Array] = [
- [PROPERTY_USAGE_DEFAULT, "PROPERTY_USAGE_DEFAULT"],
[PROPERTY_USAGE_STORAGE, "PROPERTY_USAGE_STORAGE"],
[PROPERTY_USAGE_EDITOR, "PROPERTY_USAGE_EDITOR"],
[PROPERTY_USAGE_INTERNAL, "PROPERTY_USAGE_INTERNAL"],
@@ -187,6 +194,10 @@ static func get_property_usage_string(usage: int) -> String:
var result: String = ""
+ if (usage & PROPERTY_USAGE_DEFAULT) == PROPERTY_USAGE_DEFAULT:
+ result += "PROPERTY_USAGE_DEFAULT|"
+ usage &= ~PROPERTY_USAGE_DEFAULT
+
for flag in FLAGS:
if usage & flag[0]:
result += flag[1] + "|"
diff --git a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
index a9033de7ae..c6e34cc023 100644
--- a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
+++ b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
@@ -30,7 +30,8 @@
#include "gltf_document_extension_physics.h"
-#include "scene/3d/area_3d.h"
+#include "scene/3d/physics/area_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
// Import process.
Error GLTFDocumentExtensionPhysics::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
diff --git a/modules/gltf/extensions/physics/gltf_physics_body.cpp b/modules/gltf/extensions/physics/gltf_physics_body.cpp
index 271bb9b332..7929b46542 100644
--- a/modules/gltf/extensions/physics/gltf_physics_body.cpp
+++ b/modules/gltf/extensions/physics/gltf_physics_body.cpp
@@ -30,8 +30,11 @@
#include "gltf_physics_body.h"
-#include "scene/3d/area_3d.h"
-#include "scene/3d/vehicle_body_3d.h"
+#include "scene/3d/physics/animatable_body_3d.h"
+#include "scene/3d/physics/area_3d.h"
+#include "scene/3d/physics/character_body_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
+#include "scene/3d/physics/vehicle_body_3d.h"
void GLTFPhysicsBody::_bind_methods() {
ClassDB::bind_static_method("GLTFPhysicsBody", D_METHOD("from_node", "body_node"), &GLTFPhysicsBody::from_node);
diff --git a/modules/gltf/extensions/physics/gltf_physics_body.h b/modules/gltf/extensions/physics/gltf_physics_body.h
index 6b21639a7b..ec139054ff 100644
--- a/modules/gltf/extensions/physics/gltf_physics_body.h
+++ b/modules/gltf/extensions/physics/gltf_physics_body.h
@@ -31,7 +31,7 @@
#ifndef GLTF_PHYSICS_BODY_H
#define GLTF_PHYSICS_BODY_H
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
// GLTFPhysicsBody is an intermediary between Godot's physics body nodes
// and the OMI_physics_body extension.
diff --git a/modules/gltf/extensions/physics/gltf_physics_shape.cpp b/modules/gltf/extensions/physics/gltf_physics_shape.cpp
index 467499a03f..35c99adbe5 100644
--- a/modules/gltf/extensions/physics/gltf_physics_shape.cpp
+++ b/modules/gltf/extensions/physics/gltf_physics_shape.cpp
@@ -33,7 +33,7 @@
#include "../../gltf_state.h"
#include "core/math/convex_hull.h"
-#include "scene/3d/area_3d.h"
+#include "scene/3d/physics/area_3d.h"
#include "scene/resources/3d/box_shape_3d.h"
#include "scene/resources/3d/capsule_shape_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
diff --git a/modules/gltf/extensions/physics/gltf_physics_shape.h b/modules/gltf/extensions/physics/gltf_physics_shape.h
index 4f7ac39292..ec0a8931f1 100644
--- a/modules/gltf/extensions/physics/gltf_physics_shape.h
+++ b/modules/gltf/extensions/physics/gltf_physics_shape.h
@@ -33,7 +33,7 @@
#include "../../gltf_defines.h"
-#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
class ImporterMesh;
diff --git a/modules/mono/.editorconfig b/modules/mono/.editorconfig
index db8fb2921c..1e5ae28396 100644
--- a/modules/mono/.editorconfig
+++ b/modules/mono/.editorconfig
@@ -13,22 +13,59 @@ trim_trailing_whitespace = true
max_line_length = 120
csharp_indent_case_contents_when_block = false
-[*.cs]
-# CA1707: Identifiers should not contain underscores
-# TODO:
-# Maybe we could disable this selectively only
-# where it's not desired and for generated code.
-dotnet_diagnostic.CA1707.severity = none
-# CA1711: Identifiers should not have incorrect suffix
-# Disable warning for suffixes like EventHandler, Flags, Enum, etc.
-dotnet_diagnostic.CA1711.severity = none
-# CA1716: Identifiers should not match keywords
-# TODO: We should look into this.
-dotnet_diagnostic.CA1716.severity = warning
-# CA1720: Identifiers should not contain type names
-dotnet_diagnostic.CA1720.severity = none
-# CA1805: Do not initialize unnecessarily
-# Don't tell me what to do.
-dotnet_diagnostic.CA1805.severity = none
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+
+dotnet_style_require_accessibility_modifiers = always
+
# Diagnostics to prevent defensive copies of `in` struct parameters
resharper_possibly_impure_method_call_on_readonly_variable_highlighting = error
+
+# IDE0040: Add accessibility modifiers
+dotnet_diagnostic.IDE0040.severity = warning
+
+# IDE1006: Naming rule violation
+dotnet_diagnostic.IDE1006.severity = suggestion
+
+# Severity levels for dotnet_naming_rule only affect IDE environments.
+# To have them extra visible to people, we can set them as 'warning' here without affecting compilation.
+
+# Everything should be PascalCase by default
+dotnet_naming_rule.all_should_be_camel_case.severity = warning
+dotnet_naming_rule.all_should_be_camel_case.symbols = all
+dotnet_naming_rule.all_should_be_camel_case.style = pascal_case_style
+# Non-public fields should be _camelCase
+dotnet_naming_rule.non_public_fields_should_be_underscore_camel_case.severity = warning
+dotnet_naming_rule.non_public_fields_should_be_underscore_camel_case.symbols = non_public_fields
+dotnet_naming_rule.non_public_fields_should_be_underscore_camel_case.style = underscore_camel_case_style
+# Constant fields (and local vars) should be PascalCase
+dotnet_naming_rule.constants_should_be_pascal_case.severity = warning
+dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
+dotnet_naming_rule.constants_should_be_pascal_case.style = pascal_case_style
+# Locals variables should be camelCase
+dotnet_naming_rule.local_vars_should_be_camel_case.severity = warning
+dotnet_naming_rule.local_vars_should_be_camel_case.symbols = local_vars
+dotnet_naming_rule.local_vars_should_be_camel_case.style = camel_case_style
+# Parameters should be camelCase
+dotnet_naming_rule.parameters_should_be_camel_case.severity = warning
+dotnet_naming_rule.parameters_should_be_camel_case.symbols = parameters
+dotnet_naming_rule.parameters_should_be_camel_case.style = camel_case_style
+
+dotnet_naming_symbols.all.applicable_kinds = *
+dotnet_naming_symbols.local_vars.applicable_kinds = local
+dotnet_naming_symbols.parameters.applicable_kinds = parameter
+dotnet_naming_symbols.constants.applicable_kinds = field, local
+dotnet_naming_symbols.constants.required_modifiers = const
+dotnet_naming_symbols.non_public_fields.applicable_kinds = field
+dotnet_naming_symbols.non_public_fields.applicable_accessibilities = private, protected, private_protected
+
+dotnet_naming_style.camel_case_style.capitalization = camel_case
+dotnet_naming_style.camel_case_style.required_prefix =
+dotnet_naming_style.underscore_camel_case_style.capitalization = camel_case
+dotnet_naming_style.underscore_camel_case_style.required_prefix = _
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+dotnet_naming_style.pascal_case_style.required_prefix =
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index 90a517cc40..aa6f6ef05e 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -312,7 +312,7 @@ def generate_sdk_package_versions():
)
# We write in ../SdkPackageVersions.props.
- with open(os.path.join(dirname(script_path), "SdkPackageVersions.props"), "w") as f:
+ with open(os.path.join(dirname(script_path), "SdkPackageVersions.props"), "w", encoding="utf-8") as f:
f.write(props)
f.close()
@@ -320,6 +320,8 @@ def generate_sdk_package_versions():
constants = """namespace Godot.SourceGenerators
{{
+// TODO: This is currently disabled because of https://github.com/dotnet/roslyn/issues/52904
+#pragma warning disable IDE0040 // Add accessibility modifiers.
partial class Common
{{
public const string VersionDocsUrl = "https://docs.godotengine.org/en/{docs_branch}";
@@ -338,7 +340,7 @@ def generate_sdk_package_versions():
)
os.makedirs(generators_dir, exist_ok=True)
- with open(os.path.join(generators_dir, "Common.Constants.cs"), "w") as f:
+ with open(os.path.join(generators_dir, "Common.Constants.cs"), "w", newline="\n", encoding="utf-8") as f:
f.write(constants)
f.close()
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
index 2d797e2f46..bf37651787 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Bar.cs
@@ -1,15 +1,15 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Bar : GodotObject
+ public partial class Bar : GodotObject
{
}
// Foo in another file
- partial class Foo
+ public partial class Foo
{
}
- partial class NotSameNameAsFile : GodotObject
+ public partial class NotSameNameAsFile : GodotObject
{
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
index 31e66ac306..c9e504fec7 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs
@@ -13,106 +13,106 @@ namespace Godot.SourceGenerators.Sample
[SuppressMessage("ReSharper", "InconsistentNaming")]
public partial class ExportedFields : GodotObject
{
- [Export] private Boolean field_Boolean = true;
- [Export] private Char field_Char = 'f';
- [Export] private SByte field_SByte = 10;
- [Export] private Int16 field_Int16 = 10;
- [Export] private Int32 field_Int32 = 10;
- [Export] private Int64 field_Int64 = 10;
- [Export] private Byte field_Byte = 10;
- [Export] private UInt16 field_UInt16 = 10;
- [Export] private UInt32 field_UInt32 = 10;
- [Export] private UInt64 field_UInt64 = 10;
- [Export] private Single field_Single = 10;
- [Export] private Double field_Double = 10;
- [Export] private String field_String = "foo";
+ [Export] private Boolean _fieldBoolean = true;
+ [Export] private Char _fieldChar = 'f';
+ [Export] private SByte _fieldSByte = 10;
+ [Export] private Int16 _fieldInt16 = 10;
+ [Export] private Int32 _fieldInt32 = 10;
+ [Export] private Int64 _fieldInt64 = 10;
+ [Export] private Byte _fieldByte = 10;
+ [Export] private UInt16 _fieldUInt16 = 10;
+ [Export] private UInt32 _fieldUInt32 = 10;
+ [Export] private UInt64 _fieldUInt64 = 10;
+ [Export] private Single _fieldSingle = 10;
+ [Export] private Double _fieldDouble = 10;
+ [Export] private String _fieldString = "foo";
// Godot structs
- [Export] private Vector2 field_Vector2 = new(10f, 10f);
- [Export] private Vector2I field_Vector2I = Vector2I.Up;
- [Export] private Rect2 field_Rect2 = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2I field_Rect2I = new(new Vector2I(10, 10), new Vector2I(10, 10));
- [Export] private Transform2D field_Transform2D = Transform2D.Identity;
- [Export] private Vector3 field_Vector3 = new(10f, 10f, 10f);
- [Export] private Vector3I field_Vector3I = Vector3I.Back;
- [Export] private Basis field_Basis = new Basis(Quaternion.Identity);
- [Export] private Quaternion field_Quaternion = new Quaternion(Basis.Identity);
- [Export] private Transform3D field_Transform3D = Transform3D.Identity;
- [Export] private Vector4 field_Vector4 = new(10f, 10f, 10f, 10f);
- [Export] private Vector4I field_Vector4I = Vector4I.One;
- [Export] private Projection field_Projection = Projection.Identity;
- [Export] private Aabb field_Aabb = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
- [Export] private Color field_Color = Colors.Aquamarine;
- [Export] private Plane field_Plane = Plane.PlaneXZ;
- [Export] private Callable field_Callable = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private Signal field_Signal = new Signal(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Vector2 _fieldVector2 = new(10f, 10f);
+ [Export] private Vector2I _fieldVector2I = Vector2I.Up;
+ [Export] private Rect2 _fieldRect2 = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
+ [Export] private Rect2I _fieldRect2I = new(new Vector2I(10, 10), new Vector2I(10, 10));
+ [Export] private Transform2D _fieldTransform2D = Transform2D.Identity;
+ [Export] private Vector3 _fieldVector3 = new(10f, 10f, 10f);
+ [Export] private Vector3I _fieldVector3I = Vector3I.Back;
+ [Export] private Basis _fieldBasis = new Basis(Quaternion.Identity);
+ [Export] private Quaternion _fieldQuaternion = new Quaternion(Basis.Identity);
+ [Export] private Transform3D _fieldTransform3D = Transform3D.Identity;
+ [Export] private Vector4 _fieldVector4 = new(10f, 10f, 10f, 10f);
+ [Export] private Vector4I _fieldVector4I = Vector4I.One;
+ [Export] private Projection _fieldProjection = Projection.Identity;
+ [Export] private Aabb _fieldAabb = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Color _fieldColor = Colors.Aquamarine;
+ [Export] private Plane _fieldPlane = Plane.PlaneXZ;
+ [Export] private Callable _fieldCallable = new Callable(Engine.GetMainLoop(), "_process");
+ [Export] private Signal _fieldSignal = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
- enum MyEnum
+ public enum MyEnum
{
A,
B,
C
}
- [Export] private MyEnum field_Enum = MyEnum.C;
+ [Export] private MyEnum _fieldEnum = MyEnum.C;
[Flags]
[SuppressMessage("ReSharper", "UnusedMember.Local")]
- enum MyFlagsEnum
+ public enum MyFlagsEnum
{
A,
B,
C
}
- [Export] private MyFlagsEnum field_FlagsEnum = MyFlagsEnum.C;
+ [Export] private MyFlagsEnum _fieldFlagsEnum = MyFlagsEnum.C;
// Arrays
- [Export] private Byte[] field_ByteArray = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int32[] field_Int32Array = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int64[] field_Int64Array = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Single[] field_SingleArray = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- [Export] private Double[] field_DoubleArray = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- [Export] private String[] field_StringArray = { "foo", "bar" };
- [Export(PropertyHint.Enum, "A,B,C")] private String[] field_StringArrayEnum = { "foo", "bar" };
- [Export] private Vector2[] field_Vector2Array = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
- [Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
- [Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private GodotObject[] field_GodotObjectOrDerivedArray = { null };
- [Export] private StringName[] field_StringNameArray = { "foo", "bar" };
- [Export] private NodePath[] field_NodePathArray = { "foo", "bar" };
- [Export] private Rid[] field_RidArray = { default, default, default };
+ [Export] private Byte[] _fieldByteArray = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int32[] _fieldInt32Array = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int64[] _fieldInt64Array = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Single[] _fieldSingleArray = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ [Export] private Double[] _fieldDoubleArray = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ [Export] private String[] _fieldStringArray = { "foo", "bar" };
+ [Export(PropertyHint.Enum, "A,B,C")] private String[] _fieldStringArrayEnum = { "foo", "bar" };
+ [Export] private Vector2[] _fieldVector2Array = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
+ [Export] private Vector3[] _fieldVector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
+ [Export] private Color[] _fieldColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
+ [Export] private GodotObject[] _fieldGodotObjectOrDerivedArray = { null };
+ [Export] private StringName[] _fieldStringNameArray = { "foo", "bar" };
+ [Export] private NodePath[] _fieldNodePathArray = { "foo", "bar" };
+ [Export] private Rid[] _fieldRidArray = { default, default, default };
// Note we use Array and not System.Array. This tests the generated namespace qualification.
- [Export] private Int32[] field_empty_Int32Array = Array.Empty<Int32>();
+ [Export] private Int32[] _fieldEmptyInt32Array = Array.Empty<Int32>();
// Note we use List and not System.Collections.Generic.
- [Export] private int[] field_array_from_list = new List<int>(Array.Empty<int>()).ToArray();
+ [Export] private int[] _fieldArrayFromList = new List<int>(Array.Empty<int>()).ToArray();
// Variant
- [Export] private Variant field_Variant = "foo";
+ [Export] private Variant _fieldVariant = "foo";
// Classes
- [Export] private GodotObject field_GodotObjectOrDerived;
- [Export] private Godot.Texture field_GodotResourceTexture;
- [Export] private StringName field_StringName = new StringName("foo");
- [Export] private NodePath field_NodePath = new NodePath("foo");
- [Export] private Rid field_Rid;
+ [Export] private GodotObject _fieldGodotObjectOrDerived;
+ [Export] private Godot.Texture _fieldGodotResourceTexture;
+ [Export] private StringName _fieldStringName = new StringName("foo");
+ [Export] private NodePath _fieldNodePath = new NodePath("foo");
+ [Export] private Rid _fieldRid;
[Export]
- private Godot.Collections.Dictionary field_GodotDictionary =
+ private Godot.Collections.Dictionary _fieldGodotDictionary =
new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
[Export]
- private Godot.Collections.Array field_GodotArray =
+ private Godot.Collections.Array _fieldGodotArray =
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
[Export]
- private Godot.Collections.Dictionary<string, bool> field_GodotGenericDictionary =
+ private Godot.Collections.Dictionary<string, bool> _fieldGodotGenericDictionary =
new() { { "foo", true }, { "bar", false } };
[Export]
- private Godot.Collections.Array<int> field_GodotGenericArray =
+ private Godot.Collections.Array<int> _fieldGodotGenericArray =
new() { 0, 1, 2, 3, 4, 5, 6 };
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
index aef2a8824e..91f33383ab 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs
@@ -13,41 +13,41 @@ namespace Godot.SourceGenerators.Sample
public partial class ExportedProperties : GodotObject
{
// Do not generate default value
- private String _notGenerate_Property_String = new string("not generate");
+ private String _notGeneratePropertyString = new string("not generate");
[Export]
- public String NotGenerate_Complex_Lamda_Property
+ public String NotGenerateComplexLambdaProperty
{
- get => _notGenerate_Property_String + Convert.ToInt32("1");
- set => _notGenerate_Property_String = value;
+ get => _notGeneratePropertyString + Convert.ToInt32("1");
+ set => _notGeneratePropertyString = value;
}
[Export]
- public String NotGenerate_Lamda_NoField_Property
+ public String NotGenerateLambdaNoFieldProperty
{
get => new string("not generate");
- set => _notGenerate_Property_String = value;
+ set => _notGeneratePropertyString = value;
}
[Export]
- public String NotGenerate_Complex_Return_Property
+ public String NotGenerateComplexReturnProperty
{
get
{
- return _notGenerate_Property_String + Convert.ToInt32("1");
+ return _notGeneratePropertyString + Convert.ToInt32("1");
}
set
{
- _notGenerate_Property_String = value;
+ _notGeneratePropertyString = value;
}
}
- private int _notGenerate_Property_Int = 1;
+ private int _notGeneratePropertyInt = 1;
[Export]
public string NotGenerate_Returns_Property
{
get
{
- if (_notGenerate_Property_Int == 1)
+ if (_notGeneratePropertyInt == 1)
{
return "a";
}
@@ -58,145 +58,145 @@ namespace Godot.SourceGenerators.Sample
}
set
{
- _notGenerate_Property_Int = value == "a" ? 1 : 2;
+ _notGeneratePropertyInt = value == "a" ? 1 : 2;
}
}
// Full Property
- private String _fullProperty_String = "FullProperty_String";
+ private String _fullPropertyString = "FullPropertyString";
[Export]
- public String FullProperty_String
+ public String FullPropertyString
{
get
{
- return _fullProperty_String;
+ return _fullPropertyString;
}
set
{
- _fullProperty_String = value;
+ _fullPropertyString = value;
}
}
- private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1");
+ private String _fullPropertyStringComplex = new string("FullPropertyString_Complex") + Convert.ToInt32("1");
[Export]
- public String FullProperty_String_Complex
+ public String FullPropertyStringComplex
{
get
{
- return _fullProperty_String_Complex;
+ return _fullPropertyStringComplex;
}
set
{
- _fullProperty_String_Complex = value;
+ _fullPropertyStringComplex = value;
}
}
// Lambda Property
- private String _lamdaProperty_String = "LamdaProperty_String";
+ private String _lamdaPropertyString = "LamdaPropertyString";
[Export]
- public String LamdaProperty_String
+ public String LamdaPropertyString
{
- get => _lamdaProperty_String;
- set => _lamdaProperty_String = value;
+ get => _lamdaPropertyString;
+ set => _lamdaPropertyString = value;
}
// Auto Property
- [Export] private Boolean property_Boolean { get; set; } = true;
- [Export] private Char property_Char { get; set; } = 'f';
- [Export] private SByte property_SByte { get; set; } = 10;
- [Export] private Int16 property_Int16 { get; set; } = 10;
- [Export] private Int32 property_Int32 { get; set; } = 10;
- [Export] private Int64 property_Int64 { get; set; } = 10;
- [Export] private Byte property_Byte { get; set; } = 10;
- [Export] private UInt16 property_UInt16 { get; set; } = 10;
- [Export] private UInt32 property_UInt32 { get; set; } = 10;
- [Export] private UInt64 property_UInt64 { get; set; } = 10;
- [Export] private Single property_Single { get; set; } = 10;
- [Export] private Double property_Double { get; set; } = 10;
- [Export] private String property_String { get; set; } = "foo";
+ [Export] private Boolean PropertyBoolean { get; set; } = true;
+ [Export] private Char PropertyChar { get; set; } = 'f';
+ [Export] private SByte PropertySByte { get; set; } = 10;
+ [Export] private Int16 PropertyInt16 { get; set; } = 10;
+ [Export] private Int32 PropertyInt32 { get; set; } = 10;
+ [Export] private Int64 PropertyInt64 { get; set; } = 10;
+ [Export] private Byte PropertyByte { get; set; } = 10;
+ [Export] private UInt16 PropertyUInt16 { get; set; } = 10;
+ [Export] private UInt32 PropertyUInt32 { get; set; } = 10;
+ [Export] private UInt64 PropertyUInt64 { get; set; } = 10;
+ [Export] private Single PropertySingle { get; set; } = 10;
+ [Export] private Double PropertyDouble { get; set; } = 10;
+ [Export] private String PropertyString { get; set; } = "foo";
// Godot structs
- [Export] private Vector2 property_Vector2 { get; set; } = new(10f, 10f);
- [Export] private Vector2I property_Vector2I { get; set; } = Vector2I.Up;
- [Export] private Rect2 property_Rect2 { get; set; } = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2I property_Rect2I { get; set; } = new(new Vector2I(10, 10), new Vector2I(10, 10));
- [Export] private Transform2D property_Transform2D { get; set; } = Transform2D.Identity;
- [Export] private Vector3 property_Vector3 { get; set; } = new(10f, 10f, 10f);
- [Export] private Vector3I property_Vector3I { get; set; } = Vector3I.Back;
- [Export] private Basis property_Basis { get; set; } = new Basis(Quaternion.Identity);
- [Export] private Quaternion property_Quaternion { get; set; } = new Quaternion(Basis.Identity);
- [Export] private Transform3D property_Transform3D { get; set; } = Transform3D.Identity;
- [Export] private Vector4 property_Vector4 { get; set; } = new(10f, 10f, 10f, 10f);
- [Export] private Vector4I property_Vector4I { get; set; } = Vector4I.One;
- [Export] private Projection property_Projection { get; set; } = Projection.Identity;
- [Export] private Aabb property_Aabb { get; set; } = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
- [Export] private Color property_Color { get; set; } = Colors.Aquamarine;
- [Export] private Plane property_Plane { get; set; } = Plane.PlaneXZ;
- [Export] private Callable property_Callable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private Signal property_Signal { get; set; } = new Signal(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Vector2 PropertyVector2 { get; set; } = new(10f, 10f);
+ [Export] private Vector2I PropertyVector2I { get; set; } = Vector2I.Up;
+ [Export] private Rect2 PropertyRect2 { get; set; } = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
+ [Export] private Rect2I PropertyRect2I { get; set; } = new(new Vector2I(10, 10), new Vector2I(10, 10));
+ [Export] private Transform2D PropertyTransform2D { get; set; } = Transform2D.Identity;
+ [Export] private Vector3 PropertyVector3 { get; set; } = new(10f, 10f, 10f);
+ [Export] private Vector3I PropertyVector3I { get; set; } = Vector3I.Back;
+ [Export] private Basis PropertyBasis { get; set; } = new Basis(Quaternion.Identity);
+ [Export] private Quaternion PropertyQuaternion { get; set; } = new Quaternion(Basis.Identity);
+ [Export] private Transform3D PropertyTransform3D { get; set; } = Transform3D.Identity;
+ [Export] private Vector4 PropertyVector4 { get; set; } = new(10f, 10f, 10f, 10f);
+ [Export] private Vector4I PropertyVector4I { get; set; } = Vector4I.One;
+ [Export] private Projection PropertyProjection { get; set; } = Projection.Identity;
+ [Export] private Aabb PropertyAabb { get; set; } = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Color PropertyColor { get; set; } = Colors.Aquamarine;
+ [Export] private Plane PropertyPlane { get; set; } = Plane.PlaneXZ;
+ [Export] private Callable PropertyCallable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
+ [Export] private Signal PropertySignal { get; set; } = new Signal(Engine.GetMainLoop(), "Propertylist_changed");
// Enums
[SuppressMessage("ReSharper", "UnusedMember.Local")]
- enum MyEnum
+ public enum MyEnum
{
A,
B,
C
}
- [Export] private MyEnum property_Enum { get; set; } = MyEnum.C;
+ [Export] private MyEnum PropertyEnum { get; set; } = MyEnum.C;
[Flags]
[SuppressMessage("ReSharper", "UnusedMember.Local")]
- enum MyFlagsEnum
+ public enum MyFlagsEnum
{
A,
B,
C
}
- [Export] private MyFlagsEnum property_FlagsEnum { get; set; } = MyFlagsEnum.C;
+ [Export] private MyFlagsEnum PropertyFlagsEnum { get; set; } = MyFlagsEnum.C;
// Arrays
- [Export] private Byte[] property_ByteArray { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int32[] property_Int32Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int64[] property_Int64Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Single[] property_SingleArray { get; set; } = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- [Export] private Double[] property_DoubleArray { get; set; } = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- [Export] private String[] property_StringArray { get; set; } = { "foo", "bar" };
- [Export(PropertyHint.Enum, "A,B,C")] private String[] property_StringArrayEnum { get; set; } = { "foo", "bar" };
- [Export] private Vector2[] property_Vector2Array { get; set; } = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
- [Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
- [Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private GodotObject[] property_GodotObjectOrDerivedArray { get; set; } = { null };
- [Export] private StringName[] field_StringNameArray { get; set; } = { "foo", "bar" };
- [Export] private NodePath[] field_NodePathArray { get; set; } = { "foo", "bar" };
- [Export] private Rid[] field_RidArray { get; set; } = { default, default, default };
+ [Export] private Byte[] PropertyByteArray { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int32[] PropertyInt32Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int64[] PropertyInt64Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Single[] PropertySingleArray { get; set; } = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ [Export] private Double[] PropertyDoubleArray { get; set; } = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ [Export] private String[] PropertyStringArray { get; set; } = { "foo", "bar" };
+ [Export(PropertyHint.Enum, "A,B,C")] private String[] PropertyStringArrayEnum { get; set; } = { "foo", "bar" };
+ [Export] private Vector2[] PropertyVector2Array { get; set; } = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
+ [Export] private Vector3[] PropertyVector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
+ [Export] private Color[] PropertyColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
+ [Export] private GodotObject[] PropertyGodotObjectOrDerivedArray { get; set; } = { null };
+ [Export] private StringName[] PropertyStringNameArray { get; set; } = { "foo", "bar" };
+ [Export] private NodePath[] PropertyNodePathArray { get; set; } = { "foo", "bar" };
+ [Export] private Rid[] PropertyRidArray { get; set; } = { default, default, default };
// Variant
- [Export] private Variant property_Variant { get; set; } = "foo";
+ [Export] private Variant PropertyVariant { get; set; } = "foo";
// Classes
- [Export] private GodotObject property_GodotObjectOrDerived { get; set; }
- [Export] private Godot.Texture property_GodotResourceTexture { get; set; }
- [Export] private StringName property_StringName { get; set; } = new StringName("foo");
- [Export] private NodePath property_NodePath { get; set; } = new NodePath("foo");
- [Export] private Rid property_Rid { get; set; }
+ [Export] private GodotObject PropertyGodotObjectOrDerived { get; set; }
+ [Export] private Godot.Texture PropertyGodotResourceTexture { get; set; }
+ [Export] private StringName PropertyStringName { get; set; } = new StringName("foo");
+ [Export] private NodePath PropertyNodePath { get; set; } = new NodePath("foo");
+ [Export] private Rid PropertyRid { get; set; }
[Export]
- private Godot.Collections.Dictionary property_GodotDictionary { get; set; } =
+ private Godot.Collections.Dictionary PropertyGodotDictionary { get; set; } =
new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
[Export]
- private Godot.Collections.Array property_GodotArray { get; set; } =
+ private Godot.Collections.Array PropertyGodotArray { get; set; } =
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
[Export]
- private Godot.Collections.Dictionary<string, bool> property_GodotGenericDictionary { get; set; } =
+ private Godot.Collections.Dictionary<string, bool> PropertyGodotGenericDictionary { get; set; } =
new() { { "foo", true }, { "bar", false } };
[Export]
- private Godot.Collections.Array<int> property_GodotGenericArray { get; set; } =
+ private Godot.Collections.Array<int> PropertyGodotGenericArray { get; set; } =
new() { 0, 1, 2, 3, 4, 5, 6 };
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
index 9ef72d9e02..d2293e0731 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Foo.cs
@@ -1,11 +1,11 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Foo : GodotObject
+ public partial class Foo : GodotObject
{
}
// Foo again in the same file
- partial class Foo
+ public partial class Foo
{
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
index 457d8daa8e..9d16a3170b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic.cs
@@ -3,7 +3,7 @@
namespace Godot.SourceGenerators.Sample
{
// Generic again but without generic parameters
- partial class Generic : GodotObject
+ public partial class Generic : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic1T.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic1T.cs
index 9c4f8ee1e1..6d92ff1b0b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic1T.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic1T.cs
@@ -2,7 +2,7 @@
namespace Godot.SourceGenerators.Sample
{
- partial class Generic1T<T> : GodotObject
+ public partial class Generic1T<T> : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic2T.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic2T.cs
index 80551a0b42..eef80ff951 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic2T.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Generic2T.cs
@@ -3,7 +3,7 @@
namespace Godot.SourceGenerators.Sample
{
// Generic again but different generic parameters
- partial class Generic2T<T, R> : GodotObject
+ public partial class Generic2T<T, R> : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
index 64088215e9..28685ac87a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/MoreExportedFields.cs
@@ -14,6 +14,6 @@ namespace Godot.SourceGenerators.Sample
public partial class ExportedFields : GodotObject
{
// Note we use Array and not System.Array. This tests the generated namespace qualification.
- [Export] private Int64[] field_empty_Int64Array = Array.Empty<Int64>();
+ [Export] private Int64[] _fieldEmptyInt64Array = Array.Empty<Int64>();
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/NestedClass.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/NestedClass.cs
index 3021f57115..3c533b712d 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/NestedClass.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/NestedClass.cs
@@ -11,8 +11,8 @@ public partial class NestedClass : GodotObject
[Signal]
public delegate void MySignalEventHandler(string str, int num);
- [Export] private String field_String = "foo";
- [Export] private String property_String { get; set; } = "foo";
+ [Export] private String _fieldString = "foo";
+ [Export] private String PropertyString { get; set; } = "foo";
private void Method()
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs
index 0c374169b9..c36aa55eef 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllReadOnly.cs
@@ -2,9 +2,9 @@ namespace Godot.SourceGenerators.Sample
{
public partial class AllReadOnly : GodotObject
{
- public readonly string readonly_field = "foo";
- public string readonly_auto_property { get; } = "foo";
- public string readonly_property { get => "foo"; }
- public string initonly_auto_property { get; init; }
+ public readonly string ReadonlyField = "foo";
+ public string ReadonlyAutoProperty { get; } = "foo";
+ public string ReadonlyProperty { get => "foo"; }
+ public string InitonlyAutoProperty { get; init; }
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs
index 14a1802330..48acfa6c95 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/AllWriteOnly.cs
@@ -4,7 +4,7 @@ namespace Godot.SourceGenerators.Sample
{
public partial class AllWriteOnly : GodotObject
{
- bool writeonly_backing_field = false;
- public bool writeonly_property { set => writeonly_backing_field = value; }
+ private bool _writeOnlyBackingField = false;
+ public bool WriteOnlyProperty { set => _writeOnlyBackingField = value; }
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs
index f556bdc7e4..c6ce6efe78 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/OneWayProperties/MixedReadOnlyWriteOnly.cs
@@ -2,12 +2,12 @@ namespace Godot.SourceGenerators.Sample
{
public partial class MixedReadonlyWriteOnly : GodotObject
{
- public readonly string readonly_field = "foo";
- public string readonly_auto_property { get; } = "foo";
- public string readonly_property { get => "foo"; }
- public string initonly_auto_property { get; init; }
+ public readonly string ReadOnlyField = "foo";
+ public string ReadOnlyAutoProperty { get; } = "foo";
+ public string ReadOnlyProperty { get => "foo"; }
+ public string InitOnlyAutoProperty { get; init; }
- bool writeonly_backing_field = false;
- public bool writeonly_property { set => writeonly_backing_field = value; }
+ private bool _writeOnlyBackingField = false;
+ public bool WriteOnlyProperty { set => _writeOnlyBackingField = value; }
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs
index e43a3469ae..1266f6d853 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs
@@ -26,7 +26,7 @@ namespace Godot.SourceGenerators.Sample
}
}
- partial struct OuterClass
+ public partial struct OuterClass
{
public partial class NesterClass : RefCounted
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs
index d20b354b9e..3cc5841097 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPropertiesGeneratorTests.cs
@@ -41,7 +41,7 @@ public class ScriptPropertiesGeneratorTests
}
[Fact]
- public async void OneWayPropertiesMixedReadonlyWriteOnly()
+ public async void OneWayPropertiesMixedReadOnlyWriteOnly()
{
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
"MixedReadOnlyWriteOnly.cs",
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllReadOnly_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllReadOnly_ScriptProperties.generated.cs
index db56ac30a3..96ff0f75e9 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllReadOnly_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllReadOnly_ScriptProperties.generated.cs
@@ -9,40 +9,40 @@ partial class AllReadOnly
/// </summary>
public new class PropertyName : global::Godot.GodotObject.PropertyName {
/// <summary>
- /// Cached name for the 'readonly_auto_property' property.
+ /// Cached name for the 'ReadOnlyAutoProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName readonly_auto_property = "readonly_auto_property";
+ public new static readonly global::Godot.StringName ReadOnlyAutoProperty = "ReadOnlyAutoProperty";
/// <summary>
- /// Cached name for the 'readonly_property' property.
+ /// Cached name for the 'ReadOnlyProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName readonly_property = "readonly_property";
+ public new static readonly global::Godot.StringName ReadOnlyProperty = "ReadOnlyProperty";
/// <summary>
- /// Cached name for the 'initonly_auto_property' property.
+ /// Cached name for the 'InitOnlyAutoProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName initonly_auto_property = "initonly_auto_property";
+ public new static readonly global::Godot.StringName InitOnlyAutoProperty = "InitOnlyAutoProperty";
/// <summary>
- /// Cached name for the 'readonly_field' field.
+ /// Cached name for the 'ReadOnlyField' field.
/// </summary>
- public new static readonly global::Godot.StringName readonly_field = "readonly_field";
+ public new static readonly global::Godot.StringName ReadOnlyField = "ReadOnlyField";
}
/// <inheritdoc/>
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
- if (name == PropertyName.readonly_auto_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_auto_property);
+ if (name == PropertyName.ReadOnlyAutoProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyAutoProperty);
return true;
}
- else if (name == PropertyName.readonly_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_property);
+ else if (name == PropertyName.ReadOnlyProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyProperty);
return true;
}
- else if (name == PropertyName.initonly_auto_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.initonly_auto_property);
+ else if (name == PropertyName.InitOnlyAutoProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.InitOnlyAutoProperty);
return true;
}
- else if (name == PropertyName.readonly_field) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_field);
+ else if (name == PropertyName.ReadOnlyField) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyField);
return true;
}
return base.GetGodotClassPropertyValue(name, out value);
@@ -56,10 +56,10 @@ partial class AllReadOnly
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
{
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_field, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_auto_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.initonly_auto_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyAutoProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.InitOnlyAutoProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
return properties;
}
#pragma warning restore CS0109
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllWriteOnly_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllWriteOnly_ScriptProperties.generated.cs
index 256420fe87..91dd282b99 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllWriteOnly_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/AllWriteOnly_ScriptProperties.generated.cs
@@ -9,24 +9,24 @@ partial class AllWriteOnly
/// </summary>
public new class PropertyName : global::Godot.GodotObject.PropertyName {
/// <summary>
- /// Cached name for the 'writeonly_property' property.
+ /// Cached name for the 'WriteOnlyProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName writeonly_property = "writeonly_property";
+ public new static readonly global::Godot.StringName WriteOnlyProperty = "WriteOnlyProperty";
/// <summary>
- /// Cached name for the 'writeonly_backing_field' field.
+ /// Cached name for the '_writeOnlyBackingField' field.
/// </summary>
- public new static readonly global::Godot.StringName writeonly_backing_field = "writeonly_backing_field";
+ public new static readonly global::Godot.StringName _writeOnlyBackingField = "_writeOnlyBackingField";
}
/// <inheritdoc/>
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
{
- if (name == PropertyName.writeonly_property) {
- this.writeonly_property = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ if (name == PropertyName.WriteOnlyProperty) {
+ this.WriteOnlyProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
- else if (name == PropertyName.writeonly_backing_field) {
- this.writeonly_backing_field = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ else if (name == PropertyName._writeOnlyBackingField) {
+ this._writeOnlyBackingField = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
return base.SetGodotClassPropertyValue(name, value);
@@ -35,8 +35,8 @@ partial class AllWriteOnly
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
- if (name == PropertyName.writeonly_backing_field) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this.writeonly_backing_field);
+ if (name == PropertyName._writeOnlyBackingField) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this._writeOnlyBackingField);
return true;
}
return base.GetGodotClassPropertyValue(name, out value);
@@ -50,8 +50,8 @@ partial class AllWriteOnly
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
{
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.writeonly_backing_field, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.writeonly_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName._writeOnlyBackingField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.WriteOnlyProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
return properties;
}
#pragma warning restore CS0109
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
index 915c36525b..334adc1243 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
@@ -9,488 +9,488 @@ partial class ExportedFields
/// </summary>
public new class PropertyName : global::Godot.GodotObject.PropertyName {
/// <summary>
- /// Cached name for the 'field_Boolean' field.
+ /// Cached name for the '_fieldBoolean' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Boolean = "field_Boolean";
+ public new static readonly global::Godot.StringName _fieldBoolean = "_fieldBoolean";
/// <summary>
- /// Cached name for the 'field_Char' field.
+ /// Cached name for the '_fieldChar' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Char = "field_Char";
+ public new static readonly global::Godot.StringName _fieldChar = "_fieldChar";
/// <summary>
- /// Cached name for the 'field_SByte' field.
+ /// Cached name for the '_fieldSByte' field.
/// </summary>
- public new static readonly global::Godot.StringName field_SByte = "field_SByte";
+ public new static readonly global::Godot.StringName _fieldSByte = "_fieldSByte";
/// <summary>
- /// Cached name for the 'field_Int16' field.
+ /// Cached name for the '_fieldInt16' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Int16 = "field_Int16";
+ public new static readonly global::Godot.StringName _fieldInt16 = "_fieldInt16";
/// <summary>
- /// Cached name for the 'field_Int32' field.
+ /// Cached name for the '_fieldInt32' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Int32 = "field_Int32";
+ public new static readonly global::Godot.StringName _fieldInt32 = "_fieldInt32";
/// <summary>
- /// Cached name for the 'field_Int64' field.
+ /// Cached name for the '_fieldInt64' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Int64 = "field_Int64";
+ public new static readonly global::Godot.StringName _fieldInt64 = "_fieldInt64";
/// <summary>
- /// Cached name for the 'field_Byte' field.
+ /// Cached name for the '_fieldByte' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Byte = "field_Byte";
+ public new static readonly global::Godot.StringName _fieldByte = "_fieldByte";
/// <summary>
- /// Cached name for the 'field_UInt16' field.
+ /// Cached name for the '_fieldUInt16' field.
/// </summary>
- public new static readonly global::Godot.StringName field_UInt16 = "field_UInt16";
+ public new static readonly global::Godot.StringName _fieldUInt16 = "_fieldUInt16";
/// <summary>
- /// Cached name for the 'field_UInt32' field.
+ /// Cached name for the '_fieldUInt32' field.
/// </summary>
- public new static readonly global::Godot.StringName field_UInt32 = "field_UInt32";
+ public new static readonly global::Godot.StringName _fieldUInt32 = "_fieldUInt32";
/// <summary>
- /// Cached name for the 'field_UInt64' field.
+ /// Cached name for the '_fieldUInt64' field.
/// </summary>
- public new static readonly global::Godot.StringName field_UInt64 = "field_UInt64";
+ public new static readonly global::Godot.StringName _fieldUInt64 = "_fieldUInt64";
/// <summary>
- /// Cached name for the 'field_Single' field.
+ /// Cached name for the '_fieldSingle' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Single = "field_Single";
+ public new static readonly global::Godot.StringName _fieldSingle = "_fieldSingle";
/// <summary>
- /// Cached name for the 'field_Double' field.
+ /// Cached name for the '_fieldDouble' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Double = "field_Double";
+ public new static readonly global::Godot.StringName _fieldDouble = "_fieldDouble";
/// <summary>
- /// Cached name for the 'field_String' field.
+ /// Cached name for the '_fieldString' field.
/// </summary>
- public new static readonly global::Godot.StringName field_String = "field_String";
+ public new static readonly global::Godot.StringName _fieldString = "_fieldString";
/// <summary>
- /// Cached name for the 'field_Vector2' field.
+ /// Cached name for the '_fieldVector2' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector2 = "field_Vector2";
+ public new static readonly global::Godot.StringName _fieldVector2 = "_fieldVector2";
/// <summary>
- /// Cached name for the 'field_Vector2I' field.
+ /// Cached name for the '_fieldVector2I' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector2I = "field_Vector2I";
+ public new static readonly global::Godot.StringName _fieldVector2I = "_fieldVector2I";
/// <summary>
- /// Cached name for the 'field_Rect2' field.
+ /// Cached name for the '_fieldRect2' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Rect2 = "field_Rect2";
+ public new static readonly global::Godot.StringName _fieldRect2 = "_fieldRect2";
/// <summary>
- /// Cached name for the 'field_Rect2I' field.
+ /// Cached name for the '_fieldRect2I' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Rect2I = "field_Rect2I";
+ public new static readonly global::Godot.StringName _fieldRect2I = "_fieldRect2I";
/// <summary>
- /// Cached name for the 'field_Transform2D' field.
+ /// Cached name for the '_fieldTransform2D' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Transform2D = "field_Transform2D";
+ public new static readonly global::Godot.StringName _fieldTransform2D = "_fieldTransform2D";
/// <summary>
- /// Cached name for the 'field_Vector3' field.
+ /// Cached name for the '_fieldVector3' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector3 = "field_Vector3";
+ public new static readonly global::Godot.StringName _fieldVector3 = "_fieldVector3";
/// <summary>
- /// Cached name for the 'field_Vector3I' field.
+ /// Cached name for the '_fieldVector3I' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector3I = "field_Vector3I";
+ public new static readonly global::Godot.StringName _fieldVector3I = "_fieldVector3I";
/// <summary>
- /// Cached name for the 'field_Basis' field.
+ /// Cached name for the '_fieldBasis' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Basis = "field_Basis";
+ public new static readonly global::Godot.StringName _fieldBasis = "_fieldBasis";
/// <summary>
- /// Cached name for the 'field_Quaternion' field.
+ /// Cached name for the '_fieldQuaternion' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Quaternion = "field_Quaternion";
+ public new static readonly global::Godot.StringName _fieldQuaternion = "_fieldQuaternion";
/// <summary>
- /// Cached name for the 'field_Transform3D' field.
+ /// Cached name for the '_fieldTransform3D' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Transform3D = "field_Transform3D";
+ public new static readonly global::Godot.StringName _fieldTransform3D = "_fieldTransform3D";
/// <summary>
- /// Cached name for the 'field_Vector4' field.
+ /// Cached name for the '_fieldVector4' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector4 = "field_Vector4";
+ public new static readonly global::Godot.StringName _fieldVector4 = "_fieldVector4";
/// <summary>
- /// Cached name for the 'field_Vector4I' field.
+ /// Cached name for the '_fieldVector4I' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector4I = "field_Vector4I";
+ public new static readonly global::Godot.StringName _fieldVector4I = "_fieldVector4I";
/// <summary>
- /// Cached name for the 'field_Projection' field.
+ /// Cached name for the '_fieldProjection' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Projection = "field_Projection";
+ public new static readonly global::Godot.StringName _fieldProjection = "_fieldProjection";
/// <summary>
- /// Cached name for the 'field_Aabb' field.
+ /// Cached name for the '_fieldAabb' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Aabb = "field_Aabb";
+ public new static readonly global::Godot.StringName _fieldAabb = "_fieldAabb";
/// <summary>
- /// Cached name for the 'field_Color' field.
+ /// Cached name for the '_fieldColor' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Color = "field_Color";
+ public new static readonly global::Godot.StringName _fieldColor = "_fieldColor";
/// <summary>
- /// Cached name for the 'field_Plane' field.
+ /// Cached name for the '_fieldPlane' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Plane = "field_Plane";
+ public new static readonly global::Godot.StringName _fieldPlane = "_fieldPlane";
/// <summary>
- /// Cached name for the 'field_Callable' field.
+ /// Cached name for the '_fieldCallable' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Callable = "field_Callable";
+ public new static readonly global::Godot.StringName _fieldCallable = "_fieldCallable";
/// <summary>
- /// Cached name for the 'field_Signal' field.
+ /// Cached name for the '_fieldSignal' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Signal = "field_Signal";
+ public new static readonly global::Godot.StringName _fieldSignal = "_fieldSignal";
/// <summary>
- /// Cached name for the 'field_Enum' field.
+ /// Cached name for the '_fieldEnum' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Enum = "field_Enum";
+ public new static readonly global::Godot.StringName _fieldEnum = "_fieldEnum";
/// <summary>
- /// Cached name for the 'field_FlagsEnum' field.
+ /// Cached name for the '_fieldFlagsEnum' field.
/// </summary>
- public new static readonly global::Godot.StringName field_FlagsEnum = "field_FlagsEnum";
+ public new static readonly global::Godot.StringName _fieldFlagsEnum = "_fieldFlagsEnum";
/// <summary>
- /// Cached name for the 'field_ByteArray' field.
+ /// Cached name for the '_fieldByteArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_ByteArray = "field_ByteArray";
+ public new static readonly global::Godot.StringName _fieldByteArray = "_fieldByteArray";
/// <summary>
- /// Cached name for the 'field_Int32Array' field.
+ /// Cached name for the '_fieldInt32Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Int32Array = "field_Int32Array";
+ public new static readonly global::Godot.StringName _fieldInt32Array = "_fieldInt32Array";
/// <summary>
- /// Cached name for the 'field_Int64Array' field.
+ /// Cached name for the '_fieldInt64Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Int64Array = "field_Int64Array";
+ public new static readonly global::Godot.StringName _fieldInt64Array = "_fieldInt64Array";
/// <summary>
- /// Cached name for the 'field_SingleArray' field.
+ /// Cached name for the '_fieldSingleArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_SingleArray = "field_SingleArray";
+ public new static readonly global::Godot.StringName _fieldSingleArray = "_fieldSingleArray";
/// <summary>
- /// Cached name for the 'field_DoubleArray' field.
+ /// Cached name for the '_fieldDoubleArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_DoubleArray = "field_DoubleArray";
+ public new static readonly global::Godot.StringName _fieldDoubleArray = "_fieldDoubleArray";
/// <summary>
- /// Cached name for the 'field_StringArray' field.
+ /// Cached name for the '_fieldStringArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_StringArray = "field_StringArray";
+ public new static readonly global::Godot.StringName _fieldStringArray = "_fieldStringArray";
/// <summary>
- /// Cached name for the 'field_StringArrayEnum' field.
+ /// Cached name for the '_fieldStringArrayEnum' field.
/// </summary>
- public new static readonly global::Godot.StringName field_StringArrayEnum = "field_StringArrayEnum";
+ public new static readonly global::Godot.StringName _fieldStringArrayEnum = "_fieldStringArrayEnum";
/// <summary>
- /// Cached name for the 'field_Vector2Array' field.
+ /// Cached name for the '_fieldVector2Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector2Array = "field_Vector2Array";
+ public new static readonly global::Godot.StringName _fieldVector2Array = "_fieldVector2Array";
/// <summary>
- /// Cached name for the 'field_Vector3Array' field.
+ /// Cached name for the '_fieldVector3Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Vector3Array = "field_Vector3Array";
+ public new static readonly global::Godot.StringName _fieldVector3Array = "_fieldVector3Array";
/// <summary>
- /// Cached name for the 'field_ColorArray' field.
+ /// Cached name for the '_fieldColorArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_ColorArray = "field_ColorArray";
+ public new static readonly global::Godot.StringName _fieldColorArray = "_fieldColorArray";
/// <summary>
- /// Cached name for the 'field_GodotObjectOrDerivedArray' field.
+ /// Cached name for the '_fieldGodotObjectOrDerivedArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotObjectOrDerivedArray = "field_GodotObjectOrDerivedArray";
+ public new static readonly global::Godot.StringName _fieldGodotObjectOrDerivedArray = "_fieldGodotObjectOrDerivedArray";
/// <summary>
- /// Cached name for the 'field_StringNameArray' field.
+ /// Cached name for the '_fieldStringNameArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_StringNameArray = "field_StringNameArray";
+ public new static readonly global::Godot.StringName _fieldStringNameArray = "_fieldStringNameArray";
/// <summary>
- /// Cached name for the 'field_NodePathArray' field.
+ /// Cached name for the '_fieldNodePathArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_NodePathArray = "field_NodePathArray";
+ public new static readonly global::Godot.StringName _fieldNodePathArray = "_fieldNodePathArray";
/// <summary>
- /// Cached name for the 'field_RidArray' field.
+ /// Cached name for the '_fieldRidArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_RidArray = "field_RidArray";
+ public new static readonly global::Godot.StringName _fieldRidArray = "_fieldRidArray";
/// <summary>
- /// Cached name for the 'field_empty_Int32Array' field.
+ /// Cached name for the '_fieldEmptyInt32Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_empty_Int32Array = "field_empty_Int32Array";
+ public new static readonly global::Godot.StringName _fieldEmptyInt32Array = "_fieldEmptyInt32Array";
/// <summary>
- /// Cached name for the 'field_array_from_list' field.
+ /// Cached name for the '_fieldArrayFromList' field.
/// </summary>
- public new static readonly global::Godot.StringName field_array_from_list = "field_array_from_list";
+ public new static readonly global::Godot.StringName _fieldArrayFromList = "_fieldArrayFromList";
/// <summary>
- /// Cached name for the 'field_Variant' field.
+ /// Cached name for the '_fieldVariant' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Variant = "field_Variant";
+ public new static readonly global::Godot.StringName _fieldVariant = "_fieldVariant";
/// <summary>
- /// Cached name for the 'field_GodotObjectOrDerived' field.
+ /// Cached name for the '_fieldGodotObjectOrDerived' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotObjectOrDerived = "field_GodotObjectOrDerived";
+ public new static readonly global::Godot.StringName _fieldGodotObjectOrDerived = "_fieldGodotObjectOrDerived";
/// <summary>
- /// Cached name for the 'field_GodotResourceTexture' field.
+ /// Cached name for the '_fieldGodotResourceTexture' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotResourceTexture = "field_GodotResourceTexture";
+ public new static readonly global::Godot.StringName _fieldGodotResourceTexture = "_fieldGodotResourceTexture";
/// <summary>
- /// Cached name for the 'field_StringName' field.
+ /// Cached name for the '_fieldStringName' field.
/// </summary>
- public new static readonly global::Godot.StringName field_StringName = "field_StringName";
+ public new static readonly global::Godot.StringName _fieldStringName = "_fieldStringName";
/// <summary>
- /// Cached name for the 'field_NodePath' field.
+ /// Cached name for the '_fieldNodePath' field.
/// </summary>
- public new static readonly global::Godot.StringName field_NodePath = "field_NodePath";
+ public new static readonly global::Godot.StringName _fieldNodePath = "_fieldNodePath";
/// <summary>
- /// Cached name for the 'field_Rid' field.
+ /// Cached name for the '_fieldRid' field.
/// </summary>
- public new static readonly global::Godot.StringName field_Rid = "field_Rid";
+ public new static readonly global::Godot.StringName _fieldRid = "_fieldRid";
/// <summary>
- /// Cached name for the 'field_GodotDictionary' field.
+ /// Cached name for the '_fieldGodotDictionary' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotDictionary = "field_GodotDictionary";
+ public new static readonly global::Godot.StringName _fieldGodotDictionary = "_fieldGodotDictionary";
/// <summary>
- /// Cached name for the 'field_GodotArray' field.
+ /// Cached name for the '_fieldGodotArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotArray = "field_GodotArray";
+ public new static readonly global::Godot.StringName _fieldGodotArray = "_fieldGodotArray";
/// <summary>
- /// Cached name for the 'field_GodotGenericDictionary' field.
+ /// Cached name for the '_fieldGodotGenericDictionary' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotGenericDictionary = "field_GodotGenericDictionary";
+ public new static readonly global::Godot.StringName _fieldGodotGenericDictionary = "_fieldGodotGenericDictionary";
/// <summary>
- /// Cached name for the 'field_GodotGenericArray' field.
+ /// Cached name for the '_fieldGodotGenericArray' field.
/// </summary>
- public new static readonly global::Godot.StringName field_GodotGenericArray = "field_GodotGenericArray";
+ public new static readonly global::Godot.StringName _fieldGodotGenericArray = "_fieldGodotGenericArray";
/// <summary>
- /// Cached name for the 'field_empty_Int64Array' field.
+ /// Cached name for the '_fieldEmptyInt64Array' field.
/// </summary>
- public new static readonly global::Godot.StringName field_empty_Int64Array = "field_empty_Int64Array";
+ public new static readonly global::Godot.StringName _fieldEmptyInt64Array = "_fieldEmptyInt64Array";
}
/// <inheritdoc/>
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
{
- if (name == PropertyName.field_Boolean) {
- this.field_Boolean = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ if (name == PropertyName._fieldBoolean) {
+ this._fieldBoolean = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
- else if (name == PropertyName.field_Char) {
- this.field_Char = global::Godot.NativeInterop.VariantUtils.ConvertTo<char>(value);
+ else if (name == PropertyName._fieldChar) {
+ this._fieldChar = global::Godot.NativeInterop.VariantUtils.ConvertTo<char>(value);
return true;
}
- else if (name == PropertyName.field_SByte) {
- this.field_SByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<sbyte>(value);
+ else if (name == PropertyName._fieldSByte) {
+ this._fieldSByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<sbyte>(value);
return true;
}
- else if (name == PropertyName.field_Int16) {
- this.field_Int16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<short>(value);
+ else if (name == PropertyName._fieldInt16) {
+ this._fieldInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<short>(value);
return true;
}
- else if (name == PropertyName.field_Int32) {
- this.field_Int32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
+ else if (name == PropertyName._fieldInt32) {
+ this._fieldInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
return true;
}
- else if (name == PropertyName.field_Int64) {
- this.field_Int64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<long>(value);
+ else if (name == PropertyName._fieldInt64) {
+ this._fieldInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<long>(value);
return true;
}
- else if (name == PropertyName.field_Byte) {
- this.field_Byte = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte>(value);
+ else if (name == PropertyName._fieldByte) {
+ this._fieldByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte>(value);
return true;
}
- else if (name == PropertyName.field_UInt16) {
- this.field_UInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ushort>(value);
+ else if (name == PropertyName._fieldUInt16) {
+ this._fieldUInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ushort>(value);
return true;
}
- else if (name == PropertyName.field_UInt32) {
- this.field_UInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<uint>(value);
+ else if (name == PropertyName._fieldUInt32) {
+ this._fieldUInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<uint>(value);
return true;
}
- else if (name == PropertyName.field_UInt64) {
- this.field_UInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ulong>(value);
+ else if (name == PropertyName._fieldUInt64) {
+ this._fieldUInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ulong>(value);
return true;
}
- else if (name == PropertyName.field_Single) {
- this.field_Single = global::Godot.NativeInterop.VariantUtils.ConvertTo<float>(value);
+ else if (name == PropertyName._fieldSingle) {
+ this._fieldSingle = global::Godot.NativeInterop.VariantUtils.ConvertTo<float>(value);
return true;
}
- else if (name == PropertyName.field_Double) {
- this.field_Double = global::Godot.NativeInterop.VariantUtils.ConvertTo<double>(value);
+ else if (name == PropertyName._fieldDouble) {
+ this._fieldDouble = global::Godot.NativeInterop.VariantUtils.ConvertTo<double>(value);
return true;
}
- else if (name == PropertyName.field_String) {
- this.field_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName._fieldString) {
+ this._fieldString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.field_Vector2) {
- this.field_Vector2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2>(value);
+ else if (name == PropertyName._fieldVector2) {
+ this._fieldVector2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2>(value);
return true;
}
- else if (name == PropertyName.field_Vector2I) {
- this.field_Vector2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2I>(value);
+ else if (name == PropertyName._fieldVector2I) {
+ this._fieldVector2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2I>(value);
return true;
}
- else if (name == PropertyName.field_Rect2) {
- this.field_Rect2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2>(value);
+ else if (name == PropertyName._fieldRect2) {
+ this._fieldRect2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2>(value);
return true;
}
- else if (name == PropertyName.field_Rect2I) {
- this.field_Rect2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2I>(value);
+ else if (name == PropertyName._fieldRect2I) {
+ this._fieldRect2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2I>(value);
return true;
}
- else if (name == PropertyName.field_Transform2D) {
- this.field_Transform2D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform2D>(value);
+ else if (name == PropertyName._fieldTransform2D) {
+ this._fieldTransform2D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform2D>(value);
return true;
}
- else if (name == PropertyName.field_Vector3) {
- this.field_Vector3 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3>(value);
+ else if (name == PropertyName._fieldVector3) {
+ this._fieldVector3 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3>(value);
return true;
}
- else if (name == PropertyName.field_Vector3I) {
- this.field_Vector3I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3I>(value);
+ else if (name == PropertyName._fieldVector3I) {
+ this._fieldVector3I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3I>(value);
return true;
}
- else if (name == PropertyName.field_Basis) {
- this.field_Basis = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Basis>(value);
+ else if (name == PropertyName._fieldBasis) {
+ this._fieldBasis = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Basis>(value);
return true;
}
- else if (name == PropertyName.field_Quaternion) {
- this.field_Quaternion = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Quaternion>(value);
+ else if (name == PropertyName._fieldQuaternion) {
+ this._fieldQuaternion = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Quaternion>(value);
return true;
}
- else if (name == PropertyName.field_Transform3D) {
- this.field_Transform3D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform3D>(value);
+ else if (name == PropertyName._fieldTransform3D) {
+ this._fieldTransform3D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform3D>(value);
return true;
}
- else if (name == PropertyName.field_Vector4) {
- this.field_Vector4 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4>(value);
+ else if (name == PropertyName._fieldVector4) {
+ this._fieldVector4 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4>(value);
return true;
}
- else if (name == PropertyName.field_Vector4I) {
- this.field_Vector4I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4I>(value);
+ else if (name == PropertyName._fieldVector4I) {
+ this._fieldVector4I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4I>(value);
return true;
}
- else if (name == PropertyName.field_Projection) {
- this.field_Projection = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Projection>(value);
+ else if (name == PropertyName._fieldProjection) {
+ this._fieldProjection = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Projection>(value);
return true;
}
- else if (name == PropertyName.field_Aabb) {
- this.field_Aabb = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Aabb>(value);
+ else if (name == PropertyName._fieldAabb) {
+ this._fieldAabb = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Aabb>(value);
return true;
}
- else if (name == PropertyName.field_Color) {
- this.field_Color = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color>(value);
+ else if (name == PropertyName._fieldColor) {
+ this._fieldColor = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color>(value);
return true;
}
- else if (name == PropertyName.field_Plane) {
- this.field_Plane = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Plane>(value);
+ else if (name == PropertyName._fieldPlane) {
+ this._fieldPlane = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Plane>(value);
return true;
}
- else if (name == PropertyName.field_Callable) {
- this.field_Callable = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
+ else if (name == PropertyName._fieldCallable) {
+ this._fieldCallable = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
return true;
}
- else if (name == PropertyName.field_Signal) {
- this.field_Signal = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Signal>(value);
+ else if (name == PropertyName._fieldSignal) {
+ this._fieldSignal = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Signal>(value);
return true;
}
- else if (name == PropertyName.field_Enum) {
- this.field_Enum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedFields.MyEnum>(value);
+ else if (name == PropertyName._fieldEnum) {
+ this._fieldEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedFields.MyEnum>(value);
return true;
}
- else if (name == PropertyName.field_FlagsEnum) {
- this.field_FlagsEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedFields.MyFlagsEnum>(value);
+ else if (name == PropertyName._fieldFlagsEnum) {
+ this._fieldFlagsEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedFields.MyFlagsEnum>(value);
return true;
}
- else if (name == PropertyName.field_ByteArray) {
- this.field_ByteArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte[]>(value);
+ else if (name == PropertyName._fieldByteArray) {
+ this._fieldByteArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte[]>(value);
return true;
}
- else if (name == PropertyName.field_Int32Array) {
- this.field_Int32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
+ else if (name == PropertyName._fieldInt32Array) {
+ this._fieldInt32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
return true;
}
- else if (name == PropertyName.field_Int64Array) {
- this.field_Int64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
+ else if (name == PropertyName._fieldInt64Array) {
+ this._fieldInt64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
return true;
}
- else if (name == PropertyName.field_SingleArray) {
- this.field_SingleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<float[]>(value);
+ else if (name == PropertyName._fieldSingleArray) {
+ this._fieldSingleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<float[]>(value);
return true;
}
- else if (name == PropertyName.field_DoubleArray) {
- this.field_DoubleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<double[]>(value);
+ else if (name == PropertyName._fieldDoubleArray) {
+ this._fieldDoubleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<double[]>(value);
return true;
}
- else if (name == PropertyName.field_StringArray) {
- this.field_StringArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
+ else if (name == PropertyName._fieldStringArray) {
+ this._fieldStringArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
return true;
}
- else if (name == PropertyName.field_StringArrayEnum) {
- this.field_StringArrayEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
+ else if (name == PropertyName._fieldStringArrayEnum) {
+ this._fieldStringArrayEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
return true;
}
- else if (name == PropertyName.field_Vector2Array) {
- this.field_Vector2Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2[]>(value);
+ else if (name == PropertyName._fieldVector2Array) {
+ this._fieldVector2Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2[]>(value);
return true;
}
- else if (name == PropertyName.field_Vector3Array) {
- this.field_Vector3Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3[]>(value);
+ else if (name == PropertyName._fieldVector3Array) {
+ this._fieldVector3Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3[]>(value);
return true;
}
- else if (name == PropertyName.field_ColorArray) {
- this.field_ColorArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color[]>(value);
+ else if (name == PropertyName._fieldColorArray) {
+ this._fieldColorArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color[]>(value);
return true;
}
- else if (name == PropertyName.field_GodotObjectOrDerivedArray) {
- this.field_GodotObjectOrDerivedArray = global::Godot.NativeInterop.VariantUtils.ConvertToSystemArrayOfGodotObject<global::Godot.GodotObject>(value);
+ else if (name == PropertyName._fieldGodotObjectOrDerivedArray) {
+ this._fieldGodotObjectOrDerivedArray = global::Godot.NativeInterop.VariantUtils.ConvertToSystemArrayOfGodotObject<global::Godot.GodotObject>(value);
return true;
}
- else if (name == PropertyName.field_StringNameArray) {
- this.field_StringNameArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName[]>(value);
+ else if (name == PropertyName._fieldStringNameArray) {
+ this._fieldStringNameArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName[]>(value);
return true;
}
- else if (name == PropertyName.field_NodePathArray) {
- this.field_NodePathArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath[]>(value);
+ else if (name == PropertyName._fieldNodePathArray) {
+ this._fieldNodePathArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath[]>(value);
return true;
}
- else if (name == PropertyName.field_RidArray) {
- this.field_RidArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid[]>(value);
+ else if (name == PropertyName._fieldRidArray) {
+ this._fieldRidArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid[]>(value);
return true;
}
- else if (name == PropertyName.field_empty_Int32Array) {
- this.field_empty_Int32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
+ else if (name == PropertyName._fieldEmptyInt32Array) {
+ this._fieldEmptyInt32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
return true;
}
- else if (name == PropertyName.field_array_from_list) {
- this.field_array_from_list = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
+ else if (name == PropertyName._fieldArrayFromList) {
+ this._fieldArrayFromList = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
return true;
}
- else if (name == PropertyName.field_Variant) {
- this.field_Variant = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Variant>(value);
+ else if (name == PropertyName._fieldVariant) {
+ this._fieldVariant = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Variant>(value);
return true;
}
- else if (name == PropertyName.field_GodotObjectOrDerived) {
- this.field_GodotObjectOrDerived = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.GodotObject>(value);
+ else if (name == PropertyName._fieldGodotObjectOrDerived) {
+ this._fieldGodotObjectOrDerived = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.GodotObject>(value);
return true;
}
- else if (name == PropertyName.field_GodotResourceTexture) {
- this.field_GodotResourceTexture = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Texture>(value);
+ else if (name == PropertyName._fieldGodotResourceTexture) {
+ this._fieldGodotResourceTexture = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Texture>(value);
return true;
}
- else if (name == PropertyName.field_StringName) {
- this.field_StringName = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName>(value);
+ else if (name == PropertyName._fieldStringName) {
+ this._fieldStringName = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName>(value);
return true;
}
- else if (name == PropertyName.field_NodePath) {
- this.field_NodePath = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath>(value);
+ else if (name == PropertyName._fieldNodePath) {
+ this._fieldNodePath = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath>(value);
return true;
}
- else if (name == PropertyName.field_Rid) {
- this.field_Rid = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid>(value);
+ else if (name == PropertyName._fieldRid) {
+ this._fieldRid = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid>(value);
return true;
}
- else if (name == PropertyName.field_GodotDictionary) {
- this.field_GodotDictionary = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Dictionary>(value);
+ else if (name == PropertyName._fieldGodotDictionary) {
+ this._fieldGodotDictionary = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Dictionary>(value);
return true;
}
- else if (name == PropertyName.field_GodotArray) {
- this.field_GodotArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Array>(value);
+ else if (name == PropertyName._fieldGodotArray) {
+ this._fieldGodotArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Array>(value);
return true;
}
- else if (name == PropertyName.field_GodotGenericDictionary) {
- this.field_GodotGenericDictionary = global::Godot.NativeInterop.VariantUtils.ConvertToDictionary<string, bool>(value);
+ else if (name == PropertyName._fieldGodotGenericDictionary) {
+ this._fieldGodotGenericDictionary = global::Godot.NativeInterop.VariantUtils.ConvertToDictionary<string, bool>(value);
return true;
}
- else if (name == PropertyName.field_GodotGenericArray) {
- this.field_GodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
+ else if (name == PropertyName._fieldGodotGenericArray) {
+ this._fieldGodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
return true;
}
- else if (name == PropertyName.field_empty_Int64Array) {
- this.field_empty_Int64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
+ else if (name == PropertyName._fieldEmptyInt64Array) {
+ this._fieldEmptyInt64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
return true;
}
return base.SetGodotClassPropertyValue(name, value);
@@ -499,244 +499,244 @@ partial class ExportedFields
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
- if (name == PropertyName.field_Boolean) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this.field_Boolean);
+ if (name == PropertyName._fieldBoolean) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this._fieldBoolean);
return true;
}
- else if (name == PropertyName.field_Char) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<char>(this.field_Char);
+ else if (name == PropertyName._fieldChar) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<char>(this._fieldChar);
return true;
}
- else if (name == PropertyName.field_SByte) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<sbyte>(this.field_SByte);
+ else if (name == PropertyName._fieldSByte) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<sbyte>(this._fieldSByte);
return true;
}
- else if (name == PropertyName.field_Int16) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<short>(this.field_Int16);
+ else if (name == PropertyName._fieldInt16) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<short>(this._fieldInt16);
return true;
}
- else if (name == PropertyName.field_Int32) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.field_Int32);
+ else if (name == PropertyName._fieldInt32) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this._fieldInt32);
return true;
}
- else if (name == PropertyName.field_Int64) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long>(this.field_Int64);
+ else if (name == PropertyName._fieldInt64) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long>(this._fieldInt64);
return true;
}
- else if (name == PropertyName.field_Byte) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte>(this.field_Byte);
+ else if (name == PropertyName._fieldByte) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte>(this._fieldByte);
return true;
}
- else if (name == PropertyName.field_UInt16) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ushort>(this.field_UInt16);
+ else if (name == PropertyName._fieldUInt16) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ushort>(this._fieldUInt16);
return true;
}
- else if (name == PropertyName.field_UInt32) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<uint>(this.field_UInt32);
+ else if (name == PropertyName._fieldUInt32) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<uint>(this._fieldUInt32);
return true;
}
- else if (name == PropertyName.field_UInt64) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ulong>(this.field_UInt64);
+ else if (name == PropertyName._fieldUInt64) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ulong>(this._fieldUInt64);
return true;
}
- else if (name == PropertyName.field_Single) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float>(this.field_Single);
+ else if (name == PropertyName._fieldSingle) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float>(this._fieldSingle);
return true;
}
- else if (name == PropertyName.field_Double) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double>(this.field_Double);
+ else if (name == PropertyName._fieldDouble) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double>(this._fieldDouble);
return true;
}
- else if (name == PropertyName.field_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.field_String);
+ else if (name == PropertyName._fieldString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._fieldString);
return true;
}
- else if (name == PropertyName.field_Vector2) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2>(this.field_Vector2);
+ else if (name == PropertyName._fieldVector2) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2>(this._fieldVector2);
return true;
}
- else if (name == PropertyName.field_Vector2I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2I>(this.field_Vector2I);
+ else if (name == PropertyName._fieldVector2I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2I>(this._fieldVector2I);
return true;
}
- else if (name == PropertyName.field_Rect2) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2>(this.field_Rect2);
+ else if (name == PropertyName._fieldRect2) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2>(this._fieldRect2);
return true;
}
- else if (name == PropertyName.field_Rect2I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2I>(this.field_Rect2I);
+ else if (name == PropertyName._fieldRect2I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2I>(this._fieldRect2I);
return true;
}
- else if (name == PropertyName.field_Transform2D) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform2D>(this.field_Transform2D);
+ else if (name == PropertyName._fieldTransform2D) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform2D>(this._fieldTransform2D);
return true;
}
- else if (name == PropertyName.field_Vector3) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3>(this.field_Vector3);
+ else if (name == PropertyName._fieldVector3) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3>(this._fieldVector3);
return true;
}
- else if (name == PropertyName.field_Vector3I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3I>(this.field_Vector3I);
+ else if (name == PropertyName._fieldVector3I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3I>(this._fieldVector3I);
return true;
}
- else if (name == PropertyName.field_Basis) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Basis>(this.field_Basis);
+ else if (name == PropertyName._fieldBasis) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Basis>(this._fieldBasis);
return true;
}
- else if (name == PropertyName.field_Quaternion) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Quaternion>(this.field_Quaternion);
+ else if (name == PropertyName._fieldQuaternion) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Quaternion>(this._fieldQuaternion);
return true;
}
- else if (name == PropertyName.field_Transform3D) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform3D>(this.field_Transform3D);
+ else if (name == PropertyName._fieldTransform3D) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform3D>(this._fieldTransform3D);
return true;
}
- else if (name == PropertyName.field_Vector4) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4>(this.field_Vector4);
+ else if (name == PropertyName._fieldVector4) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4>(this._fieldVector4);
return true;
}
- else if (name == PropertyName.field_Vector4I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4I>(this.field_Vector4I);
+ else if (name == PropertyName._fieldVector4I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4I>(this._fieldVector4I);
return true;
}
- else if (name == PropertyName.field_Projection) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Projection>(this.field_Projection);
+ else if (name == PropertyName._fieldProjection) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Projection>(this._fieldProjection);
return true;
}
- else if (name == PropertyName.field_Aabb) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Aabb>(this.field_Aabb);
+ else if (name == PropertyName._fieldAabb) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Aabb>(this._fieldAabb);
return true;
}
- else if (name == PropertyName.field_Color) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color>(this.field_Color);
+ else if (name == PropertyName._fieldColor) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color>(this._fieldColor);
return true;
}
- else if (name == PropertyName.field_Plane) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Plane>(this.field_Plane);
+ else if (name == PropertyName._fieldPlane) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Plane>(this._fieldPlane);
return true;
}
- else if (name == PropertyName.field_Callable) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.field_Callable);
+ else if (name == PropertyName._fieldCallable) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this._fieldCallable);
return true;
}
- else if (name == PropertyName.field_Signal) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Signal>(this.field_Signal);
+ else if (name == PropertyName._fieldSignal) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Signal>(this._fieldSignal);
return true;
}
- else if (name == PropertyName.field_Enum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedFields.MyEnum>(this.field_Enum);
+ else if (name == PropertyName._fieldEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedFields.MyEnum>(this._fieldEnum);
return true;
}
- else if (name == PropertyName.field_FlagsEnum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedFields.MyFlagsEnum>(this.field_FlagsEnum);
+ else if (name == PropertyName._fieldFlagsEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedFields.MyFlagsEnum>(this._fieldFlagsEnum);
return true;
}
- else if (name == PropertyName.field_ByteArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte[]>(this.field_ByteArray);
+ else if (name == PropertyName._fieldByteArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte[]>(this._fieldByteArray);
return true;
}
- else if (name == PropertyName.field_Int32Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this.field_Int32Array);
+ else if (name == PropertyName._fieldInt32Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this._fieldInt32Array);
return true;
}
- else if (name == PropertyName.field_Int64Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this.field_Int64Array);
+ else if (name == PropertyName._fieldInt64Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this._fieldInt64Array);
return true;
}
- else if (name == PropertyName.field_SingleArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float[]>(this.field_SingleArray);
+ else if (name == PropertyName._fieldSingleArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float[]>(this._fieldSingleArray);
return true;
}
- else if (name == PropertyName.field_DoubleArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double[]>(this.field_DoubleArray);
+ else if (name == PropertyName._fieldDoubleArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double[]>(this._fieldDoubleArray);
return true;
}
- else if (name == PropertyName.field_StringArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.field_StringArray);
+ else if (name == PropertyName._fieldStringArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this._fieldStringArray);
return true;
}
- else if (name == PropertyName.field_StringArrayEnum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.field_StringArrayEnum);
+ else if (name == PropertyName._fieldStringArrayEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this._fieldStringArrayEnum);
return true;
}
- else if (name == PropertyName.field_Vector2Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2[]>(this.field_Vector2Array);
+ else if (name == PropertyName._fieldVector2Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2[]>(this._fieldVector2Array);
return true;
}
- else if (name == PropertyName.field_Vector3Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3[]>(this.field_Vector3Array);
+ else if (name == PropertyName._fieldVector3Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3[]>(this._fieldVector3Array);
return true;
}
- else if (name == PropertyName.field_ColorArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color[]>(this.field_ColorArray);
+ else if (name == PropertyName._fieldColorArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color[]>(this._fieldColorArray);
return true;
}
- else if (name == PropertyName.field_GodotObjectOrDerivedArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromSystemArrayOfGodotObject(this.field_GodotObjectOrDerivedArray);
+ else if (name == PropertyName._fieldGodotObjectOrDerivedArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromSystemArrayOfGodotObject(this._fieldGodotObjectOrDerivedArray);
return true;
}
- else if (name == PropertyName.field_StringNameArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName[]>(this.field_StringNameArray);
+ else if (name == PropertyName._fieldStringNameArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName[]>(this._fieldStringNameArray);
return true;
}
- else if (name == PropertyName.field_NodePathArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath[]>(this.field_NodePathArray);
+ else if (name == PropertyName._fieldNodePathArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath[]>(this._fieldNodePathArray);
return true;
}
- else if (name == PropertyName.field_RidArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid[]>(this.field_RidArray);
+ else if (name == PropertyName._fieldRidArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid[]>(this._fieldRidArray);
return true;
}
- else if (name == PropertyName.field_empty_Int32Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this.field_empty_Int32Array);
+ else if (name == PropertyName._fieldEmptyInt32Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this._fieldEmptyInt32Array);
return true;
}
- else if (name == PropertyName.field_array_from_list) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this.field_array_from_list);
+ else if (name == PropertyName._fieldArrayFromList) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this._fieldArrayFromList);
return true;
}
- else if (name == PropertyName.field_Variant) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Variant>(this.field_Variant);
+ else if (name == PropertyName._fieldVariant) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Variant>(this._fieldVariant);
return true;
}
- else if (name == PropertyName.field_GodotObjectOrDerived) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.GodotObject>(this.field_GodotObjectOrDerived);
+ else if (name == PropertyName._fieldGodotObjectOrDerived) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.GodotObject>(this._fieldGodotObjectOrDerived);
return true;
}
- else if (name == PropertyName.field_GodotResourceTexture) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Texture>(this.field_GodotResourceTexture);
+ else if (name == PropertyName._fieldGodotResourceTexture) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Texture>(this._fieldGodotResourceTexture);
return true;
}
- else if (name == PropertyName.field_StringName) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName>(this.field_StringName);
+ else if (name == PropertyName._fieldStringName) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName>(this._fieldStringName);
return true;
}
- else if (name == PropertyName.field_NodePath) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath>(this.field_NodePath);
+ else if (name == PropertyName._fieldNodePath) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath>(this._fieldNodePath);
return true;
}
- else if (name == PropertyName.field_Rid) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid>(this.field_Rid);
+ else if (name == PropertyName._fieldRid) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid>(this._fieldRid);
return true;
}
- else if (name == PropertyName.field_GodotDictionary) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Dictionary>(this.field_GodotDictionary);
+ else if (name == PropertyName._fieldGodotDictionary) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Dictionary>(this._fieldGodotDictionary);
return true;
}
- else if (name == PropertyName.field_GodotArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Array>(this.field_GodotArray);
+ else if (name == PropertyName._fieldGodotArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Array>(this._fieldGodotArray);
return true;
}
- else if (name == PropertyName.field_GodotGenericDictionary) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromDictionary(this.field_GodotGenericDictionary);
+ else if (name == PropertyName._fieldGodotGenericDictionary) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromDictionary(this._fieldGodotGenericDictionary);
return true;
}
- else if (name == PropertyName.field_GodotGenericArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.field_GodotGenericArray);
+ else if (name == PropertyName._fieldGodotGenericArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this._fieldGodotGenericArray);
return true;
}
- else if (name == PropertyName.field_empty_Int64Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this.field_empty_Int64Array);
+ else if (name == PropertyName._fieldEmptyInt64Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this._fieldEmptyInt64Array);
return true;
}
return base.GetGodotClassPropertyValue(name, out value);
@@ -750,66 +750,66 @@ partial class ExportedFields
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
{
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.field_Boolean, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Char, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_SByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Int16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Int32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Int64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Byte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_UInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_UInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_UInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.field_Single, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.field_Double, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.field_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)5, name: PropertyName.field_Vector2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)6, name: PropertyName.field_Vector2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)7, name: PropertyName.field_Rect2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)8, name: PropertyName.field_Rect2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)11, name: PropertyName.field_Transform2D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)9, name: PropertyName.field_Vector3, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)10, name: PropertyName.field_Vector3I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)17, name: PropertyName.field_Basis, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)15, name: PropertyName.field_Quaternion, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)18, name: PropertyName.field_Transform3D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)12, name: PropertyName.field_Vector4, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)13, name: PropertyName.field_Vector4I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)19, name: PropertyName.field_Projection, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)16, name: PropertyName.field_Aabb, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)20, name: PropertyName.field_Color, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)14, name: PropertyName.field_Plane, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.field_Callable, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)26, name: PropertyName.field_Signal, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_Enum, hint: (global::Godot.PropertyHint)2, hintString: "A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.field_FlagsEnum, hint: (global::Godot.PropertyHint)6, hintString: "A:0,B:1,C:2", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)29, name: PropertyName.field_ByteArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName.field_Int32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.field_Int64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)32, name: PropertyName.field_SingleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)33, name: PropertyName.field_DoubleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.field_StringArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.field_StringArrayEnum, hint: (global::Godot.PropertyHint)23, hintString: "4/2:A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)35, name: PropertyName.field_Vector2Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)36, name: PropertyName.field_Vector3Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)37, name: PropertyName.field_ColorArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_GodotObjectOrDerivedArray, hint: (global::Godot.PropertyHint)23, hintString: "24/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_StringNameArray, hint: (global::Godot.PropertyHint)23, hintString: "21/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_NodePathArray, hint: (global::Godot.PropertyHint)23, hintString: "22/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_RidArray, hint: (global::Godot.PropertyHint)23, hintString: "23/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName.field_empty_Int32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName.field_array_from_list, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)0, name: PropertyName.field_Variant, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)135174, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.field_GodotObjectOrDerived, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.field_GodotResourceTexture, hint: (global::Godot.PropertyHint)17, hintString: "Texture", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)21, name: PropertyName.field_StringName, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)22, name: PropertyName.field_NodePath, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.field_Rid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.field_GodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_GodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.field_GodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_GodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.field_empty_Int64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName._fieldBoolean, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldChar, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldSByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldUInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldUInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldUInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName._fieldSingle, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName._fieldDouble, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._fieldString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)5, name: PropertyName._fieldVector2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)6, name: PropertyName._fieldVector2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)7, name: PropertyName._fieldRect2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)8, name: PropertyName._fieldRect2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)11, name: PropertyName._fieldTransform2D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)9, name: PropertyName._fieldVector3, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)10, name: PropertyName._fieldVector3I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)17, name: PropertyName._fieldBasis, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)15, name: PropertyName._fieldQuaternion, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)18, name: PropertyName._fieldTransform3D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)12, name: PropertyName._fieldVector4, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)13, name: PropertyName._fieldVector4I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)19, name: PropertyName._fieldProjection, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)16, name: PropertyName._fieldAabb, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)20, name: PropertyName._fieldColor, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)14, name: PropertyName._fieldPlane, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName._fieldCallable, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)26, name: PropertyName._fieldSignal, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldEnum, hint: (global::Godot.PropertyHint)2, hintString: "A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._fieldFlagsEnum, hint: (global::Godot.PropertyHint)6, hintString: "A:0,B:1,C:2", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)29, name: PropertyName._fieldByteArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName._fieldInt32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName._fieldInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)32, name: PropertyName._fieldSingleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)33, name: PropertyName._fieldDoubleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName._fieldStringArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName._fieldStringArrayEnum, hint: (global::Godot.PropertyHint)23, hintString: "4/2:A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)35, name: PropertyName._fieldVector2Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)36, name: PropertyName._fieldVector3Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)37, name: PropertyName._fieldColorArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldGodotObjectOrDerivedArray, hint: (global::Godot.PropertyHint)23, hintString: "24/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldStringNameArray, hint: (global::Godot.PropertyHint)23, hintString: "21/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldNodePathArray, hint: (global::Godot.PropertyHint)23, hintString: "22/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldRidArray, hint: (global::Godot.PropertyHint)23, hintString: "23/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName._fieldEmptyInt32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName._fieldArrayFromList, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)0, name: PropertyName._fieldVariant, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)135174, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName._fieldGodotObjectOrDerived, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName._fieldGodotResourceTexture, hint: (global::Godot.PropertyHint)17, hintString: "Texture", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)21, name: PropertyName._fieldStringName, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)22, name: PropertyName._fieldNodePath, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName._fieldRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName._fieldGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName._fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName._fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName._fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
return properties;
}
#pragma warning restore CS0109
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptPropertyDefVal.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptPropertyDefVal.generated.cs
index 185b8e4ac6..367cb073c0 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptPropertyDefVal.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptPropertyDefVal.generated.cs
@@ -12,126 +12,126 @@ partial class ExportedFields
internal new static global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant> GetGodotPropertyDefaultValues()
{
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(60);
- bool __field_Boolean_default_value = true;
- values.Add(PropertyName.field_Boolean, global::Godot.Variant.From<bool>(__field_Boolean_default_value));
- char __field_Char_default_value = 'f';
- values.Add(PropertyName.field_Char, global::Godot.Variant.From<char>(__field_Char_default_value));
- sbyte __field_SByte_default_value = 10;
- values.Add(PropertyName.field_SByte, global::Godot.Variant.From<sbyte>(__field_SByte_default_value));
- short __field_Int16_default_value = 10;
- values.Add(PropertyName.field_Int16, global::Godot.Variant.From<short>(__field_Int16_default_value));
- int __field_Int32_default_value = 10;
- values.Add(PropertyName.field_Int32, global::Godot.Variant.From<int>(__field_Int32_default_value));
- long __field_Int64_default_value = 10;
- values.Add(PropertyName.field_Int64, global::Godot.Variant.From<long>(__field_Int64_default_value));
- byte __field_Byte_default_value = 10;
- values.Add(PropertyName.field_Byte, global::Godot.Variant.From<byte>(__field_Byte_default_value));
- ushort __field_UInt16_default_value = 10;
- values.Add(PropertyName.field_UInt16, global::Godot.Variant.From<ushort>(__field_UInt16_default_value));
- uint __field_UInt32_default_value = 10;
- values.Add(PropertyName.field_UInt32, global::Godot.Variant.From<uint>(__field_UInt32_default_value));
- ulong __field_UInt64_default_value = 10;
- values.Add(PropertyName.field_UInt64, global::Godot.Variant.From<ulong>(__field_UInt64_default_value));
- float __field_Single_default_value = 10;
- values.Add(PropertyName.field_Single, global::Godot.Variant.From<float>(__field_Single_default_value));
- double __field_Double_default_value = 10;
- values.Add(PropertyName.field_Double, global::Godot.Variant.From<double>(__field_Double_default_value));
- string __field_String_default_value = "foo";
- values.Add(PropertyName.field_String, global::Godot.Variant.From<string>(__field_String_default_value));
- global::Godot.Vector2 __field_Vector2_default_value = new(10f, 10f);
- values.Add(PropertyName.field_Vector2, global::Godot.Variant.From<global::Godot.Vector2>(__field_Vector2_default_value));
- global::Godot.Vector2I __field_Vector2I_default_value = global::Godot.Vector2I.Up;
- values.Add(PropertyName.field_Vector2I, global::Godot.Variant.From<global::Godot.Vector2I>(__field_Vector2I_default_value));
- global::Godot.Rect2 __field_Rect2_default_value = new(new global::Godot.Vector2(10f, 10f), new global::Godot.Vector2(10f, 10f));
- values.Add(PropertyName.field_Rect2, global::Godot.Variant.From<global::Godot.Rect2>(__field_Rect2_default_value));
- global::Godot.Rect2I __field_Rect2I_default_value = new(new global::Godot.Vector2I(10, 10), new global::Godot.Vector2I(10, 10));
- values.Add(PropertyName.field_Rect2I, global::Godot.Variant.From<global::Godot.Rect2I>(__field_Rect2I_default_value));
- global::Godot.Transform2D __field_Transform2D_default_value = global::Godot.Transform2D.Identity;
- values.Add(PropertyName.field_Transform2D, global::Godot.Variant.From<global::Godot.Transform2D>(__field_Transform2D_default_value));
- global::Godot.Vector3 __field_Vector3_default_value = new(10f, 10f, 10f);
- values.Add(PropertyName.field_Vector3, global::Godot.Variant.From<global::Godot.Vector3>(__field_Vector3_default_value));
- global::Godot.Vector3I __field_Vector3I_default_value = global::Godot.Vector3I.Back;
- values.Add(PropertyName.field_Vector3I, global::Godot.Variant.From<global::Godot.Vector3I>(__field_Vector3I_default_value));
- global::Godot.Basis __field_Basis_default_value = new global::Godot.Basis(global::Godot.Quaternion.Identity);
- values.Add(PropertyName.field_Basis, global::Godot.Variant.From<global::Godot.Basis>(__field_Basis_default_value));
- global::Godot.Quaternion __field_Quaternion_default_value = new global::Godot.Quaternion(global::Godot.Basis.Identity);
- values.Add(PropertyName.field_Quaternion, global::Godot.Variant.From<global::Godot.Quaternion>(__field_Quaternion_default_value));
- global::Godot.Transform3D __field_Transform3D_default_value = global::Godot.Transform3D.Identity;
- values.Add(PropertyName.field_Transform3D, global::Godot.Variant.From<global::Godot.Transform3D>(__field_Transform3D_default_value));
- global::Godot.Vector4 __field_Vector4_default_value = new(10f, 10f, 10f, 10f);
- values.Add(PropertyName.field_Vector4, global::Godot.Variant.From<global::Godot.Vector4>(__field_Vector4_default_value));
- global::Godot.Vector4I __field_Vector4I_default_value = global::Godot.Vector4I.One;
- values.Add(PropertyName.field_Vector4I, global::Godot.Variant.From<global::Godot.Vector4I>(__field_Vector4I_default_value));
- global::Godot.Projection __field_Projection_default_value = global::Godot.Projection.Identity;
- values.Add(PropertyName.field_Projection, global::Godot.Variant.From<global::Godot.Projection>(__field_Projection_default_value));
- global::Godot.Aabb __field_Aabb_default_value = new global::Godot.Aabb(10f, 10f, 10f, new global::Godot.Vector3(1f, 1f, 1f));
- values.Add(PropertyName.field_Aabb, global::Godot.Variant.From<global::Godot.Aabb>(__field_Aabb_default_value));
- global::Godot.Color __field_Color_default_value = global::Godot.Colors.Aquamarine;
- values.Add(PropertyName.field_Color, global::Godot.Variant.From<global::Godot.Color>(__field_Color_default_value));
- global::Godot.Plane __field_Plane_default_value = global::Godot.Plane.PlaneXZ;
- values.Add(PropertyName.field_Plane, global::Godot.Variant.From<global::Godot.Plane>(__field_Plane_default_value));
- global::Godot.Callable __field_Callable_default_value = new global::Godot.Callable(global::Godot.Engine.GetMainLoop(), "_process");
- values.Add(PropertyName.field_Callable, global::Godot.Variant.From<global::Godot.Callable>(__field_Callable_default_value));
- global::Godot.Signal __field_Signal_default_value = new global::Godot.Signal(global::Godot.Engine.GetMainLoop(), "property_list_changed");
- values.Add(PropertyName.field_Signal, global::Godot.Variant.From<global::Godot.Signal>(__field_Signal_default_value));
- global::ExportedFields.MyEnum __field_Enum_default_value = global::ExportedFields.MyEnum.C;
- values.Add(PropertyName.field_Enum, global::Godot.Variant.From<global::ExportedFields.MyEnum>(__field_Enum_default_value));
- global::ExportedFields.MyFlagsEnum __field_FlagsEnum_default_value = global::ExportedFields.MyFlagsEnum.C;
- values.Add(PropertyName.field_FlagsEnum, global::Godot.Variant.From<global::ExportedFields.MyFlagsEnum>(__field_FlagsEnum_default_value));
- byte[] __field_ByteArray_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.field_ByteArray, global::Godot.Variant.From<byte[]>(__field_ByteArray_default_value));
- int[] __field_Int32Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.field_Int32Array, global::Godot.Variant.From<int[]>(__field_Int32Array_default_value));
- long[] __field_Int64Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.field_Int64Array, global::Godot.Variant.From<long[]>(__field_Int64Array_default_value));
- float[] __field_SingleArray_default_value = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- values.Add(PropertyName.field_SingleArray, global::Godot.Variant.From<float[]>(__field_SingleArray_default_value));
- double[] __field_DoubleArray_default_value = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- values.Add(PropertyName.field_DoubleArray, global::Godot.Variant.From<double[]>(__field_DoubleArray_default_value));
- string[] __field_StringArray_default_value = { "foo", "bar" };
- values.Add(PropertyName.field_StringArray, global::Godot.Variant.From<string[]>(__field_StringArray_default_value));
- string[] __field_StringArrayEnum_default_value = { "foo", "bar" };
- values.Add(PropertyName.field_StringArrayEnum, global::Godot.Variant.From<string[]>(__field_StringArrayEnum_default_value));
- global::Godot.Vector2[] __field_Vector2Array_default_value = { global::Godot.Vector2.Up, global::Godot.Vector2.Down, global::Godot.Vector2.Left, global::Godot.Vector2.Right };
- values.Add(PropertyName.field_Vector2Array, global::Godot.Variant.From<global::Godot.Vector2[]>(__field_Vector2Array_default_value));
- global::Godot.Vector3[] __field_Vector3Array_default_value = { global::Godot.Vector3.Up, global::Godot.Vector3.Down, global::Godot.Vector3.Left, global::Godot.Vector3.Right };
- values.Add(PropertyName.field_Vector3Array, global::Godot.Variant.From<global::Godot.Vector3[]>(__field_Vector3Array_default_value));
- global::Godot.Color[] __field_ColorArray_default_value = { global::Godot.Colors.Aqua, global::Godot.Colors.Aquamarine, global::Godot.Colors.Azure, global::Godot.Colors.Beige };
- values.Add(PropertyName.field_ColorArray, global::Godot.Variant.From<global::Godot.Color[]>(__field_ColorArray_default_value));
- global::Godot.GodotObject[] __field_GodotObjectOrDerivedArray_default_value = { null };
- values.Add(PropertyName.field_GodotObjectOrDerivedArray, global::Godot.Variant.CreateFrom(__field_GodotObjectOrDerivedArray_default_value));
- global::Godot.StringName[] __field_StringNameArray_default_value = { "foo", "bar" };
- values.Add(PropertyName.field_StringNameArray, global::Godot.Variant.From<global::Godot.StringName[]>(__field_StringNameArray_default_value));
- global::Godot.NodePath[] __field_NodePathArray_default_value = { "foo", "bar" };
- values.Add(PropertyName.field_NodePathArray, global::Godot.Variant.From<global::Godot.NodePath[]>(__field_NodePathArray_default_value));
- global::Godot.Rid[] __field_RidArray_default_value = { default, default, default };
- values.Add(PropertyName.field_RidArray, global::Godot.Variant.From<global::Godot.Rid[]>(__field_RidArray_default_value));
- int[] __field_empty_Int32Array_default_value = global::System.Array.Empty<int>();
- values.Add(PropertyName.field_empty_Int32Array, global::Godot.Variant.From<int[]>(__field_empty_Int32Array_default_value));
- int[] __field_array_from_list_default_value = new global::System.Collections.Generic.List<int>(global::System.Array.Empty<int>()).ToArray();
- values.Add(PropertyName.field_array_from_list, global::Godot.Variant.From<int[]>(__field_array_from_list_default_value));
- global::Godot.Variant __field_Variant_default_value = "foo";
- values.Add(PropertyName.field_Variant, global::Godot.Variant.From<global::Godot.Variant>(__field_Variant_default_value));
- global::Godot.GodotObject __field_GodotObjectOrDerived_default_value = default;
- values.Add(PropertyName.field_GodotObjectOrDerived, global::Godot.Variant.From<global::Godot.GodotObject>(__field_GodotObjectOrDerived_default_value));
- global::Godot.Texture __field_GodotResourceTexture_default_value = default;
- values.Add(PropertyName.field_GodotResourceTexture, global::Godot.Variant.From<global::Godot.Texture>(__field_GodotResourceTexture_default_value));
- global::Godot.StringName __field_StringName_default_value = new global::Godot.StringName("foo");
- values.Add(PropertyName.field_StringName, global::Godot.Variant.From<global::Godot.StringName>(__field_StringName_default_value));
- global::Godot.NodePath __field_NodePath_default_value = new global::Godot.NodePath("foo");
- values.Add(PropertyName.field_NodePath, global::Godot.Variant.From<global::Godot.NodePath>(__field_NodePath_default_value));
- global::Godot.Rid __field_Rid_default_value = default;
- values.Add(PropertyName.field_Rid, global::Godot.Variant.From<global::Godot.Rid>(__field_Rid_default_value));
- global::Godot.Collections.Dictionary __field_GodotDictionary_default_value = new() { { "foo", 10 }, { global::Godot.Vector2.Up, global::Godot.Colors.Chocolate } };
- values.Add(PropertyName.field_GodotDictionary, global::Godot.Variant.From<global::Godot.Collections.Dictionary>(__field_GodotDictionary_default_value));
- global::Godot.Collections.Array __field_GodotArray_default_value = new() { "foo", 10, global::Godot.Vector2.Up, global::Godot.Colors.Chocolate };
- values.Add(PropertyName.field_GodotArray, global::Godot.Variant.From<global::Godot.Collections.Array>(__field_GodotArray_default_value));
- global::Godot.Collections.Dictionary<string, bool> __field_GodotGenericDictionary_default_value = new() { { "foo", true }, { "bar", false } };
- values.Add(PropertyName.field_GodotGenericDictionary, global::Godot.Variant.CreateFrom(__field_GodotGenericDictionary_default_value));
- global::Godot.Collections.Array<int> __field_GodotGenericArray_default_value = new() { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.field_GodotGenericArray, global::Godot.Variant.CreateFrom(__field_GodotGenericArray_default_value));
- long[] __field_empty_Int64Array_default_value = global::System.Array.Empty<long>();
- values.Add(PropertyName.field_empty_Int64Array, global::Godot.Variant.From<long[]>(__field_empty_Int64Array_default_value));
+ bool ___fieldBoolean_default_value = true;
+ values.Add(PropertyName._fieldBoolean, global::Godot.Variant.From<bool>(___fieldBoolean_default_value));
+ char ___fieldChar_default_value = 'f';
+ values.Add(PropertyName._fieldChar, global::Godot.Variant.From<char>(___fieldChar_default_value));
+ sbyte ___fieldSByte_default_value = 10;
+ values.Add(PropertyName._fieldSByte, global::Godot.Variant.From<sbyte>(___fieldSByte_default_value));
+ short ___fieldInt16_default_value = 10;
+ values.Add(PropertyName._fieldInt16, global::Godot.Variant.From<short>(___fieldInt16_default_value));
+ int ___fieldInt32_default_value = 10;
+ values.Add(PropertyName._fieldInt32, global::Godot.Variant.From<int>(___fieldInt32_default_value));
+ long ___fieldInt64_default_value = 10;
+ values.Add(PropertyName._fieldInt64, global::Godot.Variant.From<long>(___fieldInt64_default_value));
+ byte ___fieldByte_default_value = 10;
+ values.Add(PropertyName._fieldByte, global::Godot.Variant.From<byte>(___fieldByte_default_value));
+ ushort ___fieldUInt16_default_value = 10;
+ values.Add(PropertyName._fieldUInt16, global::Godot.Variant.From<ushort>(___fieldUInt16_default_value));
+ uint ___fieldUInt32_default_value = 10;
+ values.Add(PropertyName._fieldUInt32, global::Godot.Variant.From<uint>(___fieldUInt32_default_value));
+ ulong ___fieldUInt64_default_value = 10;
+ values.Add(PropertyName._fieldUInt64, global::Godot.Variant.From<ulong>(___fieldUInt64_default_value));
+ float ___fieldSingle_default_value = 10;
+ values.Add(PropertyName._fieldSingle, global::Godot.Variant.From<float>(___fieldSingle_default_value));
+ double ___fieldDouble_default_value = 10;
+ values.Add(PropertyName._fieldDouble, global::Godot.Variant.From<double>(___fieldDouble_default_value));
+ string ___fieldString_default_value = "foo";
+ values.Add(PropertyName._fieldString, global::Godot.Variant.From<string>(___fieldString_default_value));
+ global::Godot.Vector2 ___fieldVector2_default_value = new(10f, 10f);
+ values.Add(PropertyName._fieldVector2, global::Godot.Variant.From<global::Godot.Vector2>(___fieldVector2_default_value));
+ global::Godot.Vector2I ___fieldVector2I_default_value = global::Godot.Vector2I.Up;
+ values.Add(PropertyName._fieldVector2I, global::Godot.Variant.From<global::Godot.Vector2I>(___fieldVector2I_default_value));
+ global::Godot.Rect2 ___fieldRect2_default_value = new(new global::Godot.Vector2(10f, 10f), new global::Godot.Vector2(10f, 10f));
+ values.Add(PropertyName._fieldRect2, global::Godot.Variant.From<global::Godot.Rect2>(___fieldRect2_default_value));
+ global::Godot.Rect2I ___fieldRect2I_default_value = new(new global::Godot.Vector2I(10, 10), new global::Godot.Vector2I(10, 10));
+ values.Add(PropertyName._fieldRect2I, global::Godot.Variant.From<global::Godot.Rect2I>(___fieldRect2I_default_value));
+ global::Godot.Transform2D ___fieldTransform2D_default_value = global::Godot.Transform2D.Identity;
+ values.Add(PropertyName._fieldTransform2D, global::Godot.Variant.From<global::Godot.Transform2D>(___fieldTransform2D_default_value));
+ global::Godot.Vector3 ___fieldVector3_default_value = new(10f, 10f, 10f);
+ values.Add(PropertyName._fieldVector3, global::Godot.Variant.From<global::Godot.Vector3>(___fieldVector3_default_value));
+ global::Godot.Vector3I ___fieldVector3I_default_value = global::Godot.Vector3I.Back;
+ values.Add(PropertyName._fieldVector3I, global::Godot.Variant.From<global::Godot.Vector3I>(___fieldVector3I_default_value));
+ global::Godot.Basis ___fieldBasis_default_value = new global::Godot.Basis(global::Godot.Quaternion.Identity);
+ values.Add(PropertyName._fieldBasis, global::Godot.Variant.From<global::Godot.Basis>(___fieldBasis_default_value));
+ global::Godot.Quaternion ___fieldQuaternion_default_value = new global::Godot.Quaternion(global::Godot.Basis.Identity);
+ values.Add(PropertyName._fieldQuaternion, global::Godot.Variant.From<global::Godot.Quaternion>(___fieldQuaternion_default_value));
+ global::Godot.Transform3D ___fieldTransform3D_default_value = global::Godot.Transform3D.Identity;
+ values.Add(PropertyName._fieldTransform3D, global::Godot.Variant.From<global::Godot.Transform3D>(___fieldTransform3D_default_value));
+ global::Godot.Vector4 ___fieldVector4_default_value = new(10f, 10f, 10f, 10f);
+ values.Add(PropertyName._fieldVector4, global::Godot.Variant.From<global::Godot.Vector4>(___fieldVector4_default_value));
+ global::Godot.Vector4I ___fieldVector4I_default_value = global::Godot.Vector4I.One;
+ values.Add(PropertyName._fieldVector4I, global::Godot.Variant.From<global::Godot.Vector4I>(___fieldVector4I_default_value));
+ global::Godot.Projection ___fieldProjection_default_value = global::Godot.Projection.Identity;
+ values.Add(PropertyName._fieldProjection, global::Godot.Variant.From<global::Godot.Projection>(___fieldProjection_default_value));
+ global::Godot.Aabb ___fieldAabb_default_value = new global::Godot.Aabb(10f, 10f, 10f, new global::Godot.Vector3(1f, 1f, 1f));
+ values.Add(PropertyName._fieldAabb, global::Godot.Variant.From<global::Godot.Aabb>(___fieldAabb_default_value));
+ global::Godot.Color ___fieldColor_default_value = global::Godot.Colors.Aquamarine;
+ values.Add(PropertyName._fieldColor, global::Godot.Variant.From<global::Godot.Color>(___fieldColor_default_value));
+ global::Godot.Plane ___fieldPlane_default_value = global::Godot.Plane.PlaneXZ;
+ values.Add(PropertyName._fieldPlane, global::Godot.Variant.From<global::Godot.Plane>(___fieldPlane_default_value));
+ global::Godot.Callable ___fieldCallable_default_value = new global::Godot.Callable(global::Godot.Engine.GetMainLoop(), "_process");
+ values.Add(PropertyName._fieldCallable, global::Godot.Variant.From<global::Godot.Callable>(___fieldCallable_default_value));
+ global::Godot.Signal ___fieldSignal_default_value = new global::Godot.Signal(global::Godot.Engine.GetMainLoop(), "property_list_changed");
+ values.Add(PropertyName._fieldSignal, global::Godot.Variant.From<global::Godot.Signal>(___fieldSignal_default_value));
+ global::ExportedFields.MyEnum ___fieldEnum_default_value = global::ExportedFields.MyEnum.C;
+ values.Add(PropertyName._fieldEnum, global::Godot.Variant.From<global::ExportedFields.MyEnum>(___fieldEnum_default_value));
+ global::ExportedFields.MyFlagsEnum ___fieldFlagsEnum_default_value = global::ExportedFields.MyFlagsEnum.C;
+ values.Add(PropertyName._fieldFlagsEnum, global::Godot.Variant.From<global::ExportedFields.MyFlagsEnum>(___fieldFlagsEnum_default_value));
+ byte[] ___fieldByteArray_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName._fieldByteArray, global::Godot.Variant.From<byte[]>(___fieldByteArray_default_value));
+ int[] ___fieldInt32Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName._fieldInt32Array, global::Godot.Variant.From<int[]>(___fieldInt32Array_default_value));
+ long[] ___fieldInt64Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName._fieldInt64Array, global::Godot.Variant.From<long[]>(___fieldInt64Array_default_value));
+ float[] ___fieldSingleArray_default_value = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ values.Add(PropertyName._fieldSingleArray, global::Godot.Variant.From<float[]>(___fieldSingleArray_default_value));
+ double[] ___fieldDoubleArray_default_value = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ values.Add(PropertyName._fieldDoubleArray, global::Godot.Variant.From<double[]>(___fieldDoubleArray_default_value));
+ string[] ___fieldStringArray_default_value = { "foo", "bar" };
+ values.Add(PropertyName._fieldStringArray, global::Godot.Variant.From<string[]>(___fieldStringArray_default_value));
+ string[] ___fieldStringArrayEnum_default_value = { "foo", "bar" };
+ values.Add(PropertyName._fieldStringArrayEnum, global::Godot.Variant.From<string[]>(___fieldStringArrayEnum_default_value));
+ global::Godot.Vector2[] ___fieldVector2Array_default_value = { global::Godot.Vector2.Up, global::Godot.Vector2.Down, global::Godot.Vector2.Left, global::Godot.Vector2.Right };
+ values.Add(PropertyName._fieldVector2Array, global::Godot.Variant.From<global::Godot.Vector2[]>(___fieldVector2Array_default_value));
+ global::Godot.Vector3[] ___fieldVector3Array_default_value = { global::Godot.Vector3.Up, global::Godot.Vector3.Down, global::Godot.Vector3.Left, global::Godot.Vector3.Right };
+ values.Add(PropertyName._fieldVector3Array, global::Godot.Variant.From<global::Godot.Vector3[]>(___fieldVector3Array_default_value));
+ global::Godot.Color[] ___fieldColorArray_default_value = { global::Godot.Colors.Aqua, global::Godot.Colors.Aquamarine, global::Godot.Colors.Azure, global::Godot.Colors.Beige };
+ values.Add(PropertyName._fieldColorArray, global::Godot.Variant.From<global::Godot.Color[]>(___fieldColorArray_default_value));
+ global::Godot.GodotObject[] ___fieldGodotObjectOrDerivedArray_default_value = { null };
+ values.Add(PropertyName._fieldGodotObjectOrDerivedArray, global::Godot.Variant.CreateFrom(___fieldGodotObjectOrDerivedArray_default_value));
+ global::Godot.StringName[] ___fieldStringNameArray_default_value = { "foo", "bar" };
+ values.Add(PropertyName._fieldStringNameArray, global::Godot.Variant.From<global::Godot.StringName[]>(___fieldStringNameArray_default_value));
+ global::Godot.NodePath[] ___fieldNodePathArray_default_value = { "foo", "bar" };
+ values.Add(PropertyName._fieldNodePathArray, global::Godot.Variant.From<global::Godot.NodePath[]>(___fieldNodePathArray_default_value));
+ global::Godot.Rid[] ___fieldRidArray_default_value = { default, default, default };
+ values.Add(PropertyName._fieldRidArray, global::Godot.Variant.From<global::Godot.Rid[]>(___fieldRidArray_default_value));
+ int[] ___fieldEmptyInt32Array_default_value = global::System.Array.Empty<int>();
+ values.Add(PropertyName._fieldEmptyInt32Array, global::Godot.Variant.From<int[]>(___fieldEmptyInt32Array_default_value));
+ int[] ___fieldArrayFromList_default_value = new global::System.Collections.Generic.List<int>(global::System.Array.Empty<int>()).ToArray();
+ values.Add(PropertyName._fieldArrayFromList, global::Godot.Variant.From<int[]>(___fieldArrayFromList_default_value));
+ global::Godot.Variant ___fieldVariant_default_value = "foo";
+ values.Add(PropertyName._fieldVariant, global::Godot.Variant.From<global::Godot.Variant>(___fieldVariant_default_value));
+ global::Godot.GodotObject ___fieldGodotObjectOrDerived_default_value = default;
+ values.Add(PropertyName._fieldGodotObjectOrDerived, global::Godot.Variant.From<global::Godot.GodotObject>(___fieldGodotObjectOrDerived_default_value));
+ global::Godot.Texture ___fieldGodotResourceTexture_default_value = default;
+ values.Add(PropertyName._fieldGodotResourceTexture, global::Godot.Variant.From<global::Godot.Texture>(___fieldGodotResourceTexture_default_value));
+ global::Godot.StringName ___fieldStringName_default_value = new global::Godot.StringName("foo");
+ values.Add(PropertyName._fieldStringName, global::Godot.Variant.From<global::Godot.StringName>(___fieldStringName_default_value));
+ global::Godot.NodePath ___fieldNodePath_default_value = new global::Godot.NodePath("foo");
+ values.Add(PropertyName._fieldNodePath, global::Godot.Variant.From<global::Godot.NodePath>(___fieldNodePath_default_value));
+ global::Godot.Rid ___fieldRid_default_value = default;
+ values.Add(PropertyName._fieldRid, global::Godot.Variant.From<global::Godot.Rid>(___fieldRid_default_value));
+ global::Godot.Collections.Dictionary ___fieldGodotDictionary_default_value = new() { { "foo", 10 }, { global::Godot.Vector2.Up, global::Godot.Colors.Chocolate } };
+ values.Add(PropertyName._fieldGodotDictionary, global::Godot.Variant.From<global::Godot.Collections.Dictionary>(___fieldGodotDictionary_default_value));
+ global::Godot.Collections.Array ___fieldGodotArray_default_value = new() { "foo", 10, global::Godot.Vector2.Up, global::Godot.Colors.Chocolate };
+ values.Add(PropertyName._fieldGodotArray, global::Godot.Variant.From<global::Godot.Collections.Array>(___fieldGodotArray_default_value));
+ global::Godot.Collections.Dictionary<string, bool> ___fieldGodotGenericDictionary_default_value = new() { { "foo", true }, { "bar", false } };
+ values.Add(PropertyName._fieldGodotGenericDictionary, global::Godot.Variant.CreateFrom(___fieldGodotGenericDictionary_default_value));
+ global::Godot.Collections.Array<int> ___fieldGodotGenericArray_default_value = new() { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName._fieldGodotGenericArray, global::Godot.Variant.CreateFrom(___fieldGodotGenericArray_default_value));
+ long[] ___fieldEmptyInt64Array_default_value = global::System.Array.Empty<long>();
+ values.Add(PropertyName._fieldEmptyInt64Array, global::Godot.Variant.From<long[]>(___fieldEmptyInt64Array_default_value));
return values;
}
#endif // TOOLS
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
index b5ec9b5b49..6e0e9fffbe 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
@@ -9,209 +9,209 @@ partial class ExportedProperties
/// </summary>
public new class PropertyName : global::Godot.GodotObject.PropertyName {
/// <summary>
- /// Cached name for the 'NotGenerate_Complex_Lamda_Property' property.
+ /// Cached name for the 'NotGenerateComplexLamdaProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName NotGenerate_Complex_Lamda_Property = "NotGenerate_Complex_Lamda_Property";
+ public new static readonly global::Godot.StringName NotGenerateComplexLamdaProperty = "NotGenerateComplexLamdaProperty";
/// <summary>
- /// Cached name for the 'NotGenerate_Lamda_NoField_Property' property.
+ /// Cached name for the 'NotGenerateLamdaNoFieldProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName NotGenerate_Lamda_NoField_Property = "NotGenerate_Lamda_NoField_Property";
+ public new static readonly global::Godot.StringName NotGenerateLamdaNoFieldProperty = "NotGenerateLamdaNoFieldProperty";
/// <summary>
- /// Cached name for the 'NotGenerate_Complex_Return_Property' property.
+ /// Cached name for the 'NotGenerateComplexReturnProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName NotGenerate_Complex_Return_Property = "NotGenerate_Complex_Return_Property";
+ public new static readonly global::Godot.StringName NotGenerateComplexReturnProperty = "NotGenerateComplexReturnProperty";
/// <summary>
- /// Cached name for the 'NotGenerate_Returns_Property' property.
+ /// Cached name for the 'NotGenerateReturnsProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName NotGenerate_Returns_Property = "NotGenerate_Returns_Property";
+ public new static readonly global::Godot.StringName NotGenerateReturnsProperty = "NotGenerateReturnsProperty";
/// <summary>
- /// Cached name for the 'FullProperty_String' property.
+ /// Cached name for the 'FullPropertyString' property.
/// </summary>
- public new static readonly global::Godot.StringName FullProperty_String = "FullProperty_String";
+ public new static readonly global::Godot.StringName FullPropertyString = "FullPropertyString";
/// <summary>
- /// Cached name for the 'FullProperty_String_Complex' property.
+ /// Cached name for the 'FullPropertyString_Complex' property.
/// </summary>
- public new static readonly global::Godot.StringName FullProperty_String_Complex = "FullProperty_String_Complex";
+ public new static readonly global::Godot.StringName FullPropertyString_Complex = "FullPropertyString_Complex";
/// <summary>
- /// Cached name for the 'LamdaProperty_String' property.
+ /// Cached name for the 'LamdaPropertyString' property.
/// </summary>
- public new static readonly global::Godot.StringName LamdaProperty_String = "LamdaProperty_String";
+ public new static readonly global::Godot.StringName LamdaPropertyString = "LamdaPropertyString";
/// <summary>
- /// Cached name for the 'property_Boolean' property.
+ /// Cached name for the 'PropertyBoolean' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Boolean = "property_Boolean";
+ public new static readonly global::Godot.StringName PropertyBoolean = "PropertyBoolean";
/// <summary>
- /// Cached name for the 'property_Char' property.
+ /// Cached name for the 'PropertyChar' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Char = "property_Char";
+ public new static readonly global::Godot.StringName PropertyChar = "PropertyChar";
/// <summary>
- /// Cached name for the 'property_SByte' property.
+ /// Cached name for the 'PropertySByte' property.
/// </summary>
- public new static readonly global::Godot.StringName property_SByte = "property_SByte";
+ public new static readonly global::Godot.StringName PropertySByte = "PropertySByte";
/// <summary>
- /// Cached name for the 'property_Int16' property.
+ /// Cached name for the 'PropertyInt16' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Int16 = "property_Int16";
+ public new static readonly global::Godot.StringName PropertyInt16 = "PropertyInt16";
/// <summary>
- /// Cached name for the 'property_Int32' property.
+ /// Cached name for the 'PropertyInt32' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Int32 = "property_Int32";
+ public new static readonly global::Godot.StringName PropertyInt32 = "PropertyInt32";
/// <summary>
- /// Cached name for the 'property_Int64' property.
+ /// Cached name for the 'PropertyInt64' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Int64 = "property_Int64";
+ public new static readonly global::Godot.StringName PropertyInt64 = "PropertyInt64";
/// <summary>
- /// Cached name for the 'property_Byte' property.
+ /// Cached name for the 'PropertyByte' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Byte = "property_Byte";
+ public new static readonly global::Godot.StringName PropertyByte = "PropertyByte";
/// <summary>
- /// Cached name for the 'property_UInt16' property.
+ /// Cached name for the 'PropertyUInt16' property.
/// </summary>
- public new static readonly global::Godot.StringName property_UInt16 = "property_UInt16";
+ public new static readonly global::Godot.StringName PropertyUInt16 = "PropertyUInt16";
/// <summary>
- /// Cached name for the 'property_UInt32' property.
+ /// Cached name for the 'PropertyUInt32' property.
/// </summary>
- public new static readonly global::Godot.StringName property_UInt32 = "property_UInt32";
+ public new static readonly global::Godot.StringName PropertyUInt32 = "PropertyUInt32";
/// <summary>
- /// Cached name for the 'property_UInt64' property.
+ /// Cached name for the 'PropertyUInt64' property.
/// </summary>
- public new static readonly global::Godot.StringName property_UInt64 = "property_UInt64";
+ public new static readonly global::Godot.StringName PropertyUInt64 = "PropertyUInt64";
/// <summary>
- /// Cached name for the 'property_Single' property.
+ /// Cached name for the 'PropertySingle' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Single = "property_Single";
+ public new static readonly global::Godot.StringName PropertySingle = "PropertySingle";
/// <summary>
- /// Cached name for the 'property_Double' property.
+ /// Cached name for the 'PropertyDouble' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Double = "property_Double";
+ public new static readonly global::Godot.StringName PropertyDouble = "PropertyDouble";
/// <summary>
- /// Cached name for the 'property_String' property.
+ /// Cached name for the 'PropertyString' property.
/// </summary>
- public new static readonly global::Godot.StringName property_String = "property_String";
+ public new static readonly global::Godot.StringName PropertyString = "PropertyString";
/// <summary>
- /// Cached name for the 'property_Vector2' property.
+ /// Cached name for the 'PropertyVector2' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector2 = "property_Vector2";
+ public new static readonly global::Godot.StringName PropertyVector2 = "PropertyVector2";
/// <summary>
- /// Cached name for the 'property_Vector2I' property.
+ /// Cached name for the 'PropertyVector2I' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector2I = "property_Vector2I";
+ public new static readonly global::Godot.StringName PropertyVector2I = "PropertyVector2I";
/// <summary>
- /// Cached name for the 'property_Rect2' property.
+ /// Cached name for the 'PropertyRect2' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Rect2 = "property_Rect2";
+ public new static readonly global::Godot.StringName PropertyRect2 = "PropertyRect2";
/// <summary>
- /// Cached name for the 'property_Rect2I' property.
+ /// Cached name for the 'PropertyRect2I' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Rect2I = "property_Rect2I";
+ public new static readonly global::Godot.StringName PropertyRect2I = "PropertyRect2I";
/// <summary>
- /// Cached name for the 'property_Transform2D' property.
+ /// Cached name for the 'PropertyTransform2D' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Transform2D = "property_Transform2D";
+ public new static readonly global::Godot.StringName PropertyTransform2D = "PropertyTransform2D";
/// <summary>
- /// Cached name for the 'property_Vector3' property.
+ /// Cached name for the 'PropertyVector3' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector3 = "property_Vector3";
+ public new static readonly global::Godot.StringName PropertyVector3 = "PropertyVector3";
/// <summary>
- /// Cached name for the 'property_Vector3I' property.
+ /// Cached name for the 'PropertyVector3I' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector3I = "property_Vector3I";
+ public new static readonly global::Godot.StringName PropertyVector3I = "PropertyVector3I";
/// <summary>
- /// Cached name for the 'property_Basis' property.
+ /// Cached name for the 'PropertyBasis' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Basis = "property_Basis";
+ public new static readonly global::Godot.StringName PropertyBasis = "PropertyBasis";
/// <summary>
- /// Cached name for the 'property_Quaternion' property.
+ /// Cached name for the 'PropertyQuaternion' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Quaternion = "property_Quaternion";
+ public new static readonly global::Godot.StringName PropertyQuaternion = "PropertyQuaternion";
/// <summary>
- /// Cached name for the 'property_Transform3D' property.
+ /// Cached name for the 'PropertyTransform3D' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Transform3D = "property_Transform3D";
+ public new static readonly global::Godot.StringName PropertyTransform3D = "PropertyTransform3D";
/// <summary>
- /// Cached name for the 'property_Vector4' property.
+ /// Cached name for the 'PropertyVector4' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector4 = "property_Vector4";
+ public new static readonly global::Godot.StringName PropertyVector4 = "PropertyVector4";
/// <summary>
- /// Cached name for the 'property_Vector4I' property.
+ /// Cached name for the 'PropertyVector4I' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector4I = "property_Vector4I";
+ public new static readonly global::Godot.StringName PropertyVector4I = "PropertyVector4I";
/// <summary>
- /// Cached name for the 'property_Projection' property.
+ /// Cached name for the 'PropertyProjection' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Projection = "property_Projection";
+ public new static readonly global::Godot.StringName PropertyProjection = "PropertyProjection";
/// <summary>
- /// Cached name for the 'property_Aabb' property.
+ /// Cached name for the 'PropertyAabb' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Aabb = "property_Aabb";
+ public new static readonly global::Godot.StringName PropertyAabb = "PropertyAabb";
/// <summary>
- /// Cached name for the 'property_Color' property.
+ /// Cached name for the 'PropertyColor' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Color = "property_Color";
+ public new static readonly global::Godot.StringName PropertyColor = "PropertyColor";
/// <summary>
- /// Cached name for the 'property_Plane' property.
+ /// Cached name for the 'PropertyPlane' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Plane = "property_Plane";
+ public new static readonly global::Godot.StringName PropertyPlane = "PropertyPlane";
/// <summary>
- /// Cached name for the 'property_Callable' property.
+ /// Cached name for the 'PropertyCallable' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Callable = "property_Callable";
+ public new static readonly global::Godot.StringName PropertyCallable = "PropertyCallable";
/// <summary>
- /// Cached name for the 'property_Signal' property.
+ /// Cached name for the 'PropertySignal' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Signal = "property_Signal";
+ public new static readonly global::Godot.StringName PropertySignal = "PropertySignal";
/// <summary>
- /// Cached name for the 'property_Enum' property.
+ /// Cached name for the 'PropertyEnum' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Enum = "property_Enum";
+ public new static readonly global::Godot.StringName PropertyEnum = "PropertyEnum";
/// <summary>
- /// Cached name for the 'property_FlagsEnum' property.
+ /// Cached name for the 'PropertyFlagsEnum' property.
/// </summary>
- public new static readonly global::Godot.StringName property_FlagsEnum = "property_FlagsEnum";
+ public new static readonly global::Godot.StringName PropertyFlagsEnum = "PropertyFlagsEnum";
/// <summary>
- /// Cached name for the 'property_ByteArray' property.
+ /// Cached name for the 'PropertyByteArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_ByteArray = "property_ByteArray";
+ public new static readonly global::Godot.StringName PropertyByteArray = "PropertyByteArray";
/// <summary>
- /// Cached name for the 'property_Int32Array' property.
+ /// Cached name for the 'PropertyInt32Array' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Int32Array = "property_Int32Array";
+ public new static readonly global::Godot.StringName PropertyInt32Array = "PropertyInt32Array";
/// <summary>
- /// Cached name for the 'property_Int64Array' property.
+ /// Cached name for the 'PropertyInt64Array' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Int64Array = "property_Int64Array";
+ public new static readonly global::Godot.StringName PropertyInt64Array = "PropertyInt64Array";
/// <summary>
- /// Cached name for the 'property_SingleArray' property.
+ /// Cached name for the 'PropertySingleArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_SingleArray = "property_SingleArray";
+ public new static readonly global::Godot.StringName PropertySingleArray = "PropertySingleArray";
/// <summary>
- /// Cached name for the 'property_DoubleArray' property.
+ /// Cached name for the 'PropertyDoubleArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_DoubleArray = "property_DoubleArray";
+ public new static readonly global::Godot.StringName PropertyDoubleArray = "PropertyDoubleArray";
/// <summary>
- /// Cached name for the 'property_StringArray' property.
+ /// Cached name for the 'PropertyStringArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_StringArray = "property_StringArray";
+ public new static readonly global::Godot.StringName PropertyStringArray = "PropertyStringArray";
/// <summary>
- /// Cached name for the 'property_StringArrayEnum' property.
+ /// Cached name for the 'PropertyStringArrayEnum' property.
/// </summary>
- public new static readonly global::Godot.StringName property_StringArrayEnum = "property_StringArrayEnum";
+ public new static readonly global::Godot.StringName PropertyStringArrayEnum = "PropertyStringArrayEnum";
/// <summary>
- /// Cached name for the 'property_Vector2Array' property.
+ /// Cached name for the 'PropertyVector2Array' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector2Array = "property_Vector2Array";
+ public new static readonly global::Godot.StringName PropertyVector2Array = "PropertyVector2Array";
/// <summary>
- /// Cached name for the 'property_Vector3Array' property.
+ /// Cached name for the 'PropertyVector3Array' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Vector3Array = "property_Vector3Array";
+ public new static readonly global::Godot.StringName PropertyVector3Array = "PropertyVector3Array";
/// <summary>
- /// Cached name for the 'property_ColorArray' property.
+ /// Cached name for the 'PropertyColorArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_ColorArray = "property_ColorArray";
+ public new static readonly global::Godot.StringName PropertyColorArray = "PropertyColorArray";
/// <summary>
- /// Cached name for the 'property_GodotObjectOrDerivedArray' property.
+ /// Cached name for the 'PropertyGodotObjectOrDerivedArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotObjectOrDerivedArray = "property_GodotObjectOrDerivedArray";
+ public new static readonly global::Godot.StringName PropertyGodotObjectOrDerivedArray = "PropertyGodotObjectOrDerivedArray";
/// <summary>
/// Cached name for the 'field_StringNameArray' property.
/// </summary>
@@ -225,272 +225,272 @@ partial class ExportedProperties
/// </summary>
public new static readonly global::Godot.StringName field_RidArray = "field_RidArray";
/// <summary>
- /// Cached name for the 'property_Variant' property.
+ /// Cached name for the 'PropertyVariant' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Variant = "property_Variant";
+ public new static readonly global::Godot.StringName PropertyVariant = "PropertyVariant";
/// <summary>
- /// Cached name for the 'property_GodotObjectOrDerived' property.
+ /// Cached name for the 'PropertyGodotObjectOrDerived' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotObjectOrDerived = "property_GodotObjectOrDerived";
+ public new static readonly global::Godot.StringName PropertyGodotObjectOrDerived = "PropertyGodotObjectOrDerived";
/// <summary>
- /// Cached name for the 'property_GodotResourceTexture' property.
+ /// Cached name for the 'PropertyGodotResourceTexture' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotResourceTexture = "property_GodotResourceTexture";
+ public new static readonly global::Godot.StringName PropertyGodotResourceTexture = "PropertyGodotResourceTexture";
/// <summary>
- /// Cached name for the 'property_StringName' property.
+ /// Cached name for the 'PropertyStringName' property.
/// </summary>
- public new static readonly global::Godot.StringName property_StringName = "property_StringName";
+ public new static readonly global::Godot.StringName PropertyStringName = "PropertyStringName";
/// <summary>
- /// Cached name for the 'property_NodePath' property.
+ /// Cached name for the 'PropertyNodePath' property.
/// </summary>
- public new static readonly global::Godot.StringName property_NodePath = "property_NodePath";
+ public new static readonly global::Godot.StringName PropertyNodePath = "PropertyNodePath";
/// <summary>
- /// Cached name for the 'property_Rid' property.
+ /// Cached name for the 'PropertyRid' property.
/// </summary>
- public new static readonly global::Godot.StringName property_Rid = "property_Rid";
+ public new static readonly global::Godot.StringName PropertyRid = "PropertyRid";
/// <summary>
- /// Cached name for the 'property_GodotDictionary' property.
+ /// Cached name for the 'PropertyGodotDictionary' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotDictionary = "property_GodotDictionary";
+ public new static readonly global::Godot.StringName PropertyGodotDictionary = "PropertyGodotDictionary";
/// <summary>
- /// Cached name for the 'property_GodotArray' property.
+ /// Cached name for the 'PropertyGodotArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotArray = "property_GodotArray";
+ public new static readonly global::Godot.StringName PropertyGodotArray = "PropertyGodotArray";
/// <summary>
- /// Cached name for the 'property_GodotGenericDictionary' property.
+ /// Cached name for the 'PropertyGodotGenericDictionary' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotGenericDictionary = "property_GodotGenericDictionary";
+ public new static readonly global::Godot.StringName PropertyGodotGenericDictionary = "PropertyGodotGenericDictionary";
/// <summary>
- /// Cached name for the 'property_GodotGenericArray' property.
+ /// Cached name for the 'PropertyGodotGenericArray' property.
/// </summary>
- public new static readonly global::Godot.StringName property_GodotGenericArray = "property_GodotGenericArray";
+ public new static readonly global::Godot.StringName PropertyGodotGenericArray = "PropertyGodotGenericArray";
/// <summary>
- /// Cached name for the '_notGenerate_Property_String' field.
+ /// Cached name for the '_notGeneratePropertyString' field.
/// </summary>
- public new static readonly global::Godot.StringName _notGenerate_Property_String = "_notGenerate_Property_String";
+ public new static readonly global::Godot.StringName _notGeneratePropertyString = "_notGeneratePropertyString";
/// <summary>
- /// Cached name for the '_notGenerate_Property_Int' field.
+ /// Cached name for the '_notGeneratePropertyInt' field.
/// </summary>
- public new static readonly global::Godot.StringName _notGenerate_Property_Int = "_notGenerate_Property_Int";
+ public new static readonly global::Godot.StringName _notGeneratePropertyInt = "_notGeneratePropertyInt";
/// <summary>
- /// Cached name for the '_fullProperty_String' field.
+ /// Cached name for the '_fullPropertyString' field.
/// </summary>
- public new static readonly global::Godot.StringName _fullProperty_String = "_fullProperty_String";
+ public new static readonly global::Godot.StringName _fullPropertyString = "_fullPropertyString";
/// <summary>
- /// Cached name for the '_fullProperty_String_Complex' field.
+ /// Cached name for the '_fullPropertyStringComplex' field.
/// </summary>
- public new static readonly global::Godot.StringName _fullProperty_String_Complex = "_fullProperty_String_Complex";
+ public new static readonly global::Godot.StringName _fullPropertyStringComplex = "_fullPropertyStringComplex";
/// <summary>
- /// Cached name for the '_lamdaProperty_String' field.
+ /// Cached name for the '_lamdaPropertyString' field.
/// </summary>
- public new static readonly global::Godot.StringName _lamdaProperty_String = "_lamdaProperty_String";
+ public new static readonly global::Godot.StringName _lamdaPropertyString = "_lamdaPropertyString";
}
/// <inheritdoc/>
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
{
- if (name == PropertyName.NotGenerate_Complex_Lamda_Property) {
- this.NotGenerate_Complex_Lamda_Property = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ if (name == PropertyName.NotGenerateComplexLamdaProperty) {
+ this.NotGenerateComplexLamdaProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.NotGenerate_Lamda_NoField_Property) {
- this.NotGenerate_Lamda_NoField_Property = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.NotGenerateLamdaNoFieldProperty) {
+ this.NotGenerateLamdaNoFieldProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.NotGenerate_Complex_Return_Property) {
- this.NotGenerate_Complex_Return_Property = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.NotGenerateComplexReturnProperty) {
+ this.NotGenerateComplexReturnProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.NotGenerate_Returns_Property) {
- this.NotGenerate_Returns_Property = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.NotGenerateReturnsProperty) {
+ this.NotGenerateReturnsProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.FullProperty_String) {
- this.FullProperty_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.FullPropertyString) {
+ this.FullPropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.FullProperty_String_Complex) {
- this.FullProperty_String_Complex = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.FullPropertyString_Complex) {
+ this.FullPropertyString_Complex = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.LamdaProperty_String) {
- this.LamdaProperty_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.LamdaPropertyString) {
+ this.LamdaPropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.property_Boolean) {
- this.property_Boolean = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ else if (name == PropertyName.PropertyBoolean) {
+ this.PropertyBoolean = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
- else if (name == PropertyName.property_Char) {
- this.property_Char = global::Godot.NativeInterop.VariantUtils.ConvertTo<char>(value);
+ else if (name == PropertyName.PropertyChar) {
+ this.PropertyChar = global::Godot.NativeInterop.VariantUtils.ConvertTo<char>(value);
return true;
}
- else if (name == PropertyName.property_SByte) {
- this.property_SByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<sbyte>(value);
+ else if (name == PropertyName.PropertySByte) {
+ this.PropertySByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<sbyte>(value);
return true;
}
- else if (name == PropertyName.property_Int16) {
- this.property_Int16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<short>(value);
+ else if (name == PropertyName.PropertyInt16) {
+ this.PropertyInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<short>(value);
return true;
}
- else if (name == PropertyName.property_Int32) {
- this.property_Int32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
+ else if (name == PropertyName.PropertyInt32) {
+ this.PropertyInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
return true;
}
- else if (name == PropertyName.property_Int64) {
- this.property_Int64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<long>(value);
+ else if (name == PropertyName.PropertyInt64) {
+ this.PropertyInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<long>(value);
return true;
}
- else if (name == PropertyName.property_Byte) {
- this.property_Byte = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte>(value);
+ else if (name == PropertyName.PropertyByte) {
+ this.PropertyByte = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte>(value);
return true;
}
- else if (name == PropertyName.property_UInt16) {
- this.property_UInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ushort>(value);
+ else if (name == PropertyName.PropertyUInt16) {
+ this.PropertyUInt16 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ushort>(value);
return true;
}
- else if (name == PropertyName.property_UInt32) {
- this.property_UInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<uint>(value);
+ else if (name == PropertyName.PropertyUInt32) {
+ this.PropertyUInt32 = global::Godot.NativeInterop.VariantUtils.ConvertTo<uint>(value);
return true;
}
- else if (name == PropertyName.property_UInt64) {
- this.property_UInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ulong>(value);
+ else if (name == PropertyName.PropertyUInt64) {
+ this.PropertyUInt64 = global::Godot.NativeInterop.VariantUtils.ConvertTo<ulong>(value);
return true;
}
- else if (name == PropertyName.property_Single) {
- this.property_Single = global::Godot.NativeInterop.VariantUtils.ConvertTo<float>(value);
+ else if (name == PropertyName.PropertySingle) {
+ this.PropertySingle = global::Godot.NativeInterop.VariantUtils.ConvertTo<float>(value);
return true;
}
- else if (name == PropertyName.property_Double) {
- this.property_Double = global::Godot.NativeInterop.VariantUtils.ConvertTo<double>(value);
+ else if (name == PropertyName.PropertyDouble) {
+ this.PropertyDouble = global::Godot.NativeInterop.VariantUtils.ConvertTo<double>(value);
return true;
}
- else if (name == PropertyName.property_String) {
- this.property_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName.PropertyString) {
+ this.PropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName.property_Vector2) {
- this.property_Vector2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2>(value);
+ else if (name == PropertyName.PropertyVector2) {
+ this.PropertyVector2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2>(value);
return true;
}
- else if (name == PropertyName.property_Vector2I) {
- this.property_Vector2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2I>(value);
+ else if (name == PropertyName.PropertyVector2I) {
+ this.PropertyVector2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2I>(value);
return true;
}
- else if (name == PropertyName.property_Rect2) {
- this.property_Rect2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2>(value);
+ else if (name == PropertyName.PropertyRect2) {
+ this.PropertyRect2 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2>(value);
return true;
}
- else if (name == PropertyName.property_Rect2I) {
- this.property_Rect2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2I>(value);
+ else if (name == PropertyName.PropertyRect2I) {
+ this.PropertyRect2I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rect2I>(value);
return true;
}
- else if (name == PropertyName.property_Transform2D) {
- this.property_Transform2D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform2D>(value);
+ else if (name == PropertyName.PropertyTransform2D) {
+ this.PropertyTransform2D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform2D>(value);
return true;
}
- else if (name == PropertyName.property_Vector3) {
- this.property_Vector3 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3>(value);
+ else if (name == PropertyName.PropertyVector3) {
+ this.PropertyVector3 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3>(value);
return true;
}
- else if (name == PropertyName.property_Vector3I) {
- this.property_Vector3I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3I>(value);
+ else if (name == PropertyName.PropertyVector3I) {
+ this.PropertyVector3I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3I>(value);
return true;
}
- else if (name == PropertyName.property_Basis) {
- this.property_Basis = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Basis>(value);
+ else if (name == PropertyName.PropertyBasis) {
+ this.PropertyBasis = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Basis>(value);
return true;
}
- else if (name == PropertyName.property_Quaternion) {
- this.property_Quaternion = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Quaternion>(value);
+ else if (name == PropertyName.PropertyQuaternion) {
+ this.PropertyQuaternion = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Quaternion>(value);
return true;
}
- else if (name == PropertyName.property_Transform3D) {
- this.property_Transform3D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform3D>(value);
+ else if (name == PropertyName.PropertyTransform3D) {
+ this.PropertyTransform3D = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Transform3D>(value);
return true;
}
- else if (name == PropertyName.property_Vector4) {
- this.property_Vector4 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4>(value);
+ else if (name == PropertyName.PropertyVector4) {
+ this.PropertyVector4 = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4>(value);
return true;
}
- else if (name == PropertyName.property_Vector4I) {
- this.property_Vector4I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4I>(value);
+ else if (name == PropertyName.PropertyVector4I) {
+ this.PropertyVector4I = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector4I>(value);
return true;
}
- else if (name == PropertyName.property_Projection) {
- this.property_Projection = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Projection>(value);
+ else if (name == PropertyName.PropertyProjection) {
+ this.PropertyProjection = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Projection>(value);
return true;
}
- else if (name == PropertyName.property_Aabb) {
- this.property_Aabb = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Aabb>(value);
+ else if (name == PropertyName.PropertyAabb) {
+ this.PropertyAabb = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Aabb>(value);
return true;
}
- else if (name == PropertyName.property_Color) {
- this.property_Color = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color>(value);
+ else if (name == PropertyName.PropertyColor) {
+ this.PropertyColor = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color>(value);
return true;
}
- else if (name == PropertyName.property_Plane) {
- this.property_Plane = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Plane>(value);
+ else if (name == PropertyName.PropertyPlane) {
+ this.PropertyPlane = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Plane>(value);
return true;
}
- else if (name == PropertyName.property_Callable) {
- this.property_Callable = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
+ else if (name == PropertyName.PropertyCallable) {
+ this.PropertyCallable = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
return true;
}
- else if (name == PropertyName.property_Signal) {
- this.property_Signal = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Signal>(value);
+ else if (name == PropertyName.PropertySignal) {
+ this.PropertySignal = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Signal>(value);
return true;
}
- else if (name == PropertyName.property_Enum) {
- this.property_Enum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedProperties.MyEnum>(value);
+ else if (name == PropertyName.PropertyEnum) {
+ this.PropertyEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedProperties.MyEnum>(value);
return true;
}
- else if (name == PropertyName.property_FlagsEnum) {
- this.property_FlagsEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedProperties.MyFlagsEnum>(value);
+ else if (name == PropertyName.PropertyFlagsEnum) {
+ this.PropertyFlagsEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::ExportedProperties.MyFlagsEnum>(value);
return true;
}
- else if (name == PropertyName.property_ByteArray) {
- this.property_ByteArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte[]>(value);
+ else if (name == PropertyName.PropertyByteArray) {
+ this.PropertyByteArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<byte[]>(value);
return true;
}
- else if (name == PropertyName.property_Int32Array) {
- this.property_Int32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
+ else if (name == PropertyName.PropertyInt32Array) {
+ this.PropertyInt32Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<int[]>(value);
return true;
}
- else if (name == PropertyName.property_Int64Array) {
- this.property_Int64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
+ else if (name == PropertyName.PropertyInt64Array) {
+ this.PropertyInt64Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<long[]>(value);
return true;
}
- else if (name == PropertyName.property_SingleArray) {
- this.property_SingleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<float[]>(value);
+ else if (name == PropertyName.PropertySingleArray) {
+ this.PropertySingleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<float[]>(value);
return true;
}
- else if (name == PropertyName.property_DoubleArray) {
- this.property_DoubleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<double[]>(value);
+ else if (name == PropertyName.PropertyDoubleArray) {
+ this.PropertyDoubleArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<double[]>(value);
return true;
}
- else if (name == PropertyName.property_StringArray) {
- this.property_StringArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
+ else if (name == PropertyName.PropertyStringArray) {
+ this.PropertyStringArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
return true;
}
- else if (name == PropertyName.property_StringArrayEnum) {
- this.property_StringArrayEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
+ else if (name == PropertyName.PropertyStringArrayEnum) {
+ this.PropertyStringArrayEnum = global::Godot.NativeInterop.VariantUtils.ConvertTo<string[]>(value);
return true;
}
- else if (name == PropertyName.property_Vector2Array) {
- this.property_Vector2Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2[]>(value);
+ else if (name == PropertyName.PropertyVector2Array) {
+ this.PropertyVector2Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector2[]>(value);
return true;
}
- else if (name == PropertyName.property_Vector3Array) {
- this.property_Vector3Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3[]>(value);
+ else if (name == PropertyName.PropertyVector3Array) {
+ this.PropertyVector3Array = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Vector3[]>(value);
return true;
}
- else if (name == PropertyName.property_ColorArray) {
- this.property_ColorArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color[]>(value);
+ else if (name == PropertyName.PropertyColorArray) {
+ this.PropertyColorArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Color[]>(value);
return true;
}
- else if (name == PropertyName.property_GodotObjectOrDerivedArray) {
- this.property_GodotObjectOrDerivedArray = global::Godot.NativeInterop.VariantUtils.ConvertToSystemArrayOfGodotObject<global::Godot.GodotObject>(value);
+ else if (name == PropertyName.PropertyGodotObjectOrDerivedArray) {
+ this.PropertyGodotObjectOrDerivedArray = global::Godot.NativeInterop.VariantUtils.ConvertToSystemArrayOfGodotObject<global::Godot.GodotObject>(value);
return true;
}
else if (name == PropertyName.field_StringNameArray) {
@@ -505,64 +505,64 @@ partial class ExportedProperties
this.field_RidArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid[]>(value);
return true;
}
- else if (name == PropertyName.property_Variant) {
- this.property_Variant = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Variant>(value);
+ else if (name == PropertyName.PropertyVariant) {
+ this.PropertyVariant = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Variant>(value);
return true;
}
- else if (name == PropertyName.property_GodotObjectOrDerived) {
- this.property_GodotObjectOrDerived = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.GodotObject>(value);
+ else if (name == PropertyName.PropertyGodotObjectOrDerived) {
+ this.PropertyGodotObjectOrDerived = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.GodotObject>(value);
return true;
}
- else if (name == PropertyName.property_GodotResourceTexture) {
- this.property_GodotResourceTexture = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Texture>(value);
+ else if (name == PropertyName.PropertyGodotResourceTexture) {
+ this.PropertyGodotResourceTexture = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Texture>(value);
return true;
}
- else if (name == PropertyName.property_StringName) {
- this.property_StringName = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName>(value);
+ else if (name == PropertyName.PropertyStringName) {
+ this.PropertyStringName = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.StringName>(value);
return true;
}
- else if (name == PropertyName.property_NodePath) {
- this.property_NodePath = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath>(value);
+ else if (name == PropertyName.PropertyNodePath) {
+ this.PropertyNodePath = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.NodePath>(value);
return true;
}
- else if (name == PropertyName.property_Rid) {
- this.property_Rid = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid>(value);
+ else if (name == PropertyName.PropertyRid) {
+ this.PropertyRid = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Rid>(value);
return true;
}
- else if (name == PropertyName.property_GodotDictionary) {
- this.property_GodotDictionary = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Dictionary>(value);
+ else if (name == PropertyName.PropertyGodotDictionary) {
+ this.PropertyGodotDictionary = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Dictionary>(value);
return true;
}
- else if (name == PropertyName.property_GodotArray) {
- this.property_GodotArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Array>(value);
+ else if (name == PropertyName.PropertyGodotArray) {
+ this.PropertyGodotArray = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Collections.Array>(value);
return true;
}
- else if (name == PropertyName.property_GodotGenericDictionary) {
- this.property_GodotGenericDictionary = global::Godot.NativeInterop.VariantUtils.ConvertToDictionary<string, bool>(value);
+ else if (name == PropertyName.PropertyGodotGenericDictionary) {
+ this.PropertyGodotGenericDictionary = global::Godot.NativeInterop.VariantUtils.ConvertToDictionary<string, bool>(value);
return true;
}
- else if (name == PropertyName.property_GodotGenericArray) {
- this.property_GodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
+ else if (name == PropertyName.PropertyGodotGenericArray) {
+ this.PropertyGodotGenericArray = global::Godot.NativeInterop.VariantUtils.ConvertToArray<int>(value);
return true;
}
- else if (name == PropertyName._notGenerate_Property_String) {
- this._notGenerate_Property_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName._notGeneratePropertyString) {
+ this._notGeneratePropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName._notGenerate_Property_Int) {
- this._notGenerate_Property_Int = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
+ else if (name == PropertyName._notGeneratePropertyInt) {
+ this._notGeneratePropertyInt = global::Godot.NativeInterop.VariantUtils.ConvertTo<int>(value);
return true;
}
- else if (name == PropertyName._fullProperty_String) {
- this._fullProperty_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName._fullPropertyString) {
+ this._fullPropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName._fullProperty_String_Complex) {
- this._fullProperty_String_Complex = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName._fullPropertyStringComplex) {
+ this._fullPropertyStringComplex = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
- else if (name == PropertyName._lamdaProperty_String) {
- this._lamdaProperty_String = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
+ else if (name == PropertyName._lamdaPropertyString) {
+ this._lamdaPropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
return true;
}
return base.SetGodotClassPropertyValue(name, value);
@@ -571,208 +571,208 @@ partial class ExportedProperties
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
- if (name == PropertyName.NotGenerate_Complex_Lamda_Property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerate_Complex_Lamda_Property);
+ if (name == PropertyName.NotGenerateComplexLamdaProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerateComplexLamdaProperty);
return true;
}
- else if (name == PropertyName.NotGenerate_Lamda_NoField_Property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerate_Lamda_NoField_Property);
+ else if (name == PropertyName.NotGenerateLamdaNoFieldProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerateLamdaNoFieldProperty);
return true;
}
- else if (name == PropertyName.NotGenerate_Complex_Return_Property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerate_Complex_Return_Property);
+ else if (name == PropertyName.NotGenerateComplexReturnProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerateComplexReturnProperty);
return true;
}
- else if (name == PropertyName.NotGenerate_Returns_Property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerate_Returns_Property);
+ else if (name == PropertyName.NotGenerateReturnsProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.NotGenerateReturnsProperty);
return true;
}
- else if (name == PropertyName.FullProperty_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.FullProperty_String);
+ else if (name == PropertyName.FullPropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.FullPropertyString);
return true;
}
- else if (name == PropertyName.FullProperty_String_Complex) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.FullProperty_String_Complex);
+ else if (name == PropertyName.FullPropertyString_Complex) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.FullPropertyString_Complex);
return true;
}
- else if (name == PropertyName.LamdaProperty_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.LamdaProperty_String);
+ else if (name == PropertyName.LamdaPropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.LamdaPropertyString);
return true;
}
- else if (name == PropertyName.property_Boolean) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this.property_Boolean);
+ else if (name == PropertyName.PropertyBoolean) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this.PropertyBoolean);
return true;
}
- else if (name == PropertyName.property_Char) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<char>(this.property_Char);
+ else if (name == PropertyName.PropertyChar) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<char>(this.PropertyChar);
return true;
}
- else if (name == PropertyName.property_SByte) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<sbyte>(this.property_SByte);
+ else if (name == PropertyName.PropertySByte) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<sbyte>(this.PropertySByte);
return true;
}
- else if (name == PropertyName.property_Int16) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<short>(this.property_Int16);
+ else if (name == PropertyName.PropertyInt16) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<short>(this.PropertyInt16);
return true;
}
- else if (name == PropertyName.property_Int32) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.property_Int32);
+ else if (name == PropertyName.PropertyInt32) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.PropertyInt32);
return true;
}
- else if (name == PropertyName.property_Int64) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long>(this.property_Int64);
+ else if (name == PropertyName.PropertyInt64) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long>(this.PropertyInt64);
return true;
}
- else if (name == PropertyName.property_Byte) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte>(this.property_Byte);
+ else if (name == PropertyName.PropertyByte) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte>(this.PropertyByte);
return true;
}
- else if (name == PropertyName.property_UInt16) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ushort>(this.property_UInt16);
+ else if (name == PropertyName.PropertyUInt16) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ushort>(this.PropertyUInt16);
return true;
}
- else if (name == PropertyName.property_UInt32) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<uint>(this.property_UInt32);
+ else if (name == PropertyName.PropertyUInt32) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<uint>(this.PropertyUInt32);
return true;
}
- else if (name == PropertyName.property_UInt64) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ulong>(this.property_UInt64);
+ else if (name == PropertyName.PropertyUInt64) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<ulong>(this.PropertyUInt64);
return true;
}
- else if (name == PropertyName.property_Single) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float>(this.property_Single);
+ else if (name == PropertyName.PropertySingle) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float>(this.PropertySingle);
return true;
}
- else if (name == PropertyName.property_Double) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double>(this.property_Double);
+ else if (name == PropertyName.PropertyDouble) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double>(this.PropertyDouble);
return true;
}
- else if (name == PropertyName.property_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.property_String);
+ else if (name == PropertyName.PropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.PropertyString);
return true;
}
- else if (name == PropertyName.property_Vector2) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2>(this.property_Vector2);
+ else if (name == PropertyName.PropertyVector2) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2>(this.PropertyVector2);
return true;
}
- else if (name == PropertyName.property_Vector2I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2I>(this.property_Vector2I);
+ else if (name == PropertyName.PropertyVector2I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2I>(this.PropertyVector2I);
return true;
}
- else if (name == PropertyName.property_Rect2) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2>(this.property_Rect2);
+ else if (name == PropertyName.PropertyRect2) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2>(this.PropertyRect2);
return true;
}
- else if (name == PropertyName.property_Rect2I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2I>(this.property_Rect2I);
+ else if (name == PropertyName.PropertyRect2I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rect2I>(this.PropertyRect2I);
return true;
}
- else if (name == PropertyName.property_Transform2D) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform2D>(this.property_Transform2D);
+ else if (name == PropertyName.PropertyTransform2D) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform2D>(this.PropertyTransform2D);
return true;
}
- else if (name == PropertyName.property_Vector3) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3>(this.property_Vector3);
+ else if (name == PropertyName.PropertyVector3) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3>(this.PropertyVector3);
return true;
}
- else if (name == PropertyName.property_Vector3I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3I>(this.property_Vector3I);
+ else if (name == PropertyName.PropertyVector3I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3I>(this.PropertyVector3I);
return true;
}
- else if (name == PropertyName.property_Basis) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Basis>(this.property_Basis);
+ else if (name == PropertyName.PropertyBasis) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Basis>(this.PropertyBasis);
return true;
}
- else if (name == PropertyName.property_Quaternion) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Quaternion>(this.property_Quaternion);
+ else if (name == PropertyName.PropertyQuaternion) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Quaternion>(this.PropertyQuaternion);
return true;
}
- else if (name == PropertyName.property_Transform3D) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform3D>(this.property_Transform3D);
+ else if (name == PropertyName.PropertyTransform3D) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Transform3D>(this.PropertyTransform3D);
return true;
}
- else if (name == PropertyName.property_Vector4) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4>(this.property_Vector4);
+ else if (name == PropertyName.PropertyVector4) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4>(this.PropertyVector4);
return true;
}
- else if (name == PropertyName.property_Vector4I) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4I>(this.property_Vector4I);
+ else if (name == PropertyName.PropertyVector4I) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector4I>(this.PropertyVector4I);
return true;
}
- else if (name == PropertyName.property_Projection) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Projection>(this.property_Projection);
+ else if (name == PropertyName.PropertyProjection) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Projection>(this.PropertyProjection);
return true;
}
- else if (name == PropertyName.property_Aabb) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Aabb>(this.property_Aabb);
+ else if (name == PropertyName.PropertyAabb) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Aabb>(this.PropertyAabb);
return true;
}
- else if (name == PropertyName.property_Color) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color>(this.property_Color);
+ else if (name == PropertyName.PropertyColor) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color>(this.PropertyColor);
return true;
}
- else if (name == PropertyName.property_Plane) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Plane>(this.property_Plane);
+ else if (name == PropertyName.PropertyPlane) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Plane>(this.PropertyPlane);
return true;
}
- else if (name == PropertyName.property_Callable) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.property_Callable);
+ else if (name == PropertyName.PropertyCallable) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.PropertyCallable);
return true;
}
- else if (name == PropertyName.property_Signal) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Signal>(this.property_Signal);
+ else if (name == PropertyName.PropertySignal) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Signal>(this.PropertySignal);
return true;
}
- else if (name == PropertyName.property_Enum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedProperties.MyEnum>(this.property_Enum);
+ else if (name == PropertyName.PropertyEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedProperties.MyEnum>(this.PropertyEnum);
return true;
}
- else if (name == PropertyName.property_FlagsEnum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedProperties.MyFlagsEnum>(this.property_FlagsEnum);
+ else if (name == PropertyName.PropertyFlagsEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::ExportedProperties.MyFlagsEnum>(this.PropertyFlagsEnum);
return true;
}
- else if (name == PropertyName.property_ByteArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte[]>(this.property_ByteArray);
+ else if (name == PropertyName.PropertyByteArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<byte[]>(this.PropertyByteArray);
return true;
}
- else if (name == PropertyName.property_Int32Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this.property_Int32Array);
+ else if (name == PropertyName.PropertyInt32Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int[]>(this.PropertyInt32Array);
return true;
}
- else if (name == PropertyName.property_Int64Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this.property_Int64Array);
+ else if (name == PropertyName.PropertyInt64Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<long[]>(this.PropertyInt64Array);
return true;
}
- else if (name == PropertyName.property_SingleArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float[]>(this.property_SingleArray);
+ else if (name == PropertyName.PropertySingleArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<float[]>(this.PropertySingleArray);
return true;
}
- else if (name == PropertyName.property_DoubleArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double[]>(this.property_DoubleArray);
+ else if (name == PropertyName.PropertyDoubleArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<double[]>(this.PropertyDoubleArray);
return true;
}
- else if (name == PropertyName.property_StringArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.property_StringArray);
+ else if (name == PropertyName.PropertyStringArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.PropertyStringArray);
return true;
}
- else if (name == PropertyName.property_StringArrayEnum) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.property_StringArrayEnum);
+ else if (name == PropertyName.PropertyStringArrayEnum) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string[]>(this.PropertyStringArrayEnum);
return true;
}
- else if (name == PropertyName.property_Vector2Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2[]>(this.property_Vector2Array);
+ else if (name == PropertyName.PropertyVector2Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector2[]>(this.PropertyVector2Array);
return true;
}
- else if (name == PropertyName.property_Vector3Array) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3[]>(this.property_Vector3Array);
+ else if (name == PropertyName.PropertyVector3Array) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Vector3[]>(this.PropertyVector3Array);
return true;
}
- else if (name == PropertyName.property_ColorArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color[]>(this.property_ColorArray);
+ else if (name == PropertyName.PropertyColorArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Color[]>(this.PropertyColorArray);
return true;
}
- else if (name == PropertyName.property_GodotObjectOrDerivedArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromSystemArrayOfGodotObject(this.property_GodotObjectOrDerivedArray);
+ else if (name == PropertyName.PropertyGodotObjectOrDerivedArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromSystemArrayOfGodotObject(this.PropertyGodotObjectOrDerivedArray);
return true;
}
else if (name == PropertyName.field_StringNameArray) {
@@ -787,64 +787,64 @@ partial class ExportedProperties
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid[]>(this.field_RidArray);
return true;
}
- else if (name == PropertyName.property_Variant) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Variant>(this.property_Variant);
+ else if (name == PropertyName.PropertyVariant) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Variant>(this.PropertyVariant);
return true;
}
- else if (name == PropertyName.property_GodotObjectOrDerived) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.GodotObject>(this.property_GodotObjectOrDerived);
+ else if (name == PropertyName.PropertyGodotObjectOrDerived) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.GodotObject>(this.PropertyGodotObjectOrDerived);
return true;
}
- else if (name == PropertyName.property_GodotResourceTexture) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Texture>(this.property_GodotResourceTexture);
+ else if (name == PropertyName.PropertyGodotResourceTexture) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Texture>(this.PropertyGodotResourceTexture);
return true;
}
- else if (name == PropertyName.property_StringName) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName>(this.property_StringName);
+ else if (name == PropertyName.PropertyStringName) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.StringName>(this.PropertyStringName);
return true;
}
- else if (name == PropertyName.property_NodePath) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath>(this.property_NodePath);
+ else if (name == PropertyName.PropertyNodePath) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.NodePath>(this.PropertyNodePath);
return true;
}
- else if (name == PropertyName.property_Rid) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid>(this.property_Rid);
+ else if (name == PropertyName.PropertyRid) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Rid>(this.PropertyRid);
return true;
}
- else if (name == PropertyName.property_GodotDictionary) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Dictionary>(this.property_GodotDictionary);
+ else if (name == PropertyName.PropertyGodotDictionary) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Dictionary>(this.PropertyGodotDictionary);
return true;
}
- else if (name == PropertyName.property_GodotArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Array>(this.property_GodotArray);
+ else if (name == PropertyName.PropertyGodotArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Collections.Array>(this.PropertyGodotArray);
return true;
}
- else if (name == PropertyName.property_GodotGenericDictionary) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromDictionary(this.property_GodotGenericDictionary);
+ else if (name == PropertyName.PropertyGodotGenericDictionary) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromDictionary(this.PropertyGodotGenericDictionary);
return true;
}
- else if (name == PropertyName.property_GodotGenericArray) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.property_GodotGenericArray);
+ else if (name == PropertyName.PropertyGodotGenericArray) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFromArray(this.PropertyGodotGenericArray);
return true;
}
- else if (name == PropertyName._notGenerate_Property_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._notGenerate_Property_String);
+ else if (name == PropertyName._notGeneratePropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._notGeneratePropertyString);
return true;
}
- else if (name == PropertyName._notGenerate_Property_Int) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this._notGenerate_Property_Int);
+ else if (name == PropertyName._notGeneratePropertyInt) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this._notGeneratePropertyInt);
return true;
}
- else if (name == PropertyName._fullProperty_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._fullProperty_String);
+ else if (name == PropertyName._fullPropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._fullPropertyString);
return true;
}
- else if (name == PropertyName._fullProperty_String_Complex) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._fullProperty_String_Complex);
+ else if (name == PropertyName._fullPropertyStringComplex) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._fullPropertyStringComplex);
return true;
}
- else if (name == PropertyName._lamdaProperty_String) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._lamdaProperty_String);
+ else if (name == PropertyName._lamdaPropertyString) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this._lamdaPropertyString);
return true;
}
return base.GetGodotClassPropertyValue(name, out value);
@@ -858,75 +858,75 @@ partial class ExportedProperties
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
{
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._notGenerate_Property_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerate_Complex_Lamda_Property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerate_Lamda_NoField_Property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerate_Complex_Return_Property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._notGenerate_Property_Int, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerate_Returns_Property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._fullProperty_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.FullProperty_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._fullProperty_String_Complex, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.FullProperty_String_Complex, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._lamdaProperty_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.LamdaProperty_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.property_Boolean, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Char, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_SByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Int16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Int32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Int64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Byte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_UInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_UInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_UInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.property_Single, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.property_Double, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.property_String, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)5, name: PropertyName.property_Vector2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)6, name: PropertyName.property_Vector2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)7, name: PropertyName.property_Rect2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)8, name: PropertyName.property_Rect2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)11, name: PropertyName.property_Transform2D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)9, name: PropertyName.property_Vector3, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)10, name: PropertyName.property_Vector3I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)17, name: PropertyName.property_Basis, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)15, name: PropertyName.property_Quaternion, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)18, name: PropertyName.property_Transform3D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)12, name: PropertyName.property_Vector4, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)13, name: PropertyName.property_Vector4I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)19, name: PropertyName.property_Projection, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)16, name: PropertyName.property_Aabb, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)20, name: PropertyName.property_Color, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)14, name: PropertyName.property_Plane, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.property_Callable, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)26, name: PropertyName.property_Signal, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_Enum, hint: (global::Godot.PropertyHint)2, hintString: "A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.property_FlagsEnum, hint: (global::Godot.PropertyHint)6, hintString: "A:0,B:1,C:2", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)29, name: PropertyName.property_ByteArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName.property_Int32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.property_Int64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)32, name: PropertyName.property_SingleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)33, name: PropertyName.property_DoubleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.property_StringArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.property_StringArrayEnum, hint: (global::Godot.PropertyHint)23, hintString: "4/2:A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)35, name: PropertyName.property_Vector2Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)36, name: PropertyName.property_Vector3Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)37, name: PropertyName.property_ColorArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.property_GodotObjectOrDerivedArray, hint: (global::Godot.PropertyHint)23, hintString: "24/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._notGeneratePropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerateComplexLamdaProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerateLamdaNoFieldProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerateComplexReturnProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName._notGeneratePropertyInt, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.NotGenerateReturnsProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._fullPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.FullPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._fullPropertyStringComplex, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.FullPropertyString_Complex, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName._lamdaPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.LamdaPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.PropertyBoolean, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyChar, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertySByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyUInt16, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyUInt32, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyUInt64, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.PropertySingle, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.PropertyDouble, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.PropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)5, name: PropertyName.PropertyVector2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)6, name: PropertyName.PropertyVector2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)7, name: PropertyName.PropertyRect2, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)8, name: PropertyName.PropertyRect2I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)11, name: PropertyName.PropertyTransform2D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)9, name: PropertyName.PropertyVector3, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)10, name: PropertyName.PropertyVector3I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)17, name: PropertyName.PropertyBasis, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)15, name: PropertyName.PropertyQuaternion, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)18, name: PropertyName.PropertyTransform3D, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)12, name: PropertyName.PropertyVector4, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)13, name: PropertyName.PropertyVector4I, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)19, name: PropertyName.PropertyProjection, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)16, name: PropertyName.PropertyAabb, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)20, name: PropertyName.PropertyColor, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)14, name: PropertyName.PropertyPlane, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.PropertyCallable, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)26, name: PropertyName.PropertySignal, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyEnum, hint: (global::Godot.PropertyHint)2, hintString: "A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.PropertyFlagsEnum, hint: (global::Godot.PropertyHint)6, hintString: "A:0,B:1,C:2", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)29, name: PropertyName.PropertyByteArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)30, name: PropertyName.PropertyInt32Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.PropertyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)32, name: PropertyName.PropertySingleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)33, name: PropertyName.PropertyDoubleArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.PropertyStringArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)34, name: PropertyName.PropertyStringArrayEnum, hint: (global::Godot.PropertyHint)23, hintString: "4/2:A,B,C", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)35, name: PropertyName.PropertyVector2Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)36, name: PropertyName.PropertyVector3Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)37, name: PropertyName.PropertyColorArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.PropertyGodotObjectOrDerivedArray, hint: (global::Godot.PropertyHint)23, hintString: "24/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_StringNameArray, hint: (global::Godot.PropertyHint)23, hintString: "21/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_NodePathArray, hint: (global::Godot.PropertyHint)23, hintString: "22/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.field_RidArray, hint: (global::Godot.PropertyHint)23, hintString: "23/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)0, name: PropertyName.property_Variant, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)135174, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.property_GodotObjectOrDerived, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.property_GodotResourceTexture, hint: (global::Godot.PropertyHint)17, hintString: "Texture", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)21, name: PropertyName.property_StringName, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)22, name: PropertyName.property_NodePath, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.property_Rid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.property_GodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.property_GodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.property_GodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.property_GodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)0, name: PropertyName.PropertyVariant, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)135174, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.PropertyGodotObjectOrDerived, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)24, name: PropertyName.PropertyGodotResourceTexture, hint: (global::Godot.PropertyHint)17, hintString: "Texture", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)21, name: PropertyName.PropertyStringName, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)22, name: PropertyName.PropertyNodePath, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.PropertyRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.PropertyGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
return properties;
}
#pragma warning restore CS0109
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs
index a4cd10d080..a1b01aed4f 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs
@@ -12,134 +12,134 @@ partial class ExportedProperties
internal new static global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant> GetGodotPropertyDefaultValues()
{
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(64);
- string __NotGenerate_Complex_Lamda_Property_default_value = default;
- values.Add(PropertyName.NotGenerate_Complex_Lamda_Property, global::Godot.Variant.From<string>(__NotGenerate_Complex_Lamda_Property_default_value));
- string __NotGenerate_Lamda_NoField_Property_default_value = default;
- values.Add(PropertyName.NotGenerate_Lamda_NoField_Property, global::Godot.Variant.From<string>(__NotGenerate_Lamda_NoField_Property_default_value));
- string __NotGenerate_Complex_Return_Property_default_value = default;
- values.Add(PropertyName.NotGenerate_Complex_Return_Property, global::Godot.Variant.From<string>(__NotGenerate_Complex_Return_Property_default_value));
- string __NotGenerate_Returns_Property_default_value = default;
- values.Add(PropertyName.NotGenerate_Returns_Property, global::Godot.Variant.From<string>(__NotGenerate_Returns_Property_default_value));
- string __FullProperty_String_default_value = "FullProperty_String";
- values.Add(PropertyName.FullProperty_String, global::Godot.Variant.From<string>(__FullProperty_String_default_value));
- string __FullProperty_String_Complex_default_value = new string("FullProperty_String_Complex") + global::System.Convert.ToInt32("1");
- values.Add(PropertyName.FullProperty_String_Complex, global::Godot.Variant.From<string>(__FullProperty_String_Complex_default_value));
- string __LamdaProperty_String_default_value = "LamdaProperty_String";
- values.Add(PropertyName.LamdaProperty_String, global::Godot.Variant.From<string>(__LamdaProperty_String_default_value));
- bool __property_Boolean_default_value = true;
- values.Add(PropertyName.property_Boolean, global::Godot.Variant.From<bool>(__property_Boolean_default_value));
- char __property_Char_default_value = 'f';
- values.Add(PropertyName.property_Char, global::Godot.Variant.From<char>(__property_Char_default_value));
- sbyte __property_SByte_default_value = 10;
- values.Add(PropertyName.property_SByte, global::Godot.Variant.From<sbyte>(__property_SByte_default_value));
- short __property_Int16_default_value = 10;
- values.Add(PropertyName.property_Int16, global::Godot.Variant.From<short>(__property_Int16_default_value));
- int __property_Int32_default_value = 10;
- values.Add(PropertyName.property_Int32, global::Godot.Variant.From<int>(__property_Int32_default_value));
- long __property_Int64_default_value = 10;
- values.Add(PropertyName.property_Int64, global::Godot.Variant.From<long>(__property_Int64_default_value));
- byte __property_Byte_default_value = 10;
- values.Add(PropertyName.property_Byte, global::Godot.Variant.From<byte>(__property_Byte_default_value));
- ushort __property_UInt16_default_value = 10;
- values.Add(PropertyName.property_UInt16, global::Godot.Variant.From<ushort>(__property_UInt16_default_value));
- uint __property_UInt32_default_value = 10;
- values.Add(PropertyName.property_UInt32, global::Godot.Variant.From<uint>(__property_UInt32_default_value));
- ulong __property_UInt64_default_value = 10;
- values.Add(PropertyName.property_UInt64, global::Godot.Variant.From<ulong>(__property_UInt64_default_value));
- float __property_Single_default_value = 10;
- values.Add(PropertyName.property_Single, global::Godot.Variant.From<float>(__property_Single_default_value));
- double __property_Double_default_value = 10;
- values.Add(PropertyName.property_Double, global::Godot.Variant.From<double>(__property_Double_default_value));
- string __property_String_default_value = "foo";
- values.Add(PropertyName.property_String, global::Godot.Variant.From<string>(__property_String_default_value));
- global::Godot.Vector2 __property_Vector2_default_value = new(10f, 10f);
- values.Add(PropertyName.property_Vector2, global::Godot.Variant.From<global::Godot.Vector2>(__property_Vector2_default_value));
- global::Godot.Vector2I __property_Vector2I_default_value = global::Godot.Vector2I.Up;
- values.Add(PropertyName.property_Vector2I, global::Godot.Variant.From<global::Godot.Vector2I>(__property_Vector2I_default_value));
- global::Godot.Rect2 __property_Rect2_default_value = new(new global::Godot.Vector2(10f, 10f), new global::Godot.Vector2(10f, 10f));
- values.Add(PropertyName.property_Rect2, global::Godot.Variant.From<global::Godot.Rect2>(__property_Rect2_default_value));
- global::Godot.Rect2I __property_Rect2I_default_value = new(new global::Godot.Vector2I(10, 10), new global::Godot.Vector2I(10, 10));
- values.Add(PropertyName.property_Rect2I, global::Godot.Variant.From<global::Godot.Rect2I>(__property_Rect2I_default_value));
- global::Godot.Transform2D __property_Transform2D_default_value = global::Godot.Transform2D.Identity;
- values.Add(PropertyName.property_Transform2D, global::Godot.Variant.From<global::Godot.Transform2D>(__property_Transform2D_default_value));
- global::Godot.Vector3 __property_Vector3_default_value = new(10f, 10f, 10f);
- values.Add(PropertyName.property_Vector3, global::Godot.Variant.From<global::Godot.Vector3>(__property_Vector3_default_value));
- global::Godot.Vector3I __property_Vector3I_default_value = global::Godot.Vector3I.Back;
- values.Add(PropertyName.property_Vector3I, global::Godot.Variant.From<global::Godot.Vector3I>(__property_Vector3I_default_value));
- global::Godot.Basis __property_Basis_default_value = new global::Godot.Basis(global::Godot.Quaternion.Identity);
- values.Add(PropertyName.property_Basis, global::Godot.Variant.From<global::Godot.Basis>(__property_Basis_default_value));
- global::Godot.Quaternion __property_Quaternion_default_value = new global::Godot.Quaternion(global::Godot.Basis.Identity);
- values.Add(PropertyName.property_Quaternion, global::Godot.Variant.From<global::Godot.Quaternion>(__property_Quaternion_default_value));
- global::Godot.Transform3D __property_Transform3D_default_value = global::Godot.Transform3D.Identity;
- values.Add(PropertyName.property_Transform3D, global::Godot.Variant.From<global::Godot.Transform3D>(__property_Transform3D_default_value));
- global::Godot.Vector4 __property_Vector4_default_value = new(10f, 10f, 10f, 10f);
- values.Add(PropertyName.property_Vector4, global::Godot.Variant.From<global::Godot.Vector4>(__property_Vector4_default_value));
- global::Godot.Vector4I __property_Vector4I_default_value = global::Godot.Vector4I.One;
- values.Add(PropertyName.property_Vector4I, global::Godot.Variant.From<global::Godot.Vector4I>(__property_Vector4I_default_value));
- global::Godot.Projection __property_Projection_default_value = global::Godot.Projection.Identity;
- values.Add(PropertyName.property_Projection, global::Godot.Variant.From<global::Godot.Projection>(__property_Projection_default_value));
- global::Godot.Aabb __property_Aabb_default_value = new global::Godot.Aabb(10f, 10f, 10f, new global::Godot.Vector3(1f, 1f, 1f));
- values.Add(PropertyName.property_Aabb, global::Godot.Variant.From<global::Godot.Aabb>(__property_Aabb_default_value));
- global::Godot.Color __property_Color_default_value = global::Godot.Colors.Aquamarine;
- values.Add(PropertyName.property_Color, global::Godot.Variant.From<global::Godot.Color>(__property_Color_default_value));
- global::Godot.Plane __property_Plane_default_value = global::Godot.Plane.PlaneXZ;
- values.Add(PropertyName.property_Plane, global::Godot.Variant.From<global::Godot.Plane>(__property_Plane_default_value));
- global::Godot.Callable __property_Callable_default_value = new global::Godot.Callable(global::Godot.Engine.GetMainLoop(), "_process");
- values.Add(PropertyName.property_Callable, global::Godot.Variant.From<global::Godot.Callable>(__property_Callable_default_value));
- global::Godot.Signal __property_Signal_default_value = new global::Godot.Signal(global::Godot.Engine.GetMainLoop(), "property_list_changed");
- values.Add(PropertyName.property_Signal, global::Godot.Variant.From<global::Godot.Signal>(__property_Signal_default_value));
- global::ExportedProperties.MyEnum __property_Enum_default_value = global::ExportedProperties.MyEnum.C;
- values.Add(PropertyName.property_Enum, global::Godot.Variant.From<global::ExportedProperties.MyEnum>(__property_Enum_default_value));
- global::ExportedProperties.MyFlagsEnum __property_FlagsEnum_default_value = global::ExportedProperties.MyFlagsEnum.C;
- values.Add(PropertyName.property_FlagsEnum, global::Godot.Variant.From<global::ExportedProperties.MyFlagsEnum>(__property_FlagsEnum_default_value));
- byte[] __property_ByteArray_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.property_ByteArray, global::Godot.Variant.From<byte[]>(__property_ByteArray_default_value));
- int[] __property_Int32Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.property_Int32Array, global::Godot.Variant.From<int[]>(__property_Int32Array_default_value));
- long[] __property_Int64Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.property_Int64Array, global::Godot.Variant.From<long[]>(__property_Int64Array_default_value));
- float[] __property_SingleArray_default_value = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- values.Add(PropertyName.property_SingleArray, global::Godot.Variant.From<float[]>(__property_SingleArray_default_value));
- double[] __property_DoubleArray_default_value = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- values.Add(PropertyName.property_DoubleArray, global::Godot.Variant.From<double[]>(__property_DoubleArray_default_value));
- string[] __property_StringArray_default_value = { "foo", "bar" };
- values.Add(PropertyName.property_StringArray, global::Godot.Variant.From<string[]>(__property_StringArray_default_value));
- string[] __property_StringArrayEnum_default_value = { "foo", "bar" };
- values.Add(PropertyName.property_StringArrayEnum, global::Godot.Variant.From<string[]>(__property_StringArrayEnum_default_value));
- global::Godot.Vector2[] __property_Vector2Array_default_value = { global::Godot.Vector2.Up, global::Godot.Vector2.Down, global::Godot.Vector2.Left, global::Godot.Vector2.Right };
- values.Add(PropertyName.property_Vector2Array, global::Godot.Variant.From<global::Godot.Vector2[]>(__property_Vector2Array_default_value));
- global::Godot.Vector3[] __property_Vector3Array_default_value = { global::Godot.Vector3.Up, global::Godot.Vector3.Down, global::Godot.Vector3.Left, global::Godot.Vector3.Right };
- values.Add(PropertyName.property_Vector3Array, global::Godot.Variant.From<global::Godot.Vector3[]>(__property_Vector3Array_default_value));
- global::Godot.Color[] __property_ColorArray_default_value = { global::Godot.Colors.Aqua, global::Godot.Colors.Aquamarine, global::Godot.Colors.Azure, global::Godot.Colors.Beige };
- values.Add(PropertyName.property_ColorArray, global::Godot.Variant.From<global::Godot.Color[]>(__property_ColorArray_default_value));
- global::Godot.GodotObject[] __property_GodotObjectOrDerivedArray_default_value = { null };
- values.Add(PropertyName.property_GodotObjectOrDerivedArray, global::Godot.Variant.CreateFrom(__property_GodotObjectOrDerivedArray_default_value));
+ string __NotGenerateComplexLamdaProperty_default_value = default;
+ values.Add(PropertyName.NotGenerateComplexLamdaProperty, global::Godot.Variant.From<string>(__NotGenerateComplexLamdaProperty_default_value));
+ string __NotGenerateLamdaNoFieldProperty_default_value = default;
+ values.Add(PropertyName.NotGenerateLamdaNoFieldProperty, global::Godot.Variant.From<string>(__NotGenerateLamdaNoFieldProperty_default_value));
+ string __NotGenerateComplexReturnProperty_default_value = default;
+ values.Add(PropertyName.NotGenerateComplexReturnProperty, global::Godot.Variant.From<string>(__NotGenerateComplexReturnProperty_default_value));
+ string __NotGenerateReturnsProperty_default_value = default;
+ values.Add(PropertyName.NotGenerateReturnsProperty, global::Godot.Variant.From<string>(__NotGenerateReturnsProperty_default_value));
+ string __FullPropertyString_default_value = "FullPropertyString";
+ values.Add(PropertyName.FullPropertyString, global::Godot.Variant.From<string>(__FullPropertyString_default_value));
+ string __FullPropertyString_Complex_default_value = new string("FullPropertyString_Complex") + global::System.Convert.ToInt32("1");
+ values.Add(PropertyName.FullPropertyString_Complex, global::Godot.Variant.From<string>(__FullPropertyString_Complex_default_value));
+ string __LamdaPropertyString_default_value = "LamdaPropertyString";
+ values.Add(PropertyName.LamdaPropertyString, global::Godot.Variant.From<string>(__LamdaPropertyString_default_value));
+ bool __PropertyBoolean_default_value = true;
+ values.Add(PropertyName.PropertyBoolean, global::Godot.Variant.From<bool>(__PropertyBoolean_default_value));
+ char __PropertyChar_default_value = 'f';
+ values.Add(PropertyName.PropertyChar, global::Godot.Variant.From<char>(__PropertyChar_default_value));
+ sbyte __PropertySByte_default_value = 10;
+ values.Add(PropertyName.PropertySByte, global::Godot.Variant.From<sbyte>(__PropertySByte_default_value));
+ short __PropertyInt16_default_value = 10;
+ values.Add(PropertyName.PropertyInt16, global::Godot.Variant.From<short>(__PropertyInt16_default_value));
+ int __PropertyInt32_default_value = 10;
+ values.Add(PropertyName.PropertyInt32, global::Godot.Variant.From<int>(__PropertyInt32_default_value));
+ long __PropertyInt64_default_value = 10;
+ values.Add(PropertyName.PropertyInt64, global::Godot.Variant.From<long>(__PropertyInt64_default_value));
+ byte __PropertyByte_default_value = 10;
+ values.Add(PropertyName.PropertyByte, global::Godot.Variant.From<byte>(__PropertyByte_default_value));
+ ushort __PropertyUInt16_default_value = 10;
+ values.Add(PropertyName.PropertyUInt16, global::Godot.Variant.From<ushort>(__PropertyUInt16_default_value));
+ uint __PropertyUInt32_default_value = 10;
+ values.Add(PropertyName.PropertyUInt32, global::Godot.Variant.From<uint>(__PropertyUInt32_default_value));
+ ulong __PropertyUInt64_default_value = 10;
+ values.Add(PropertyName.PropertyUInt64, global::Godot.Variant.From<ulong>(__PropertyUInt64_default_value));
+ float __PropertySingle_default_value = 10;
+ values.Add(PropertyName.PropertySingle, global::Godot.Variant.From<float>(__PropertySingle_default_value));
+ double __PropertyDouble_default_value = 10;
+ values.Add(PropertyName.PropertyDouble, global::Godot.Variant.From<double>(__PropertyDouble_default_value));
+ string __PropertyString_default_value = "foo";
+ values.Add(PropertyName.PropertyString, global::Godot.Variant.From<string>(__PropertyString_default_value));
+ global::Godot.Vector2 __PropertyVector2_default_value = new(10f, 10f);
+ values.Add(PropertyName.PropertyVector2, global::Godot.Variant.From<global::Godot.Vector2>(__PropertyVector2_default_value));
+ global::Godot.Vector2I __PropertyVector2I_default_value = global::Godot.Vector2I.Up;
+ values.Add(PropertyName.PropertyVector2I, global::Godot.Variant.From<global::Godot.Vector2I>(__PropertyVector2I_default_value));
+ global::Godot.Rect2 __PropertyRect2_default_value = new(new global::Godot.Vector2(10f, 10f), new global::Godot.Vector2(10f, 10f));
+ values.Add(PropertyName.PropertyRect2, global::Godot.Variant.From<global::Godot.Rect2>(__PropertyRect2_default_value));
+ global::Godot.Rect2I __PropertyRect2I_default_value = new(new global::Godot.Vector2I(10, 10), new global::Godot.Vector2I(10, 10));
+ values.Add(PropertyName.PropertyRect2I, global::Godot.Variant.From<global::Godot.Rect2I>(__PropertyRect2I_default_value));
+ global::Godot.Transform2D __PropertyTransform2D_default_value = global::Godot.Transform2D.Identity;
+ values.Add(PropertyName.PropertyTransform2D, global::Godot.Variant.From<global::Godot.Transform2D>(__PropertyTransform2D_default_value));
+ global::Godot.Vector3 __PropertyVector3_default_value = new(10f, 10f, 10f);
+ values.Add(PropertyName.PropertyVector3, global::Godot.Variant.From<global::Godot.Vector3>(__PropertyVector3_default_value));
+ global::Godot.Vector3I __PropertyVector3I_default_value = global::Godot.Vector3I.Back;
+ values.Add(PropertyName.PropertyVector3I, global::Godot.Variant.From<global::Godot.Vector3I>(__PropertyVector3I_default_value));
+ global::Godot.Basis __PropertyBasis_default_value = new global::Godot.Basis(global::Godot.Quaternion.Identity);
+ values.Add(PropertyName.PropertyBasis, global::Godot.Variant.From<global::Godot.Basis>(__PropertyBasis_default_value));
+ global::Godot.Quaternion __PropertyQuaternion_default_value = new global::Godot.Quaternion(global::Godot.Basis.Identity);
+ values.Add(PropertyName.PropertyQuaternion, global::Godot.Variant.From<global::Godot.Quaternion>(__PropertyQuaternion_default_value));
+ global::Godot.Transform3D __PropertyTransform3D_default_value = global::Godot.Transform3D.Identity;
+ values.Add(PropertyName.PropertyTransform3D, global::Godot.Variant.From<global::Godot.Transform3D>(__PropertyTransform3D_default_value));
+ global::Godot.Vector4 __PropertyVector4_default_value = new(10f, 10f, 10f, 10f);
+ values.Add(PropertyName.PropertyVector4, global::Godot.Variant.From<global::Godot.Vector4>(__PropertyVector4_default_value));
+ global::Godot.Vector4I __PropertyVector4I_default_value = global::Godot.Vector4I.One;
+ values.Add(PropertyName.PropertyVector4I, global::Godot.Variant.From<global::Godot.Vector4I>(__PropertyVector4I_default_value));
+ global::Godot.Projection __PropertyProjection_default_value = global::Godot.Projection.Identity;
+ values.Add(PropertyName.PropertyProjection, global::Godot.Variant.From<global::Godot.Projection>(__PropertyProjection_default_value));
+ global::Godot.Aabb __PropertyAabb_default_value = new global::Godot.Aabb(10f, 10f, 10f, new global::Godot.Vector3(1f, 1f, 1f));
+ values.Add(PropertyName.PropertyAabb, global::Godot.Variant.From<global::Godot.Aabb>(__PropertyAabb_default_value));
+ global::Godot.Color __PropertyColor_default_value = global::Godot.Colors.Aquamarine;
+ values.Add(PropertyName.PropertyColor, global::Godot.Variant.From<global::Godot.Color>(__PropertyColor_default_value));
+ global::Godot.Plane __PropertyPlane_default_value = global::Godot.Plane.PlaneXZ;
+ values.Add(PropertyName.PropertyPlane, global::Godot.Variant.From<global::Godot.Plane>(__PropertyPlane_default_value));
+ global::Godot.Callable __PropertyCallable_default_value = new global::Godot.Callable(global::Godot.Engine.GetMainLoop(), "_process");
+ values.Add(PropertyName.PropertyCallable, global::Godot.Variant.From<global::Godot.Callable>(__PropertyCallable_default_value));
+ global::Godot.Signal __PropertySignal_default_value = new global::Godot.Signal(global::Godot.Engine.GetMainLoop(), "Propertylist_changed");
+ values.Add(PropertyName.PropertySignal, global::Godot.Variant.From<global::Godot.Signal>(__PropertySignal_default_value));
+ global::ExportedProperties.MyEnum __PropertyEnum_default_value = global::ExportedProperties.MyEnum.C;
+ values.Add(PropertyName.PropertyEnum, global::Godot.Variant.From<global::ExportedProperties.MyEnum>(__PropertyEnum_default_value));
+ global::ExportedProperties.MyFlagsEnum __PropertyFlagsEnum_default_value = global::ExportedProperties.MyFlagsEnum.C;
+ values.Add(PropertyName.PropertyFlagsEnum, global::Godot.Variant.From<global::ExportedProperties.MyFlagsEnum>(__PropertyFlagsEnum_default_value));
+ byte[] __PropertyByteArray_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName.PropertyByteArray, global::Godot.Variant.From<byte[]>(__PropertyByteArray_default_value));
+ int[] __PropertyInt32Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName.PropertyInt32Array, global::Godot.Variant.From<int[]>(__PropertyInt32Array_default_value));
+ long[] __PropertyInt64Array_default_value = { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName.PropertyInt64Array, global::Godot.Variant.From<long[]>(__PropertyInt64Array_default_value));
+ float[] __PropertySingleArray_default_value = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ values.Add(PropertyName.PropertySingleArray, global::Godot.Variant.From<float[]>(__PropertySingleArray_default_value));
+ double[] __PropertyDoubleArray_default_value = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ values.Add(PropertyName.PropertyDoubleArray, global::Godot.Variant.From<double[]>(__PropertyDoubleArray_default_value));
+ string[] __PropertyStringArray_default_value = { "foo", "bar" };
+ values.Add(PropertyName.PropertyStringArray, global::Godot.Variant.From<string[]>(__PropertyStringArray_default_value));
+ string[] __PropertyStringArrayEnum_default_value = { "foo", "bar" };
+ values.Add(PropertyName.PropertyStringArrayEnum, global::Godot.Variant.From<string[]>(__PropertyStringArrayEnum_default_value));
+ global::Godot.Vector2[] __PropertyVector2Array_default_value = { global::Godot.Vector2.Up, global::Godot.Vector2.Down, global::Godot.Vector2.Left, global::Godot.Vector2.Right };
+ values.Add(PropertyName.PropertyVector2Array, global::Godot.Variant.From<global::Godot.Vector2[]>(__PropertyVector2Array_default_value));
+ global::Godot.Vector3[] __PropertyVector3Array_default_value = { global::Godot.Vector3.Up, global::Godot.Vector3.Down, global::Godot.Vector3.Left, global::Godot.Vector3.Right };
+ values.Add(PropertyName.PropertyVector3Array, global::Godot.Variant.From<global::Godot.Vector3[]>(__PropertyVector3Array_default_value));
+ global::Godot.Color[] __PropertyColorArray_default_value = { global::Godot.Colors.Aqua, global::Godot.Colors.Aquamarine, global::Godot.Colors.Azure, global::Godot.Colors.Beige };
+ values.Add(PropertyName.PropertyColorArray, global::Godot.Variant.From<global::Godot.Color[]>(__PropertyColorArray_default_value));
+ global::Godot.GodotObject[] __PropertyGodotObjectOrDerivedArray_default_value = { null };
+ values.Add(PropertyName.PropertyGodotObjectOrDerivedArray, global::Godot.Variant.CreateFrom(__PropertyGodotObjectOrDerivedArray_default_value));
global::Godot.StringName[] __field_StringNameArray_default_value = { "foo", "bar" };
values.Add(PropertyName.field_StringNameArray, global::Godot.Variant.From<global::Godot.StringName[]>(__field_StringNameArray_default_value));
global::Godot.NodePath[] __field_NodePathArray_default_value = { "foo", "bar" };
values.Add(PropertyName.field_NodePathArray, global::Godot.Variant.From<global::Godot.NodePath[]>(__field_NodePathArray_default_value));
global::Godot.Rid[] __field_RidArray_default_value = { default, default, default };
values.Add(PropertyName.field_RidArray, global::Godot.Variant.From<global::Godot.Rid[]>(__field_RidArray_default_value));
- global::Godot.Variant __property_Variant_default_value = "foo";
- values.Add(PropertyName.property_Variant, global::Godot.Variant.From<global::Godot.Variant>(__property_Variant_default_value));
- global::Godot.GodotObject __property_GodotObjectOrDerived_default_value = default;
- values.Add(PropertyName.property_GodotObjectOrDerived, global::Godot.Variant.From<global::Godot.GodotObject>(__property_GodotObjectOrDerived_default_value));
- global::Godot.Texture __property_GodotResourceTexture_default_value = default;
- values.Add(PropertyName.property_GodotResourceTexture, global::Godot.Variant.From<global::Godot.Texture>(__property_GodotResourceTexture_default_value));
- global::Godot.StringName __property_StringName_default_value = new global::Godot.StringName("foo");
- values.Add(PropertyName.property_StringName, global::Godot.Variant.From<global::Godot.StringName>(__property_StringName_default_value));
- global::Godot.NodePath __property_NodePath_default_value = new global::Godot.NodePath("foo");
- values.Add(PropertyName.property_NodePath, global::Godot.Variant.From<global::Godot.NodePath>(__property_NodePath_default_value));
- global::Godot.Rid __property_Rid_default_value = default;
- values.Add(PropertyName.property_Rid, global::Godot.Variant.From<global::Godot.Rid>(__property_Rid_default_value));
- global::Godot.Collections.Dictionary __property_GodotDictionary_default_value = new() { { "foo", 10 }, { global::Godot.Vector2.Up, global::Godot.Colors.Chocolate } };
- values.Add(PropertyName.property_GodotDictionary, global::Godot.Variant.From<global::Godot.Collections.Dictionary>(__property_GodotDictionary_default_value));
- global::Godot.Collections.Array __property_GodotArray_default_value = new() { "foo", 10, global::Godot.Vector2.Up, global::Godot.Colors.Chocolate };
- values.Add(PropertyName.property_GodotArray, global::Godot.Variant.From<global::Godot.Collections.Array>(__property_GodotArray_default_value));
- global::Godot.Collections.Dictionary<string, bool> __property_GodotGenericDictionary_default_value = new() { { "foo", true }, { "bar", false } };
- values.Add(PropertyName.property_GodotGenericDictionary, global::Godot.Variant.CreateFrom(__property_GodotGenericDictionary_default_value));
- global::Godot.Collections.Array<int> __property_GodotGenericArray_default_value = new() { 0, 1, 2, 3, 4, 5, 6 };
- values.Add(PropertyName.property_GodotGenericArray, global::Godot.Variant.CreateFrom(__property_GodotGenericArray_default_value));
+ global::Godot.Variant __PropertyVariant_default_value = "foo";
+ values.Add(PropertyName.PropertyVariant, global::Godot.Variant.From<global::Godot.Variant>(__PropertyVariant_default_value));
+ global::Godot.GodotObject __PropertyGodotObjectOrDerived_default_value = default;
+ values.Add(PropertyName.PropertyGodotObjectOrDerived, global::Godot.Variant.From<global::Godot.GodotObject>(__PropertyGodotObjectOrDerived_default_value));
+ global::Godot.Texture __PropertyGodotResourceTexture_default_value = default;
+ values.Add(PropertyName.PropertyGodotResourceTexture, global::Godot.Variant.From<global::Godot.Texture>(__PropertyGodotResourceTexture_default_value));
+ global::Godot.StringName __PropertyStringName_default_value = new global::Godot.StringName("foo");
+ values.Add(PropertyName.PropertyStringName, global::Godot.Variant.From<global::Godot.StringName>(__PropertyStringName_default_value));
+ global::Godot.NodePath __PropertyNodePath_default_value = new global::Godot.NodePath("foo");
+ values.Add(PropertyName.PropertyNodePath, global::Godot.Variant.From<global::Godot.NodePath>(__PropertyNodePath_default_value));
+ global::Godot.Rid __PropertyRid_default_value = default;
+ values.Add(PropertyName.PropertyRid, global::Godot.Variant.From<global::Godot.Rid>(__PropertyRid_default_value));
+ global::Godot.Collections.Dictionary __PropertyGodotDictionary_default_value = new() { { "foo", 10 }, { global::Godot.Vector2.Up, global::Godot.Colors.Chocolate } };
+ values.Add(PropertyName.PropertyGodotDictionary, global::Godot.Variant.From<global::Godot.Collections.Dictionary>(__PropertyGodotDictionary_default_value));
+ global::Godot.Collections.Array __PropertyGodotArray_default_value = new() { "foo", 10, global::Godot.Vector2.Up, global::Godot.Colors.Chocolate };
+ values.Add(PropertyName.PropertyGodotArray, global::Godot.Variant.From<global::Godot.Collections.Array>(__PropertyGodotArray_default_value));
+ global::Godot.Collections.Dictionary<string, bool> __PropertyGodotGenericDictionary_default_value = new() { { "foo", true }, { "bar", false } };
+ values.Add(PropertyName.PropertyGodotGenericDictionary, global::Godot.Variant.CreateFrom(__PropertyGodotGenericDictionary_default_value));
+ global::Godot.Collections.Array<int> __PropertyGodotGenericArray_default_value = new() { 0, 1, 2, 3, 4, 5, 6 };
+ values.Add(PropertyName.PropertyGodotGenericArray, global::Godot.Variant.CreateFrom(__PropertyGodotGenericArray_default_value));
return values;
}
#endif // TOOLS
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/MixedReadOnlyWriteOnly_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/MixedReadOnlyWriteOnly_ScriptProperties.generated.cs
index f812457aa5..91f808f55e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/MixedReadOnlyWriteOnly_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/MixedReadOnlyWriteOnly_ScriptProperties.generated.cs
@@ -9,40 +9,40 @@ partial class MixedReadOnlyWriteOnly
/// </summary>
public new class PropertyName : global::Godot.GodotObject.PropertyName {
/// <summary>
- /// Cached name for the 'readonly_auto_property' property.
+ /// Cached name for the 'ReadOnlyAutoProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName readonly_auto_property = "readonly_auto_property";
+ public new static readonly global::Godot.StringName ReadOnlyAutoProperty = "ReadOnlyAutoProperty";
/// <summary>
- /// Cached name for the 'readonly_property' property.
+ /// Cached name for the 'ReadOnlyProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName readonly_property = "readonly_property";
+ public new static readonly global::Godot.StringName ReadOnlyProperty = "ReadOnlyProperty";
/// <summary>
- /// Cached name for the 'initonly_auto_property' property.
+ /// Cached name for the 'InitOnlyAutoProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName initonly_auto_property = "initonly_auto_property";
+ public new static readonly global::Godot.StringName InitOnlyAutoProperty = "InitOnlyAutoProperty";
/// <summary>
- /// Cached name for the 'writeonly_property' property.
+ /// Cached name for the 'WriteOnlyProperty' property.
/// </summary>
- public new static readonly global::Godot.StringName writeonly_property = "writeonly_property";
+ public new static readonly global::Godot.StringName WriteOnlyProperty = "WriteOnlyProperty";
/// <summary>
- /// Cached name for the 'readonly_field' field.
+ /// Cached name for the 'ReadOnlyField' field.
/// </summary>
- public new static readonly global::Godot.StringName readonly_field = "readonly_field";
+ public new static readonly global::Godot.StringName ReadOnlyField = "ReadOnlyField";
/// <summary>
- /// Cached name for the 'writeonly_backing_field' field.
+ /// Cached name for the '_writeOnlyBackingField' field.
/// </summary>
- public new static readonly global::Godot.StringName writeonly_backing_field = "writeonly_backing_field";
+ public new static readonly global::Godot.StringName _writeOnlyBackingField = "_writeOnlyBackingField";
}
/// <inheritdoc/>
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
{
- if (name == PropertyName.writeonly_property) {
- this.writeonly_property = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ if (name == PropertyName.WriteOnlyProperty) {
+ this.WriteOnlyProperty = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
- else if (name == PropertyName.writeonly_backing_field) {
- this.writeonly_backing_field = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
+ else if (name == PropertyName._writeOnlyBackingField) {
+ this._writeOnlyBackingField = global::Godot.NativeInterop.VariantUtils.ConvertTo<bool>(value);
return true;
}
return base.SetGodotClassPropertyValue(name, value);
@@ -51,24 +51,24 @@ partial class MixedReadOnlyWriteOnly
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
{
- if (name == PropertyName.readonly_auto_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_auto_property);
+ if (name == PropertyName.ReadOnlyAutoProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyAutoProperty);
return true;
}
- else if (name == PropertyName.readonly_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_property);
+ else if (name == PropertyName.ReadOnlyProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyProperty);
return true;
}
- else if (name == PropertyName.initonly_auto_property) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.initonly_auto_property);
+ else if (name == PropertyName.InitOnlyAutoProperty) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.InitOnlyAutoProperty);
return true;
}
- else if (name == PropertyName.readonly_field) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.readonly_field);
+ else if (name == PropertyName.ReadOnlyField) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.ReadOnlyField);
return true;
}
- else if (name == PropertyName.writeonly_backing_field) {
- value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this.writeonly_backing_field);
+ else if (name == PropertyName._writeOnlyBackingField) {
+ value = global::Godot.NativeInterop.VariantUtils.CreateFrom<bool>(this._writeOnlyBackingField);
return true;
}
return base.GetGodotClassPropertyValue(name, out value);
@@ -82,12 +82,12 @@ partial class MixedReadOnlyWriteOnly
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
{
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_field, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_auto_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.readonly_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.initonly_auto_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.writeonly_backing_field, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
- properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.writeonly_property, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyAutoProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.ReadOnlyProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.InitOnlyAutoProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName._writeOnlyBackingField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
+ properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.WriteOnlyProperty, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
return properties;
}
#pragma warning restore CS0109
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllReadOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllReadOnly.cs
index 94c2bda363..2586db1137 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllReadOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllReadOnly.cs
@@ -2,8 +2,8 @@ using Godot;
public partial class AllReadOnly : GodotObject
{
- public readonly string readonly_field = "foo";
- public string readonly_auto_property { get; } = "foo";
- public string readonly_property { get => "foo"; }
- public string initonly_auto_property { get; init; }
+ public readonly string ReadOnlyField = "foo";
+ public string ReadOnlyAutoProperty { get; } = "foo";
+ public string ReadOnlyProperty { get => "foo"; }
+ public string InitOnlyAutoProperty { get; init; }
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllWriteOnly.cs
index 156d6bb6a5..e2ebff4876 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllWriteOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/AllWriteOnly.cs
@@ -2,6 +2,6 @@ using Godot;
public partial class AllWriteOnly : GodotObject
{
- bool writeonly_backing_field = false;
- public bool writeonly_property { set => writeonly_backing_field = value; }
+ private bool _writeOnlyBackingField = false;
+ public bool WriteOnlyProperty { set => _writeOnlyBackingField = value; }
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Bar.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Bar.cs
index dfe2217c26..d364e40bf0 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Bar.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Bar.cs
@@ -1,14 +1,14 @@
using Godot;
-partial class Bar : GodotObject
+public partial class Bar : GodotObject
{
}
// Foo in another file
-partial class Foo
+public partial class Foo
{
}
-partial class NotSameNameAsFile : GodotObject
+public partial class NotSameNameAsFile : GodotObject
{
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedFields.cs
index 09d654ffcb..0938d10afe 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedFields.cs
@@ -4,99 +4,99 @@ using System.Collections.Generic;
public partial class ExportedFields : GodotObject
{
- [Export] private Boolean field_Boolean = true;
- [Export] private Char field_Char = 'f';
- [Export] private SByte field_SByte = 10;
- [Export] private Int16 field_Int16 = 10;
- [Export] private Int32 field_Int32 = 10;
- [Export] private Int64 field_Int64 = 10;
- [Export] private Byte field_Byte = 10;
- [Export] private UInt16 field_UInt16 = 10;
- [Export] private UInt32 field_UInt32 = 10;
- [Export] private UInt64 field_UInt64 = 10;
- [Export] private Single field_Single = 10;
- [Export] private Double field_Double = 10;
- [Export] private String field_String = "foo";
+ [Export] private Boolean _fieldBoolean = true;
+ [Export] private Char _fieldChar = 'f';
+ [Export] private SByte _fieldSByte = 10;
+ [Export] private Int16 _fieldInt16 = 10;
+ [Export] private Int32 _fieldInt32 = 10;
+ [Export] private Int64 _fieldInt64 = 10;
+ [Export] private Byte _fieldByte = 10;
+ [Export] private UInt16 _fieldUInt16 = 10;
+ [Export] private UInt32 _fieldUInt32 = 10;
+ [Export] private UInt64 _fieldUInt64 = 10;
+ [Export] private Single _fieldSingle = 10;
+ [Export] private Double _fieldDouble = 10;
+ [Export] private String _fieldString = "foo";
// Godot structs
- [Export] private Vector2 field_Vector2 = new(10f, 10f);
- [Export] private Vector2I field_Vector2I = Vector2I.Up;
- [Export] private Rect2 field_Rect2 = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2I field_Rect2I = new(new Vector2I(10, 10), new Vector2I(10, 10));
- [Export] private Transform2D field_Transform2D = Transform2D.Identity;
- [Export] private Vector3 field_Vector3 = new(10f, 10f, 10f);
- [Export] private Vector3I field_Vector3I = Vector3I.Back;
- [Export] private Basis field_Basis = new Basis(Quaternion.Identity);
- [Export] private Quaternion field_Quaternion = new Quaternion(Basis.Identity);
- [Export] private Transform3D field_Transform3D = Transform3D.Identity;
- [Export] private Vector4 field_Vector4 = new(10f, 10f, 10f, 10f);
- [Export] private Vector4I field_Vector4I = Vector4I.One;
- [Export] private Projection field_Projection = Projection.Identity;
- [Export] private Aabb field_Aabb = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
- [Export] private Color field_Color = Colors.Aquamarine;
- [Export] private Plane field_Plane = Plane.PlaneXZ;
- [Export] private Callable field_Callable = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private Signal field_Signal = new Signal(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Vector2 _fieldVector2 = new(10f, 10f);
+ [Export] private Vector2I _fieldVector2I = Vector2I.Up;
+ [Export] private Rect2 _fieldRect2 = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
+ [Export] private Rect2I _fieldRect2I = new(new Vector2I(10, 10), new Vector2I(10, 10));
+ [Export] private Transform2D _fieldTransform2D = Transform2D.Identity;
+ [Export] private Vector3 _fieldVector3 = new(10f, 10f, 10f);
+ [Export] private Vector3I _fieldVector3I = Vector3I.Back;
+ [Export] private Basis _fieldBasis = new Basis(Quaternion.Identity);
+ [Export] private Quaternion _fieldQuaternion = new Quaternion(Basis.Identity);
+ [Export] private Transform3D _fieldTransform3D = Transform3D.Identity;
+ [Export] private Vector4 _fieldVector4 = new(10f, 10f, 10f, 10f);
+ [Export] private Vector4I _fieldVector4I = Vector4I.One;
+ [Export] private Projection _fieldProjection = Projection.Identity;
+ [Export] private Aabb _fieldAabb = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Color _fieldColor = Colors.Aquamarine;
+ [Export] private Plane _fieldPlane = Plane.PlaneXZ;
+ [Export] private Callable _fieldCallable = new Callable(Engine.GetMainLoop(), "_process");
+ [Export] private Signal _fieldSignal = new Signal(Engine.GetMainLoop(), "property_list_changed");
// Enums
- enum MyEnum
+ public enum MyEnum
{
A,
B,
C
}
- [Export] private MyEnum field_Enum = MyEnum.C;
+ [Export] private MyEnum _fieldEnum = MyEnum.C;
[Flags]
- enum MyFlagsEnum
+ public enum MyFlagsEnum
{
A,
B,
C
}
- [Export] private MyFlagsEnum field_FlagsEnum = MyFlagsEnum.C;
+ [Export] private MyFlagsEnum _fieldFlagsEnum = MyFlagsEnum.C;
// Arrays
- [Export] private Byte[] field_ByteArray = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int32[] field_Int32Array = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int64[] field_Int64Array = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Single[] field_SingleArray = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- [Export] private Double[] field_DoubleArray = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- [Export] private String[] field_StringArray = { "foo", "bar" };
- [Export(PropertyHint.Enum, "A,B,C")] private String[] field_StringArrayEnum = { "foo", "bar" };
- [Export] private Vector2[] field_Vector2Array = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
- [Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
- [Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private GodotObject[] field_GodotObjectOrDerivedArray = { null };
- [Export] private StringName[] field_StringNameArray = { "foo", "bar" };
- [Export] private NodePath[] field_NodePathArray = { "foo", "bar" };
- [Export] private Rid[] field_RidArray = { default, default, default };
+ [Export] private Byte[] _fieldByteArray = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int32[] _fieldInt32Array = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int64[] _fieldInt64Array = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Single[] _fieldSingleArray = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ [Export] private Double[] _fieldDoubleArray = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ [Export] private String[] _fieldStringArray = { "foo", "bar" };
+ [Export(PropertyHint.Enum, "A,B,C")] private String[] _fieldStringArrayEnum = { "foo", "bar" };
+ [Export] private Vector2[] _fieldVector2Array = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
+ [Export] private Vector3[] _fieldVector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
+ [Export] private Color[] _fieldColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
+ [Export] private GodotObject[] _fieldGodotObjectOrDerivedArray = { null };
+ [Export] private StringName[] _fieldStringNameArray = { "foo", "bar" };
+ [Export] private NodePath[] _fieldNodePathArray = { "foo", "bar" };
+ [Export] private Rid[] _fieldRidArray = { default, default, default };
// Note we use Array and not System.Array. This tests the generated namespace qualification.
- [Export] private Int32[] field_empty_Int32Array = Array.Empty<Int32>();
+ [Export] private Int32[] _fieldEmptyInt32Array = Array.Empty<Int32>();
// Note we use List and not System.Collections.Generic.
- [Export] private int[] field_array_from_list = new List<int>(Array.Empty<int>()).ToArray();
+ [Export] private int[] _fieldArrayFromList = new List<int>(Array.Empty<int>()).ToArray();
// Variant
- [Export] private Variant field_Variant = "foo";
+ [Export] private Variant _fieldVariant = "foo";
// Classes
- [Export] private GodotObject field_GodotObjectOrDerived;
- [Export] private Godot.Texture field_GodotResourceTexture;
- [Export] private StringName field_StringName = new StringName("foo");
- [Export] private NodePath field_NodePath = new NodePath("foo");
- [Export] private Rid field_Rid;
+ [Export] private GodotObject _fieldGodotObjectOrDerived;
+ [Export] private Godot.Texture _fieldGodotResourceTexture;
+ [Export] private StringName _fieldStringName = new StringName("foo");
+ [Export] private NodePath _fieldNodePath = new NodePath("foo");
+ [Export] private Rid _fieldRid;
[Export]
- private Godot.Collections.Dictionary field_GodotDictionary = new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
+ private Godot.Collections.Dictionary _fieldGodotDictionary = new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
[Export]
- private Godot.Collections.Array field_GodotArray = new() { "foo", 10, Vector2.Up, Colors.Chocolate };
+ private Godot.Collections.Array _fieldGodotArray = new() { "foo", 10, Vector2.Up, Colors.Chocolate };
[Export]
- private Godot.Collections.Dictionary<string, bool> field_GodotGenericDictionary = new() { { "foo", true }, { "bar", false } };
+ private Godot.Collections.Dictionary<string, bool> _fieldGodotGenericDictionary = new() { { "foo", true }, { "bar", false } };
[Export]
- private Godot.Collections.Array<int> field_GodotGenericArray = new() { 0, 1, 2, 3, 4, 5, 6 };
+ private Godot.Collections.Array<int> _fieldGodotGenericArray = new() { 0, 1, 2, 3, 4, 5, 6 };
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs
index 3783838dae..9ae23066fc 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs
@@ -4,41 +4,41 @@ using System;
public partial class ExportedProperties : GodotObject
{
// Do not generate default value
- private String _notGenerate_Property_String = new string("not generate");
+ private String _notGeneratePropertyString = new string("not generate");
[Export]
- public String NotGenerate_Complex_Lamda_Property
+ public String NotGenerateComplexLamdaProperty
{
- get => _notGenerate_Property_String + Convert.ToInt32("1");
- set => _notGenerate_Property_String = value;
+ get => _notGeneratePropertyString + Convert.ToInt32("1");
+ set => _notGeneratePropertyString = value;
}
[Export]
- public String NotGenerate_Lamda_NoField_Property
+ public String NotGenerateLamdaNoFieldProperty
{
get => new string("not generate");
- set => _notGenerate_Property_String = value;
+ set => _notGeneratePropertyString = value;
}
[Export]
- public String NotGenerate_Complex_Return_Property
+ public String NotGenerateComplexReturnProperty
{
get
{
- return _notGenerate_Property_String + Convert.ToInt32("1");
+ return _notGeneratePropertyString + Convert.ToInt32("1");
}
set
{
- _notGenerate_Property_String = value;
+ _notGeneratePropertyString = value;
}
}
- private int _notGenerate_Property_Int = 1;
+ private int _notGeneratePropertyInt = 1;
[Export]
- public string NotGenerate_Returns_Property
+ public string NotGenerateReturnsProperty
{
get
{
- if (_notGenerate_Property_Int == 1)
+ if (_notGeneratePropertyInt == 1)
{
return "a";
}
@@ -49,138 +49,138 @@ public partial class ExportedProperties : GodotObject
}
set
{
- _notGenerate_Property_Int = value == "a" ? 1 : 2;
+ _notGeneratePropertyInt = value == "a" ? 1 : 2;
}
}
// Full Property
- private String _fullProperty_String = "FullProperty_String";
+ private String _fullPropertyString = "FullPropertyString";
[Export]
- public String FullProperty_String
+ public String FullPropertyString
{
get
{
- return _fullProperty_String;
+ return _fullPropertyString;
}
set
{
- _fullProperty_String = value;
+ _fullPropertyString = value;
}
}
- private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1");
+ private String _fullPropertyStringComplex = new string("FullPropertyString_Complex") + Convert.ToInt32("1");
[Export]
- public String FullProperty_String_Complex
+ public String FullPropertyString_Complex
{
get
{
- return _fullProperty_String_Complex;
+ return _fullPropertyStringComplex;
}
set
{
- _fullProperty_String_Complex = value;
+ _fullPropertyStringComplex = value;
}
}
// Lambda Property
- private String _lamdaProperty_String = "LamdaProperty_String";
+ private String _lamdaPropertyString = "LamdaPropertyString";
[Export]
- public String LamdaProperty_String
+ public String LamdaPropertyString
{
- get => _lamdaProperty_String;
- set => _lamdaProperty_String = value;
+ get => _lamdaPropertyString;
+ set => _lamdaPropertyString = value;
}
// Auto Property
- [Export] private Boolean property_Boolean { get; set; } = true;
- [Export] private Char property_Char { get; set; } = 'f';
- [Export] private SByte property_SByte { get; set; } = 10;
- [Export] private Int16 property_Int16 { get; set; } = 10;
- [Export] private Int32 property_Int32 { get; set; } = 10;
- [Export] private Int64 property_Int64 { get; set; } = 10;
- [Export] private Byte property_Byte { get; set; } = 10;
- [Export] private UInt16 property_UInt16 { get; set; } = 10;
- [Export] private UInt32 property_UInt32 { get; set; } = 10;
- [Export] private UInt64 property_UInt64 { get; set; } = 10;
- [Export] private Single property_Single { get; set; } = 10;
- [Export] private Double property_Double { get; set; } = 10;
- [Export] private String property_String { get; set; } = "foo";
+ [Export] private Boolean PropertyBoolean { get; set; } = true;
+ [Export] private Char PropertyChar { get; set; } = 'f';
+ [Export] private SByte PropertySByte { get; set; } = 10;
+ [Export] private Int16 PropertyInt16 { get; set; } = 10;
+ [Export] private Int32 PropertyInt32 { get; set; } = 10;
+ [Export] private Int64 PropertyInt64 { get; set; } = 10;
+ [Export] private Byte PropertyByte { get; set; } = 10;
+ [Export] private UInt16 PropertyUInt16 { get; set; } = 10;
+ [Export] private UInt32 PropertyUInt32 { get; set; } = 10;
+ [Export] private UInt64 PropertyUInt64 { get; set; } = 10;
+ [Export] private Single PropertySingle { get; set; } = 10;
+ [Export] private Double PropertyDouble { get; set; } = 10;
+ [Export] private String PropertyString { get; set; } = "foo";
// Godot structs
- [Export] private Vector2 property_Vector2 { get; set; } = new(10f, 10f);
- [Export] private Vector2I property_Vector2I { get; set; } = Vector2I.Up;
- [Export] private Rect2 property_Rect2 { get; set; } = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
- [Export] private Rect2I property_Rect2I { get; set; } = new(new Vector2I(10, 10), new Vector2I(10, 10));
- [Export] private Transform2D property_Transform2D { get; set; } = Transform2D.Identity;
- [Export] private Vector3 property_Vector3 { get; set; } = new(10f, 10f, 10f);
- [Export] private Vector3I property_Vector3I { get; set; } = Vector3I.Back;
- [Export] private Basis property_Basis { get; set; } = new Basis(Quaternion.Identity);
- [Export] private Quaternion property_Quaternion { get; set; } = new Quaternion(Basis.Identity);
- [Export] private Transform3D property_Transform3D { get; set; } = Transform3D.Identity;
- [Export] private Vector4 property_Vector4 { get; set; } = new(10f, 10f, 10f, 10f);
- [Export] private Vector4I property_Vector4I { get; set; } = Vector4I.One;
- [Export] private Projection property_Projection { get; set; } = Projection.Identity;
- [Export] private Aabb property_Aabb { get; set; } = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
- [Export] private Color property_Color { get; set; } = Colors.Aquamarine;
- [Export] private Plane property_Plane { get; set; } = Plane.PlaneXZ;
- [Export] private Callable property_Callable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
- [Export] private Signal property_Signal { get; set; } = new Signal(Engine.GetMainLoop(), "property_list_changed");
+ [Export] private Vector2 PropertyVector2 { get; set; } = new(10f, 10f);
+ [Export] private Vector2I PropertyVector2I { get; set; } = Vector2I.Up;
+ [Export] private Rect2 PropertyRect2 { get; set; } = new(new Vector2(10f, 10f), new Vector2(10f, 10f));
+ [Export] private Rect2I PropertyRect2I { get; set; } = new(new Vector2I(10, 10), new Vector2I(10, 10));
+ [Export] private Transform2D PropertyTransform2D { get; set; } = Transform2D.Identity;
+ [Export] private Vector3 PropertyVector3 { get; set; } = new(10f, 10f, 10f);
+ [Export] private Vector3I PropertyVector3I { get; set; } = Vector3I.Back;
+ [Export] private Basis PropertyBasis { get; set; } = new Basis(Quaternion.Identity);
+ [Export] private Quaternion PropertyQuaternion { get; set; } = new Quaternion(Basis.Identity);
+ [Export] private Transform3D PropertyTransform3D { get; set; } = Transform3D.Identity;
+ [Export] private Vector4 PropertyVector4 { get; set; } = new(10f, 10f, 10f, 10f);
+ [Export] private Vector4I PropertyVector4I { get; set; } = Vector4I.One;
+ [Export] private Projection PropertyProjection { get; set; } = Projection.Identity;
+ [Export] private Aabb PropertyAabb { get; set; } = new Aabb(10f, 10f, 10f, new Vector3(1f, 1f, 1f));
+ [Export] private Color PropertyColor { get; set; } = Colors.Aquamarine;
+ [Export] private Plane PropertyPlane { get; set; } = Plane.PlaneXZ;
+ [Export] private Callable PropertyCallable { get; set; } = new Callable(Engine.GetMainLoop(), "_process");
+ [Export] private Signal PropertySignal { get; set; } = new Signal(Engine.GetMainLoop(), "Propertylist_changed");
// Enums
- enum MyEnum
+ public enum MyEnum
{
A,
B,
C
}
- [Export] private MyEnum property_Enum { get; set; } = MyEnum.C;
+ [Export] private MyEnum PropertyEnum { get; set; } = MyEnum.C;
[Flags]
- enum MyFlagsEnum
+ public enum MyFlagsEnum
{
A,
B,
C
}
- [Export] private MyFlagsEnum property_FlagsEnum { get; set; } = MyFlagsEnum.C;
+ [Export] private MyFlagsEnum PropertyFlagsEnum { get; set; } = MyFlagsEnum.C;
// Arrays
- [Export] private Byte[] property_ByteArray { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int32[] property_Int32Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Int64[] property_Int64Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
- [Export] private Single[] property_SingleArray { get; set; } = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
- [Export] private Double[] property_DoubleArray { get; set; } = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
- [Export] private String[] property_StringArray { get; set; } = { "foo", "bar" };
- [Export(PropertyHint.Enum, "A,B,C")] private String[] property_StringArrayEnum { get; set; } = { "foo", "bar" };
- [Export] private Vector2[] property_Vector2Array { get; set; } = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
- [Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
- [Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
- [Export] private GodotObject[] property_GodotObjectOrDerivedArray { get; set; } = { null };
+ [Export] private Byte[] PropertyByteArray { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int32[] PropertyInt32Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Int64[] PropertyInt64Array { get; set; } = { 0, 1, 2, 3, 4, 5, 6 };
+ [Export] private Single[] PropertySingleArray { get; set; } = { 0f, 1f, 2f, 3f, 4f, 5f, 6f };
+ [Export] private Double[] PropertyDoubleArray { get; set; } = { 0d, 1d, 2d, 3d, 4d, 5d, 6d };
+ [Export] private String[] PropertyStringArray { get; set; } = { "foo", "bar" };
+ [Export(PropertyHint.Enum, "A,B,C")] private String[] PropertyStringArrayEnum { get; set; } = { "foo", "bar" };
+ [Export] private Vector2[] PropertyVector2Array { get; set; } = { Vector2.Up, Vector2.Down, Vector2.Left, Vector2.Right };
+ [Export] private Vector3[] PropertyVector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
+ [Export] private Color[] PropertyColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
+ [Export] private GodotObject[] PropertyGodotObjectOrDerivedArray { get; set; } = { null };
[Export] private StringName[] field_StringNameArray { get; set; } = { "foo", "bar" };
[Export] private NodePath[] field_NodePathArray { get; set; } = { "foo", "bar" };
[Export] private Rid[] field_RidArray { get; set; } = { default, default, default };
// Variant
- [Export] private Variant property_Variant { get; set; } = "foo";
+ [Export] private Variant PropertyVariant { get; set; } = "foo";
// Classes
- [Export] private GodotObject property_GodotObjectOrDerived { get; set; }
- [Export] private Godot.Texture property_GodotResourceTexture { get; set; }
- [Export] private StringName property_StringName { get; set; } = new StringName("foo");
- [Export] private NodePath property_NodePath { get; set; } = new NodePath("foo");
- [Export] private Rid property_Rid { get; set; }
+ [Export] private GodotObject PropertyGodotObjectOrDerived { get; set; }
+ [Export] private Godot.Texture PropertyGodotResourceTexture { get; set; }
+ [Export] private StringName PropertyStringName { get; set; } = new StringName("foo");
+ [Export] private NodePath PropertyNodePath { get; set; } = new NodePath("foo");
+ [Export] private Rid PropertyRid { get; set; }
[Export]
- private Godot.Collections.Dictionary property_GodotDictionary { get; set; } = new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
+ private Godot.Collections.Dictionary PropertyGodotDictionary { get; set; } = new() { { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
[Export]
- private Godot.Collections.Array property_GodotArray { get; set; } = new() { "foo", 10, Vector2.Up, Colors.Chocolate };
+ private Godot.Collections.Array PropertyGodotArray { get; set; } = new() { "foo", 10, Vector2.Up, Colors.Chocolate };
[Export]
- private Godot.Collections.Dictionary<string, bool> property_GodotGenericDictionary { get; set; } = new() { { "foo", true }, { "bar", false } };
+ private Godot.Collections.Dictionary<string, bool> PropertyGodotGenericDictionary { get; set; } = new() { { "foo", true }, { "bar", false } };
[Export]
- private Godot.Collections.Array<int> property_GodotGenericArray { get; set; } = new() { 0, 1, 2, 3, 4, 5, 6 };
+ private Godot.Collections.Array<int> PropertyGodotGenericArray { get; set; } = new() { 0, 1, 2, 3, 4, 5, 6 };
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Foo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Foo.cs
index 26853553c7..53801990d3 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Foo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Foo.cs
@@ -1,10 +1,10 @@
using Godot;
-partial class Foo : GodotObject
+public partial class Foo : GodotObject
{
}
// Foo again in the same file
-partial class Foo
+public partial class Foo
{
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.GD0003.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.GD0003.cs
index 15c1e03801..83e9094a25 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.GD0003.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.GD0003.cs
@@ -1,18 +1,18 @@
using Godot;
-partial class Generic<T> : GodotObject
+public partial class Generic<T> : GodotObject
{
private int _field;
}
// Generic again but different generic parameters
-partial class {|GD0003:Generic|}<T, R> : GodotObject
+public partial class {|GD0003:Generic|}<T, R> : GodotObject
{
private int _field;
}
// Generic again but without generic parameters
-partial class {|GD0003:Generic|} : GodotObject
+public partial class {|GD0003:Generic|} : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.cs
index 5a83e21e96..ce8a7fe218 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/Generic.cs
@@ -1,6 +1,6 @@
using Godot;
-partial class Generic<T> : GodotObject
+public partial class Generic<T> : GodotObject
{
private int _field;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MixedReadOnlyWriteOnly.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MixedReadOnlyWriteOnly.cs
index 61a48cefc9..190a3fb256 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MixedReadOnlyWriteOnly.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MixedReadOnlyWriteOnly.cs
@@ -2,11 +2,11 @@ using Godot;
public partial class MixedReadOnlyWriteOnly : GodotObject
{
- public readonly string readonly_field = "foo";
- public string readonly_auto_property { get; } = "foo";
- public string readonly_property { get => "foo"; }
- public string initonly_auto_property { get; init; }
+ public readonly string ReadOnlyField = "foo";
+ public string ReadOnlyAutoProperty { get; } = "foo";
+ public string ReadOnlyProperty { get => "foo"; }
+ public string InitOnlyAutoProperty { get; init; }
- bool writeonly_backing_field = false;
- public bool writeonly_property { set => writeonly_backing_field = value; }
+ bool _writeOnlyBackingField = false;
+ public bool WriteOnlyProperty { set => _writeOnlyBackingField = value; }
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MoreExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MoreExportedFields.cs
index 47063a9cdf..0cf462f799 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MoreExportedFields.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MoreExportedFields.cs
@@ -4,5 +4,5 @@ using System;
public partial class ExportedFields : GodotObject
{
// Note we use Array and not System.Array. This tests the generated namespace qualification.
- [Export] private Int64[] field_empty_Int64Array = Array.Empty<Int64>();
+ [Export] private Int64[] _fieldEmptyInt64Array = Array.Empty<Int64>();
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ScriptBoilerplate.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ScriptBoilerplate.cs
index 5506465b92..b431522e7c 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ScriptBoilerplate.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ScriptBoilerplate.cs
@@ -24,7 +24,7 @@ public partial class ScriptBoilerplate : Node
}
}
-partial struct OuterClass
+public partial struct OuterClass
{
public partial class NestedClass : RefCounted
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
index 35db0d6f10..9784bd0b78 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -9,7 +9,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Godot.SourceGenerators
{
- static class ExtensionMethods
+ internal static class ExtensionMethods
{
public static bool TryGetGlobalAnalyzerProperty(
this GeneratorExecutionContext context, string property, out string? value
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GlobalClassAnalyzer.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GlobalClassAnalyzer.cs
index 77530ea049..22af25b9c4 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GlobalClassAnalyzer.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GlobalClassAnalyzer.cs
@@ -1,9 +1,7 @@
using System.Collections.Immutable;
using System.Linq;
-
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Godot.SourceGenerators
@@ -23,10 +21,8 @@ namespace Godot.SourceGenerators
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
}
- private void AnalyzeNode(SyntaxNodeAnalysisContext context)
+ private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
- var typeClassDecl = (ClassDeclarationSyntax)context.Node;
-
// Return if not a type symbol or the type is not a global class.
if (context.ContainingSymbol is not INamedTypeSymbol typeSymbol ||
!typeSymbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotGlobalClassAttribute() ?? false))
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
index f837dcd810..f314f7dada 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs
@@ -171,7 +171,7 @@ namespace Godot.SourceGenerators
if (godotClassMethods.Length > 0)
{
- const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string ListType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" /// <summary>\n")
.Append(" /// Get the method information for all the methods declared in this class.\n")
@@ -182,11 +182,11 @@ namespace Godot.SourceGenerators
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
source.Append(" internal new static ")
- .Append(listType)
+ .Append(ListType)
.Append(" GetGodotMethodList()\n {\n");
source.Append(" var methods = new ")
- .Append(listType)
+ .Append(ListType)
.Append("(")
.Append(godotClassMethods.Length)
.Append(");\n");
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index ecd208e38e..a0e410e31a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -246,7 +246,7 @@ namespace Godot.SourceGenerators
}
// Generate GetGodotPropertyList
- const string dictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
+ const string DictionaryType = "global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
source.Append(" /// <summary>\n")
.Append(" /// Get the property information for all the properties declared in this class.\n")
@@ -257,11 +257,11 @@ namespace Godot.SourceGenerators
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
source.Append(" internal new static ")
- .Append(dictionaryType)
+ .Append(DictionaryType)
.Append(" GetGodotPropertyList()\n {\n");
source.Append(" var properties = new ")
- .Append(dictionaryType)
+ .Append(DictionaryType)
.Append("();\n");
// To retain the definition order (and display categories correctly), we want to
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
index 0ec0a0827c..d13a828875 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs
@@ -351,7 +351,7 @@ namespace Godot.SourceGenerators
{
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- const string dictionaryType =
+ const string DictionaryType =
"global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>";
source.Append("#if TOOLS\n");
@@ -366,11 +366,11 @@ namespace Godot.SourceGenerators
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
source.Append(" internal new static ");
- source.Append(dictionaryType);
+ source.Append(DictionaryType);
source.Append(" GetGodotPropertyDefaultValues()\n {\n");
source.Append(" var values = new ");
- source.Append(dictionaryType);
+ source.Append(DictionaryType);
source.Append("(");
source.Append(exportedMembers.Count);
source.Append(");\n");
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index ff8422ea09..107bd93faa 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
@@ -225,7 +225,7 @@ namespace Godot.SourceGenerators
if (godotSignalDelegates.Count > 0)
{
- const string listType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
+ const string ListType = "global::System.Collections.Generic.List<global::Godot.Bridge.MethodInfo>";
source.Append(" /// <summary>\n")
.Append(" /// Get the signal information for all the signals declared in this class.\n")
@@ -236,11 +236,11 @@ namespace Godot.SourceGenerators
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
source.Append(" internal new static ")
- .Append(listType)
+ .Append(ListType)
.Append(" GetGodotSignalList()\n {\n");
source.Append(" var signals = new ")
- .Append(listType)
+ .Append(ListType)
.Append("(")
.Append(godotSignalDelegates.Count)
.Append(");\n");
diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs
index 3072ca2857..5bf07f626b 100644
--- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs
@@ -210,7 +210,7 @@ namespace GodotTools.OpenVisualStudio
return null;
}
- static string NormalizePath(string path)
+ private static string NormalizePath(string path)
{
return new Uri(Path.GetFullPath(path)).LocalPath
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
index 90c443ebb8..175bb78051 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
@@ -1,3 +1,6 @@
+#pragma warning disable IDE1006 // Naming rule violation
+// ReSharper disable InconsistentNaming
+
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
@@ -8,7 +11,6 @@ using GodotTools.IdeMessaging.Requests;
namespace GodotTools.Internals
{
- [SuppressMessage("ReSharper", "InconsistentNaming")]
[GenerateUnmanagedCallbacks(typeof(InternalUnmanagedCallbacks))]
internal static partial class Internal
{
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 7960a1ad5b..0a9162bd28 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1538,7 +1538,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append("namespace " BINDINGS_NAMESPACE ";\n\n");
- p_output.append("public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n{");
+ p_output.append("public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" OPEN_BLOCK);
for (const ConstantInterface &iconstant : global_constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
@@ -1589,50 +1589,48 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
_log("Declaring global enum '%s' inside struct '%s'\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data());
- p_output.append("\npublic partial struct ");
- p_output.append(enum_class_name);
- p_output.append("\n" OPEN_BLOCK);
+ p_output << "\npublic partial struct " << enum_class_name << "\n" OPEN_BLOCK;
}
+ const String maybe_indent = !enum_in_static_class ? "" : INDENT1;
+
if (ienum.is_flags) {
- p_output.append("\n[System.Flags]");
+ p_output << "\n"
+ << maybe_indent << "[System.Flags]";
}
- p_output.append("\npublic enum ");
- p_output.append(enum_proxy_name);
- p_output.append(" : long");
- p_output.append("\n" OPEN_BLOCK);
+ p_output << "\n"
+ << maybe_indent << "public enum " << enum_proxy_name << " : long"
+ << "\n"
+ << maybe_indent << OPEN_BLOCK;
- const ConstantInterface &last = ienum.constants.back()->get();
for (const ConstantInterface &iconstant : ienum.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- p_output.append(INDENT1 "/// <summary>\n");
+ p_output << maybe_indent << INDENT1 "/// <summary>\n";
for (int i = 0; i < summary_lines.size(); i++) {
- p_output.append(INDENT1 "/// ");
- p_output.append(summary_lines[i]);
- p_output.append("\n");
+ p_output << maybe_indent << INDENT1 "/// " << summary_lines[i] << "\n";
}
- p_output.append(INDENT1 "/// </summary>\n");
+ p_output << maybe_indent << INDENT1 "/// </summary>\n";
}
}
- p_output.append(INDENT1);
- p_output.append(iconstant.proxy_name);
- p_output.append(" = ");
- p_output.append(itos(iconstant.value));
- p_output.append(&iconstant != &last ? ",\n" : "\n");
+ p_output << maybe_indent << INDENT1
+ << iconstant.proxy_name
+ << " = "
+ << itos(iconstant.value)
+ << ",\n";
}
- p_output.append(CLOSE_BLOCK);
+ p_output << maybe_indent << CLOSE_BLOCK;
if (enum_in_static_class) {
- p_output.append(CLOSE_BLOCK);
+ p_output << CLOSE_BLOCK;
}
}
}
@@ -2162,7 +2160,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output << MEMBER_BEGIN "public " << itype.proxy_name << "() : this("
<< (itype.memory_own ? "true" : "false") << ")\n" OPEN_BLOCK_L1
<< INDENT2 "unsafe\n" INDENT2 OPEN_BLOCK
- << INDENT3 "_ConstructAndInitialize(" CS_STATIC_FIELD_NATIVE_CTOR ", "
+ << INDENT3 "ConstructAndInitialize(" CS_STATIC_FIELD_NATIVE_CTOR ", "
<< BINDINGS_NATIVE_NAME_FIELD ", CachedType, refCounted: "
<< (itype.is_ref_counted ? "true" : "false") << ");\n"
<< CLOSE_BLOCK_L2 CLOSE_BLOCK_L1;
@@ -2171,7 +2169,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output << MEMBER_BEGIN "internal " << itype.proxy_name << "() : this("
<< (itype.memory_own ? "true" : "false") << ")\n" OPEN_BLOCK_L1
<< INDENT2 "unsafe\n" INDENT2 OPEN_BLOCK
- << INDENT3 "_ConstructAndInitialize(null, "
+ << INDENT3 "ConstructAndInitialize(null, "
<< BINDINGS_NATIVE_NAME_FIELD ", CachedType, refCounted: "
<< (itype.is_ref_counted ? "true" : "false") << ");\n"
<< CLOSE_BLOCK_L2 CLOSE_BLOCK_L1;
@@ -2180,7 +2178,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add.. em.. trick constructor. Sort of.
output.append(MEMBER_BEGIN "internal ");
output.append(itype.proxy_name);
- output.append("(bool " CS_PARAM_MEMORYOWN ") : base(" CS_PARAM_MEMORYOWN ") {}\n");
+ output.append("(bool " CS_PARAM_MEMORYOWN ") : base(" CS_PARAM_MEMORYOWN ") { }\n");
}
}
@@ -2241,6 +2239,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
<< INDENT1 "/// <param name=\"args\">Arguments to use with the invoked method.</param>\n"
<< INDENT1 "/// <param name=\"ret\">Value returned by the invoked method.</param>\n";
+ // Avoid raising diagnostics because of calls to obsolete methods.
+ output << "#pragma warning disable CS0618 // Member is obsolete\n";
+
output << INDENT1 "protected internal " << (is_derived_type ? "override" : "virtual")
<< " bool " CS_METHOD_INVOKE_GODOT_CLASS_METHOD "(in godot_string_name method, "
<< "NativeVariantPtrArgs args, out godot_variant ret)\n"
@@ -2319,6 +2320,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output << INDENT1 "}\n";
+ output << "#pragma warning restore CS0618\n";
+
// Generate HasGodotClassMethod
output << MEMBER_BEGIN "/// <summary>\n"
@@ -2969,7 +2972,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
ERR_FAIL_NULL_V(arg_type, ERR_BUG); // Argument type not found
if (idx != 0) {
- p_output << ",";
+ p_output << ", ";
}
p_output << sformat(arg_type->cs_variant_to_managed,
@@ -3568,7 +3571,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.is_deprecated = itype.class_doc->is_deprecated;
itype.deprecation_message = itype.class_doc->deprecated_message;
- if (itype.deprecation_message.is_empty()) {
+ if (itype.is_deprecated && itype.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Type: '" + itype.proxy_name + "'.");
itype.deprecation_message = "This class is deprecated.";
}
@@ -3652,7 +3655,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iprop.is_deprecated = iprop.prop_doc->is_deprecated;
iprop.deprecation_message = iprop.prop_doc->deprecated_message;
- if (iprop.deprecation_message.is_empty()) {
+ if (iprop.is_deprecated && iprop.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Property: '" + itype.proxy_name + "." + iprop.proxy_name + "'.");
iprop.deprecation_message = "This property is deprecated.";
}
@@ -3841,7 +3844,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
imethod.is_deprecated = imethod.method_doc->is_deprecated;
imethod.deprecation_message = imethod.method_doc->deprecated_message;
- if (imethod.deprecation_message.is_empty()) {
+ if (imethod.is_deprecated && imethod.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Method: '" + itype.proxy_name + "." + imethod.proxy_name + "'.");
imethod.deprecation_message = "This method is deprecated.";
}
@@ -3957,7 +3960,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
isignal.is_deprecated = isignal.method_doc->is_deprecated;
isignal.deprecation_message = isignal.method_doc->deprecated_message;
- if (isignal.deprecation_message.is_empty()) {
+ if (isignal.is_deprecated && isignal.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Signal: '" + itype.proxy_name + "." + isignal.proxy_name + "'.");
isignal.deprecation_message = "This signal is deprecated.";
}
@@ -4007,7 +4010,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iconstant.is_deprecated = iconstant.const_doc->is_deprecated;
iconstant.deprecation_message = iconstant.const_doc->deprecated_message;
- if (iconstant.deprecation_message.is_empty()) {
+ if (iconstant.is_deprecated && iconstant.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Enum member: '" + itype.proxy_name + "." + ienum.proxy_name + "." + iconstant.proxy_name + "'.");
iconstant.deprecation_message = "This enum member is deprecated.";
}
@@ -4059,7 +4062,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iconstant.is_deprecated = iconstant.const_doc->is_deprecated;
iconstant.deprecation_message = iconstant.const_doc->deprecated_message;
- if (iconstant.deprecation_message.is_empty()) {
+ if (iconstant.is_deprecated && iconstant.deprecation_message.is_empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Constant: '" + itype.proxy_name + "." + iconstant.proxy_name + "'.");
iconstant.deprecation_message = "This constant is deprecated.";
}
diff --git a/modules/mono/glue/GodotSharp/.editorconfig b/modules/mono/glue/GodotSharp/.editorconfig
index 987e6c543b..0d9a88ecb8 100644
--- a/modules/mono/glue/GodotSharp/.editorconfig
+++ b/modules/mono/glue/GodotSharp/.editorconfig
@@ -1,18 +1,37 @@
+# This file should only contain severity override to diagnostics, in order to make generated and
+# interop code compilation readable. We want to limit the scope of suppression as much as possible.
+
[**/Generated/**.cs]
+# IDE1006: Naming rule violation
+dotnet_diagnostic.IDE1006.severity = none
# CA1062: Validate parameter is non-null before using it
# Useful for generated code, as it disables nullable
dotnet_diagnostic.CA1062.severity = error
# CA1069: Enums should not have duplicate values
dotnet_diagnostic.CA1069.severity = none
+# CA1707: Identifiers should not contain underscores
+dotnet_diagnostic.CA1707.severity = none
# CA1708: Identifiers should differ by more than case
dotnet_diagnostic.CA1708.severity = none
+# CA1711: Identifiers should not have incorrect suffix
+# Disable warning for suffixes like EventHandler, Flags, Enum, etc.
+dotnet_diagnostic.CA1711.severity = none
# CA1716: Identifiers should not match keywords
# This is suppressed, because it will report `@event` as well as `event`
dotnet_diagnostic.CA1716.severity = none
+# CA1720: Identifiers should not contain type names
+dotnet_diagnostic.CA1720.severity = none
# CS1591: Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS1591.severity = none
# CS1573: Parameter has no matching param tag in the XML comment
dotnet_diagnostic.CS1573.severity = none
+# TODO: Temporary change to not pollute the warnings, but this denotes with ou doc generation
+# CS1734: XML comment on '' has a paramref tag for '', but there is no parameter by that name
+dotnet_diagnostic.CS1734.severity = none
+
+[GodotSharp/Core/NativeInterop/**.cs]
+# CA1720: Identifiers should not contain type names
+dotnet_diagnostic.CA1720.severity = none
[GodotSharp/Core/**.cs]
# CS1591: Missing XML comment for publicly visible type or member
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
index 750e11777d..f3f6759e1d 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
@@ -387,7 +387,7 @@ using Godot.NativeInterop;
}
private static bool IsGodotInteropStruct(ITypeSymbol type) =>
- GodotInteropStructs.Contains(type.FullQualifiedNameOmitGlobal());
+ _godotInteropStructs.Contains(type.FullQualifiedNameOmitGlobal());
private static bool IsByRefParameter(IParameterSymbol parameter) =>
parameter.RefKind is RefKind.In or RefKind.Out or RefKind.Ref;
@@ -448,7 +448,7 @@ using Godot.NativeInterop;
source.Append(";\n");
}
- private static readonly string[] GodotInteropStructs =
+ private static readonly string[] _godotInteropStructs =
{
"Godot.NativeInterop.godot_ref",
"Godot.NativeInterop.godot_variant_call_error",
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs b/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs
index daaf4730fd..4e80afc4a5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs
@@ -8,6 +8,8 @@ using System.ComponentModel;
namespace Godot;
#pragma warning disable CS1734 // XML comment on 'X' has a paramref tag for 'Y', but there is no parameter by that name.
+// TODO: This is currently disabled because of https://github.com/dotnet/roslyn/issues/52904
+#pragma warning disable IDE0040 // Add accessibility modifiers.
partial class AnimationNode
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index fa74d5e101..9b5aec7031 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -151,7 +151,6 @@ namespace Godot.Collections
// from derived types (e.g.: Node[]). Implicit conversion from Derived[] to Base[] are
// fine as long as the array is not mutated. However, Span does this type checking at
// instantiation, so it's not possible to use it even when not mutating anything.
- // ReSharper disable once RedundantNameQualifier
/// <summary>
/// Constructs a new <see cref="Array"/> from the given ReadOnlySpan's elements.
/// </summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs
index 6a73d6f70c..c53e964156 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RpcAttribute.cs
@@ -19,7 +19,7 @@ namespace Godot
/// <summary>
/// If the method will also be called locally; otherwise, it is only called remotely.
/// </summary>
- public bool CallLocal { get; init; } = false;
+ public bool CallLocal { get; init; }
/// <summary>
/// Transfer mode for the annotated method.
@@ -29,7 +29,7 @@ namespace Godot
/// <summary>
/// Transfer channel for the annotated mode.
/// </summary>
- public int TransferChannel { get; init; } = 0;
+ public int TransferChannel { get; init; }
/// <summary>
/// Constructs a <see cref="RpcAttribute"/> instance.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/AlcReloadCfg.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/AlcReloadCfg.cs
index ac2e2fae3c..af1f4860cd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/AlcReloadCfg.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/AlcReloadCfg.cs
@@ -2,7 +2,7 @@ namespace Godot.Bridge;
public static class AlcReloadCfg
{
- private static bool _configured = false;
+ private static bool _configured;
public static void Configure(bool alcReloadEnabled)
{
@@ -14,5 +14,5 @@ public static class AlcReloadCfg
IsAlcReloadingEnabled = alcReloadEnabled;
}
- internal static bool IsAlcReloadingEnabled = false;
+ internal static bool IsAlcReloadingEnabled;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index 0f271d6547..1b23276bbd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -30,7 +30,8 @@ namespace Godot.Bridge
foreach (var type in typesInAlc.Keys)
{
if (_scriptTypeBiMap.RemoveByScriptType(type, out IntPtr scriptPtr) &&
- (!_pathTypeBiMap.TryGetScriptPath(type, out string? scriptPath) || scriptPath.StartsWith("csharp://")))
+ (!_pathTypeBiMap.TryGetScriptPath(type, out string? scriptPath) ||
+ scriptPath.StartsWith("csharp://", StringComparison.Ordinal)))
{
// For scripts without a path, we need to keep the class qualified name for reloading
_scriptDataForReload.TryAdd(scriptPtr,
@@ -584,7 +585,7 @@ namespace Godot.Bridge
// (every Resource must have a unique path). So we create a unique "virtual" path
// for each type.
- if (!scriptPath.StartsWith("res://"))
+ if (!scriptPath.StartsWith("res://", StringComparison.Ordinal))
{
throw new ArgumentException("Script path must start with 'res://'.", nameof(scriptPath));
}
@@ -597,7 +598,7 @@ namespace Godot.Bridge
{
// This path is slower, but it's only executed for the first instantiation of the type
- if (scriptType.IsConstructedGenericType && !scriptPath.StartsWith("csharp://"))
+ if (scriptType.IsConstructedGenericType && !scriptPath.StartsWith("csharp://", StringComparison.Ordinal))
{
// If the script type is generic it can't be loaded using the real script path.
// Construct a virtual path unique to this constructed generic type and add it
@@ -700,7 +701,6 @@ namespace Godot.Bridge
return godot_bool.False;
}
- // ReSharper disable once RedundantNameQualifier
if (!typeof(GodotObject).IsAssignableFrom(scriptType))
{
// The class no longer inherits GodotObject, can't reload
@@ -1007,8 +1007,9 @@ namespace Godot.Bridge
return (List<MethodInfo>?)getGodotMethodListMethod.Invoke(null, null);
}
+#pragma warning disable IDE1006 // Naming rule violation
// ReSharper disable once InconsistentNaming
- [SuppressMessage("ReSharper", "NotAccessedField.Local")]
+ // ReSharper disable once NotAccessedField.Local
[StructLayout(LayoutKind.Sequential)]
private ref struct godotsharp_property_info
{
@@ -1025,6 +1026,7 @@ namespace Godot.Bridge
HintString.Dispose();
}
}
+#pragma warning restore IDE1006
[UnmanagedCallersOnly]
internal static unsafe void GetPropertyInfoList(IntPtr scriptPtr,
@@ -1063,9 +1065,9 @@ namespace Godot.Bridge
int length = properties.Count;
// There's no recursion here, so it's ok to go with a big enough number for most cases
- // stackMaxSize = stackMaxLength * sizeof(godotsharp_property_info)
- const int stackMaxLength = 32;
- bool useStack = length < stackMaxLength;
+ // StackMaxSize = StackMaxLength * sizeof(godotsharp_property_info)
+ const int StackMaxLength = 32;
+ bool useStack = length < StackMaxLength;
godotsharp_property_info* interopProperties;
@@ -1073,7 +1075,7 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_info[stackMaxLength];
+ var aux = stackalloc godotsharp_property_info[StackMaxLength];
interopProperties = aux;
}
else
@@ -1124,8 +1126,9 @@ namespace Godot.Bridge
}
}
+#pragma warning disable IDE1006 // Naming rule violation
// ReSharper disable once InconsistentNaming
- [SuppressMessage("ReSharper", "NotAccessedField.Local")]
+ // ReSharper disable once NotAccessedField.Local
[StructLayout(LayoutKind.Sequential)]
private ref struct godotsharp_property_def_val_pair
{
@@ -1133,6 +1136,7 @@ namespace Godot.Bridge
public godot_string_name Name; // Not owned
public godot_variant Value; // Not owned
}
+#pragma warning restore IDE1006
private delegate bool InvokeGodotClassStaticMethodDelegate(in godot_string_name method, NativeVariantPtrArgs args, out godot_variant ret);
@@ -1252,9 +1256,9 @@ namespace Godot.Bridge
int length = defaultValues.Count;
// There's no recursion here, so it's ok to go with a big enough number for most cases
- // stackMaxSize = stackMaxLength * sizeof(godotsharp_property_def_val_pair)
- const int stackMaxLength = 32;
- bool useStack = length < stackMaxLength;
+ // StackMaxSize = StackMaxLength * sizeof(godotsharp_property_def_val_pair)
+ const int StackMaxLength = 32;
+ bool useStack = length < StackMaxLength;
godotsharp_property_def_val_pair* interopDefaultValues;
@@ -1262,7 +1266,7 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
- var aux = stackalloc godotsharp_property_def_val_pair[stackMaxLength];
+ var aux = stackalloc godotsharp_property_def_val_pair[StackMaxLength];
interopDefaultValues = aux;
}
else
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index c29a0f2bd8..72a3fe3ed0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -38,7 +38,9 @@ namespace Godot
public float B;
/// <summary>
- /// The color's alpha (transparency) component, typically on the range of 0 to 1.
+ /// The color's alpha component, typically on the range of 0 to 1.
+ /// A value of 0 means that the color is fully transparent.
+ /// A value of 1 means that the color is fully opaque.
/// </summary>
public float A;
@@ -534,7 +536,11 @@ namespace Godot
/// <param name="r">The color's red component, typically on the range of 0 to 1.</param>
/// <param name="g">The color's green component, typically on the range of 0 to 1.</param>
/// <param name="b">The color's blue component, typically on the range of 0 to 1.</param>
- /// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
+ /// <param name="a">
+ /// The color's alpha value, typically on the range of 0 to 1.
+ /// A value of 0 means that the color is fully transparent.
+ /// A value of 1 means that the color is fully opaque.
+ /// </param>
public Color(float r, float g, float b, float a = 1.0f)
{
R = r;
@@ -547,7 +553,11 @@ namespace Godot
/// Constructs a <see cref="Color"/> from an existing color and an alpha value.
/// </summary>
/// <param name="c">The color to construct from. Only its RGB values are used.</param>
- /// <param name="a">The color's alpha (transparency) value, typically on the range of 0 to 1. Default: 1.</param>
+ /// <param name="a">
+ /// The color's alpha value, typically on the range of 0 to 1.
+ /// A value of 0 means that the color is fully transparent.
+ /// A value of 1 means that the color is fully opaque.
+ /// </param>
public Color(Color c, float a = 1.0f)
{
R = c.R;
@@ -784,7 +794,7 @@ namespace Godot
name = name.Replace(".", string.Empty, StringComparison.Ordinal);
name = name.ToUpperInvariant();
- return Colors.namedColors.TryGetValue(name, out color);
+ return Colors.NamedColors.TryGetValue(name, out color);
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
index 44b1c2554c..5cb16fc385 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
@@ -9,7 +9,7 @@ namespace Godot
public static class Colors
{
// Color names and values are derived from core/math/color_names.inc
- internal static readonly Dictionary<string, Color> namedColors = new Dictionary<string, Color> {
+ internal static readonly Dictionary<string, Color> NamedColors = new Dictionary<string, Color> {
{ "ALICEBLUE", Colors.AliceBlue },
{ "ANTIQUEWHITE", Colors.AntiqueWhite },
{ "AQUA", Colors.Aqua },
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/CustomGCHandle.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/CustomGCHandle.cs
index 42f19ace1a..28a4e1bc76 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/CustomGCHandle.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/CustomGCHandle.cs
@@ -26,7 +26,6 @@ public static class CustomGCHandle
[MethodImpl(MethodImplOptions.NoInlining)]
public static bool IsAlcBeingUnloaded(AssemblyLoadContext alc) => _alcsBeingUnloaded.TryGetValue(alc, out _);
- // ReSharper disable once RedundantNameQualifier
private static ConcurrentDictionary<
AssemblyLoadContext,
ConcurrentDictionary<GCHandle, object>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs
index 57b292793a..0d96a9a5c1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs
@@ -62,8 +62,9 @@ namespace Godot
Trace.Listeners.Add(new GodotTraceListener());
}
- [StructLayout(LayoutKind.Sequential)]
+#pragma warning disable IDE1006 // Naming rule violation
// ReSharper disable once InconsistentNaming
+ [StructLayout(LayoutKind.Sequential)]
internal ref struct godot_stack_info
{
public godot_string File;
@@ -71,8 +72,8 @@ namespace Godot
public int Line;
}
- [StructLayout(LayoutKind.Sequential)]
// ReSharper disable once InconsistentNaming
+ [StructLayout(LayoutKind.Sequential)]
internal ref struct godot_stack_info_vector
{
private IntPtr _writeProxy;
@@ -101,6 +102,7 @@ namespace Godot
_ptr = null;
}
}
+#pragma warning restore IDE1006
internal static unsafe StackFrame? GetCurrentStackFrame(int skipFrames = 0)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index fc6e7a3ebe..c680142638 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -141,7 +141,6 @@ namespace Godot
return true;
}
}
- // ReSharper disable once RedundantNameQualifier
case GodotObject godotObject:
{
using (var stream = new MemoryStream())
@@ -414,7 +413,6 @@ namespace Godot
case TargetKind.GodotObject:
{
ulong objectId = reader.ReadUInt64();
- // ReSharper disable once RedundantNameQualifier
GodotObject? godotObject = GodotObject.InstanceFromId(objectId);
if (godotObject == null)
return false;
@@ -495,7 +493,7 @@ namespace Godot
string methodName = reader.ReadString();
- int flags = reader.ReadInt32();
+ BindingFlags flags = (BindingFlags)reader.ReadInt32();
bool hasReturn = reader.ReadBoolean();
Type? returnType = hasReturn ? DeserializeType(reader) : typeof(void);
@@ -511,7 +509,11 @@ namespace Godot
parameterTypes[i] = parameterType;
}
- methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags, null, parameterTypes, null);
+#pragma warning disable REFL045 // These flags are insufficient to match any members
+ // TODO: Suppressing invalid warning, remove when issue is fixed
+ // https://github.com/DotNetAnalyzers/ReflectionAnalyzers/issues/209
+ methodInfo = declaringType.GetMethod(methodName, flags, null, parameterTypes, null);
+#pragma warning restore REFL045
return methodInfo != null && methodInfo.ReturnType == returnType;
}
@@ -588,7 +590,6 @@ namespace Godot
internal static class RuntimeTypeConversionHelper
{
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
public static godot_variant ConvertToVariant(object? obj)
{
if (obj == null)
@@ -713,10 +714,8 @@ namespace Godot
private delegate object? ConvertToSystemObjectFunc(in godot_variant managed);
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
- // ReSharper disable once RedundantNameQualifier
private static readonly System.Collections.Generic.Dictionary<Type, ConvertToSystemObjectFunc>
- ToSystemObjectFuncByType = new()
+ _toSystemObjectFuncByType = new()
{
[typeof(bool)] = (in godot_variant variant) => VariantUtils.ConvertTo<bool>(variant),
[typeof(char)] = (in godot_variant variant) => VariantUtils.ConvertTo<char>(variant),
@@ -771,10 +770,9 @@ namespace Godot
[typeof(Variant)] = (in godot_variant variant) => VariantUtils.ConvertTo<Variant>(variant),
};
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
public static object? ConvertToObjectOfType(in godot_variant variant, Type type)
{
- if (ToSystemObjectFuncByType.TryGetValue(type, out var func))
+ if (_toSystemObjectFuncByType.TryGetValue(type, out var func))
return func(variant);
if (typeof(GodotObject).IsAssignableFrom(type))
@@ -838,8 +836,7 @@ namespace Godot
if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>))
{
- var ctor = type.GetConstructor(BindingFlags.Default,
- new[] { typeof(Godot.Collections.Dictionary) });
+ var ctor = type.GetConstructor(new[] { typeof(Godot.Collections.Dictionary) });
if (ctor == null)
throw new InvalidOperationException("Dictionary constructor not found");
@@ -852,8 +849,7 @@ namespace Godot
if (genericTypeDef == typeof(Godot.Collections.Array<>))
{
- var ctor = type.GetConstructor(BindingFlags.Default,
- new[] { typeof(Godot.Collections.Array) });
+ var ctor = type.GetConstructor(new[] { typeof(Godot.Collections.Array) });
if (ctor == null)
throw new InvalidOperationException("Array constructor not found");
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
index 53292e10cf..0ae3e1e130 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs
@@ -59,7 +59,6 @@ namespace Godot
GD.Print("Unloading: Finished disposing tracked instances.");
}
- // ReSharper disable once RedundantNameQualifier
private static ConcurrentDictionary<WeakReference<GodotObject>, byte> GodotObjectInstances { get; } =
new();
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
index 84b2a04276..0be9cdc953 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
@@ -10,8 +10,8 @@ namespace Godot
{
public partial class GodotObject : IDisposable
{
- private bool _disposed = false;
- private static readonly Type CachedType = typeof(GodotObject);
+ private bool _disposed;
+ private static readonly Type _cachedType = typeof(GodotObject);
internal IntPtr NativePtr;
private bool _memoryOwn;
@@ -25,11 +25,11 @@ namespace Godot
{
unsafe
{
- _ConstructAndInitialize(NativeCtor, NativeName, CachedType, refCounted: false);
+ ConstructAndInitialize(NativeCtor, NativeName, _cachedType, refCounted: false);
}
}
- internal unsafe void _ConstructAndInitialize(
+ internal unsafe void ConstructAndInitialize(
delegate* unmanaged<IntPtr> nativeCtor,
StringName nativeName,
Type cachedType,
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index 09269508b7..16d4616fcd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -36,11 +36,11 @@ namespace Godot
public const real_t NaN = real_t.NaN;
// 0.0174532924f and 0.0174532925199433
- private const float _degToRadConstF = (float)0.0174532925199432957692369077M;
- private const double _degToRadConstD = (double)0.0174532925199432957692369077M;
+ private const float DegToRadConstF = (float)0.0174532925199432957692369077M;
+ private const double DegToRadConstD = (double)0.0174532925199432957692369077M;
// 57.29578f and 57.2957795130823
- private const float _radToDegConstF = (float)57.295779513082320876798154814M;
- private const double _radToDegConstD = (double)57.295779513082320876798154814M;
+ private const float RadToDegConstF = (float)57.295779513082320876798154814M;
+ private const double RadToDegConstD = (double)57.295779513082320876798154814M;
/// <summary>
/// Returns the absolute value of <paramref name="s"/> (i.e. positive value).
@@ -760,7 +760,7 @@ namespace Godot
/// <returns>The same angle expressed in radians.</returns>
public static float DegToRad(float deg)
{
- return deg * _degToRadConstF;
+ return deg * DegToRadConstF;
}
/// <summary>
@@ -770,7 +770,7 @@ namespace Godot
/// <returns>The same angle expressed in radians.</returns>
public static double DegToRad(double deg)
{
- return deg * _degToRadConstD;
+ return deg * DegToRadConstD;
}
/// <summary>
@@ -957,10 +957,10 @@ namespace Godot
return true;
}
// Then check for approximate equality.
- float tolerance = _epsilonF * Math.Abs(a);
- if (tolerance < _epsilonF)
+ float tolerance = EpsilonF * Math.Abs(a);
+ if (tolerance < EpsilonF)
{
- tolerance = _epsilonF;
+ tolerance = EpsilonF;
}
return Math.Abs(a - b) < tolerance;
}
@@ -981,10 +981,10 @@ namespace Godot
return true;
}
// Then check for approximate equality.
- double tolerance = _epsilonD * Math.Abs(a);
- if (tolerance < _epsilonD)
+ double tolerance = EpsilonD * Math.Abs(a);
+ if (tolerance < EpsilonD)
{
- tolerance = _epsilonD;
+ tolerance = EpsilonD;
}
return Math.Abs(a - b) < tolerance;
}
@@ -1069,7 +1069,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsZeroApprox(float s)
{
- return Math.Abs(s) < _epsilonF;
+ return Math.Abs(s) < EpsilonF;
}
/// <summary>
@@ -1084,7 +1084,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsZeroApprox(double s)
{
- return Math.Abs(s) < _epsilonD;
+ return Math.Abs(s) < EpsilonD;
}
/// <summary>
@@ -1412,7 +1412,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RadToDeg(float rad)
{
- return rad * _radToDegConstF;
+ return rad * RadToDegConstF;
}
/// <summary>
@@ -1423,7 +1423,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double RadToDeg(double rad)
{
- return rad * _radToDegConstD;
+ return rad * RadToDegConstD;
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
index cc2d61f58d..9020602cb4 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
@@ -21,8 +21,8 @@ namespace Godot
public const real_t Sqrt2 = (real_t)1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
// Epsilon size should depend on the precision used.
- private const float _epsilonF = 1e-06f;
- private const double _epsilonD = 1e-14;
+ private const float EpsilonF = 1e-06f;
+ private const double EpsilonD = 1e-14;
/// <summary>
/// A very small number used for float comparison with error tolerance.
@@ -31,7 +31,7 @@ namespace Godot
#if REAL_T_IS_DOUBLE
public const real_t Epsilon = _epsilonD;
#else
- public const real_t Epsilon = _epsilonF;
+ public const real_t Epsilon = EpsilonF;
#endif
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
index a8642a916c..a019dd3513 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
@@ -1,3 +1,7 @@
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+#pragma warning disable IDE1006 // Naming rule violation
+// ReSharper disable InconsistentNaming
+
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
@@ -24,7 +28,6 @@ namespace Godot.NativeInterop
}
// Apparently a struct with a byte is not blittable? It crashes when calling a UnmanagedCallersOnly function ptr.
- // ReSharper disable once InconsistentNaming
public enum godot_bool : byte
{
True = 1,
@@ -32,7 +35,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_ref
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -62,7 +64,6 @@ namespace Godot.NativeInterop
}
}
- [SuppressMessage("ReSharper", "InconsistentNaming")]
public enum godot_variant_call_error_error
{
GODOT_CALL_ERROR_CALL_OK = 0,
@@ -75,7 +76,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_variant_call_error
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -106,7 +106,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_csharp_type_info
{
private godot_string _className;
@@ -161,7 +160,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_variant
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -176,7 +174,6 @@ namespace Godot.NativeInterop
private godot_variant_data _data;
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
private unsafe ref struct godot_variant_data
{
[FieldOffset(0)] public godot_bool _bool;
@@ -212,7 +209,6 @@ namespace Godot.NativeInterop
[FieldOffset(0)] public godot_array _m_array;
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public struct godot_variant_obj_data
{
public ulong id;
@@ -220,7 +216,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public struct godot_variant_data_mem
{
#pragma warning disable 169
@@ -480,7 +475,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
internal struct movable
{
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
@@ -502,7 +496,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_string
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -534,7 +527,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_string_name
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -590,7 +582,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
internal struct movable
{
private IntPtr _data;
@@ -607,7 +598,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_node_path
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -638,7 +628,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
internal struct movable
{
private IntPtr _data;
@@ -655,7 +644,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_signal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -698,7 +686,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_callable
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -736,7 +723,6 @@ namespace Godot.NativeInterop
// Don't pass a C# default constructed `godot_array` to native code, unless it's going to
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -817,7 +803,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
internal struct movable
{
private unsafe ArrayPrivate* _p;
@@ -838,7 +823,6 @@ namespace Godot.NativeInterop
// Don't pass a C# default constructed `godot_dictionary` to native code, unless it's going to
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
[StructLayout(LayoutKind.Explicit)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_dictionary
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -886,7 +870,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
internal struct movable
{
private unsafe DictionaryPrivate* _p;
@@ -903,7 +886,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_byte_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -935,7 +917,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_int32_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -967,7 +948,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_int64_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -999,7 +979,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_float32_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1031,7 +1010,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_float64_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1063,7 +1041,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_string_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1095,7 +1072,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_vector2_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1127,7 +1103,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_vector3_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1159,7 +1134,6 @@ namespace Godot.NativeInterop
}
[StructLayout(LayoutKind.Sequential)]
- // ReSharper disable once InconsistentNaming
public ref struct godot_packed_color_array
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1190,7 +1164,6 @@ namespace Godot.NativeInterop
}
}
- [SuppressMessage("ReSharper", "InconsistentNaming")]
public enum godot_error_handler_type
{
ERR_HANDLER_ERROR = 0,
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 0cc89d78af..9f7fa53e24 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+
using System;
using System.Runtime.InteropServices;
using Godot.Collections;
@@ -213,13 +215,13 @@ namespace Godot.NativeInterop
if (p_string.Buffer == IntPtr.Zero)
return string.Empty;
- const int sizeOfChar32 = 4;
+ const int SizeOfChar32 = 4;
byte* bytes = (byte*)p_string.Buffer;
int size = p_string.Size;
if (size == 0)
return string.Empty;
size -= 1; // zero at the end
- int sizeInBytes = size * sizeOfChar32;
+ int sizeInBytes = size * SizeOfChar32;
return System.Text.Encoding.UTF32.GetString(bytes, sizeInBytes);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
index d181bf2c0f..fef21fae46 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
@@ -1,9 +1,11 @@
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+#pragma warning disable IDE1006 // Naming rule violation
+// ReSharper disable InconsistentNaming
+
using System;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Godot.SourceGenerators.Internal;
-// ReSharper disable InconsistentNaming
namespace Godot.NativeInterop
{
@@ -16,7 +18,7 @@ namespace Godot.NativeInterop
[GenerateUnmanagedCallbacks(typeof(UnmanagedCallbacks))]
public static unsafe partial class NativeFuncs
{
- private static bool initialized = false;
+ private static bool initialized;
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Global
public static void Initialize(IntPtr unmanagedCallbacks, int unmanagedCallbacksSize)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
index 44ec16dca9..9f237e4d00 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+#pragma warning disable IDE1006 // Naming rule violation
// ReSharper disable InconsistentNaming
namespace Godot.NativeInterop
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
index e6bcd9393d..464b517428 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -1,8 +1,11 @@
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+#pragma warning disable IDE1006 // Naming rule violation
+// ReSharper disable InconsistentNaming
+
using System;
using System.Runtime.CompilerServices;
using Godot.Collections;
-// ReSharper disable InconsistentNaming
#nullable enable
@@ -240,7 +243,6 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromSystemArrayOfRid(Span<Rid> from)
=> CreateFromArray(new Collections.Array(from));
- // ReSharper disable once RedundantNameQualifier
public static godot_variant CreateFromSystemArrayOfGodotObject(GodotObject[]? from)
{
if (from == null)
@@ -306,7 +308,6 @@ namespace Godot.NativeInterop
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- // ReSharper disable once RedundantNameQualifier
public static godot_variant CreateFromGodotObject(GodotObject? from)
=> from != null ? CreateFromGodotObjectPtr(GodotObject.GetPtr(from)) : default;
@@ -459,7 +460,6 @@ namespace Godot.NativeInterop
=> p_var.Type == Variant.Type.Object ? p_var.Object : IntPtr.Zero;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- // ReSharper disable once RedundantNameQualifier
public static GodotObject ConvertToGodotObject(in godot_variant p_var)
=> InteropUtils.UnmanagedGetManaged(ConvertToGodotObjectPtr(p_var));
@@ -615,7 +615,6 @@ namespace Godot.NativeInterop
}
public static T[] ConvertToSystemArrayOfGodotObject<T>(in godot_variant p_var)
- // ReSharper disable once RedundantNameQualifier
where T : GodotObject
{
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
index 12b0a47079..d8f7214c2f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Godot.NativeInterop;
@@ -25,7 +24,6 @@ public partial class VariantUtils
// ReSharper disable once StaticMemberInGenericType
internal static unsafe delegate*<in godot_variant, T> FromVariantCb;
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
static GenericConversion()
{
RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle);
@@ -33,7 +31,6 @@ public partial class VariantUtils
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
public static godot_variant CreateFrom<[MustBeVariant] T>(in T from)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -224,7 +221,6 @@ public partial class VariantUtils
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
- [SuppressMessage("ReSharper", "RedundantNameQualifier")]
public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
index 2aac23d799..c0889fb0e8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -251,10 +251,10 @@ namespace Godot
/// <param name="right">The right clipping distance.</param>
/// <param name="bottom">The bottom clipping distance.</param>
/// <param name="top">The top clipping distance.</param>
- /// <param name="near">The near clipping distance.</param>
- /// <param name="far">The far clipping distance.</param>
+ /// <param name="depthNear">The near clipping distance.</param>
+ /// <param name="depthFar">The far clipping distance.</param>
/// <returns>The created projection.</returns>
- public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t depth_near, real_t depth_far)
+ public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t depthNear, real_t depthFar)
{
if (right <= left)
{
@@ -264,18 +264,18 @@ namespace Godot
{
throw new ArgumentException("top is less or equal to bottom.");
}
- if (depth_far <= depth_near)
+ if (depthFar <= depthNear)
{
throw new ArgumentException("far is less or equal to near.");
}
- real_t x = 2 * depth_near / (right - left);
- real_t y = 2 * depth_near / (top - bottom);
+ real_t x = 2 * depthNear / (right - left);
+ real_t y = 2 * depthNear / (top - bottom);
real_t a = (right + left) / (right - left);
real_t b = (top + bottom) / (top - bottom);
- real_t c = -(depth_far + depth_near) / (depth_far - depth_near);
- real_t d = -2 * depth_far * depth_near / (depth_far - depth_near);
+ real_t c = -(depthFar + depthNear) / (depthFar - depthNear);
+ real_t d = -2 * depthFar * depthNear / (depthFar - depthNear);
return new Projection(
new Vector4(x, 0, 0, 0),
@@ -293,17 +293,17 @@ namespace Godot
/// <param name="size">The frustum size.</param>
/// <param name="aspect">The aspect ratio.</param>
/// <param name="offset">The offset to apply.</param>
- /// <param name="near">The near clipping distance.</param>
- /// <param name="far">The far clipping distance.</param>
+ /// <param name="depthNear">The near clipping distance.</param>
+ /// <param name="depthFar">The far clipping distance.</param>
/// <param name="flipFov">If the field of view is flipped over the projection's diagonal.</param>
/// <returns>The created projection.</returns>
- public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t depth_near, real_t depth_far, bool flipFov)
+ public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t depthNear, real_t depthFar, bool flipFov)
{
if (!flipFov)
{
size *= aspect;
}
- return CreateFrustum(-size / 2 + offset.X, +size / 2 + offset.X, -size / aspect / 2 + offset.Y, +size / aspect / 2 + offset.Y, depth_near, depth_far);
+ return CreateFrustum(-size / 2 + offset.X, +size / 2 + offset.X, -size / aspect / 2 + offset.Y, +size / aspect / 2 + offset.Y, depthNear, depthFar);
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index f249bac69c..9cd5498fa8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -1836,8 +1836,8 @@ namespace Godot
return Uri.EscapeDataString(instance);
}
- private const string _uniqueNodePrefix = "%";
- private static readonly string[] _invalidNodeNameCharacters = { ".", ":", "@", "/", "\"", _uniqueNodePrefix };
+ private const string UniqueNodePrefix = "%";
+ private static readonly string[] _invalidNodeNameCharacters = { ".", ":", "@", "/", "\"", UniqueNodePrefix };
/// <summary>
/// Removes any characters from the string that are prohibited in
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
index 9aad965ad0..036a26328a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Godot.NativeInterop;
@@ -7,7 +6,6 @@ namespace Godot;
#nullable enable
-[SuppressMessage("ReSharper", "RedundantNameQualifier")]
public partial struct Variant : IDisposable
{
internal godot_variant.movable NativeVar;
diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/Compat.cs b/modules/mono/glue/GodotSharp/GodotSharpEditor/Compat.cs
index 7a3bb0df7e..d1289ee6ba 100644
--- a/modules/mono/glue/GodotSharp/GodotSharpEditor/Compat.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/Compat.cs
@@ -7,6 +7,9 @@ using System.ComponentModel;
namespace Godot;
+// TODO: This is currently disabled because of https://github.com/dotnet/roslyn/issues/52904
+#pragma warning disable IDE0040 // Add accessibility modifiers.
+
partial class EditorUndoRedoManager
{
/// <inheritdoc cref="CreateAction(string, UndoRedo.MergeMode, GodotObject, bool)"/>
diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp
index 9fdfb20842..d1ac784103 100644
--- a/modules/navigation/2d/nav_mesh_generator_2d.cpp
+++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp
@@ -35,7 +35,7 @@
#include "core/config/project_settings.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/multimesh_instance_2d.h"
-#include "scene/2d/physics_body_2d.h"
+#include "scene/2d/physics/static_body_2d.h"
#include "scene/2d/polygon_2d.h"
#include "scene/2d/tile_map.h"
#include "scene/resources/2d/capsule_shape_2d.h"
diff --git a/modules/navigation/3d/nav_mesh_generator_3d.cpp b/modules/navigation/3d/nav_mesh_generator_3d.cpp
index 4cd4f60edc..e1ed9c51aa 100644
--- a/modules/navigation/3d/nav_mesh_generator_3d.cpp
+++ b/modules/navigation/3d/nav_mesh_generator_3d.cpp
@@ -37,7 +37,7 @@
#include "core/os/thread.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
#include "scene/resources/3d/box_shape_3d.h"
#include "scene/resources/3d/capsule_shape_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
diff --git a/modules/navigation/nav_agent.h b/modules/navigation/nav_agent.h
index 00b5bc13ab..18997803f2 100644
--- a/modules/navigation/nav_agent.h
+++ b/modules/navigation/nav_agent.h
@@ -31,7 +31,6 @@
#ifndef NAV_AGENT_H
#define NAV_AGENT_H
-#include "nav_agent.h"
#include "nav_rid.h"
#include "core/object/class_db.h"
diff --git a/scene/2d/SCsub b/scene/2d/SCsub
index fc61250247..94e1ab6c96 100644
--- a/scene/2d/SCsub
+++ b/scene/2d/SCsub
@@ -3,3 +3,6 @@
Import("env")
env.add_source_files(env.scene_sources, "*.cpp")
+
+# Chain load SCsubs
+SConscript("physics/SCsub")
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 4762ae28f8..cbd3c244d9 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -32,8 +32,8 @@
#include "audio_stream_player_2d.compat.inc"
#include "core/config/project_settings.h"
-#include "scene/2d/area_2d.h"
#include "scene/2d/audio_listener_2d.h"
+#include "scene/2d/physics/area_2d.h"
#include "scene/audio/audio_stream_player_internal.h"
#include "scene/main/viewport.h"
#include "scene/resources/world_2d.h"
diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp
deleted file mode 100644
index 41b121a482..0000000000
--- a/scene/2d/joint_2d.cpp
+++ /dev/null
@@ -1,564 +0,0 @@
-/**************************************************************************/
-/* joint_2d.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "joint_2d.h"
-
-#include "physics_body_2d.h"
-#include "scene/scene_string_names.h"
-
-void Joint2D::_disconnect_signals() {
- Node *node_a = get_node_or_null(a);
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- if (body_a) {
- body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
- }
-
- Node *node_b = get_node_or_null(b);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
- if (body_b) {
- body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
- }
-}
-
-void Joint2D::_body_exit_tree() {
- _disconnect_signals();
- _update_joint(true);
- update_configuration_warnings();
-}
-
-void Joint2D::_update_joint(bool p_only_free) {
- if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
- PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
- }
-
- ba = RID();
- bb = RID();
- configured = false;
-
- if (p_only_free || !is_inside_tree()) {
- PhysicsServer2D::get_singleton()->joint_clear(joint);
- warning = String();
- return;
- }
-
- Node *node_a = get_node_or_null(a);
- Node *node_b = get_node_or_null(b);
-
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
-
- bool valid = false;
-
- if (node_a && !body_a && node_b && !body_b) {
- warning = RTR("Node A and Node B must be PhysicsBody2Ds");
- } else if (node_a && !body_a) {
- warning = RTR("Node A must be a PhysicsBody2D");
- } else if (node_b && !body_b) {
- warning = RTR("Node B must be a PhysicsBody2D");
- } else if (!body_a || !body_b) {
- warning = RTR("Joint is not connected to two PhysicsBody2Ds");
- } else if (body_a == body_b) {
- warning = RTR("Node A and Node B must be different PhysicsBody2Ds");
- } else {
- warning = String();
- valid = true;
- }
-
- update_configuration_warnings();
-
- if (!valid) {
- PhysicsServer2D::get_singleton()->joint_clear(joint);
- return;
- }
-
- if (body_a) {
- body_a->force_update_transform();
- }
-
- if (body_b) {
- body_b->force_update_transform();
- }
-
- configured = true;
-
- _configure_joint(joint, body_a, body_b);
-
- ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
-
- PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
-
- ba = body_a->get_rid();
- bb = body_b->get_rid();
-
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
-
- PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
-}
-
-void Joint2D::set_node_a(const NodePath &p_node_a) {
- if (a == p_node_a) {
- return;
- }
-
- if (is_configured()) {
- _disconnect_signals();
- }
-
- a = p_node_a;
- if (Engine::get_singleton()->is_editor_hint()) {
- // When in editor, the setter may be called as a result of node rename.
- // It happens before the node actually changes its name, which triggers false warning.
- callable_mp(this, &Joint2D::_update_joint).call_deferred();
- } else {
- _update_joint();
- }
-}
-
-NodePath Joint2D::get_node_a() const {
- return a;
-}
-
-void Joint2D::set_node_b(const NodePath &p_node_b) {
- if (b == p_node_b) {
- return;
- }
-
- if (is_configured()) {
- _disconnect_signals();
- }
-
- b = p_node_b;
- if (Engine::get_singleton()->is_editor_hint()) {
- callable_mp(this, &Joint2D::_update_joint).call_deferred();
- } else {
- _update_joint();
- }
-}
-
-NodePath Joint2D::get_node_b() const {
- return b;
-}
-
-void Joint2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_POST_ENTER_TREE: {
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint();
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint(true);
- } break;
- }
-}
-
-void Joint2D::set_bias(real_t p_bias) {
- bias = p_bias;
- if (joint.is_valid()) {
- PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
- }
-}
-
-real_t Joint2D::get_bias() const {
- return bias;
-}
-
-void Joint2D::set_exclude_nodes_from_collision(bool p_enable) {
- if (exclude_from_collision == p_enable) {
- return;
- }
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint(true);
- exclude_from_collision = p_enable;
- _update_joint();
-}
-
-bool Joint2D::get_exclude_nodes_from_collision() const {
- return exclude_from_collision;
-}
-
-PackedStringArray Joint2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node2D::get_configuration_warnings();
-
- if (!warning.is_empty()) {
- warnings.push_back(warning);
- }
-
- return warnings;
-}
-
-void Joint2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint2D::set_node_a);
- ClassDB::bind_method(D_METHOD("get_node_a"), &Joint2D::get_node_a);
-
- ClassDB::bind_method(D_METHOD("set_node_b", "node"), &Joint2D::set_node_b);
- ClassDB::bind_method(D_METHOD("get_node_b"), &Joint2D::get_node_b);
-
- ClassDB::bind_method(D_METHOD("set_bias", "bias"), &Joint2D::set_bias);
- ClassDB::bind_method(D_METHOD("get_bias"), &Joint2D::get_bias);
-
- ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint2D::set_exclude_nodes_from_collision);
- ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision);
-
- ClassDB::bind_method(D_METHOD("get_rid"), &Joint2D::get_rid);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_a", "get_node_a");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_b", "get_node_b");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,0.9,0.001"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_collision"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
-}
-
-Joint2D::Joint2D() {
- joint = PhysicsServer2D::get_singleton()->joint_create();
- set_hide_clip_children(true);
-}
-
-Joint2D::~Joint2D() {
- ERR_FAIL_NULL(PhysicsServer2D::get_singleton());
- PhysicsServer2D::get_singleton()->free(joint);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-void PinJoint2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_DRAW: {
- if (!is_inside_tree()) {
- break;
- }
-
- if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
- break;
- }
-
- draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(0, -10), Point2(0, +10), Color(0.7, 0.6, 0.0, 0.5), 3);
- } break;
- }
-}
-
-void PinJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
- PhysicsServer2D::get_singleton()->joint_make_pin(p_joint, get_global_position(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
- PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
- PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, angular_limit_upper);
- PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, angular_limit_lower);
- PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
- PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
- PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
-}
-
-void PinJoint2D::set_softness(real_t p_softness) {
- if (softness == p_softness) {
- return;
- }
- softness = p_softness;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_SOFTNESS, p_softness);
- }
-}
-
-real_t PinJoint2D::get_softness() const {
- return softness;
-}
-
-void PinJoint2D::set_angular_limit_lower(real_t p_angular_limit_lower) {
- if (angular_limit_lower == p_angular_limit_lower) {
- return;
- }
- angular_limit_lower = p_angular_limit_lower;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, p_angular_limit_lower);
- }
-}
-
-real_t PinJoint2D::get_angular_limit_lower() const {
- return angular_limit_lower;
-}
-
-void PinJoint2D::set_angular_limit_upper(real_t p_angular_limit_upper) {
- if (angular_limit_upper == p_angular_limit_upper) {
- return;
- }
- angular_limit_upper = p_angular_limit_upper;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, p_angular_limit_upper);
- }
-}
-
-real_t PinJoint2D::get_angular_limit_upper() const {
- return angular_limit_upper;
-}
-
-void PinJoint2D::set_motor_target_velocity(real_t p_motor_target_velocity) {
- if (motor_target_velocity == p_motor_target_velocity) {
- return;
- }
- motor_target_velocity = p_motor_target_velocity;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
- }
-}
-
-real_t PinJoint2D::get_motor_target_velocity() const {
- return motor_target_velocity;
-}
-
-void PinJoint2D::set_motor_enabled(bool p_motor_enabled) {
- if (motor_enabled == p_motor_enabled) {
- return;
- }
- motor_enabled = p_motor_enabled;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
- }
-}
-
-bool PinJoint2D::is_motor_enabled() const {
- return motor_enabled;
-}
-
-void PinJoint2D::set_angular_limit_enabled(bool p_angular_limit_enabled) {
- if (angular_limit_enabled == p_angular_limit_enabled) {
- return;
- }
- angular_limit_enabled = p_angular_limit_enabled;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
- }
-}
-
-bool PinJoint2D::is_angular_limit_enabled() const {
- return angular_limit_enabled;
-}
-
-void PinJoint2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_softness", "softness"), &PinJoint2D::set_softness);
- ClassDB::bind_method(D_METHOD("get_softness"), &PinJoint2D::get_softness);
- ClassDB::bind_method(D_METHOD("set_angular_limit_lower", "angular_limit_lower"), &PinJoint2D::set_angular_limit_lower);
- ClassDB::bind_method(D_METHOD("get_angular_limit_lower"), &PinJoint2D::get_angular_limit_lower);
- ClassDB::bind_method(D_METHOD("set_angular_limit_upper", "angular_limit_upper"), &PinJoint2D::set_angular_limit_upper);
- ClassDB::bind_method(D_METHOD("get_angular_limit_upper"), &PinJoint2D::get_angular_limit_upper);
- ClassDB::bind_method(D_METHOD("set_motor_target_velocity", "motor_target_velocity"), &PinJoint2D::set_motor_target_velocity);
- ClassDB::bind_method(D_METHOD("get_motor_target_velocity"), &PinJoint2D::get_motor_target_velocity);
- ClassDB::bind_method(D_METHOD("set_motor_enabled", "enabled"), &PinJoint2D::set_motor_enabled);
- ClassDB::bind_method(D_METHOD("is_motor_enabled"), &PinJoint2D::is_motor_enabled);
- ClassDB::bind_method(D_METHOD("set_angular_limit_enabled", "enabled"), &PinJoint2D::set_angular_limit_enabled);
- ClassDB::bind_method(D_METHOD("is_angular_limit_enabled"), &PinJoint2D::is_angular_limit_enabled);
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.00,16,0.01,exp"), "set_softness", "get_softness");
- ADD_GROUP("Angular Limit", "angular_limit_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "angular_limit_enabled"), "set_angular_limit_enabled", "is_angular_limit_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_lower", "get_angular_limit_lower");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_upper", "get_angular_limit_upper");
- ADD_GROUP("Motor", "motor_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motor_enabled"), "set_motor_enabled", "is_motor_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motor_target_velocity", PROPERTY_HINT_RANGE, U"-200,200,0.01,or_greater,or_less,radians_as_degrees,suffix:\u00B0/s"), "set_motor_target_velocity", "get_motor_target_velocity");
-}
-
-PinJoint2D::PinJoint2D() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-void GrooveJoint2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_DRAW: {
- if (!is_inside_tree()) {
- break;
- }
-
- if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
- break;
- }
-
- draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(-10, length), Point2(+10, length), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(0, 0), Point2(0, length), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(-10, initial_offset), Point2(+10, initial_offset), Color(0.8, 0.8, 0.9, 0.5), 5);
- } break;
- }
-}
-
-void GrooveJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
- Transform2D gt = get_global_transform();
- Vector2 groove_A1 = gt.get_origin();
- Vector2 groove_A2 = gt.xform(Vector2(0, length));
- Vector2 anchor_B = gt.xform(Vector2(0, initial_offset));
-
- PhysicsServer2D::get_singleton()->joint_make_groove(p_joint, groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
-}
-
-void GrooveJoint2D::set_length(real_t p_length) {
- length = p_length;
- queue_redraw();
-}
-
-real_t GrooveJoint2D::get_length() const {
- return length;
-}
-
-void GrooveJoint2D::set_initial_offset(real_t p_initial_offset) {
- initial_offset = p_initial_offset;
- queue_redraw();
-}
-
-real_t GrooveJoint2D::get_initial_offset() const {
- return initial_offset;
-}
-
-void GrooveJoint2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_length", "length"), &GrooveJoint2D::set_length);
- ClassDB::bind_method(D_METHOD("get_length"), &GrooveJoint2D::get_length);
- ClassDB::bind_method(D_METHOD("set_initial_offset", "offset"), &GrooveJoint2D::set_initial_offset);
- ClassDB::bind_method(D_METHOD("get_initial_offset"), &GrooveJoint2D::get_initial_offset);
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "initial_offset", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_initial_offset", "get_initial_offset");
-}
-
-GrooveJoint2D::GrooveJoint2D() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-void DampedSpringJoint2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_DRAW: {
- if (!is_inside_tree()) {
- break;
- }
-
- if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
- break;
- }
-
- draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(-10, length), Point2(+10, length), Color(0.7, 0.6, 0.0, 0.5), 3);
- draw_line(Point2(0, 0), Point2(0, length), Color(0.7, 0.6, 0.0, 0.5), 3);
- } break;
- }
-}
-
-void DampedSpringJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
- Transform2D gt = get_global_transform();
- Vector2 anchor_A = gt.get_origin();
- Vector2 anchor_B = gt.xform(Vector2(0, length));
-
- PhysicsServer2D::get_singleton()->joint_make_damped_spring(p_joint, anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
- if (rest_length) {
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
- }
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
-}
-
-void DampedSpringJoint2D::set_length(real_t p_length) {
- length = p_length;
- queue_redraw();
-}
-
-real_t DampedSpringJoint2D::get_length() const {
- return length;
-}
-
-void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) {
- rest_length = p_rest_length;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, p_rest_length ? p_rest_length : length);
- }
-}
-
-real_t DampedSpringJoint2D::get_rest_length() const {
- return rest_length;
-}
-
-void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) {
- stiffness = p_stiffness;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_STIFFNESS, p_stiffness);
- }
-}
-
-real_t DampedSpringJoint2D::get_stiffness() const {
- return stiffness;
-}
-
-void DampedSpringJoint2D::set_damping(real_t p_damping) {
- damping = p_damping;
- queue_redraw();
- if (is_configured()) {
- PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_DAMPING, p_damping);
- }
-}
-
-real_t DampedSpringJoint2D::get_damping() const {
- return damping;
-}
-
-void DampedSpringJoint2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_length", "length"), &DampedSpringJoint2D::set_length);
- ClassDB::bind_method(D_METHOD("get_length"), &DampedSpringJoint2D::get_length);
- ClassDB::bind_method(D_METHOD("set_rest_length", "rest_length"), &DampedSpringJoint2D::set_rest_length);
- ClassDB::bind_method(D_METHOD("get_rest_length"), &DampedSpringJoint2D::get_rest_length);
- ClassDB::bind_method(D_METHOD("set_stiffness", "stiffness"), &DampedSpringJoint2D::set_stiffness);
- ClassDB::bind_method(D_METHOD("get_stiffness"), &DampedSpringJoint2D::get_stiffness);
- ClassDB::bind_method(D_METHOD("set_damping", "damping"), &DampedSpringJoint2D::set_damping);
- ClassDB::bind_method(D_METHOD("get_damping"), &DampedSpringJoint2D::get_damping);
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rest_length", PROPERTY_HINT_RANGE, "0,65535,1,exp,suffix:px"), "set_rest_length", "get_rest_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness", PROPERTY_HINT_RANGE, "0.1,64,0.1,exp"), "set_stiffness", "get_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0.01,16,0.01,exp"), "set_damping", "get_damping");
-}
-
-DampedSpringJoint2D::DampedSpringJoint2D() {
-}
diff --git a/scene/2d/joint_2d.h b/scene/2d/joint_2d.h
deleted file mode 100644
index 5ff75a77a1..0000000000
--- a/scene/2d/joint_2d.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/**************************************************************************/
-/* joint_2d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef JOINT_2D_H
-#define JOINT_2D_H
-
-#include "node_2d.h"
-
-class PhysicsBody2D;
-
-class Joint2D : public Node2D {
- GDCLASS(Joint2D, Node2D);
-
- RID joint;
- RID ba, bb;
-
- NodePath a;
- NodePath b;
- real_t bias = 0.0;
-
- bool exclude_from_collision = true;
- bool configured = false;
- String warning;
-
-protected:
- void _disconnect_signals();
- void _body_exit_tree();
- void _update_joint(bool p_only_free = false);
-
- void _notification(int p_what);
- virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
-
- static void _bind_methods();
-
- _FORCE_INLINE_ bool is_configured() const { return configured; }
-
-public:
- virtual PackedStringArray get_configuration_warnings() const override;
-
- void set_node_a(const NodePath &p_node_a);
- NodePath get_node_a() const;
-
- void set_node_b(const NodePath &p_node_b);
- NodePath get_node_b() const;
-
- void set_bias(real_t p_bias);
- real_t get_bias() const;
-
- void set_exclude_nodes_from_collision(bool p_enable);
- bool get_exclude_nodes_from_collision() const;
-
- RID get_rid() const { return joint; }
- Joint2D();
- ~Joint2D();
-};
-
-class PinJoint2D : public Joint2D {
- GDCLASS(PinJoint2D, Joint2D);
-
- real_t softness = 0.0;
- real_t angular_limit_lower = 0.0;
- real_t angular_limit_upper = 0.0;
- real_t motor_target_velocity = 0.0;
- bool motor_enabled = false;
- bool angular_limit_enabled = false;
-
-protected:
- void _notification(int p_what);
- virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_softness(real_t p_softness);
- real_t get_softness() const;
- void set_angular_limit_lower(real_t p_angular_limit_lower);
- real_t get_angular_limit_lower() const;
- void set_angular_limit_upper(real_t p_angular_limit_upper);
- real_t get_angular_limit_upper() const;
- void set_motor_target_velocity(real_t p_motor_target_velocity);
- real_t get_motor_target_velocity() const;
-
- void set_motor_enabled(bool p_motor_enabled);
- bool is_motor_enabled() const;
- void set_angular_limit_enabled(bool p_angular_limit_enabled);
- bool is_angular_limit_enabled() const;
-
- PinJoint2D();
-};
-
-class GrooveJoint2D : public Joint2D {
- GDCLASS(GrooveJoint2D, Joint2D);
-
- real_t length = 50.0;
- real_t initial_offset = 25.0;
-
-protected:
- void _notification(int p_what);
- virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_length(real_t p_length);
- real_t get_length() const;
-
- void set_initial_offset(real_t p_initial_offset);
- real_t get_initial_offset() const;
-
- GrooveJoint2D();
-};
-
-class DampedSpringJoint2D : public Joint2D {
- GDCLASS(DampedSpringJoint2D, Joint2D);
-
- real_t stiffness = 20.0;
- real_t damping = 1.0;
- real_t rest_length = 0.0;
- real_t length = 50.0;
-
-protected:
- void _notification(int p_what);
- virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_length(real_t p_length);
- real_t get_length() const;
-
- void set_rest_length(real_t p_rest_length);
- real_t get_rest_length() const;
-
- void set_damping(real_t p_damping);
- real_t get_damping() const;
-
- void set_stiffness(real_t p_stiffness);
- real_t get_stiffness() const;
-
- DampedSpringJoint2D();
-};
-
-#endif // JOINT_2D_H
diff --git a/scene/2d/physics/SCsub b/scene/2d/physics/SCsub
new file mode 100644
index 0000000000..e7fd3fe643
--- /dev/null
+++ b/scene/2d/physics/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.scene_sources, "*.cpp")
+
+# Chain load SCsubs
+SConscript("joints/SCsub")
diff --git a/scene/2d/physics/animatable_body_2d.cpp b/scene/2d/physics/animatable_body_2d.cpp
new file mode 100644
index 0000000000..10e90e708b
--- /dev/null
+++ b/scene/2d/physics/animatable_body_2d.cpp
@@ -0,0 +1,111 @@
+/**************************************************************************/
+/* animatable_body_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "animatable_body_2d.h"
+
+void AnimatableBody2D::set_sync_to_physics(bool p_enable) {
+ if (sync_to_physics == p_enable) {
+ return;
+ }
+
+ sync_to_physics = p_enable;
+
+ _update_kinematic_motion();
+}
+
+bool AnimatableBody2D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void AnimatableBody2D::_update_kinematic_motion() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ if (sync_to_physics) {
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody2D::_body_state_changed));
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ }
+}
+
+void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
+ if (!sync_to_physics) {
+ return;
+ }
+
+ last_valid_transform = p_state->get_transform();
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+}
+
+void AnimatableBody2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ last_valid_transform = get_global_transform();
+ _update_kinematic_motion();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ // Used by sync to physics, send the new transform to the physics...
+ Transform2D new_transform = get_global_transform();
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+
+ // ... but then revert changes.
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ } break;
+ }
+}
+
+void AnimatableBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
+}
+
+AnimatableBody2D::AnimatableBody2D() :
+ StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
+}
diff --git a/scene/2d/physics/animatable_body_2d.h b/scene/2d/physics/animatable_body_2d.h
new file mode 100644
index 0000000000..e510d5cc9c
--- /dev/null
+++ b/scene/2d/physics/animatable_body_2d.h
@@ -0,0 +1,61 @@
+/**************************************************************************/
+/* animatable_body_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef ANIMATABLE_BODY_2D_H
+#define ANIMATABLE_BODY_2D_H
+
+#include "scene/2d/physics/static_body_2d.h"
+
+class AnimatableBody2D : public StaticBody2D {
+ GDCLASS(AnimatableBody2D, StaticBody2D);
+
+private:
+ bool sync_to_physics = true;
+
+ Transform2D last_valid_transform;
+
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState2D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ AnimatableBody2D();
+
+private:
+ void _update_kinematic_motion();
+
+ void set_sync_to_physics(bool p_enable);
+ bool is_sync_to_physics_enabled() const;
+};
+
+#endif // ANIMATABLE_BODY_2D_H
diff --git a/scene/2d/area_2d.cpp b/scene/2d/physics/area_2d.cpp
index b1ff94dda4..b1ff94dda4 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/physics/area_2d.cpp
diff --git a/scene/2d/area_2d.h b/scene/2d/physics/area_2d.h
index 9d6e04b706..7c59d76e00 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/physics/area_2d.h
@@ -32,7 +32,7 @@
#define AREA_2D_H
#include "core/templates/vset.h"
-#include "scene/2d/collision_object_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
class Area2D : public CollisionObject2D {
GDCLASS(Area2D, CollisionObject2D);
diff --git a/scene/2d/physics/character_body_2d.cpp b/scene/2d/physics/character_body_2d.cpp
new file mode 100644
index 0000000000..e5d575a159
--- /dev/null
+++ b/scene/2d/physics/character_body_2d.cpp
@@ -0,0 +1,755 @@
+/**************************************************************************/
+/* character_body_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "character_body_2d.h"
+
+// So, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
+#define FLOOR_ANGLE_THRESHOLD 0.01
+
+bool CharacterBody2D::move_and_slide() {
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
+ double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
+
+ Vector2 current_platform_velocity = platform_velocity;
+ Transform2D gt = get_global_transform();
+ previous_position = gt.columns[2];
+
+ if ((on_floor || on_wall) && platform_rid.is_valid()) {
+ bool excluded = false;
+ if (on_floor) {
+ excluded = (platform_floor_layers & platform_layer) == 0;
+ } else if (on_wall) {
+ excluded = (platform_wall_layers & platform_layer) == 0;
+ }
+ if (!excluded) {
+ //this approach makes sure there is less delay between the actual body velocity and the one we saved
+ PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid);
+ if (bs) {
+ Vector2 local_position = gt.columns[2] - bs->get_transform().columns[2];
+ current_platform_velocity = bs->get_velocity_at_local_position(local_position);
+ } else {
+ // Body is removed or destroyed, invalidate floor.
+ current_platform_velocity = Vector2();
+ platform_rid = RID();
+ }
+ } else {
+ current_platform_velocity = Vector2();
+ }
+ }
+
+ motion_results.clear();
+ last_motion = Vector2();
+
+ bool was_on_floor = on_floor;
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
+
+ if (!current_platform_velocity.is_zero_approx()) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+ parameters.exclude_bodies.insert(platform_rid);
+ if (platform_object_id.is_valid()) {
+ parameters.exclude_objects.insert(platform_object_id);
+ }
+
+ PhysicsServer2D::MotionResult floor_result;
+ if (move_and_collide(parameters, floor_result, false, false)) {
+ motion_results.push_back(floor_result);
+ _set_collision_direction(floor_result);
+ }
+ }
+
+ if (motion_mode == MOTION_MODE_GROUNDED) {
+ _move_and_slide_grounded(delta, was_on_floor);
+ } else {
+ _move_and_slide_floating(delta);
+ }
+
+ // Compute real velocity.
+ real_velocity = get_position_delta() / delta;
+
+ if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) {
+ // Add last platform velocity when just left a moving platform.
+ if (!on_floor && !on_wall) {
+ if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) {
+ current_platform_velocity = current_platform_velocity.slide(up_direction);
+ }
+ velocity += current_platform_velocity;
+ }
+ }
+
+ return motion_results.size() > 0;
+}
+
+void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
+ Vector2 motion = velocity * p_delta;
+ Vector2 motion_slide_up = motion.slide(up_direction);
+
+ Vector2 prev_floor_normal = floor_normal;
+
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ floor_normal = Vector2();
+ platform_velocity = Vector2();
+
+ // No sliding on first attempt to keep floor motion stable when possible,
+ // When stop on slope is enabled or when there is no up direction.
+ bool sliding_enabled = !floor_stop_on_slope;
+ // Constant speed can be applied only the first time sliding is enabled.
+ bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
+ bool first_slide = true;
+ bool vel_dir_facing_up = velocity.dot(up_direction) > 0;
+ Vector2 last_travel;
+
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
+ Vector2 prev_position = parameters.from.columns[2];
+
+ PhysicsServer2D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
+
+ last_motion = result.travel;
+
+ if (collided) {
+ motion_results.push_back(result);
+ _set_collision_direction(result);
+
+ // If we hit a ceiling platform, we set the vertical velocity to at least the platform one.
+ if (on_ceiling && result.collider_velocity != Vector2() && result.collider_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (result.collision_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector2 ceiling_vertical_velocity = up_direction * up_direction.dot(result.collider_velocity);
+ Vector2 motion_vertical_velocity = up_direction * up_direction.dot(velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
+ }
+ }
+ }
+
+ if (on_floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
+ Transform2D gt = get_global_transform();
+ if (result.travel.length() <= margin + CMP_EPSILON) {
+ gt.columns[2] -= result.travel;
+ }
+ set_global_transform(gt);
+ velocity = Vector2();
+ last_motion = Vector2();
+ motion = Vector2();
+ break;
+ }
+
+ if (result.remainder.is_zero_approx()) {
+ motion = Vector2();
+ break;
+ }
+
+ // Move on floor only checks.
+ if (floor_block_on_wall && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
+ // Avoid to move forward on a wall if floor_block_on_wall is true.
+ if (p_was_on_floor && !on_floor && !vel_dir_facing_up) {
+ // If the movement is large the body can be prevented from reaching the walls.
+ if (result.travel.length() <= margin + CMP_EPSILON) {
+ // Cancels the motion.
+ Transform2D gt = get_global_transform();
+ gt.columns[2] -= result.travel;
+ set_global_transform(gt);
+ }
+ // Determines if you are on the ground.
+ _snap_on_floor(true, false, true);
+ velocity = Vector2();
+ last_motion = Vector2();
+ motion = Vector2();
+ break;
+ }
+ // Prevents the body from being able to climb a slope when it moves forward against the wall.
+ else if (!on_floor) {
+ motion = up_direction * up_direction.dot(result.remainder);
+ motion = motion.slide(result.collision_normal);
+ } else {
+ motion = result.remainder;
+ }
+ }
+ // Constant Speed when the slope is upward.
+ else if (floor_constant_speed && is_on_floor_only() && can_apply_constant_speed && p_was_on_floor && motion.dot(result.collision_normal) < 0) {
+ can_apply_constant_speed = false;
+ Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
+ motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
+ }
+ // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
+ else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
+ Vector2 slide_motion = result.remainder.slide(result.collision_normal);
+ if (slide_motion.dot(velocity) > 0.0) {
+ motion = slide_motion;
+ } else {
+ motion = Vector2();
+ }
+ if (slide_on_ceiling && on_ceiling) {
+ // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
+ if (vel_dir_facing_up) {
+ velocity = velocity.slide(result.collision_normal);
+ } else {
+ // Avoid acceleration in slope when falling.
+ velocity = up_direction * up_direction.dot(velocity);
+ }
+ }
+ }
+ // No sliding on first attempt to keep floor motion stable when possible.
+ else {
+ motion = result.remainder;
+ if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) {
+ velocity = velocity.slide(up_direction);
+ motion = motion.slide(up_direction);
+ }
+ }
+
+ last_travel = result.travel;
+ }
+ // When you move forward in a downward slope you don’t collide because you will be in the air.
+ // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
+ else if (floor_constant_speed && first_slide && _on_floor_if_snapped(p_was_on_floor, vel_dir_facing_up)) {
+ can_apply_constant_speed = false;
+ sliding_enabled = true;
+ Transform2D gt = get_global_transform();
+ gt.columns[2] = prev_position;
+ set_global_transform(gt);
+
+ Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
+ motion = motion_slide_norm * (motion_slide_up.length());
+ collided = true;
+ }
+
+ can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
+ sliding_enabled = true;
+ first_slide = false;
+
+ if (!collided || motion.is_zero_approx()) {
+ break;
+ }
+ }
+
+ _snap_on_floor(p_was_on_floor, vel_dir_facing_up);
+
+ // Scales the horizontal velocity according to the wall slope.
+ if (is_on_wall_only() && motion_slide_up.dot(motion_results.get(0).collision_normal) < 0) {
+ Vector2 slide_motion = velocity.slide(motion_results.get(0).collision_normal);
+ if (motion_slide_up.dot(slide_motion) < 0) {
+ velocity = up_direction * up_direction.dot(velocity);
+ } else {
+ // Keeps the vertical motion from velocity and add the horizontal motion of the projection.
+ velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
+ }
+ }
+
+ // Reset the gravity accumulation when touching the ground.
+ if (on_floor && !vel_dir_facing_up) {
+ velocity = velocity.slide(up_direction);
+ }
+}
+
+void CharacterBody2D::_move_and_slide_floating(double p_delta) {
+ Vector2 motion = velocity * p_delta;
+
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ floor_normal = Vector2();
+ platform_velocity = Vector2();
+
+ bool first_slide = true;
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
+ PhysicsServer2D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, false);
+
+ last_motion = result.travel;
+
+ if (collided) {
+ motion_results.push_back(result);
+ _set_collision_direction(result);
+
+ if (result.remainder.is_zero_approx()) {
+ motion = Vector2();
+ break;
+ }
+
+ if (wall_min_slide_angle != 0 && result.get_angle(-velocity.normalized()) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) {
+ motion = Vector2();
+ } else if (first_slide) {
+ Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
+ motion = motion_slide_norm * (motion.length() - result.travel.length());
+ } else {
+ motion = result.remainder.slide(result.collision_normal);
+ }
+
+ if (motion.dot(velocity) <= 0.0) {
+ motion = Vector2();
+ }
+ }
+
+ if (!collided || motion.is_zero_approx()) {
+ break;
+ }
+
+ first_slide = false;
+ }
+}
+void CharacterBody2D::apply_floor_snap() {
+ _apply_floor_snap();
+}
+
+// Method that avoids the p_wall_as_floor parameter for the public method.
+void CharacterBody2D::_apply_floor_snap(bool p_wall_as_floor) {
+ if (on_floor) {
+ return;
+ }
+
+ // Snap by at least collision margin to keep floor state consistent.
+ real_t length = MAX(floor_snap_length, margin);
+
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+ parameters.collide_separation_ray = true;
+
+ PhysicsServer2D::MotionResult result;
+ if (move_and_collide(parameters, result, true, false)) {
+ if ((result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) ||
+ (p_wall_as_floor && result.get_angle(-up_direction) > floor_max_angle + FLOOR_ANGLE_THRESHOLD)) {
+ on_floor = true;
+ floor_normal = result.collision_normal;
+ _set_platform_data(result);
+
+ if (floor_stop_on_slope) {
+ // move and collide may stray the object a bit because of pre un-stucking,
+ // so only ensure that motion happens on floor direction in this case.
+ if (result.travel.length() > margin) {
+ result.travel = up_direction * up_direction.dot(result.travel);
+ } else {
+ result.travel = Vector2();
+ }
+ }
+
+ parameters.from.columns[2] += result.travel;
+ set_global_transform(parameters.from);
+ }
+ }
+}
+
+void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor) {
+ if (on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
+ return;
+ }
+
+ _apply_floor_snap(p_wall_as_floor);
+}
+
+bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) {
+ if (up_direction == Vector2() || on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
+ return false;
+ }
+
+ // Snap by at least collision margin to keep floor state consistent.
+ real_t length = MAX(floor_snap_length, margin);
+
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+ parameters.collide_separation_ray = true;
+
+ PhysicsServer2D::MotionResult result;
+ if (move_and_collide(parameters, result, true, false)) {
+ if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
+ if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ on_floor = true;
+ floor_normal = p_result.collision_normal;
+ _set_platform_data(p_result);
+ } else if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(-up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ on_ceiling = true;
+ } else {
+ on_wall = true;
+ wall_normal = p_result.collision_normal;
+ // Don't apply wall velocity when the collider is a CharacterBody2D.
+ if (Object::cast_to<CharacterBody2D>(ObjectDB::get_instance(p_result.collider_id)) == nullptr) {
+ _set_platform_data(p_result);
+ }
+ }
+}
+
+void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) {
+ platform_rid = p_result.collider;
+ platform_object_id = p_result.collider_id;
+ platform_velocity = p_result.collider_velocity;
+ platform_layer = PhysicsServer2D::get_singleton()->body_get_collision_layer(platform_rid);
+}
+
+const Vector2 &CharacterBody2D::get_velocity() const {
+ return velocity;
+}
+
+void CharacterBody2D::set_velocity(const Vector2 &p_velocity) {
+ velocity = p_velocity;
+}
+
+bool CharacterBody2D::is_on_floor() const {
+ return on_floor;
+}
+
+bool CharacterBody2D::is_on_floor_only() const {
+ return on_floor && !on_wall && !on_ceiling;
+}
+
+bool CharacterBody2D::is_on_wall() const {
+ return on_wall;
+}
+
+bool CharacterBody2D::is_on_wall_only() const {
+ return on_wall && !on_floor && !on_ceiling;
+}
+
+bool CharacterBody2D::is_on_ceiling() const {
+ return on_ceiling;
+}
+
+bool CharacterBody2D::is_on_ceiling_only() const {
+ return on_ceiling && !on_floor && !on_wall;
+}
+
+const Vector2 &CharacterBody2D::get_floor_normal() const {
+ return floor_normal;
+}
+
+const Vector2 &CharacterBody2D::get_wall_normal() const {
+ return wall_normal;
+}
+
+const Vector2 &CharacterBody2D::get_last_motion() const {
+ return last_motion;
+}
+
+Vector2 CharacterBody2D::get_position_delta() const {
+ return get_global_transform().columns[2] - previous_position;
+}
+
+const Vector2 &CharacterBody2D::get_real_velocity() const {
+ return real_velocity;
+}
+
+real_t CharacterBody2D::get_floor_angle(const Vector2 &p_up_direction) const {
+ ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
+ return Math::acos(floor_normal.dot(p_up_direction));
+}
+
+const Vector2 &CharacterBody2D::get_platform_velocity() const {
+ return platform_velocity;
+}
+
+int CharacterBody2D::get_slide_collision_count() const {
+ return motion_results.size();
+}
+
+PhysicsServer2D::MotionResult CharacterBody2D::get_slide_collision(int p_bounce) const {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer2D::MotionResult());
+ return motion_results[p_bounce];
+}
+
+Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision2D>());
+ if (p_bounce >= slide_colliders.size()) {
+ slide_colliders.resize(p_bounce + 1);
+ }
+
+ // Create a new instance when the cached reference is invalid or still in use in script.
+ if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) {
+ slide_colliders.write[p_bounce].instantiate();
+ slide_colliders.write[p_bounce]->owner = this;
+ }
+
+ slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
+ return slide_colliders[p_bounce];
+}
+
+Ref<KinematicCollision2D> CharacterBody2D::_get_last_slide_collision() {
+ if (motion_results.size() == 0) {
+ return Ref<KinematicCollision2D>();
+ }
+ return _get_slide_collision(motion_results.size() - 1);
+}
+
+void CharacterBody2D::set_safe_margin(real_t p_margin) {
+ margin = p_margin;
+}
+
+real_t CharacterBody2D::get_safe_margin() const {
+ return margin;
+}
+
+bool CharacterBody2D::is_floor_stop_on_slope_enabled() const {
+ return floor_stop_on_slope;
+}
+
+void CharacterBody2D::set_floor_stop_on_slope_enabled(bool p_enabled) {
+ floor_stop_on_slope = p_enabled;
+}
+
+bool CharacterBody2D::is_floor_constant_speed_enabled() const {
+ return floor_constant_speed;
+}
+
+void CharacterBody2D::set_floor_constant_speed_enabled(bool p_enabled) {
+ floor_constant_speed = p_enabled;
+}
+
+bool CharacterBody2D::is_floor_block_on_wall_enabled() const {
+ return floor_block_on_wall;
+}
+
+void CharacterBody2D::set_floor_block_on_wall_enabled(bool p_enabled) {
+ floor_block_on_wall = p_enabled;
+}
+
+bool CharacterBody2D::is_slide_on_ceiling_enabled() const {
+ return slide_on_ceiling;
+}
+
+void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) {
+ slide_on_ceiling = p_enabled;
+}
+
+uint32_t CharacterBody2D::get_platform_floor_layers() const {
+ return platform_floor_layers;
+}
+
+void CharacterBody2D::set_platform_floor_layers(uint32_t p_exclude_layers) {
+ platform_floor_layers = p_exclude_layers;
+}
+
+uint32_t CharacterBody2D::get_platform_wall_layers() const {
+ return platform_wall_layers;
+}
+
+void CharacterBody2D::set_platform_wall_layers(uint32_t p_exclude_layers) {
+ platform_wall_layers = p_exclude_layers;
+}
+
+void CharacterBody2D::set_motion_mode(MotionMode p_mode) {
+ motion_mode = p_mode;
+}
+
+CharacterBody2D::MotionMode CharacterBody2D::get_motion_mode() const {
+ return motion_mode;
+}
+
+void CharacterBody2D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) {
+ platform_on_leave = p_on_leave_apply_velocity;
+}
+
+CharacterBody2D::PlatformOnLeave CharacterBody2D::get_platform_on_leave() const {
+ return platform_on_leave;
+}
+
+int CharacterBody2D::get_max_slides() const {
+ return max_slides;
+}
+
+void CharacterBody2D::set_max_slides(int p_max_slides) {
+ ERR_FAIL_COND(p_max_slides < 1);
+ max_slides = p_max_slides;
+}
+
+real_t CharacterBody2D::get_floor_max_angle() const {
+ return floor_max_angle;
+}
+
+void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody2D::get_floor_snap_length() {
+ return floor_snap_length;
+}
+
+void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) {
+ ERR_FAIL_COND(p_floor_snap_length < 0);
+ floor_snap_length = p_floor_snap_length;
+}
+
+real_t CharacterBody2D::get_wall_min_slide_angle() const {
+ return wall_min_slide_angle;
+}
+
+void CharacterBody2D::set_wall_min_slide_angle(real_t p_radians) {
+ wall_min_slide_angle = p_radians;
+}
+
+const Vector2 &CharacterBody2D::get_up_direction() const {
+ return up_direction;
+}
+
+void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
+ ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Floating motion mode instead.");
+ up_direction = p_up_direction.normalized();
+}
+
+void CharacterBody2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ // Reset move_and_slide() data.
+ on_floor = false;
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ on_ceiling = false;
+ on_wall = false;
+ motion_results.clear();
+ platform_velocity = Vector2();
+ } break;
+ }
+}
+
+void CharacterBody2D::_validate_property(PropertyInfo &p_property) const {
+ if (motion_mode == MOTION_MODE_FLOATING) {
+ if (p_property.name.begins_with("floor_") || p_property.name == "up_direction" || p_property.name == "slide_on_ceiling") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ } else {
+ if (p_property.name == "wall_min_slide_angle") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+}
+
+void CharacterBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody2D::move_and_slide);
+ ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody2D::apply_floor_snap);
+
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody2D::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody2D::get_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "margin"), &CharacterBody2D::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody2D::get_safe_margin);
+ ClassDB::bind_method(D_METHOD("is_floor_stop_on_slope_enabled"), &CharacterBody2D::is_floor_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_floor_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_constant_speed_enabled", "enabled"), &CharacterBody2D::set_floor_constant_speed_enabled);
+ ClassDB::bind_method(D_METHOD("is_floor_constant_speed_enabled"), &CharacterBody2D::is_floor_constant_speed_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_block_on_wall_enabled", "enabled"), &CharacterBody2D::set_floor_block_on_wall_enabled);
+ ClassDB::bind_method(D_METHOD("is_floor_block_on_wall_enabled"), &CharacterBody2D::is_floor_block_on_wall_enabled);
+ ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled);
+ ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody2D::set_platform_floor_layers);
+ ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody2D::get_platform_floor_layers);
+ ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody2D::set_platform_wall_layers);
+ ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody2D::get_platform_wall_layers);
+
+ ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
+ ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length);
+ ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length);
+ ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody2D::get_wall_min_slide_angle);
+ ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody2D::set_wall_min_slide_angle);
+ ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
+ ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
+ ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode);
+ ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody2D::get_motion_mode);
+ ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody2D::set_platform_on_leave);
+ ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody2D::get_platform_on_leave);
+
+ ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only);
+ ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
+ ClassDB::bind_method(D_METHOD("get_wall_normal"), &CharacterBody2D::get_wall_normal);
+ ClassDB::bind_method(D_METHOD("get_last_motion"), &CharacterBody2D::get_last_motion);
+ ClassDB::bind_method(D_METHOD("get_position_delta"), &CharacterBody2D::get_position_delta);
+ ClassDB::bind_method(D_METHOD("get_real_velocity"), &CharacterBody2D::get_real_velocity);
+ ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &CharacterBody2D::get_floor_angle, DEFVAL(Vector2(0.0, -1.0)));
+ ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity);
+ ClassDB::bind_method(D_METHOD("get_slide_collision_count"), &CharacterBody2D::get_slide_collision_count);
+ ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
+ ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody2D::_get_last_slide_collision);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle");
+
+ ADD_GROUP("Floor", "floor_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees"), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length");
+
+ ADD_GROUP("Moving Platform", "platform_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
+
+ ADD_GROUP("Collision", "");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:px"), "set_safe_margin", "get_safe_margin");
+
+ BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED);
+ BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING);
+
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY);
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY);
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING);
+}
+
+CharacterBody2D::CharacterBody2D() :
+ PhysicsBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
+}
+
+CharacterBody2D::~CharacterBody2D() {
+ for (int i = 0; i < slide_colliders.size(); i++) {
+ if (slide_colliders[i].is_valid()) {
+ slide_colliders.write[i]->owner = nullptr;
+ }
+ }
+}
diff --git a/scene/2d/physics/character_body_2d.h b/scene/2d/physics/character_body_2d.h
new file mode 100644
index 0000000000..395438a1f1
--- /dev/null
+++ b/scene/2d/physics/character_body_2d.h
@@ -0,0 +1,173 @@
+/**************************************************************************/
+/* character_body_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef CHARACTER_BODY_2D_H
+#define CHARACTER_BODY_2D_H
+
+#include "scene/2d/physics/kinematic_collision_2d.h"
+#include "scene/2d/physics/physics_body_2d.h"
+
+class CharacterBody2D : public PhysicsBody2D {
+ GDCLASS(CharacterBody2D, PhysicsBody2D);
+
+public:
+ enum MotionMode {
+ MOTION_MODE_GROUNDED,
+ MOTION_MODE_FLOATING,
+ };
+ enum PlatformOnLeave {
+ PLATFORM_ON_LEAVE_ADD_VELOCITY,
+ PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY,
+ PLATFORM_ON_LEAVE_DO_NOTHING,
+ };
+ bool move_and_slide();
+ void apply_floor_snap();
+
+ const Vector2 &get_velocity() const;
+ void set_velocity(const Vector2 &p_velocity);
+
+ bool is_on_floor() const;
+ bool is_on_floor_only() const;
+ bool is_on_wall() const;
+ bool is_on_wall_only() const;
+ bool is_on_ceiling() const;
+ bool is_on_ceiling_only() const;
+ const Vector2 &get_last_motion() const;
+ Vector2 get_position_delta() const;
+ const Vector2 &get_floor_normal() const;
+ const Vector2 &get_wall_normal() const;
+ const Vector2 &get_real_velocity() const;
+
+ real_t get_floor_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const;
+ const Vector2 &get_platform_velocity() const;
+
+ int get_slide_collision_count() const;
+ PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
+
+ void set_safe_margin(real_t p_margin);
+ real_t get_safe_margin() const;
+
+ bool is_floor_stop_on_slope_enabled() const;
+ void set_floor_stop_on_slope_enabled(bool p_enabled);
+
+ bool is_floor_constant_speed_enabled() const;
+ void set_floor_constant_speed_enabled(bool p_enabled);
+
+ bool is_floor_block_on_wall_enabled() const;
+ void set_floor_block_on_wall_enabled(bool p_enabled);
+
+ bool is_slide_on_ceiling_enabled() const;
+ void set_slide_on_ceiling_enabled(bool p_enabled);
+
+ int get_max_slides() const;
+ void set_max_slides(int p_max_slides);
+
+ real_t get_floor_max_angle() const;
+ void set_floor_max_angle(real_t p_radians);
+
+ real_t get_floor_snap_length();
+ void set_floor_snap_length(real_t p_floor_snap_length);
+
+ real_t get_wall_min_slide_angle() const;
+ void set_wall_min_slide_angle(real_t p_radians);
+
+ uint32_t get_platform_floor_layers() const;
+ void set_platform_floor_layers(const uint32_t p_exclude_layer);
+
+ uint32_t get_platform_wall_layers() const;
+ void set_platform_wall_layers(const uint32_t p_exclude_layer);
+
+ void set_motion_mode(MotionMode p_mode);
+ MotionMode get_motion_mode() const;
+
+ void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity);
+ PlatformOnLeave get_platform_on_leave() const;
+
+ CharacterBody2D();
+ ~CharacterBody2D();
+
+private:
+ real_t margin = 0.08;
+ MotionMode motion_mode = MOTION_MODE_GROUNDED;
+ PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY;
+
+ bool floor_constant_speed = false;
+ bool floor_stop_on_slope = true;
+ bool floor_block_on_wall = true;
+ bool slide_on_ceiling = true;
+ int max_slides = 4;
+ int platform_layer = 0;
+ real_t floor_max_angle = Math::deg_to_rad((real_t)45.0);
+ real_t floor_snap_length = 1;
+ real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0);
+ Vector2 up_direction = Vector2(0.0, -1.0);
+ uint32_t platform_floor_layers = UINT32_MAX;
+ uint32_t platform_wall_layers = 0;
+ Vector2 velocity;
+
+ Vector2 floor_normal;
+ Vector2 platform_velocity;
+ Vector2 wall_normal;
+ Vector2 last_motion;
+ Vector2 previous_position;
+ Vector2 real_velocity;
+
+ RID platform_rid;
+ ObjectID platform_object_id;
+ bool on_floor = false;
+ bool on_ceiling = false;
+ bool on_wall = false;
+
+ Vector<PhysicsServer2D::MotionResult> motion_results;
+ Vector<Ref<KinematicCollision2D>> slide_colliders;
+
+ void _move_and_slide_floating(double p_delta);
+ void _move_and_slide_grounded(double p_delta, bool p_was_on_floor);
+
+ Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
+ Ref<KinematicCollision2D> _get_last_slide_collision();
+ const Vector2 &get_up_direction() const;
+ bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up);
+ void set_up_direction(const Vector2 &p_up_direction);
+ void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
+ void _set_platform_data(const PhysicsServer2D::MotionResult &p_result);
+ void _apply_floor_snap(bool p_wall_as_floor = false);
+ void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor = false);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
+};
+
+VARIANT_ENUM_CAST(CharacterBody2D::MotionMode);
+VARIANT_ENUM_CAST(CharacterBody2D::PlatformOnLeave);
+
+#endif // CHARACTER_BODY_2D_H
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/physics/collision_object_2d.cpp
index 4e5852984b..4e5852984b 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/physics/collision_object_2d.cpp
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/physics/collision_object_2d.h
index 2c8534665c..2c8534665c 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/physics/collision_object_2d.h
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/physics/collision_polygon_2d.cpp
index 3bc5bce8f0..96ef346d23 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/physics/collision_polygon_2d.cpp
@@ -30,9 +30,9 @@
#include "collision_polygon_2d.h"
-#include "collision_object_2d.h"
#include "core/math/geometry_2d.h"
-#include "scene/2d/area_2d.h"
+#include "scene/2d/physics/area_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
#include "scene/resources/2d/concave_polygon_shape_2d.h"
#include "scene/resources/2d/convex_polygon_shape_2d.h"
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/physics/collision_polygon_2d.h
index f1ee30babe..f1ee30babe 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/physics/collision_polygon_2d.h
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/physics/collision_shape_2d.cpp
index 5539e49135..6fc29ffe63 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/physics/collision_shape_2d.cpp
@@ -30,8 +30,8 @@
#include "collision_shape_2d.h"
-#include "collision_object_2d.h"
-#include "scene/2d/area_2d.h"
+#include "scene/2d/physics/area_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
#include "scene/resources/2d/concave_polygon_shape_2d.h"
#include "scene/resources/2d/convex_polygon_shape_2d.h"
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/physics/collision_shape_2d.h
index 65436f1539..65436f1539 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/physics/collision_shape_2d.h
diff --git a/scene/2d/physics/joints/SCsub b/scene/2d/physics/joints/SCsub
new file mode 100644
index 0000000000..fc61250247
--- /dev/null
+++ b/scene/2d/physics/joints/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/2d/physics/joints/damped_spring_joint_2d.cpp b/scene/2d/physics/joints/damped_spring_joint_2d.cpp
new file mode 100644
index 0000000000..4b210ec0c7
--- /dev/null
+++ b/scene/2d/physics/joints/damped_spring_joint_2d.cpp
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/* damped_spring_joint_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "damped_spring_joint_2d.h"
+
+#include "scene/2d/physics/physics_body_2d.h"
+
+void DampedSpringJoint2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ if (!is_inside_tree()) {
+ break;
+ }
+
+ if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
+ }
+
+ draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(-10, length), Point2(+10, length), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(0, 0), Point2(0, length), Color(0.7, 0.6, 0.0, 0.5), 3);
+ } break;
+ }
+}
+
+void DampedSpringJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+ Transform2D gt = get_global_transform();
+ Vector2 anchor_A = gt.get_origin();
+ Vector2 anchor_B = gt.xform(Vector2(0, length));
+
+ PhysicsServer2D::get_singleton()->joint_make_damped_spring(p_joint, anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid());
+ if (rest_length) {
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, rest_length);
+ }
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_STIFFNESS, stiffness);
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(p_joint, PhysicsServer2D::DAMPED_SPRING_DAMPING, damping);
+}
+
+void DampedSpringJoint2D::set_length(real_t p_length) {
+ length = p_length;
+ queue_redraw();
+}
+
+real_t DampedSpringJoint2D::get_length() const {
+ return length;
+}
+
+void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) {
+ rest_length = p_rest_length;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_REST_LENGTH, p_rest_length ? p_rest_length : length);
+ }
+}
+
+real_t DampedSpringJoint2D::get_rest_length() const {
+ return rest_length;
+}
+
+void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) {
+ stiffness = p_stiffness;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_STIFFNESS, p_stiffness);
+ }
+}
+
+real_t DampedSpringJoint2D::get_stiffness() const {
+ return stiffness;
+}
+
+void DampedSpringJoint2D::set_damping(real_t p_damping) {
+ damping = p_damping;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->damped_spring_joint_set_param(get_rid(), PhysicsServer2D::DAMPED_SPRING_DAMPING, p_damping);
+ }
+}
+
+real_t DampedSpringJoint2D::get_damping() const {
+ return damping;
+}
+
+void DampedSpringJoint2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_length", "length"), &DampedSpringJoint2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"), &DampedSpringJoint2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_rest_length", "rest_length"), &DampedSpringJoint2D::set_rest_length);
+ ClassDB::bind_method(D_METHOD("get_rest_length"), &DampedSpringJoint2D::get_rest_length);
+ ClassDB::bind_method(D_METHOD("set_stiffness", "stiffness"), &DampedSpringJoint2D::set_stiffness);
+ ClassDB::bind_method(D_METHOD("get_stiffness"), &DampedSpringJoint2D::get_stiffness);
+ ClassDB::bind_method(D_METHOD("set_damping", "damping"), &DampedSpringJoint2D::set_damping);
+ ClassDB::bind_method(D_METHOD("get_damping"), &DampedSpringJoint2D::get_damping);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rest_length", PROPERTY_HINT_RANGE, "0,65535,1,exp,suffix:px"), "set_rest_length", "get_rest_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness", PROPERTY_HINT_RANGE, "0.1,64,0.1,exp"), "set_stiffness", "get_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0.01,16,0.01,exp"), "set_damping", "get_damping");
+}
+
+DampedSpringJoint2D::DampedSpringJoint2D() {
+}
diff --git a/scene/2d/physics/joints/damped_spring_joint_2d.h b/scene/2d/physics/joints/damped_spring_joint_2d.h
new file mode 100644
index 0000000000..de9fda80b9
--- /dev/null
+++ b/scene/2d/physics/joints/damped_spring_joint_2d.h
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* damped_spring_joint_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef DAMPED_SPRING_JOINT_2D_H
+#define DAMPED_SPRING_JOINT_2D_H
+
+#include "scene/2d/physics/joints/joint_2d.h"
+
+class PhysicsBody2D;
+
+class DampedSpringJoint2D : public Joint2D {
+ GDCLASS(DampedSpringJoint2D, Joint2D);
+
+ real_t stiffness = 20.0;
+ real_t damping = 1.0;
+ real_t rest_length = 0.0;
+ real_t length = 50.0;
+
+protected:
+ void _notification(int p_what);
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_length(real_t p_length);
+ real_t get_length() const;
+
+ void set_rest_length(real_t p_rest_length);
+ real_t get_rest_length() const;
+
+ void set_damping(real_t p_damping);
+ real_t get_damping() const;
+
+ void set_stiffness(real_t p_stiffness);
+ real_t get_stiffness() const;
+
+ DampedSpringJoint2D();
+};
+
+#endif // DAMPED_SPRING_JOINT_2D_H
diff --git a/scene/2d/physics/joints/groove_joint_2d.cpp b/scene/2d/physics/joints/groove_joint_2d.cpp
new file mode 100644
index 0000000000..415a49d8bd
--- /dev/null
+++ b/scene/2d/physics/joints/groove_joint_2d.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* groove_joint_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "groove_joint_2d.h"
+
+#include "scene/2d/physics/physics_body_2d.h"
+
+void GrooveJoint2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ if (!is_inside_tree()) {
+ break;
+ }
+
+ if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
+ }
+
+ draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(-10, length), Point2(+10, length), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(0, 0), Point2(0, length), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(-10, initial_offset), Point2(+10, initial_offset), Color(0.8, 0.8, 0.9, 0.5), 5);
+ } break;
+ }
+}
+
+void GrooveJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+ Transform2D gt = get_global_transform();
+ Vector2 groove_A1 = gt.get_origin();
+ Vector2 groove_A2 = gt.xform(Vector2(0, length));
+ Vector2 anchor_B = gt.xform(Vector2(0, initial_offset));
+
+ PhysicsServer2D::get_singleton()->joint_make_groove(p_joint, groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid());
+}
+
+void GrooveJoint2D::set_length(real_t p_length) {
+ length = p_length;
+ queue_redraw();
+}
+
+real_t GrooveJoint2D::get_length() const {
+ return length;
+}
+
+void GrooveJoint2D::set_initial_offset(real_t p_initial_offset) {
+ initial_offset = p_initial_offset;
+ queue_redraw();
+}
+
+real_t GrooveJoint2D::get_initial_offset() const {
+ return initial_offset;
+}
+
+void GrooveJoint2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_length", "length"), &GrooveJoint2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"), &GrooveJoint2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_initial_offset", "offset"), &GrooveJoint2D::set_initial_offset);
+ ClassDB::bind_method(D_METHOD("get_initial_offset"), &GrooveJoint2D::get_initial_offset);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "initial_offset", PROPERTY_HINT_RANGE, "1,65535,1,exp,suffix:px"), "set_initial_offset", "get_initial_offset");
+}
+
+GrooveJoint2D::GrooveJoint2D() {
+}
diff --git a/scene/2d/physics/joints/groove_joint_2d.h b/scene/2d/physics/joints/groove_joint_2d.h
new file mode 100644
index 0000000000..b04692fbff
--- /dev/null
+++ b/scene/2d/physics/joints/groove_joint_2d.h
@@ -0,0 +1,59 @@
+/**************************************************************************/
+/* groove_joint_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef GROOVE_JOINT_2D_H
+#define GROOVE_JOINT_2D_H
+
+#include "scene/2d/physics/joints/joint_2d.h"
+
+class PhysicsBody2D;
+
+class GrooveJoint2D : public Joint2D {
+ GDCLASS(GrooveJoint2D, Joint2D);
+
+ real_t length = 50.0;
+ real_t initial_offset = 25.0;
+
+protected:
+ void _notification(int p_what);
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_length(real_t p_length);
+ real_t get_length() const;
+
+ void set_initial_offset(real_t p_initial_offset);
+ real_t get_initial_offset() const;
+
+ GrooveJoint2D();
+};
+
+#endif // GROOVE_JOINT_2D_H
diff --git a/scene/2d/physics/joints/joint_2d.cpp b/scene/2d/physics/joints/joint_2d.cpp
new file mode 100644
index 0000000000..dd1697a29c
--- /dev/null
+++ b/scene/2d/physics/joints/joint_2d.cpp
@@ -0,0 +1,254 @@
+/**************************************************************************/
+/* joint_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "joint_2d.h"
+
+#include "scene/2d/physics/physics_body_2d.h"
+#include "scene/scene_string_names.h"
+
+void Joint2D::_disconnect_signals() {
+ Node *node_a = get_node_or_null(a);
+ PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
+ if (body_a) {
+ body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ }
+
+ Node *node_b = get_node_or_null(b);
+ PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
+ if (body_b) {
+ body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ }
+}
+
+void Joint2D::_body_exit_tree() {
+ _disconnect_signals();
+ _update_joint(true);
+ update_configuration_warnings();
+}
+
+void Joint2D::_update_joint(bool p_only_free) {
+ if (ba.is_valid() && bb.is_valid() && exclude_from_collision) {
+ PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false);
+ }
+
+ ba = RID();
+ bb = RID();
+ configured = false;
+
+ if (p_only_free || !is_inside_tree()) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
+ warning = String();
+ return;
+ }
+
+ Node *node_a = get_node_or_null(a);
+ Node *node_b = get_node_or_null(b);
+
+ PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
+ PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
+
+ bool valid = false;
+
+ if (node_a && !body_a && node_b && !body_b) {
+ warning = RTR("Node A and Node B must be PhysicsBody2Ds");
+ } else if (node_a && !body_a) {
+ warning = RTR("Node A must be a PhysicsBody2D");
+ } else if (node_b && !body_b) {
+ warning = RTR("Node B must be a PhysicsBody2D");
+ } else if (!body_a || !body_b) {
+ warning = RTR("Joint is not connected to two PhysicsBody2Ds");
+ } else if (body_a == body_b) {
+ warning = RTR("Node A and Node B must be different PhysicsBody2Ds");
+ } else {
+ warning = String();
+ valid = true;
+ }
+
+ update_configuration_warnings();
+
+ if (!valid) {
+ PhysicsServer2D::get_singleton()->joint_clear(joint);
+ return;
+ }
+
+ if (body_a) {
+ body_a->force_update_transform();
+ }
+
+ if (body_b) {
+ body_b->force_update_transform();
+ }
+
+ configured = true;
+
+ _configure_joint(joint, body_a, body_b);
+
+ ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
+
+ PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
+
+ ba = body_a->get_rid();
+ bb = body_b->get_rid();
+
+ body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+
+ PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
+}
+
+void Joint2D::set_node_a(const NodePath &p_node_a) {
+ if (a == p_node_a) {
+ return;
+ }
+
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+
+ a = p_node_a;
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // When in editor, the setter may be called as a result of node rename.
+ // It happens before the node actually changes its name, which triggers false warning.
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
+}
+
+NodePath Joint2D::get_node_a() const {
+ return a;
+}
+
+void Joint2D::set_node_b(const NodePath &p_node_b) {
+ if (b == p_node_b) {
+ return;
+ }
+
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+
+ b = p_node_b;
+ if (Engine::get_singleton()->is_editor_hint()) {
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
+}
+
+NodePath Joint2D::get_node_b() const {
+ return b;
+}
+
+void Joint2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_POST_ENTER_TREE: {
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint(true);
+ } break;
+ }
+}
+
+void Joint2D::set_bias(real_t p_bias) {
+ bias = p_bias;
+ if (joint.is_valid()) {
+ PhysicsServer2D::get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
+ }
+}
+
+real_t Joint2D::get_bias() const {
+ return bias;
+}
+
+void Joint2D::set_exclude_nodes_from_collision(bool p_enable) {
+ if (exclude_from_collision == p_enable) {
+ return;
+ }
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint(true);
+ exclude_from_collision = p_enable;
+ _update_joint();
+}
+
+bool Joint2D::get_exclude_nodes_from_collision() const {
+ return exclude_from_collision;
+}
+
+PackedStringArray Joint2D::get_configuration_warnings() const {
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
+
+ if (!warning.is_empty()) {
+ warnings.push_back(warning);
+ }
+
+ return warnings;
+}
+
+void Joint2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint2D::set_node_a);
+ ClassDB::bind_method(D_METHOD("get_node_a"), &Joint2D::get_node_a);
+
+ ClassDB::bind_method(D_METHOD("set_node_b", "node"), &Joint2D::set_node_b);
+ ClassDB::bind_method(D_METHOD("get_node_b"), &Joint2D::get_node_b);
+
+ ClassDB::bind_method(D_METHOD("set_bias", "bias"), &Joint2D::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"), &Joint2D::get_bias);
+
+ ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint2D::set_exclude_nodes_from_collision);
+ ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision);
+
+ ClassDB::bind_method(D_METHOD("get_rid"), &Joint2D::get_rid);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_a", "get_node_a");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_b", "get_node_b");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,0.9,0.001"), "set_bias", "get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_collision"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
+}
+
+Joint2D::Joint2D() {
+ joint = PhysicsServer2D::get_singleton()->joint_create();
+ set_hide_clip_children(true);
+}
+
+Joint2D::~Joint2D() {
+ ERR_FAIL_NULL(PhysicsServer2D::get_singleton());
+ PhysicsServer2D::get_singleton()->free(joint);
+}
diff --git a/scene/2d/physics/joints/joint_2d.h b/scene/2d/physics/joints/joint_2d.h
new file mode 100644
index 0000000000..bdd2730bfa
--- /dev/null
+++ b/scene/2d/physics/joints/joint_2d.h
@@ -0,0 +1,84 @@
+/**************************************************************************/
+/* joint_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef JOINT_2D_H
+#define JOINT_2D_H
+
+#include "scene/2d/node_2d.h"
+
+class PhysicsBody2D;
+
+class Joint2D : public Node2D {
+ GDCLASS(Joint2D, Node2D);
+
+ RID joint;
+ RID ba, bb;
+
+ NodePath a;
+ NodePath b;
+ real_t bias = 0.0;
+
+ bool exclude_from_collision = true;
+ bool configured = false;
+ String warning;
+
+protected:
+ void _disconnect_signals();
+ void _body_exit_tree();
+ void _update_joint(bool p_only_free = false);
+
+ void _notification(int p_what);
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0;
+
+ static void _bind_methods();
+
+ _FORCE_INLINE_ bool is_configured() const { return configured; }
+
+public:
+ virtual PackedStringArray get_configuration_warnings() const override;
+
+ void set_node_a(const NodePath &p_node_a);
+ NodePath get_node_a() const;
+
+ void set_node_b(const NodePath &p_node_b);
+ NodePath get_node_b() const;
+
+ void set_bias(real_t p_bias);
+ real_t get_bias() const;
+
+ void set_exclude_nodes_from_collision(bool p_enable);
+ bool get_exclude_nodes_from_collision() const;
+
+ RID get_rid() const { return joint; }
+ Joint2D();
+ ~Joint2D();
+};
+
+#endif // JOINT_2D_H
diff --git a/scene/2d/physics/joints/pin_joint_2d.cpp b/scene/2d/physics/joints/pin_joint_2d.cpp
new file mode 100644
index 0000000000..6ff0c485f5
--- /dev/null
+++ b/scene/2d/physics/joints/pin_joint_2d.cpp
@@ -0,0 +1,177 @@
+/**************************************************************************/
+/* pin_joint_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "pin_joint_2d.h"
+
+#include "scene/2d/physics/physics_body_2d.h"
+
+void PinJoint2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ if (!is_inside_tree()) {
+ break;
+ }
+
+ if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+ break;
+ }
+
+ draw_line(Point2(-10, 0), Point2(+10, 0), Color(0.7, 0.6, 0.0, 0.5), 3);
+ draw_line(Point2(0, -10), Point2(0, +10), Color(0.7, 0.6, 0.0, 0.5), 3);
+ } break;
+ }
+}
+
+void PinJoint2D::_configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
+ PhysicsServer2D::get_singleton()->joint_make_pin(p_joint, get_global_position(), body_a->get_rid(), body_b ? body_b->get_rid() : RID());
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, angular_limit_upper);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, angular_limit_lower);
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(p_joint, PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
+}
+
+void PinJoint2D::set_softness(real_t p_softness) {
+ if (softness == p_softness) {
+ return;
+ }
+ softness = p_softness;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_SOFTNESS, p_softness);
+ }
+}
+
+real_t PinJoint2D::get_softness() const {
+ return softness;
+}
+
+void PinJoint2D::set_angular_limit_lower(real_t p_angular_limit_lower) {
+ if (angular_limit_lower == p_angular_limit_lower) {
+ return;
+ }
+ angular_limit_lower = p_angular_limit_lower;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_LOWER, p_angular_limit_lower);
+ }
+}
+
+real_t PinJoint2D::get_angular_limit_lower() const {
+ return angular_limit_lower;
+}
+
+void PinJoint2D::set_angular_limit_upper(real_t p_angular_limit_upper) {
+ if (angular_limit_upper == p_angular_limit_upper) {
+ return;
+ }
+ angular_limit_upper = p_angular_limit_upper;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_LIMIT_UPPER, p_angular_limit_upper);
+ }
+}
+
+real_t PinJoint2D::get_angular_limit_upper() const {
+ return angular_limit_upper;
+}
+
+void PinJoint2D::set_motor_target_velocity(real_t p_motor_target_velocity) {
+ if (motor_target_velocity == p_motor_target_velocity) {
+ return;
+ }
+ motor_target_velocity = p_motor_target_velocity;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer2D::PIN_JOINT_MOTOR_TARGET_VELOCITY, motor_target_velocity);
+ }
+}
+
+real_t PinJoint2D::get_motor_target_velocity() const {
+ return motor_target_velocity;
+}
+
+void PinJoint2D::set_motor_enabled(bool p_motor_enabled) {
+ if (motor_enabled == p_motor_enabled) {
+ return;
+ }
+ motor_enabled = p_motor_enabled;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_MOTOR_ENABLED, motor_enabled);
+ }
+}
+
+bool PinJoint2D::is_motor_enabled() const {
+ return motor_enabled;
+}
+
+void PinJoint2D::set_angular_limit_enabled(bool p_angular_limit_enabled) {
+ if (angular_limit_enabled == p_angular_limit_enabled) {
+ return;
+ }
+ angular_limit_enabled = p_angular_limit_enabled;
+ queue_redraw();
+ if (is_configured()) {
+ PhysicsServer2D::get_singleton()->pin_joint_set_flag(get_rid(), PhysicsServer2D::PIN_JOINT_FLAG_ANGULAR_LIMIT_ENABLED, angular_limit_enabled);
+ }
+}
+
+bool PinJoint2D::is_angular_limit_enabled() const {
+ return angular_limit_enabled;
+}
+
+void PinJoint2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_softness", "softness"), &PinJoint2D::set_softness);
+ ClassDB::bind_method(D_METHOD("get_softness"), &PinJoint2D::get_softness);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_lower", "angular_limit_lower"), &PinJoint2D::set_angular_limit_lower);
+ ClassDB::bind_method(D_METHOD("get_angular_limit_lower"), &PinJoint2D::get_angular_limit_lower);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_upper", "angular_limit_upper"), &PinJoint2D::set_angular_limit_upper);
+ ClassDB::bind_method(D_METHOD("get_angular_limit_upper"), &PinJoint2D::get_angular_limit_upper);
+ ClassDB::bind_method(D_METHOD("set_motor_target_velocity", "motor_target_velocity"), &PinJoint2D::set_motor_target_velocity);
+ ClassDB::bind_method(D_METHOD("get_motor_target_velocity"), &PinJoint2D::get_motor_target_velocity);
+ ClassDB::bind_method(D_METHOD("set_motor_enabled", "enabled"), &PinJoint2D::set_motor_enabled);
+ ClassDB::bind_method(D_METHOD("is_motor_enabled"), &PinJoint2D::is_motor_enabled);
+ ClassDB::bind_method(D_METHOD("set_angular_limit_enabled", "enabled"), &PinJoint2D::set_angular_limit_enabled);
+ ClassDB::bind_method(D_METHOD("is_angular_limit_enabled"), &PinJoint2D::is_angular_limit_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.00,16,0.01,exp"), "set_softness", "get_softness");
+ ADD_GROUP("Angular Limit", "angular_limit_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "angular_limit_enabled"), "set_angular_limit_enabled", "is_angular_limit_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_lower", "get_angular_limit_lower");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_angular_limit_upper", "get_angular_limit_upper");
+ ADD_GROUP("Motor", "motor_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motor_enabled"), "set_motor_enabled", "is_motor_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motor_target_velocity", PROPERTY_HINT_RANGE, U"-200,200,0.01,or_greater,or_less,radians_as_degrees,suffix:\u00B0/s"), "set_motor_target_velocity", "get_motor_target_velocity");
+}
+
+PinJoint2D::PinJoint2D() {
+}
diff --git a/scene/2d/physics/joints/pin_joint_2d.h b/scene/2d/physics/joints/pin_joint_2d.h
new file mode 100644
index 0000000000..c2d78ba324
--- /dev/null
+++ b/scene/2d/physics/joints/pin_joint_2d.h
@@ -0,0 +1,71 @@
+/**************************************************************************/
+/* pin_joint_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PIN_JOINT_2D_H
+#define PIN_JOINT_2D_H
+
+#include "scene/2d/physics/joints/joint_2d.h"
+
+class PhysicsBody2D;
+
+class PinJoint2D : public Joint2D {
+ GDCLASS(PinJoint2D, Joint2D);
+
+ real_t softness = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_upper = 0.0;
+ real_t motor_target_velocity = 0.0;
+ bool motor_enabled = false;
+ bool angular_limit_enabled = false;
+
+protected:
+ void _notification(int p_what);
+ virtual void _configure_joint(RID p_joint, PhysicsBody2D *body_a, PhysicsBody2D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_softness(real_t p_softness);
+ real_t get_softness() const;
+ void set_angular_limit_lower(real_t p_angular_limit_lower);
+ real_t get_angular_limit_lower() const;
+ void set_angular_limit_upper(real_t p_angular_limit_upper);
+ real_t get_angular_limit_upper() const;
+ void set_motor_target_velocity(real_t p_motor_target_velocity);
+ real_t get_motor_target_velocity() const;
+
+ void set_motor_enabled(bool p_motor_enabled);
+ bool is_motor_enabled() const;
+ void set_angular_limit_enabled(bool p_angular_limit_enabled);
+ bool is_angular_limit_enabled() const;
+
+ PinJoint2D();
+};
+
+#endif // PIN_JOINT_2D_H
diff --git a/scene/2d/physics/kinematic_collision_2d.cpp b/scene/2d/physics/kinematic_collision_2d.cpp
new file mode 100644
index 0000000000..7e7c33b259
--- /dev/null
+++ b/scene/2d/physics/kinematic_collision_2d.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* kinematic_collision_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "kinematic_collision_2d.h"
+
+#include "scene/2d/physics/character_body_2d.h"
+#include "scene/2d/physics/physics_body_2d.h"
+
+Vector2 KinematicCollision2D::get_position() const {
+ return result.collision_point;
+}
+
+Vector2 KinematicCollision2D::get_normal() const {
+ return result.collision_normal;
+}
+
+Vector2 KinematicCollision2D::get_travel() const {
+ return result.travel;
+}
+
+Vector2 KinematicCollision2D::get_remainder() const {
+ return result.remainder;
+}
+
+real_t KinematicCollision2D::get_angle(const Vector2 &p_up_direction) const {
+ ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
+ return result.get_angle(p_up_direction);
+}
+
+real_t KinematicCollision2D::get_depth() const {
+ return result.collision_depth;
+}
+
+Object *KinematicCollision2D::get_local_shape() const {
+ if (!owner) {
+ return nullptr;
+ }
+ uint32_t ownerid = owner->shape_find_owner(result.collision_local_shape);
+ return owner->shape_owner_get_owner(ownerid);
+}
+
+Object *KinematicCollision2D::get_collider() const {
+ if (result.collider_id.is_valid()) {
+ return ObjectDB::get_instance(result.collider_id);
+ }
+
+ return nullptr;
+}
+
+ObjectID KinematicCollision2D::get_collider_id() const {
+ return result.collider_id;
+}
+
+RID KinematicCollision2D::get_collider_rid() const {
+ return result.collider;
+}
+
+Object *KinematicCollision2D::get_collider_shape() const {
+ Object *collider = get_collider();
+ if (collider) {
+ CollisionObject2D *obj2d = Object::cast_to<CollisionObject2D>(collider);
+ if (obj2d) {
+ uint32_t ownerid = obj2d->shape_find_owner(result.collider_shape);
+ return obj2d->shape_owner_get_owner(ownerid);
+ }
+ }
+
+ return nullptr;
+}
+
+int KinematicCollision2D::get_collider_shape_index() const {
+ return result.collider_shape;
+}
+
+Vector2 KinematicCollision2D::get_collider_velocity() const {
+ return result.collider_velocity;
+}
+
+void KinematicCollision2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision2D::get_position);
+ ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision2D::get_normal);
+ ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision2D::get_travel);
+ ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision2D::get_remainder);
+ ClassDB::bind_method(D_METHOD("get_angle", "up_direction"), &KinematicCollision2D::get_angle, DEFVAL(Vector2(0.0, -1.0)));
+ ClassDB::bind_method(D_METHOD("get_depth"), &KinematicCollision2D::get_depth);
+ ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision2D::get_local_shape);
+ ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision2D::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision2D::get_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collider_rid"), &KinematicCollision2D::get_collider_rid);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision2D::get_collider_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision2D::get_collider_velocity);
+}
diff --git a/scene/2d/physics/kinematic_collision_2d.h b/scene/2d/physics/kinematic_collision_2d.h
new file mode 100644
index 0000000000..0d187b87a5
--- /dev/null
+++ b/scene/2d/physics/kinematic_collision_2d.h
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* kinematic_collision_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef KINEMATIC_COLLISION_2D_H
+#define KINEMATIC_COLLISION_2D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/physics_server_2d.h"
+
+class CharacterBody2D;
+class PhysicsBody2D;
+
+class KinematicCollision2D : public RefCounted {
+ GDCLASS(KinematicCollision2D, RefCounted);
+
+ PhysicsBody2D *owner = nullptr;
+ friend class PhysicsBody2D;
+ friend class CharacterBody2D;
+ PhysicsServer2D::MotionResult result;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Vector2 get_position() const;
+ Vector2 get_normal() const;
+ Vector2 get_travel() const;
+ Vector2 get_remainder() const;
+ real_t get_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const;
+ real_t get_depth() const;
+ Object *get_local_shape() const;
+ Object *get_collider() const;
+ ObjectID get_collider_id() const;
+ RID get_collider_rid() const;
+ Object *get_collider_shape() const;
+ int get_collider_shape_index() const;
+ Vector2 get_collider_velocity() const;
+};
+
+#endif // KINEMATIC_COLLISION_2D_H
diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physics/physical_bone_2d.cpp
index 64cf56fa85..77bb8c24b8 100644
--- a/scene/2d/physical_bone_2d.cpp
+++ b/scene/2d/physics/physical_bone_2d.cpp
@@ -30,7 +30,7 @@
#include "physical_bone_2d.h"
-#include "scene/2d/joint_2d.h"
+#include "scene/2d/physics/joints/joint_2d.h"
void PhysicalBone2D::_notification(int p_what) {
switch (p_what) {
diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physics/physical_bone_2d.h
index e585f2c0ed..0547469b5e 100644
--- a/scene/2d/physical_bone_2d.h
+++ b/scene/2d/physics/physical_bone_2d.h
@@ -31,7 +31,7 @@
#ifndef PHYSICAL_BONE_2D_H
#define PHYSICAL_BONE_2D_H
-#include "scene/2d/physics_body_2d.h"
+#include "scene/2d/physics/rigid_body_2d.h"
#include "scene/2d/skeleton_2d.h"
class Joint2D;
diff --git a/scene/2d/physics/physics_body_2d.cpp b/scene/2d/physics/physics_body_2d.cpp
new file mode 100644
index 0000000000..81120d0b01
--- /dev/null
+++ b/scene/2d/physics/physics_body_2d.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************/
+/* physics_body_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "physics_body_2d.h"
+
+#include "scene/scene_string_names.h"
+
+void PhysicsBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_gravity"), &PhysicsBody2D::get_gravity);
+
+ ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
+ ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with);
+}
+
+PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
+ CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
+ set_body_mode(p_mode);
+ set_pickable(false);
+}
+
+PhysicsBody2D::~PhysicsBody2D() {
+ if (motion_cache.is_valid()) {
+ motion_cache->owner = nullptr;
+ }
+}
+
+Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
+ parameters.recovery_as_collision = p_recovery_as_collision;
+
+ PhysicsServer2D::MotionResult result;
+
+ if (move_and_collide(parameters, result, p_test_only)) {
+ // Create a new instance when the cached reference is invalid or still in use in script.
+ if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) {
+ motion_cache.instantiate();
+ motion_cache->owner = this;
+ }
+
+ motion_cache->result = result;
+ return motion_cache;
+ }
+
+ return Ref<KinematicCollision2D>();
+}
+
+bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
+ if (is_only_update_transform_changes_enabled()) {
+ ERR_PRINT("Move functions do not work together with 'sync to physics' option. See the documentation for details.");
+ }
+
+ bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
+
+ // Restore direction of motion to be along original motion,
+ // in order to avoid sliding due to recovery,
+ // but only if collision depth is low enough to avoid tunneling.
+ if (p_cancel_sliding) {
+ real_t motion_length = p_parameters.motion.length();
+ real_t precision = 0.001;
+
+ if (colliding) {
+ // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
+ // so even in normal resting cases the depth can be a bit more than the margin.
+ precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
+
+ if (r_result.collision_depth > p_parameters.margin + precision) {
+ p_cancel_sliding = false;
+ }
+ }
+
+ if (p_cancel_sliding) {
+ // When motion is null, recovery is the resulting motion.
+ Vector2 motion_normal;
+ if (motion_length > CMP_EPSILON) {
+ motion_normal = p_parameters.motion / motion_length;
+ }
+
+ // Check depth of recovery.
+ real_t projected_length = r_result.travel.dot(motion_normal);
+ Vector2 recovery = r_result.travel - motion_normal * projected_length;
+ real_t recovery_length = recovery.length();
+ // Fixes cases where canceling slide causes the motion to go too deep into the ground,
+ // because we're only taking rest information into account and not general recovery.
+ if (recovery_length < p_parameters.margin + precision) {
+ // Apply adjustment to motion.
+ r_result.travel = motion_normal * projected_length;
+ r_result.remainder = p_parameters.motion - r_result.travel;
+ }
+ }
+ }
+
+ if (!p_test_only) {
+ Transform2D gt = p_parameters.from;
+ gt.columns[2] += r_result.travel;
+ set_global_transform(gt);
+ }
+
+ return colliding;
+}
+
+bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+
+ PhysicsServer2D::MotionResult *r = nullptr;
+ PhysicsServer2D::MotionResult temp_result;
+ if (r_collision.is_valid()) {
+ // Needs const_cast because method bindings don't support non-const Ref.
+ r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result);
+ } else {
+ r = &temp_result;
+ }
+
+ PhysicsServer2D::MotionParameters parameters(p_from, p_motion, p_margin);
+ parameters.recovery_as_collision = p_recovery_as_collision;
+
+ return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
+}
+
+Vector2 PhysicsBody2D::get_gravity() const {
+ PhysicsDirectBodyState2D *state = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid());
+ ERR_FAIL_NULL_V(state, Vector2());
+ return state->get_total_gravity();
+}
+
+TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
+ List<RID> exceptions;
+ PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
+ Array ret;
+ for (const RID &body : exceptions) {
+ ObjectID instance_id = PhysicsServer2D::get_singleton()->body_get_object_instance_id(body);
+ Object *obj = ObjectDB::get_instance(instance_id);
+ PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(obj);
+ ret.append(physics_body);
+ }
+ return ret;
+}
+
+void PhysicsBody2D::add_collision_exception_with(Node *p_node) {
+ ERR_FAIL_NULL(p_node);
+ PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
+ ERR_FAIL_NULL_MSG(physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
+ PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid());
+}
+
+void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
+ ERR_FAIL_NULL(p_node);
+ PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
+ ERR_FAIL_NULL_MSG(physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
+ PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid());
+}
diff --git a/scene/2d/physics/physics_body_2d.h b/scene/2d/physics/physics_body_2d.h
new file mode 100644
index 0000000000..43bc479881
--- /dev/null
+++ b/scene/2d/physics/physics_body_2d.h
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/* physics_body_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PHYSICS_BODY_2D_H
+#define PHYSICS_BODY_2D_H
+
+#include "core/templates/vset.h"
+#include "scene/2d/physics/collision_object_2d.h"
+#include "scene/2d/physics/kinematic_collision_2d.h"
+#include "scene/resources/physics_material.h"
+#include "servers/physics_server_2d.h"
+
+class PhysicsBody2D : public CollisionObject2D {
+ GDCLASS(PhysicsBody2D, CollisionObject2D);
+
+protected:
+ static void _bind_methods();
+ PhysicsBody2D(PhysicsServer2D::BodyMode p_mode);
+
+ Ref<KinematicCollision2D> motion_cache;
+
+ Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+
+public:
+ bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
+ bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+ Vector2 get_gravity() const;
+
+ TypedArray<PhysicsBody2D> get_collision_exceptions();
+ void add_collision_exception_with(Node *p_node); //must be physicsbody
+ void remove_collision_exception_with(Node *p_node);
+
+ virtual ~PhysicsBody2D();
+};
+
+#endif // PHYSICS_BODY_2D_H
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/physics/ray_cast_2d.cpp
index f27ac169b6..cb9497c14e 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/physics/ray_cast_2d.cpp
@@ -30,7 +30,7 @@
#include "ray_cast_2d.h"
-#include "collision_object_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
#include "scene/resources/world_2d.h"
void RayCast2D::set_target_position(const Vector2 &p_point) {
diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/physics/ray_cast_2d.h
index 0a856635da..0a856635da 100644
--- a/scene/2d/ray_cast_2d.h
+++ b/scene/2d/physics/ray_cast_2d.h
diff --git a/scene/2d/physics/rigid_body_2d.cpp b/scene/2d/physics/rigid_body_2d.cpp
new file mode 100644
index 0000000000..12112510a8
--- /dev/null
+++ b/scene/2d/physics/rigid_body_2d.cpp
@@ -0,0 +1,817 @@
+/**************************************************************************/
+/* rigid_body_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "rigid_body_2d.h"
+
+#include "scene/scene_string_names.h"
+
+void RigidBody2D::_body_enter_tree(ObjectID p_id) {
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_FAIL_NULL(node);
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(E->value.in_scene);
+
+ contact_monitor->locked = true;
+
+ E->value.in_scene = true;
+ emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+
+ for (int i = 0; i < E->value.shapes.size(); i++) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+}
+
+void RigidBody2D::_body_exit_tree(ObjectID p_id) {
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_FAIL_NULL(node);
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(!E->value.in_scene);
+ E->value.in_scene = false;
+
+ contact_monitor->locked = true;
+
+ emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+
+ for (int i = 0; i < E->value.shapes.size(); i++) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+}
+
+void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
+ bool body_in = p_status == 1;
+ ObjectID objid = p_instance;
+
+ Object *obj = ObjectDB::get_instance(objid);
+ Node *node = Object::cast_to<Node>(obj);
+
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
+
+ ERR_FAIL_COND(!body_in && !E);
+
+ if (body_in) {
+ if (!E) {
+ E = contact_monitor->body_map.insert(objid, BodyState());
+ E->value.rid = p_body;
+ //E->value.rc=0;
+ E->value.in_scene = node && node->is_inside_tree();
+ if (node) {
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
+ if (E->value.in_scene) {
+ emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ }
+ }
+
+ //E->value.rc++;
+ }
+
+ if (node) {
+ E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
+ }
+
+ if (E->value.in_scene) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
+ }
+
+ } else {
+ //E->value.rc--;
+
+ if (node) {
+ E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
+ }
+
+ bool in_scene = E->value.in_scene;
+
+ if (E->value.shapes.is_empty()) {
+ if (node) {
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
+ if (in_scene) {
+ emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ }
+ }
+
+ contact_monitor->body_map.remove(E);
+ }
+ if (node && in_scene) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape);
+ }
+ }
+}
+
+struct _RigidBody2DInOut {
+ RID rid;
+ ObjectID id;
+ int shape = 0;
+ int local_shape = 0;
+};
+
+void RigidBody2D::_sync_body_state(PhysicsDirectBodyState2D *p_state) {
+ if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
+ set_block_transform_notify(true);
+ set_global_transform(p_state->get_transform());
+ set_block_transform_notify(false);
+ }
+
+ linear_velocity = p_state->get_linear_velocity();
+ angular_velocity = p_state->get_angular_velocity();
+
+ contact_count = p_state->get_contact_count();
+
+ if (sleeping != p_state->is_sleeping()) {
+ sleeping = p_state->is_sleeping();
+ emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
+ }
+}
+
+void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
+ lock_callback();
+
+ if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
+ _sync_body_state(p_state);
+
+ Transform2D old_transform = get_global_transform();
+ GDVIRTUAL_CALL(_integrate_forces, p_state);
+ Transform2D new_transform = get_global_transform();
+
+ if (new_transform != old_transform) {
+ // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+ }
+ }
+
+ _sync_body_state(p_state);
+
+ if (contact_monitor) {
+ contact_monitor->locked = true;
+
+ //untag all
+ int rc = 0;
+ for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ for (int i = 0; i < E.value.shapes.size(); i++) {
+ E.value.shapes[i].tagged = false;
+ rc++;
+ }
+ }
+
+ _RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut));
+ int toadd_count = 0; //state->get_contact_count();
+ RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction));
+ int toremove_count = 0;
+
+ //put the ones to add
+
+ for (int i = 0; i < p_state->get_contact_count(); i++) {
+ RID col_rid = p_state->get_contact_collider(i);
+ ObjectID col_obj = p_state->get_contact_collider_id(i);
+ int local_shape = p_state->get_contact_local_shape(i);
+ int col_shape = p_state->get_contact_collider_shape(i);
+
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
+ if (!E) {
+ toadd[toadd_count].rid = col_rid;
+ toadd[toadd_count].local_shape = local_shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
+ toadd_count++;
+ continue;
+ }
+
+ ShapePair sp(col_shape, local_shape);
+ int idx = E->value.shapes.find(sp);
+ if (idx == -1) {
+ toadd[toadd_count].rid = col_rid;
+ toadd[toadd_count].local_shape = local_shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
+ toadd_count++;
+ continue;
+ }
+
+ E->value.shapes[idx].tagged = true;
+ }
+
+ //put the ones to remove
+
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ for (int i = 0; i < E.value.shapes.size(); i++) {
+ if (!E.value.shapes[i].tagged) {
+ toremove[toremove_count].rid = E.value.rid;
+ toremove[toremove_count].body_id = E.key;
+ toremove[toremove_count].pair = E.value.shapes[i];
+ toremove_count++;
+ }
+ }
+ }
+
+ //process removals
+
+ for (int i = 0; i < toremove_count; i++) {
+ _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
+ }
+
+ //process additions
+
+ for (int i = 0; i < toadd_count; i++) {
+ _body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+ }
+
+ unlock_callback();
+}
+
+void RigidBody2D::_apply_body_mode() {
+ if (freeze) {
+ switch (freeze_mode) {
+ case FREEZE_MODE_STATIC: {
+ set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
+ } break;
+ case FREEZE_MODE_KINEMATIC: {
+ set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
+ } break;
+ }
+ } else if (lock_rotation) {
+ set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR);
+ } else {
+ set_body_mode(PhysicsServer2D::BODY_MODE_RIGID);
+ }
+}
+
+void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) {
+ if (p_lock_rotation == lock_rotation) {
+ return;
+ }
+
+ lock_rotation = p_lock_rotation;
+ _apply_body_mode();
+}
+
+bool RigidBody2D::is_lock_rotation_enabled() const {
+ return lock_rotation;
+}
+
+void RigidBody2D::set_freeze_enabled(bool p_freeze) {
+ if (p_freeze == freeze) {
+ return;
+ }
+
+ freeze = p_freeze;
+ _apply_body_mode();
+}
+
+bool RigidBody2D::is_freeze_enabled() const {
+ return freeze;
+}
+
+void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) {
+ if (p_freeze_mode == freeze_mode) {
+ return;
+ }
+
+ freeze_mode = p_freeze_mode;
+ _apply_body_mode();
+}
+
+RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const {
+ return freeze_mode;
+}
+
+void RigidBody2D::set_mass(real_t p_mass) {
+ ERR_FAIL_COND(p_mass <= 0);
+ mass = p_mass;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass);
+}
+
+real_t RigidBody2D::get_mass() const {
+ return mass;
+}
+
+void RigidBody2D::set_inertia(real_t p_inertia) {
+ ERR_FAIL_COND(p_inertia < 0);
+ inertia = p_inertia;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
+}
+
+real_t RigidBody2D::get_inertia() const {
+ return inertia;
+}
+
+void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
+ if (center_of_mass_mode == p_mode) {
+ return;
+ }
+
+ center_of_mass_mode = p_mode;
+
+ switch (center_of_mass_mode) {
+ case CENTER_OF_MASS_MODE_AUTO: {
+ center_of_mass = Vector2();
+ PhysicsServer2D::get_singleton()->body_reset_mass_properties(get_rid());
+ if (inertia != 0.0) {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
+ }
+ } break;
+
+ case CENTER_OF_MASS_MODE_CUSTOM: {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+ } break;
+ }
+}
+
+RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
+ return center_of_mass_mode;
+}
+
+void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) {
+ if (center_of_mass == p_center_of_mass) {
+ return;
+ }
+
+ ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
+ center_of_mass = p_center_of_mass;
+
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+}
+
+const Vector2 &RigidBody2D::get_center_of_mass() const {
+ return center_of_mass;
+}
+
+void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
+ if (physics_material_override.is_valid()) {
+ physics_material_override->disconnect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
+ }
+
+ physics_material_override = p_physics_material_override;
+
+ if (physics_material_override.is_valid()) {
+ physics_material_override->connect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
+ }
+ _reload_physics_characteristics();
+}
+
+Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const {
+ return physics_material_override;
+}
+
+void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) {
+ gravity_scale = p_gravity_scale;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
+}
+
+real_t RigidBody2D::get_gravity_scale() const {
+ return gravity_scale;
+}
+
+void RigidBody2D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void RigidBody2D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
+void RigidBody2D::set_linear_damp(real_t p_linear_damp) {
+ ERR_FAIL_COND(p_linear_damp < -1);
+ linear_damp = p_linear_damp;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp);
+}
+
+real_t RigidBody2D::get_linear_damp() const {
+ return linear_damp;
+}
+
+void RigidBody2D::set_angular_damp(real_t p_angular_damp) {
+ ERR_FAIL_COND(p_angular_damp < -1);
+ angular_damp = p_angular_damp;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
+}
+
+real_t RigidBody2D::get_angular_damp() const {
+ return angular_damp;
+}
+
+void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) {
+ Vector2 axis = p_axis.normalized();
+ linear_velocity -= axis * axis.dot(linear_velocity);
+ linear_velocity += p_axis;
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+}
+
+void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) {
+ linear_velocity = p_velocity;
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+}
+
+Vector2 RigidBody2D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+void RigidBody2D::set_angular_velocity(real_t p_velocity) {
+ angular_velocity = p_velocity;
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
+}
+
+real_t RigidBody2D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void RigidBody2D::set_use_custom_integrator(bool p_enable) {
+ if (custom_integrator == p_enable) {
+ return;
+ }
+
+ custom_integrator = p_enable;
+ PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
+}
+
+bool RigidBody2D::is_using_custom_integrator() {
+ return custom_integrator;
+}
+
+void RigidBody2D::set_sleeping(bool p_sleeping) {
+ sleeping = p_sleeping;
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping);
+}
+
+void RigidBody2D::set_can_sleep(bool p_active) {
+ can_sleep = p_active;
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active);
+}
+
+bool RigidBody2D::is_able_to_sleep() const {
+ return can_sleep;
+}
+
+bool RigidBody2D::is_sleeping() const {
+ return sleeping;
+}
+
+void RigidBody2D::set_max_contacts_reported(int p_amount) {
+ max_contacts_reported = p_amount;
+ PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
+}
+
+int RigidBody2D::get_max_contacts_reported() const {
+ return max_contacts_reported;
+}
+
+int RigidBody2D::get_contact_count() const {
+ return contact_count;
+}
+
+void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) {
+ PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
+}
+
+void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
+ PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
+}
+
+void RigidBody2D::apply_torque_impulse(real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
+}
+
+void RigidBody2D::apply_central_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
+}
+
+void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
+ PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
+}
+
+void RigidBody2D::apply_torque(real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
+}
+
+void RigidBody2D::add_constant_central_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
+}
+
+void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
+ PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
+}
+
+void RigidBody2D::add_constant_torque(const real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
+}
+
+void RigidBody2D::set_constant_force(const Vector2 &p_force) {
+ PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
+}
+
+Vector2 RigidBody2D::get_constant_force() const {
+ return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
+}
+
+void RigidBody2D::set_constant_torque(real_t p_torque) {
+ PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
+}
+
+real_t RigidBody2D::get_constant_torque() const {
+ return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
+}
+
+void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
+ ccd_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode));
+}
+
+RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const {
+ return ccd_mode;
+}
+
+TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const {
+ ERR_FAIL_NULL_V(contact_monitor, TypedArray<Node2D>());
+
+ TypedArray<Node2D> ret;
+ ret.resize(contact_monitor->body_map.size());
+ int idx = 0;
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ Object *obj = ObjectDB::get_instance(E.key);
+ if (!obj) {
+ ret.resize(ret.size() - 1); //ops
+ } else {
+ ret[idx++] = obj;
+ }
+ }
+
+ return ret;
+}
+
+void RigidBody2D::set_contact_monitor(bool p_enabled) {
+ if (p_enabled == is_contact_monitor_enabled()) {
+ return;
+ }
+
+ if (!p_enabled) {
+ ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
+
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ //clean up mess
+ Object *obj = ObjectDB::get_instance(E.key);
+ Node *node = Object::cast_to<Node>(obj);
+
+ if (node) {
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
+ }
+ }
+
+ memdelete(contact_monitor);
+ contact_monitor = nullptr;
+ } else {
+ contact_monitor = memnew(ContactMonitor);
+ contact_monitor->locked = false;
+ }
+}
+
+bool RigidBody2D::is_contact_monitor_enabled() const {
+ return contact_monitor != nullptr;
+}
+
+void RigidBody2D::_notification(int p_what) {
+#ifdef TOOLS_ENABLED
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_notify_local_transform(true); // Used for warnings and only in editor.
+ }
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ update_configuration_warnings();
+ } break;
+ }
+#endif
+}
+
+PackedStringArray RigidBody2D::get_configuration_warnings() const {
+ Transform2D t = get_transform();
+
+ PackedStringArray warnings = CollisionObject2D::get_configuration_warnings();
+
+ if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) {
+ warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
+ }
+
+ return warnings;
+}
+
+void RigidBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass);
+
+ ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia);
+ ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass);
+
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override);
+
+ ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count);
+
+ ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator);
+ ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator);
+
+ ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor);
+ ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode);
+
+ ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse);
+
+ ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force);
+ ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque);
+
+ ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force);
+ ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2());
+ ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force);
+ ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque);
+ ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping);
+ ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping);
+
+ ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep);
+ ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep);
+
+ ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled);
+ ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled);
+ ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode);
+ ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode);
+
+ ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
+
+ GDVIRTUAL_BIND(_integrate_forces, "state");
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
+ ADD_GROUP("Mass Distribution", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
+ ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5px\u00B2"), "set_inertia", "get_inertia");
+ ADD_GROUP("Deactivation", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
+ ADD_GROUP("Solver", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
+ ADD_GROUP("Linear", "linear_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_GROUP("Angular", "angular_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_GROUP("Constant Forces", "constant_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px/s\u00B2"), "set_constant_force", "get_constant_force");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
+
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
+
+ BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
+ BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
+
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+
+ BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
+ BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
+}
+
+void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
+ if (p_property.name == "center_of_mass") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+}
+
+RigidBody2D::RigidBody2D() :
+ PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed));
+}
+
+RigidBody2D::~RigidBody2D() {
+ if (contact_monitor) {
+ memdelete(contact_monitor);
+ }
+}
+
+void RigidBody2D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
+ }
+}
diff --git a/scene/2d/physics/rigid_body_2d.h b/scene/2d/physics/rigid_body_2d.h
new file mode 100644
index 0000000000..40af66f28d
--- /dev/null
+++ b/scene/2d/physics/rigid_body_2d.h
@@ -0,0 +1,249 @@
+/**************************************************************************/
+/* rigid_body_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef RIGID_BODY_2D_H
+#define RIGID_BODY_2D_H
+
+#include "scene/2d/physics/static_body_2d.h"
+
+class RigidBody2D : public PhysicsBody2D {
+ GDCLASS(RigidBody2D, PhysicsBody2D);
+
+public:
+ enum FreezeMode {
+ FREEZE_MODE_STATIC,
+ FREEZE_MODE_KINEMATIC,
+ };
+
+ enum CenterOfMassMode {
+ CENTER_OF_MASS_MODE_AUTO,
+ CENTER_OF_MASS_MODE_CUSTOM,
+ };
+
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
+ enum CCDMode {
+ CCD_MODE_DISABLED,
+ CCD_MODE_CAST_RAY,
+ CCD_MODE_CAST_SHAPE,
+ };
+
+private:
+ bool can_sleep = true;
+ bool lock_rotation = false;
+ bool freeze = false;
+ FreezeMode freeze_mode = FREEZE_MODE_STATIC;
+
+ real_t mass = 1.0;
+ real_t inertia = 0.0;
+ CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
+ Vector2 center_of_mass;
+
+ Ref<PhysicsMaterial> physics_material_override;
+ real_t gravity_scale = 1.0;
+
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
+ Vector2 linear_velocity;
+ real_t angular_velocity = 0.0;
+ bool sleeping = false;
+
+ int max_contacts_reported = 0;
+ int contact_count = 0;
+
+ bool custom_integrator = false;
+
+ CCDMode ccd_mode = CCD_MODE_DISABLED;
+
+ struct ShapePair {
+ int body_shape = 0;
+ int local_shape = 0;
+ bool tagged = false;
+ bool operator<(const ShapePair &p_sp) const {
+ if (body_shape == p_sp.body_shape) {
+ return local_shape < p_sp.local_shape;
+ }
+
+ return body_shape < p_sp.body_shape;
+ }
+
+ ShapePair() {}
+ ShapePair(int p_bs, int p_ls) {
+ body_shape = p_bs;
+ local_shape = p_ls;
+ }
+ };
+ struct RigidBody2D_RemoveAction {
+ RID rid;
+ ObjectID body_id;
+ ShapePair pair;
+ };
+ struct BodyState {
+ RID rid;
+ //int rc;
+ bool in_scene = false;
+ VSet<ShapePair> shapes;
+ };
+
+ struct ContactMonitor {
+ bool locked = false;
+ HashMap<ObjectID, BodyState> body_map;
+ };
+
+ ContactMonitor *contact_monitor = nullptr;
+ void _body_enter_tree(ObjectID p_id);
+ void _body_exit_tree(ObjectID p_id);
+
+ void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
+
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState2D *p_state);
+
+ void _sync_body_state(PhysicsDirectBodyState2D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+ void _validate_property(PropertyInfo &p_property) const;
+
+ GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState2D *)
+
+ void _apply_body_mode();
+
+public:
+ void set_lock_rotation_enabled(bool p_lock_rotation);
+ bool is_lock_rotation_enabled() const;
+
+ void set_freeze_enabled(bool p_freeze);
+ bool is_freeze_enabled() const;
+
+ void set_freeze_mode(FreezeMode p_freeze_mode);
+ FreezeMode get_freeze_mode() const;
+
+ void set_mass(real_t p_mass);
+ real_t get_mass() const;
+
+ void set_inertia(real_t p_inertia);
+ real_t get_inertia() const;
+
+ void set_center_of_mass_mode(CenterOfMassMode p_mode);
+ CenterOfMassMode get_center_of_mass_mode() const;
+
+ void set_center_of_mass(const Vector2 &p_center_of_mass);
+ const Vector2 &get_center_of_mass() const;
+
+ void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
+ Ref<PhysicsMaterial> get_physics_material_override() const;
+
+ void set_gravity_scale(real_t p_gravity_scale);
+ real_t get_gravity_scale() const;
+
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
+ void set_linear_damp(real_t p_linear_damp);
+ real_t get_linear_damp() const;
+
+ void set_angular_damp(real_t p_angular_damp);
+ real_t get_angular_damp() const;
+
+ void set_linear_velocity(const Vector2 &p_velocity);
+ Vector2 get_linear_velocity() const;
+
+ void set_axis_velocity(const Vector2 &p_axis);
+
+ void set_angular_velocity(real_t p_velocity);
+ real_t get_angular_velocity() const;
+
+ void set_use_custom_integrator(bool p_enable);
+ bool is_using_custom_integrator();
+
+ void set_sleeping(bool p_sleeping);
+ bool is_sleeping() const;
+
+ void set_can_sleep(bool p_active);
+ bool is_able_to_sleep() const;
+
+ void set_contact_monitor(bool p_enabled);
+ bool is_contact_monitor_enabled() const;
+
+ void set_max_contacts_reported(int p_amount);
+ int get_max_contacts_reported() const;
+ int get_contact_count() const;
+
+ void set_continuous_collision_detection_mode(CCDMode p_mode);
+ CCDMode get_continuous_collision_detection_mode() const;
+
+ void apply_central_impulse(const Vector2 &p_impulse);
+ void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2());
+ void apply_torque_impulse(real_t p_torque);
+
+ void apply_central_force(const Vector2 &p_force);
+ void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
+ void apply_torque(real_t p_torque);
+
+ void add_constant_central_force(const Vector2 &p_force);
+ void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
+ void add_constant_torque(real_t p_torque);
+
+ void set_constant_force(const Vector2 &p_force);
+ Vector2 get_constant_force() const;
+
+ void set_constant_torque(real_t p_torque);
+ real_t get_constant_torque() const;
+
+ TypedArray<Node2D> get_colliding_bodies() const; //function for script
+
+ virtual PackedStringArray get_configuration_warnings() const override;
+
+ RigidBody2D();
+ ~RigidBody2D();
+
+private:
+ void _reload_physics_characteristics();
+};
+
+VARIANT_ENUM_CAST(RigidBody2D::FreezeMode);
+VARIANT_ENUM_CAST(RigidBody2D::CenterOfMassMode);
+VARIANT_ENUM_CAST(RigidBody2D::DampMode);
+VARIANT_ENUM_CAST(RigidBody2D::CCDMode);
+
+#endif // RIGID_BODY_2D_H
diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/physics/shape_cast_2d.cpp
index 38e3b3180b..00be84b622 100644
--- a/scene/2d/shape_cast_2d.cpp
+++ b/scene/2d/physics/shape_cast_2d.cpp
@@ -31,8 +31,8 @@
#include "shape_cast_2d.h"
#include "core/config/engine.h"
-#include "scene/2d/collision_object_2d.h"
-#include "scene/2d/physics_body_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
+#include "scene/2d/physics/physics_body_2d.h"
#include "scene/resources/2d/circle_shape_2d.h"
#include "servers/physics_2d/godot_physics_server_2d.h"
diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/physics/shape_cast_2d.h
index 6b8fd5b798..6b8fd5b798 100644
--- a/scene/2d/shape_cast_2d.h
+++ b/scene/2d/physics/shape_cast_2d.h
diff --git a/scene/2d/physics/static_body_2d.cpp b/scene/2d/physics/static_body_2d.cpp
new file mode 100644
index 0000000000..3c5af73c1e
--- /dev/null
+++ b/scene/2d/physics/static_body_2d.cpp
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/* static_body_2d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "static_body_2d.h"
+
+void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
+ constant_linear_velocity = p_vel;
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+}
+
+void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
+ constant_angular_velocity = p_vel;
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+}
+
+Vector2 StaticBody2D::get_constant_linear_velocity() const {
+ return constant_linear_velocity;
+}
+
+real_t StaticBody2D::get_constant_angular_velocity() const {
+ return constant_angular_velocity;
+}
+
+void StaticBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
+ if (physics_material_override.is_valid()) {
+ physics_material_override->disconnect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
+ }
+
+ physics_material_override = p_physics_material_override;
+
+ if (physics_material_override.is_valid()) {
+ physics_material_override->connect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
+ }
+ _reload_physics_characteristics();
+}
+
+Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
+ return physics_material_override;
+}
+
+void StaticBody2D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
+ }
+}
+
+void StaticBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+}
+
+StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
+ PhysicsBody2D(p_mode) {
+}
diff --git a/scene/2d/physics/static_body_2d.h b/scene/2d/physics/static_body_2d.h
new file mode 100644
index 0000000000..ce05596d94
--- /dev/null
+++ b/scene/2d/physics/static_body_2d.h
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* static_body_2d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef STATIC_BODY_2D_H
+#define STATIC_BODY_2D_H
+
+#include "scene/2d/physics/physics_body_2d.h"
+
+class StaticBody2D : public PhysicsBody2D {
+ GDCLASS(StaticBody2D, PhysicsBody2D);
+
+private:
+ Vector2 constant_linear_velocity;
+ real_t constant_angular_velocity = 0.0;
+
+ Ref<PhysicsMaterial> physics_material_override;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
+ Ref<PhysicsMaterial> get_physics_material_override() const;
+
+ void set_constant_linear_velocity(const Vector2 &p_vel);
+ void set_constant_angular_velocity(real_t p_vel);
+
+ Vector2 get_constant_linear_velocity() const;
+ real_t get_constant_angular_velocity() const;
+
+ StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC);
+
+private:
+ void _reload_physics_characteristics();
+};
+
+#endif // STATIC_BODY_2D_H
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
deleted file mode 100644
index 92af3fa3f0..0000000000
--- a/scene/2d/physics_body_2d.cpp
+++ /dev/null
@@ -1,1923 +0,0 @@
-/**************************************************************************/
-/* physics_body_2d.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "physics_body_2d.h"
-
-#include "scene/scene_string_names.h"
-
-void PhysicsBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_gravity"), &PhysicsBody2D::get_gravity);
-
- ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
- ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
- ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with);
-}
-
-PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
- CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
- set_body_mode(p_mode);
- set_pickable(false);
-}
-
-PhysicsBody2D::~PhysicsBody2D() {
- if (motion_cache.is_valid()) {
- motion_cache->owner = nullptr;
- }
-}
-
-Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
- parameters.recovery_as_collision = p_recovery_as_collision;
-
- PhysicsServer2D::MotionResult result;
-
- if (move_and_collide(parameters, result, p_test_only)) {
- // Create a new instance when the cached reference is invalid or still in use in script.
- if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) {
- motion_cache.instantiate();
- motion_cache->owner = this;
- }
-
- motion_cache->result = result;
- return motion_cache;
- }
-
- return Ref<KinematicCollision2D>();
-}
-
-bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
- if (is_only_update_transform_changes_enabled()) {
- ERR_PRINT("Move functions do not work together with 'sync to physics' option. See the documentation for details.");
- }
-
- bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
-
- // Restore direction of motion to be along original motion,
- // in order to avoid sliding due to recovery,
- // but only if collision depth is low enough to avoid tunneling.
- if (p_cancel_sliding) {
- real_t motion_length = p_parameters.motion.length();
- real_t precision = 0.001;
-
- if (colliding) {
- // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
- // so even in normal resting cases the depth can be a bit more than the margin.
- precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
-
- if (r_result.collision_depth > p_parameters.margin + precision) {
- p_cancel_sliding = false;
- }
- }
-
- if (p_cancel_sliding) {
- // When motion is null, recovery is the resulting motion.
- Vector2 motion_normal;
- if (motion_length > CMP_EPSILON) {
- motion_normal = p_parameters.motion / motion_length;
- }
-
- // Check depth of recovery.
- real_t projected_length = r_result.travel.dot(motion_normal);
- Vector2 recovery = r_result.travel - motion_normal * projected_length;
- real_t recovery_length = recovery.length();
- // Fixes cases where canceling slide causes the motion to go too deep into the ground,
- // because we're only taking rest information into account and not general recovery.
- if (recovery_length < p_parameters.margin + precision) {
- // Apply adjustment to motion.
- r_result.travel = motion_normal * projected_length;
- r_result.remainder = p_parameters.motion - r_result.travel;
- }
- }
- }
-
- if (!p_test_only) {
- Transform2D gt = p_parameters.from;
- gt.columns[2] += r_result.travel;
- set_global_transform(gt);
- }
-
- return colliding;
-}
-
-bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
-
- PhysicsServer2D::MotionResult *r = nullptr;
- PhysicsServer2D::MotionResult temp_result;
- if (r_collision.is_valid()) {
- // Needs const_cast because method bindings don't support non-const Ref.
- r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result);
- } else {
- r = &temp_result;
- }
-
- PhysicsServer2D::MotionParameters parameters(p_from, p_motion, p_margin);
- parameters.recovery_as_collision = p_recovery_as_collision;
-
- return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
-}
-
-Vector2 PhysicsBody2D::get_gravity() const {
- PhysicsDirectBodyState2D *state = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid());
- ERR_FAIL_NULL_V(state, Vector2());
- return state->get_total_gravity();
-}
-
-TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
- List<RID> exceptions;
- PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
- Array ret;
- for (const RID &body : exceptions) {
- ObjectID instance_id = PhysicsServer2D::get_singleton()->body_get_object_instance_id(body);
- Object *obj = ObjectDB::get_instance(instance_id);
- PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(obj);
- ret.append(physics_body);
- }
- return ret;
-}
-
-void PhysicsBody2D::add_collision_exception_with(Node *p_node) {
- ERR_FAIL_NULL(p_node);
- PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_NULL_MSG(physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
- PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid());
-}
-
-void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
- ERR_FAIL_NULL(p_node);
- PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_NULL_MSG(physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
- PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid());
-}
-
-void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
- constant_linear_velocity = p_vel;
-
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
-}
-
-void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
- constant_angular_velocity = p_vel;
-
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
-}
-
-Vector2 StaticBody2D::get_constant_linear_velocity() const {
- return constant_linear_velocity;
-}
-
-real_t StaticBody2D::get_constant_angular_velocity() const {
- return constant_angular_velocity;
-}
-
-void StaticBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
- if (physics_material_override.is_valid()) {
- physics_material_override->disconnect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
- }
-
- physics_material_override = p_physics_material_override;
-
- if (physics_material_override.is_valid()) {
- physics_material_override->connect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
- }
- _reload_physics_characteristics();
-}
-
-Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
- return physics_material_override;
-}
-
-void StaticBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
-}
-
-StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
- PhysicsBody2D(p_mode) {
-}
-
-void StaticBody2D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-void AnimatableBody2D::set_sync_to_physics(bool p_enable) {
- if (sync_to_physics == p_enable) {
- return;
- }
-
- sync_to_physics = p_enable;
-
- _update_kinematic_motion();
-}
-
-bool AnimatableBody2D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void AnimatableBody2D::_update_kinematic_motion() {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
-
- if (sync_to_physics) {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody2D::_body_state_changed));
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-}
-
-void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
- if (!sync_to_physics) {
- return;
- }
-
- last_valid_transform = p_state->get_transform();
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
-}
-
-void AnimatableBody2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- last_valid_transform = get_global_transform();
- _update_kinematic_motion();
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- } break;
-
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- // Used by sync to physics, send the new transform to the physics...
- Transform2D new_transform = get_global_transform();
-
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
-
- // ... but then revert changes.
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
- } break;
- }
-}
-
-void AnimatableBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
-}
-
-AnimatableBody2D::AnimatableBody2D() :
- StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
-}
-
-void RigidBody2D::_body_enter_tree(ObjectID p_id) {
- Object *obj = ObjectDB::get_instance(p_id);
- Node *node = Object::cast_to<Node>(obj);
- ERR_FAIL_NULL(node);
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
- ERR_FAIL_COND(!E);
- ERR_FAIL_COND(E->value.in_scene);
-
- contact_monitor->locked = true;
-
- E->value.in_scene = true;
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
-
- for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
- }
-
- contact_monitor->locked = false;
-}
-
-void RigidBody2D::_body_exit_tree(ObjectID p_id) {
- Object *obj = ObjectDB::get_instance(p_id);
- Node *node = Object::cast_to<Node>(obj);
- ERR_FAIL_NULL(node);
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
- ERR_FAIL_COND(!E);
- ERR_FAIL_COND(!E->value.in_scene);
- E->value.in_scene = false;
-
- contact_monitor->locked = true;
-
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
-
- for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
- }
-
- contact_monitor->locked = false;
-}
-
-void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
- bool body_in = p_status == 1;
- ObjectID objid = p_instance;
-
- Object *obj = ObjectDB::get_instance(objid);
- Node *node = Object::cast_to<Node>(obj);
-
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
-
- ERR_FAIL_COND(!body_in && !E);
-
- if (body_in) {
- if (!E) {
- E = contact_monitor->body_map.insert(objid, BodyState());
- E->value.rid = p_body;
- //E->value.rc=0;
- E->value.in_scene = node && node->is_inside_tree();
- if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
- if (E->value.in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
- }
- }
-
- //E->value.rc++;
- }
-
- if (node) {
- E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
- }
-
- if (E->value.in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
- }
-
- } else {
- //E->value.rc--;
-
- if (node) {
- E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
- }
-
- bool in_scene = E->value.in_scene;
-
- if (E->value.shapes.is_empty()) {
- if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
- if (in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
- }
- }
-
- contact_monitor->body_map.remove(E);
- }
- if (node && in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape);
- }
- }
-}
-
-struct _RigidBody2DInOut {
- RID rid;
- ObjectID id;
- int shape = 0;
- int local_shape = 0;
-};
-
-void RigidBody2D::_sync_body_state(PhysicsDirectBodyState2D *p_state) {
- if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
- set_block_transform_notify(true);
- set_global_transform(p_state->get_transform());
- set_block_transform_notify(false);
- }
-
- linear_velocity = p_state->get_linear_velocity();
- angular_velocity = p_state->get_angular_velocity();
-
- contact_count = p_state->get_contact_count();
-
- if (sleeping != p_state->is_sleeping()) {
- sleeping = p_state->is_sleeping();
- emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
- }
-}
-
-void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
- lock_callback();
-
- if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
- _sync_body_state(p_state);
-
- Transform2D old_transform = get_global_transform();
- GDVIRTUAL_CALL(_integrate_forces, p_state);
- Transform2D new_transform = get_global_transform();
-
- if (new_transform != old_transform) {
- // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
- }
- }
-
- _sync_body_state(p_state);
-
- if (contact_monitor) {
- contact_monitor->locked = true;
-
- //untag all
- int rc = 0;
- for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- for (int i = 0; i < E.value.shapes.size(); i++) {
- E.value.shapes[i].tagged = false;
- rc++;
- }
- }
-
- _RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut));
- int toadd_count = 0; //state->get_contact_count();
- RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction));
- int toremove_count = 0;
-
- //put the ones to add
-
- for (int i = 0; i < p_state->get_contact_count(); i++) {
- RID col_rid = p_state->get_contact_collider(i);
- ObjectID col_obj = p_state->get_contact_collider_id(i);
- int local_shape = p_state->get_contact_local_shape(i);
- int col_shape = p_state->get_contact_collider_shape(i);
-
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
- if (!E) {
- toadd[toadd_count].rid = col_rid;
- toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = col_obj;
- toadd[toadd_count].shape = col_shape;
- toadd_count++;
- continue;
- }
-
- ShapePair sp(col_shape, local_shape);
- int idx = E->value.shapes.find(sp);
- if (idx == -1) {
- toadd[toadd_count].rid = col_rid;
- toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = col_obj;
- toadd[toadd_count].shape = col_shape;
- toadd_count++;
- continue;
- }
-
- E->value.shapes[idx].tagged = true;
- }
-
- //put the ones to remove
-
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- for (int i = 0; i < E.value.shapes.size(); i++) {
- if (!E.value.shapes[i].tagged) {
- toremove[toremove_count].rid = E.value.rid;
- toremove[toremove_count].body_id = E.key;
- toremove[toremove_count].pair = E.value.shapes[i];
- toremove_count++;
- }
- }
- }
-
- //process removals
-
- for (int i = 0; i < toremove_count; i++) {
- _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
- }
-
- //process additions
-
- for (int i = 0; i < toadd_count; i++) {
- _body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
- }
-
- contact_monitor->locked = false;
- }
-
- unlock_callback();
-}
-
-void RigidBody2D::_apply_body_mode() {
- if (freeze) {
- switch (freeze_mode) {
- case FREEZE_MODE_STATIC: {
- set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
- } break;
- case FREEZE_MODE_KINEMATIC: {
- set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
- } break;
- }
- } else if (lock_rotation) {
- set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR);
- } else {
- set_body_mode(PhysicsServer2D::BODY_MODE_RIGID);
- }
-}
-
-void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) {
- if (p_lock_rotation == lock_rotation) {
- return;
- }
-
- lock_rotation = p_lock_rotation;
- _apply_body_mode();
-}
-
-bool RigidBody2D::is_lock_rotation_enabled() const {
- return lock_rotation;
-}
-
-void RigidBody2D::set_freeze_enabled(bool p_freeze) {
- if (p_freeze == freeze) {
- return;
- }
-
- freeze = p_freeze;
- _apply_body_mode();
-}
-
-bool RigidBody2D::is_freeze_enabled() const {
- return freeze;
-}
-
-void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) {
- if (p_freeze_mode == freeze_mode) {
- return;
- }
-
- freeze_mode = p_freeze_mode;
- _apply_body_mode();
-}
-
-RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const {
- return freeze_mode;
-}
-
-void RigidBody2D::set_mass(real_t p_mass) {
- ERR_FAIL_COND(p_mass <= 0);
- mass = p_mass;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass);
-}
-
-real_t RigidBody2D::get_mass() const {
- return mass;
-}
-
-void RigidBody2D::set_inertia(real_t p_inertia) {
- ERR_FAIL_COND(p_inertia < 0);
- inertia = p_inertia;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
-}
-
-real_t RigidBody2D::get_inertia() const {
- return inertia;
-}
-
-void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
- if (center_of_mass_mode == p_mode) {
- return;
- }
-
- center_of_mass_mode = p_mode;
-
- switch (center_of_mass_mode) {
- case CENTER_OF_MASS_MODE_AUTO: {
- center_of_mass = Vector2();
- PhysicsServer2D::get_singleton()->body_reset_mass_properties(get_rid());
- if (inertia != 0.0) {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
- }
- } break;
-
- case CENTER_OF_MASS_MODE_CUSTOM: {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
- } break;
- }
-}
-
-RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
- return center_of_mass_mode;
-}
-
-void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) {
- if (center_of_mass == p_center_of_mass) {
- return;
- }
-
- ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
- center_of_mass = p_center_of_mass;
-
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
-}
-
-const Vector2 &RigidBody2D::get_center_of_mass() const {
- return center_of_mass;
-}
-
-void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
- if (physics_material_override.is_valid()) {
- physics_material_override->disconnect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
- }
-
- physics_material_override = p_physics_material_override;
-
- if (physics_material_override.is_valid()) {
- physics_material_override->connect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
- }
- _reload_physics_characteristics();
-}
-
-Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const {
- return physics_material_override;
-}
-
-void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) {
- gravity_scale = p_gravity_scale;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
-}
-
-real_t RigidBody2D::get_gravity_scale() const {
- return gravity_scale;
-}
-
-void RigidBody2D::set_linear_damp_mode(DampMode p_mode) {
- linear_damp_mode = p_mode;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
-}
-
-RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const {
- return linear_damp_mode;
-}
-
-void RigidBody2D::set_angular_damp_mode(DampMode p_mode) {
- angular_damp_mode = p_mode;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
-}
-
-RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const {
- return angular_damp_mode;
-}
-
-void RigidBody2D::set_linear_damp(real_t p_linear_damp) {
- ERR_FAIL_COND(p_linear_damp < -1);
- linear_damp = p_linear_damp;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp);
-}
-
-real_t RigidBody2D::get_linear_damp() const {
- return linear_damp;
-}
-
-void RigidBody2D::set_angular_damp(real_t p_angular_damp) {
- ERR_FAIL_COND(p_angular_damp < -1);
- angular_damp = p_angular_damp;
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
-}
-
-real_t RigidBody2D::get_angular_damp() const {
- return angular_damp;
-}
-
-void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) {
- Vector2 axis = p_axis.normalized();
- linear_velocity -= axis * axis.dot(linear_velocity);
- linear_velocity += p_axis;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
-}
-
-void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) {
- linear_velocity = p_velocity;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
-}
-
-Vector2 RigidBody2D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-void RigidBody2D::set_angular_velocity(real_t p_velocity) {
- angular_velocity = p_velocity;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
-}
-
-real_t RigidBody2D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-void RigidBody2D::set_use_custom_integrator(bool p_enable) {
- if (custom_integrator == p_enable) {
- return;
- }
-
- custom_integrator = p_enable;
- PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
-}
-
-bool RigidBody2D::is_using_custom_integrator() {
- return custom_integrator;
-}
-
-void RigidBody2D::set_sleeping(bool p_sleeping) {
- sleeping = p_sleeping;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping);
-}
-
-void RigidBody2D::set_can_sleep(bool p_active) {
- can_sleep = p_active;
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active);
-}
-
-bool RigidBody2D::is_able_to_sleep() const {
- return can_sleep;
-}
-
-bool RigidBody2D::is_sleeping() const {
- return sleeping;
-}
-
-void RigidBody2D::set_max_contacts_reported(int p_amount) {
- max_contacts_reported = p_amount;
- PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
-}
-
-int RigidBody2D::get_max_contacts_reported() const {
- return max_contacts_reported;
-}
-
-int RigidBody2D::get_contact_count() const {
- return contact_count;
-}
-
-void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) {
- PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
-}
-
-void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
- PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
-}
-
-void RigidBody2D::apply_torque_impulse(real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
-}
-
-void RigidBody2D::apply_central_force(const Vector2 &p_force) {
- PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
-}
-
-void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
- PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
-}
-
-void RigidBody2D::apply_torque(real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
-}
-
-void RigidBody2D::add_constant_central_force(const Vector2 &p_force) {
- PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
-}
-
-void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
- PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
-}
-
-void RigidBody2D::add_constant_torque(const real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
-}
-
-void RigidBody2D::set_constant_force(const Vector2 &p_force) {
- PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
-}
-
-Vector2 RigidBody2D::get_constant_force() const {
- return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
-}
-
-void RigidBody2D::set_constant_torque(real_t p_torque) {
- PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
-}
-
-real_t RigidBody2D::get_constant_torque() const {
- return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
-}
-
-void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
- ccd_mode = p_mode;
- PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode));
-}
-
-RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const {
- return ccd_mode;
-}
-
-TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const {
- ERR_FAIL_NULL_V(contact_monitor, TypedArray<Node2D>());
-
- TypedArray<Node2D> ret;
- ret.resize(contact_monitor->body_map.size());
- int idx = 0;
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
- }
- }
-
- return ret;
-}
-
-void RigidBody2D::set_contact_monitor(bool p_enabled) {
- if (p_enabled == is_contact_monitor_enabled()) {
- return;
- }
-
- if (!p_enabled) {
- ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
-
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- //clean up mess
- Object *obj = ObjectDB::get_instance(E.key);
- Node *node = Object::cast_to<Node>(obj);
-
- if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
- }
- }
-
- memdelete(contact_monitor);
- contact_monitor = nullptr;
- } else {
- contact_monitor = memnew(ContactMonitor);
- contact_monitor->locked = false;
- }
-}
-
-bool RigidBody2D::is_contact_monitor_enabled() const {
- return contact_monitor != nullptr;
-}
-
-void RigidBody2D::_notification(int p_what) {
-#ifdef TOOLS_ENABLED
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (Engine::get_singleton()->is_editor_hint()) {
- set_notify_local_transform(true); // Used for warnings and only in editor.
- }
- } break;
-
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- update_configuration_warnings();
- } break;
- }
-#endif
-}
-
-PackedStringArray RigidBody2D::get_configuration_warnings() const {
- Transform2D t = get_transform();
-
- PackedStringArray warnings = CollisionObject2D::get_configuration_warnings();
-
- if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) {
- warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
- }
-
- return warnings;
-}
-
-void RigidBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass);
- ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass);
-
- ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia);
- ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia);
-
- ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode);
- ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode);
-
- ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass);
- ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override);
-
- ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale);
- ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode);
- ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode);
- ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp);
- ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp);
- ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp);
-
- ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity);
-
- ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported);
- ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported);
- ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count);
-
- ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator);
- ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator);
-
- ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor);
- ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled);
-
- ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode);
- ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode);
-
- ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity);
- ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2());
- ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2());
- ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse);
-
- ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force);
- ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2());
- ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque);
-
- ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force);
- ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2());
- ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque);
-
- ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force);
- ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force);
-
- ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque);
- ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque);
-
- ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping);
- ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping);
-
- ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep);
- ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep);
-
- ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled);
- ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled);
-
- ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled);
- ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled);
-
- ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode);
- ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode);
-
- ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
-
- GDVIRTUAL_BIND(_integrate_forces, "state");
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
- ADD_GROUP("Mass Distribution", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
- ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5px\u00B2"), "set_inertia", "get_inertia");
- ADD_GROUP("Deactivation", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
- ADD_GROUP("Solver", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
- ADD_GROUP("Linear", "linear_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
- ADD_GROUP("Angular", "angular_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_GROUP("Constant Forces", "constant_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px/s\u00B2"), "set_constant_force", "get_constant_force");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
-
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
-
- BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
- BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
-
- BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
- BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
-
- BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
- BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
-
- BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
- BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
- BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
-}
-
-void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
- if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
- if (p_property.name == "center_of_mass") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
- }
-}
-
-RigidBody2D::RigidBody2D() :
- PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed));
-}
-
-RigidBody2D::~RigidBody2D() {
- if (contact_monitor) {
- memdelete(contact_monitor);
- }
-}
-
-void RigidBody2D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-//////////////////////////
-
-// So, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
-#define FLOOR_ANGLE_THRESHOLD 0.01
-
-bool CharacterBody2D::move_and_slide() {
- // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
- double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
-
- Vector2 current_platform_velocity = platform_velocity;
- Transform2D gt = get_global_transform();
- previous_position = gt.columns[2];
-
- if ((on_floor || on_wall) && platform_rid.is_valid()) {
- bool excluded = false;
- if (on_floor) {
- excluded = (platform_floor_layers & platform_layer) == 0;
- } else if (on_wall) {
- excluded = (platform_wall_layers & platform_layer) == 0;
- }
- if (!excluded) {
- //this approach makes sure there is less delay between the actual body velocity and the one we saved
- PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid);
- if (bs) {
- Vector2 local_position = gt.columns[2] - bs->get_transform().columns[2];
- current_platform_velocity = bs->get_velocity_at_local_position(local_position);
- } else {
- // Body is removed or destroyed, invalidate floor.
- current_platform_velocity = Vector2();
- platform_rid = RID();
- }
- } else {
- current_platform_velocity = Vector2();
- }
- }
-
- motion_results.clear();
- last_motion = Vector2();
-
- bool was_on_floor = on_floor;
- on_floor = false;
- on_ceiling = false;
- on_wall = false;
-
- if (!current_platform_velocity.is_zero_approx()) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
- parameters.exclude_bodies.insert(platform_rid);
- if (platform_object_id.is_valid()) {
- parameters.exclude_objects.insert(platform_object_id);
- }
-
- PhysicsServer2D::MotionResult floor_result;
- if (move_and_collide(parameters, floor_result, false, false)) {
- motion_results.push_back(floor_result);
- _set_collision_direction(floor_result);
- }
- }
-
- if (motion_mode == MOTION_MODE_GROUNDED) {
- _move_and_slide_grounded(delta, was_on_floor);
- } else {
- _move_and_slide_floating(delta);
- }
-
- // Compute real velocity.
- real_velocity = get_position_delta() / delta;
-
- if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) {
- // Add last platform velocity when just left a moving platform.
- if (!on_floor && !on_wall) {
- if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) {
- current_platform_velocity = current_platform_velocity.slide(up_direction);
- }
- velocity += current_platform_velocity;
- }
- }
-
- return motion_results.size() > 0;
-}
-
-void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
- Vector2 motion = velocity * p_delta;
- Vector2 motion_slide_up = motion.slide(up_direction);
-
- Vector2 prev_floor_normal = floor_normal;
-
- platform_rid = RID();
- platform_object_id = ObjectID();
- floor_normal = Vector2();
- platform_velocity = Vector2();
-
- // No sliding on first attempt to keep floor motion stable when possible,
- // When stop on slope is enabled or when there is no up direction.
- bool sliding_enabled = !floor_stop_on_slope;
- // Constant speed can be applied only the first time sliding is enabled.
- bool can_apply_constant_speed = sliding_enabled;
- // If the platform's ceiling push down the body.
- bool apply_ceiling_velocity = false;
- bool first_slide = true;
- bool vel_dir_facing_up = velocity.dot(up_direction) > 0;
- Vector2 last_travel;
-
- for (int iteration = 0; iteration < max_slides; ++iteration) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
-
- Vector2 prev_position = parameters.from.columns[2];
-
- PhysicsServer2D::MotionResult result;
- bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
-
- last_motion = result.travel;
-
- if (collided) {
- motion_results.push_back(result);
- _set_collision_direction(result);
-
- // If we hit a ceiling platform, we set the vertical velocity to at least the platform one.
- if (on_ceiling && result.collider_velocity != Vector2() && result.collider_velocity.dot(up_direction) < 0) {
- // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
- if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (result.collision_normal + up_direction).length() < 0.01) {
- apply_ceiling_velocity = true;
- Vector2 ceiling_vertical_velocity = up_direction * up_direction.dot(result.collider_velocity);
- Vector2 motion_vertical_velocity = up_direction * up_direction.dot(velocity);
- if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
- velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
- }
- }
- }
-
- if (on_floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
- Transform2D gt = get_global_transform();
- if (result.travel.length() <= margin + CMP_EPSILON) {
- gt.columns[2] -= result.travel;
- }
- set_global_transform(gt);
- velocity = Vector2();
- last_motion = Vector2();
- motion = Vector2();
- break;
- }
-
- if (result.remainder.is_zero_approx()) {
- motion = Vector2();
- break;
- }
-
- // Move on floor only checks.
- if (floor_block_on_wall && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
- // Avoid to move forward on a wall if floor_block_on_wall is true.
- if (p_was_on_floor && !on_floor && !vel_dir_facing_up) {
- // If the movement is large the body can be prevented from reaching the walls.
- if (result.travel.length() <= margin + CMP_EPSILON) {
- // Cancels the motion.
- Transform2D gt = get_global_transform();
- gt.columns[2] -= result.travel;
- set_global_transform(gt);
- }
- // Determines if you are on the ground.
- _snap_on_floor(true, false, true);
- velocity = Vector2();
- last_motion = Vector2();
- motion = Vector2();
- break;
- }
- // Prevents the body from being able to climb a slope when it moves forward against the wall.
- else if (!on_floor) {
- motion = up_direction * up_direction.dot(result.remainder);
- motion = motion.slide(result.collision_normal);
- } else {
- motion = result.remainder;
- }
- }
- // Constant Speed when the slope is upward.
- else if (floor_constant_speed && is_on_floor_only() && can_apply_constant_speed && p_was_on_floor && motion.dot(result.collision_normal) < 0) {
- can_apply_constant_speed = false;
- Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
- motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
- }
- // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
- Vector2 slide_motion = result.remainder.slide(result.collision_normal);
- if (slide_motion.dot(velocity) > 0.0) {
- motion = slide_motion;
- } else {
- motion = Vector2();
- }
- if (slide_on_ceiling && on_ceiling) {
- // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
- if (vel_dir_facing_up) {
- velocity = velocity.slide(result.collision_normal);
- } else {
- // Avoid acceleration in slope when falling.
- velocity = up_direction * up_direction.dot(velocity);
- }
- }
- }
- // No sliding on first attempt to keep floor motion stable when possible.
- else {
- motion = result.remainder;
- if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) {
- velocity = velocity.slide(up_direction);
- motion = motion.slide(up_direction);
- }
- }
-
- last_travel = result.travel;
- }
- // When you move forward in a downward slope you don’t collide because you will be in the air.
- // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
- else if (floor_constant_speed && first_slide && _on_floor_if_snapped(p_was_on_floor, vel_dir_facing_up)) {
- can_apply_constant_speed = false;
- sliding_enabled = true;
- Transform2D gt = get_global_transform();
- gt.columns[2] = prev_position;
- set_global_transform(gt);
-
- Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
- motion = motion_slide_norm * (motion_slide_up.length());
- collided = true;
- }
-
- can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
- sliding_enabled = true;
- first_slide = false;
-
- if (!collided || motion.is_zero_approx()) {
- break;
- }
- }
-
- _snap_on_floor(p_was_on_floor, vel_dir_facing_up);
-
- // Scales the horizontal velocity according to the wall slope.
- if (is_on_wall_only() && motion_slide_up.dot(motion_results.get(0).collision_normal) < 0) {
- Vector2 slide_motion = velocity.slide(motion_results.get(0).collision_normal);
- if (motion_slide_up.dot(slide_motion) < 0) {
- velocity = up_direction * up_direction.dot(velocity);
- } else {
- // Keeps the vertical motion from velocity and add the horizontal motion of the projection.
- velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
- }
- }
-
- // Reset the gravity accumulation when touching the ground.
- if (on_floor && !vel_dir_facing_up) {
- velocity = velocity.slide(up_direction);
- }
-}
-
-void CharacterBody2D::_move_and_slide_floating(double p_delta) {
- Vector2 motion = velocity * p_delta;
-
- platform_rid = RID();
- platform_object_id = ObjectID();
- floor_normal = Vector2();
- platform_velocity = Vector2();
-
- bool first_slide = true;
- for (int iteration = 0; iteration < max_slides; ++iteration) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
-
- PhysicsServer2D::MotionResult result;
- bool collided = move_and_collide(parameters, result, false, false);
-
- last_motion = result.travel;
-
- if (collided) {
- motion_results.push_back(result);
- _set_collision_direction(result);
-
- if (result.remainder.is_zero_approx()) {
- motion = Vector2();
- break;
- }
-
- if (wall_min_slide_angle != 0 && result.get_angle(-velocity.normalized()) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) {
- motion = Vector2();
- } else if (first_slide) {
- Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
- motion = motion_slide_norm * (motion.length() - result.travel.length());
- } else {
- motion = result.remainder.slide(result.collision_normal);
- }
-
- if (motion.dot(velocity) <= 0.0) {
- motion = Vector2();
- }
- }
-
- if (!collided || motion.is_zero_approx()) {
- break;
- }
-
- first_slide = false;
- }
-}
-void CharacterBody2D::apply_floor_snap() {
- _apply_floor_snap();
-}
-
-// Method that avoids the p_wall_as_floor parameter for the public method.
-void CharacterBody2D::_apply_floor_snap(bool p_wall_as_floor) {
- if (on_floor) {
- return;
- }
-
- // Snap by at least collision margin to keep floor state consistent.
- real_t length = MAX(floor_snap_length, margin);
-
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
- parameters.collide_separation_ray = true;
-
- PhysicsServer2D::MotionResult result;
- if (move_and_collide(parameters, result, true, false)) {
- if ((result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) ||
- (p_wall_as_floor && result.get_angle(-up_direction) > floor_max_angle + FLOOR_ANGLE_THRESHOLD)) {
- on_floor = true;
- floor_normal = result.collision_normal;
- _set_platform_data(result);
-
- if (floor_stop_on_slope) {
- // move and collide may stray the object a bit because of pre un-stucking,
- // so only ensure that motion happens on floor direction in this case.
- if (result.travel.length() > margin) {
- result.travel = up_direction * up_direction.dot(result.travel);
- } else {
- result.travel = Vector2();
- }
- }
-
- parameters.from.columns[2] += result.travel;
- set_global_transform(parameters.from);
- }
- }
-}
-
-void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor) {
- if (on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
- return;
- }
-
- _apply_floor_snap(p_wall_as_floor);
-}
-
-bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) {
- if (up_direction == Vector2() || on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
- return false;
- }
-
- // Snap by at least collision margin to keep floor state consistent.
- real_t length = MAX(floor_snap_length, margin);
-
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
- parameters.collide_separation_ray = true;
-
- PhysicsServer2D::MotionResult result;
- if (move_and_collide(parameters, result, true, false)) {
- if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
- return true;
- }
- }
-
- return false;
-}
-
-void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
- if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
- on_floor = true;
- floor_normal = p_result.collision_normal;
- _set_platform_data(p_result);
- } else if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(-up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
- on_ceiling = true;
- } else {
- on_wall = true;
- wall_normal = p_result.collision_normal;
- // Don't apply wall velocity when the collider is a CharacterBody2D.
- if (Object::cast_to<CharacterBody2D>(ObjectDB::get_instance(p_result.collider_id)) == nullptr) {
- _set_platform_data(p_result);
- }
- }
-}
-
-void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) {
- platform_rid = p_result.collider;
- platform_object_id = p_result.collider_id;
- platform_velocity = p_result.collider_velocity;
- platform_layer = PhysicsServer2D::get_singleton()->body_get_collision_layer(platform_rid);
-}
-
-const Vector2 &CharacterBody2D::get_velocity() const {
- return velocity;
-}
-
-void CharacterBody2D::set_velocity(const Vector2 &p_velocity) {
- velocity = p_velocity;
-}
-
-bool CharacterBody2D::is_on_floor() const {
- return on_floor;
-}
-
-bool CharacterBody2D::is_on_floor_only() const {
- return on_floor && !on_wall && !on_ceiling;
-}
-
-bool CharacterBody2D::is_on_wall() const {
- return on_wall;
-}
-
-bool CharacterBody2D::is_on_wall_only() const {
- return on_wall && !on_floor && !on_ceiling;
-}
-
-bool CharacterBody2D::is_on_ceiling() const {
- return on_ceiling;
-}
-
-bool CharacterBody2D::is_on_ceiling_only() const {
- return on_ceiling && !on_floor && !on_wall;
-}
-
-const Vector2 &CharacterBody2D::get_floor_normal() const {
- return floor_normal;
-}
-
-const Vector2 &CharacterBody2D::get_wall_normal() const {
- return wall_normal;
-}
-
-const Vector2 &CharacterBody2D::get_last_motion() const {
- return last_motion;
-}
-
-Vector2 CharacterBody2D::get_position_delta() const {
- return get_global_transform().columns[2] - previous_position;
-}
-
-const Vector2 &CharacterBody2D::get_real_velocity() const {
- return real_velocity;
-}
-
-real_t CharacterBody2D::get_floor_angle(const Vector2 &p_up_direction) const {
- ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
- return Math::acos(floor_normal.dot(p_up_direction));
-}
-
-const Vector2 &CharacterBody2D::get_platform_velocity() const {
- return platform_velocity;
-}
-
-int CharacterBody2D::get_slide_collision_count() const {
- return motion_results.size();
-}
-
-PhysicsServer2D::MotionResult CharacterBody2D::get_slide_collision(int p_bounce) const {
- ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer2D::MotionResult());
- return motion_results[p_bounce];
-}
-
-Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
- ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision2D>());
- if (p_bounce >= slide_colliders.size()) {
- slide_colliders.resize(p_bounce + 1);
- }
-
- // Create a new instance when the cached reference is invalid or still in use in script.
- if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) {
- slide_colliders.write[p_bounce].instantiate();
- slide_colliders.write[p_bounce]->owner = this;
- }
-
- slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
- return slide_colliders[p_bounce];
-}
-
-Ref<KinematicCollision2D> CharacterBody2D::_get_last_slide_collision() {
- if (motion_results.size() == 0) {
- return Ref<KinematicCollision2D>();
- }
- return _get_slide_collision(motion_results.size() - 1);
-}
-
-void CharacterBody2D::set_safe_margin(real_t p_margin) {
- margin = p_margin;
-}
-
-real_t CharacterBody2D::get_safe_margin() const {
- return margin;
-}
-
-bool CharacterBody2D::is_floor_stop_on_slope_enabled() const {
- return floor_stop_on_slope;
-}
-
-void CharacterBody2D::set_floor_stop_on_slope_enabled(bool p_enabled) {
- floor_stop_on_slope = p_enabled;
-}
-
-bool CharacterBody2D::is_floor_constant_speed_enabled() const {
- return floor_constant_speed;
-}
-
-void CharacterBody2D::set_floor_constant_speed_enabled(bool p_enabled) {
- floor_constant_speed = p_enabled;
-}
-
-bool CharacterBody2D::is_floor_block_on_wall_enabled() const {
- return floor_block_on_wall;
-}
-
-void CharacterBody2D::set_floor_block_on_wall_enabled(bool p_enabled) {
- floor_block_on_wall = p_enabled;
-}
-
-bool CharacterBody2D::is_slide_on_ceiling_enabled() const {
- return slide_on_ceiling;
-}
-
-void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) {
- slide_on_ceiling = p_enabled;
-}
-
-uint32_t CharacterBody2D::get_platform_floor_layers() const {
- return platform_floor_layers;
-}
-
-void CharacterBody2D::set_platform_floor_layers(uint32_t p_exclude_layers) {
- platform_floor_layers = p_exclude_layers;
-}
-
-uint32_t CharacterBody2D::get_platform_wall_layers() const {
- return platform_wall_layers;
-}
-
-void CharacterBody2D::set_platform_wall_layers(uint32_t p_exclude_layers) {
- platform_wall_layers = p_exclude_layers;
-}
-
-void CharacterBody2D::set_motion_mode(MotionMode p_mode) {
- motion_mode = p_mode;
-}
-
-CharacterBody2D::MotionMode CharacterBody2D::get_motion_mode() const {
- return motion_mode;
-}
-
-void CharacterBody2D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) {
- platform_on_leave = p_on_leave_apply_velocity;
-}
-
-CharacterBody2D::PlatformOnLeave CharacterBody2D::get_platform_on_leave() const {
- return platform_on_leave;
-}
-
-int CharacterBody2D::get_max_slides() const {
- return max_slides;
-}
-
-void CharacterBody2D::set_max_slides(int p_max_slides) {
- ERR_FAIL_COND(p_max_slides < 1);
- max_slides = p_max_slides;
-}
-
-real_t CharacterBody2D::get_floor_max_angle() const {
- return floor_max_angle;
-}
-
-void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
- floor_max_angle = p_radians;
-}
-
-real_t CharacterBody2D::get_floor_snap_length() {
- return floor_snap_length;
-}
-
-void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) {
- ERR_FAIL_COND(p_floor_snap_length < 0);
- floor_snap_length = p_floor_snap_length;
-}
-
-real_t CharacterBody2D::get_wall_min_slide_angle() const {
- return wall_min_slide_angle;
-}
-
-void CharacterBody2D::set_wall_min_slide_angle(real_t p_radians) {
- wall_min_slide_angle = p_radians;
-}
-
-const Vector2 &CharacterBody2D::get_up_direction() const {
- return up_direction;
-}
-
-void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
- ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Floating motion mode instead.");
- up_direction = p_up_direction.normalized();
-}
-
-void CharacterBody2D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- // Reset move_and_slide() data.
- on_floor = false;
- platform_rid = RID();
- platform_object_id = ObjectID();
- on_ceiling = false;
- on_wall = false;
- motion_results.clear();
- platform_velocity = Vector2();
- } break;
- }
-}
-
-void CharacterBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody2D::move_and_slide);
- ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody2D::apply_floor_snap);
-
- ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody2D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody2D::get_velocity);
-
- ClassDB::bind_method(D_METHOD("set_safe_margin", "margin"), &CharacterBody2D::set_safe_margin);
- ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody2D::get_safe_margin);
- ClassDB::bind_method(D_METHOD("is_floor_stop_on_slope_enabled"), &CharacterBody2D::is_floor_stop_on_slope_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_floor_stop_on_slope_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_constant_speed_enabled", "enabled"), &CharacterBody2D::set_floor_constant_speed_enabled);
- ClassDB::bind_method(D_METHOD("is_floor_constant_speed_enabled"), &CharacterBody2D::is_floor_constant_speed_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_block_on_wall_enabled", "enabled"), &CharacterBody2D::set_floor_block_on_wall_enabled);
- ClassDB::bind_method(D_METHOD("is_floor_block_on_wall_enabled"), &CharacterBody2D::is_floor_block_on_wall_enabled);
- ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled);
- ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled);
-
- ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody2D::set_platform_floor_layers);
- ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody2D::get_platform_floor_layers);
- ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody2D::set_platform_wall_layers);
- ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody2D::get_platform_wall_layers);
-
- ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
- ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
- ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
- ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length);
- ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length);
- ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody2D::get_wall_min_slide_angle);
- ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody2D::set_wall_min_slide_angle);
- ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
- ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
- ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode);
- ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody2D::get_motion_mode);
- ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody2D::set_platform_on_leave);
- ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody2D::get_platform_on_leave);
-
- ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
- ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only);
- ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only);
- ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
- ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only);
- ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
- ClassDB::bind_method(D_METHOD("get_wall_normal"), &CharacterBody2D::get_wall_normal);
- ClassDB::bind_method(D_METHOD("get_last_motion"), &CharacterBody2D::get_last_motion);
- ClassDB::bind_method(D_METHOD("get_position_delta"), &CharacterBody2D::get_position_delta);
- ClassDB::bind_method(D_METHOD("get_real_velocity"), &CharacterBody2D::get_real_velocity);
- ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &CharacterBody2D::get_floor_angle, DEFVAL(Vector2(0.0, -1.0)));
- ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity);
- ClassDB::bind_method(D_METHOD("get_slide_collision_count"), &CharacterBody2D::get_slide_collision_count);
- ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
- ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody2D::_get_last_slide_collision);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle");
-
- ADD_GROUP("Floor", "floor_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees"), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length");
-
- ADD_GROUP("Moving Platform", "platform_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
-
- ADD_GROUP("Collision", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:px"), "set_safe_margin", "get_safe_margin");
-
- BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED);
- BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING);
-
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY);
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY);
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING);
-}
-
-void CharacterBody2D::_validate_property(PropertyInfo &p_property) const {
- if (motion_mode == MOTION_MODE_FLOATING) {
- if (p_property.name.begins_with("floor_") || p_property.name == "up_direction" || p_property.name == "slide_on_ceiling") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
- } else {
- if (p_property.name == "wall_min_slide_angle") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
- }
-}
-
-CharacterBody2D::CharacterBody2D() :
- PhysicsBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
-}
-
-CharacterBody2D::~CharacterBody2D() {
- for (int i = 0; i < slide_colliders.size(); i++) {
- if (slide_colliders[i].is_valid()) {
- slide_colliders.write[i]->owner = nullptr;
- }
- }
-}
-
-////////////////////////
-
-Vector2 KinematicCollision2D::get_position() const {
- return result.collision_point;
-}
-
-Vector2 KinematicCollision2D::get_normal() const {
- return result.collision_normal;
-}
-
-Vector2 KinematicCollision2D::get_travel() const {
- return result.travel;
-}
-
-Vector2 KinematicCollision2D::get_remainder() const {
- return result.remainder;
-}
-
-real_t KinematicCollision2D::get_angle(const Vector2 &p_up_direction) const {
- ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
- return result.get_angle(p_up_direction);
-}
-
-real_t KinematicCollision2D::get_depth() const {
- return result.collision_depth;
-}
-
-Object *KinematicCollision2D::get_local_shape() const {
- if (!owner) {
- return nullptr;
- }
- uint32_t ownerid = owner->shape_find_owner(result.collision_local_shape);
- return owner->shape_owner_get_owner(ownerid);
-}
-
-Object *KinematicCollision2D::get_collider() const {
- if (result.collider_id.is_valid()) {
- return ObjectDB::get_instance(result.collider_id);
- }
-
- return nullptr;
-}
-
-ObjectID KinematicCollision2D::get_collider_id() const {
- return result.collider_id;
-}
-
-RID KinematicCollision2D::get_collider_rid() const {
- return result.collider;
-}
-
-Object *KinematicCollision2D::get_collider_shape() const {
- Object *collider = get_collider();
- if (collider) {
- CollisionObject2D *obj2d = Object::cast_to<CollisionObject2D>(collider);
- if (obj2d) {
- uint32_t ownerid = obj2d->shape_find_owner(result.collider_shape);
- return obj2d->shape_owner_get_owner(ownerid);
- }
- }
-
- return nullptr;
-}
-
-int KinematicCollision2D::get_collider_shape_index() const {
- return result.collider_shape;
-}
-
-Vector2 KinematicCollision2D::get_collider_velocity() const {
- return result.collider_velocity;
-}
-
-void KinematicCollision2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision2D::get_position);
- ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision2D::get_normal);
- ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision2D::get_travel);
- ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision2D::get_remainder);
- ClassDB::bind_method(D_METHOD("get_angle", "up_direction"), &KinematicCollision2D::get_angle, DEFVAL(Vector2(0.0, -1.0)));
- ClassDB::bind_method(D_METHOD("get_depth"), &KinematicCollision2D::get_depth);
- ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision2D::get_local_shape);
- ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision2D::get_collider);
- ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision2D::get_collider_id);
- ClassDB::bind_method(D_METHOD("get_collider_rid"), &KinematicCollision2D::get_collider_rid);
- ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision2D::get_collider_shape);
- ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision2D::get_collider_shape_index);
- ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision2D::get_collider_velocity);
-}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
deleted file mode 100644
index 88161e284a..0000000000
--- a/scene/2d/physics_body_2d.h
+++ /dev/null
@@ -1,493 +0,0 @@
-/**************************************************************************/
-/* physics_body_2d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef PHYSICS_BODY_2D_H
-#define PHYSICS_BODY_2D_H
-
-#include "core/templates/vset.h"
-#include "scene/2d/collision_object_2d.h"
-#include "scene/resources/physics_material.h"
-#include "servers/physics_server_2d.h"
-
-class KinematicCollision2D;
-
-class PhysicsBody2D : public CollisionObject2D {
- GDCLASS(PhysicsBody2D, CollisionObject2D);
-
-protected:
- static void _bind_methods();
- PhysicsBody2D(PhysicsServer2D::BodyMode p_mode);
-
- Ref<KinematicCollision2D> motion_cache;
-
- Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
-
-public:
- bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
- Vector2 get_gravity() const;
-
- TypedArray<PhysicsBody2D> get_collision_exceptions();
- void add_collision_exception_with(Node *p_node); //must be physicsbody
- void remove_collision_exception_with(Node *p_node);
-
- virtual ~PhysicsBody2D();
-};
-
-class StaticBody2D : public PhysicsBody2D {
- GDCLASS(StaticBody2D, PhysicsBody2D);
-
-private:
- Vector2 constant_linear_velocity;
- real_t constant_angular_velocity = 0.0;
-
- Ref<PhysicsMaterial> physics_material_override;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
- Ref<PhysicsMaterial> get_physics_material_override() const;
-
- void set_constant_linear_velocity(const Vector2 &p_vel);
- void set_constant_angular_velocity(real_t p_vel);
-
- Vector2 get_constant_linear_velocity() const;
- real_t get_constant_angular_velocity() const;
-
- StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC);
-
-private:
- void _reload_physics_characteristics();
-};
-
-class AnimatableBody2D : public StaticBody2D {
- GDCLASS(AnimatableBody2D, StaticBody2D);
-
-private:
- bool sync_to_physics = true;
-
- Transform2D last_valid_transform;
-
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
- void _body_state_changed(PhysicsDirectBodyState2D *p_state);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- AnimatableBody2D();
-
-private:
- void _update_kinematic_motion();
-
- void set_sync_to_physics(bool p_enable);
- bool is_sync_to_physics_enabled() const;
-};
-
-class RigidBody2D : public PhysicsBody2D {
- GDCLASS(RigidBody2D, PhysicsBody2D);
-
-public:
- enum FreezeMode {
- FREEZE_MODE_STATIC,
- FREEZE_MODE_KINEMATIC,
- };
-
- enum CenterOfMassMode {
- CENTER_OF_MASS_MODE_AUTO,
- CENTER_OF_MASS_MODE_CUSTOM,
- };
-
- enum DampMode {
- DAMP_MODE_COMBINE,
- DAMP_MODE_REPLACE,
- };
-
- enum CCDMode {
- CCD_MODE_DISABLED,
- CCD_MODE_CAST_RAY,
- CCD_MODE_CAST_SHAPE,
- };
-
-private:
- bool can_sleep = true;
- bool lock_rotation = false;
- bool freeze = false;
- FreezeMode freeze_mode = FREEZE_MODE_STATIC;
-
- real_t mass = 1.0;
- real_t inertia = 0.0;
- CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
- Vector2 center_of_mass;
-
- Ref<PhysicsMaterial> physics_material_override;
- real_t gravity_scale = 1.0;
-
- DampMode linear_damp_mode = DAMP_MODE_COMBINE;
- DampMode angular_damp_mode = DAMP_MODE_COMBINE;
-
- real_t linear_damp = 0.0;
- real_t angular_damp = 0.0;
-
- Vector2 linear_velocity;
- real_t angular_velocity = 0.0;
- bool sleeping = false;
-
- int max_contacts_reported = 0;
- int contact_count = 0;
-
- bool custom_integrator = false;
-
- CCDMode ccd_mode = CCD_MODE_DISABLED;
-
- struct ShapePair {
- int body_shape = 0;
- int local_shape = 0;
- bool tagged = false;
- bool operator<(const ShapePair &p_sp) const {
- if (body_shape == p_sp.body_shape) {
- return local_shape < p_sp.local_shape;
- }
-
- return body_shape < p_sp.body_shape;
- }
-
- ShapePair() {}
- ShapePair(int p_bs, int p_ls) {
- body_shape = p_bs;
- local_shape = p_ls;
- }
- };
- struct RigidBody2D_RemoveAction {
- RID rid;
- ObjectID body_id;
- ShapePair pair;
- };
- struct BodyState {
- RID rid;
- //int rc;
- bool in_scene = false;
- VSet<ShapePair> shapes;
- };
-
- struct ContactMonitor {
- bool locked = false;
- HashMap<ObjectID, BodyState> body_map;
- };
-
- ContactMonitor *contact_monitor = nullptr;
- void _body_enter_tree(ObjectID p_id);
- void _body_exit_tree(ObjectID p_id);
-
- void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
-
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
- void _body_state_changed(PhysicsDirectBodyState2D *p_state);
-
- void _sync_body_state(PhysicsDirectBodyState2D *p_state);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
- void _validate_property(PropertyInfo &p_property) const;
-
- GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState2D *)
-
- void _apply_body_mode();
-
-public:
- void set_lock_rotation_enabled(bool p_lock_rotation);
- bool is_lock_rotation_enabled() const;
-
- void set_freeze_enabled(bool p_freeze);
- bool is_freeze_enabled() const;
-
- void set_freeze_mode(FreezeMode p_freeze_mode);
- FreezeMode get_freeze_mode() const;
-
- void set_mass(real_t p_mass);
- real_t get_mass() const;
-
- void set_inertia(real_t p_inertia);
- real_t get_inertia() const;
-
- void set_center_of_mass_mode(CenterOfMassMode p_mode);
- CenterOfMassMode get_center_of_mass_mode() const;
-
- void set_center_of_mass(const Vector2 &p_center_of_mass);
- const Vector2 &get_center_of_mass() const;
-
- void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
- Ref<PhysicsMaterial> get_physics_material_override() const;
-
- void set_gravity_scale(real_t p_gravity_scale);
- real_t get_gravity_scale() const;
-
- void set_linear_damp_mode(DampMode p_mode);
- DampMode get_linear_damp_mode() const;
-
- void set_angular_damp_mode(DampMode p_mode);
- DampMode get_angular_damp_mode() const;
-
- void set_linear_damp(real_t p_linear_damp);
- real_t get_linear_damp() const;
-
- void set_angular_damp(real_t p_angular_damp);
- real_t get_angular_damp() const;
-
- void set_linear_velocity(const Vector2 &p_velocity);
- Vector2 get_linear_velocity() const;
-
- void set_axis_velocity(const Vector2 &p_axis);
-
- void set_angular_velocity(real_t p_velocity);
- real_t get_angular_velocity() const;
-
- void set_use_custom_integrator(bool p_enable);
- bool is_using_custom_integrator();
-
- void set_sleeping(bool p_sleeping);
- bool is_sleeping() const;
-
- void set_can_sleep(bool p_active);
- bool is_able_to_sleep() const;
-
- void set_contact_monitor(bool p_enabled);
- bool is_contact_monitor_enabled() const;
-
- void set_max_contacts_reported(int p_amount);
- int get_max_contacts_reported() const;
- int get_contact_count() const;
-
- void set_continuous_collision_detection_mode(CCDMode p_mode);
- CCDMode get_continuous_collision_detection_mode() const;
-
- void apply_central_impulse(const Vector2 &p_impulse);
- void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2());
- void apply_torque_impulse(real_t p_torque);
-
- void apply_central_force(const Vector2 &p_force);
- void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
- void apply_torque(real_t p_torque);
-
- void add_constant_central_force(const Vector2 &p_force);
- void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
- void add_constant_torque(real_t p_torque);
-
- void set_constant_force(const Vector2 &p_force);
- Vector2 get_constant_force() const;
-
- void set_constant_torque(real_t p_torque);
- real_t get_constant_torque() const;
-
- TypedArray<Node2D> get_colliding_bodies() const; //function for script
-
- virtual PackedStringArray get_configuration_warnings() const override;
-
- RigidBody2D();
- ~RigidBody2D();
-
-private:
- void _reload_physics_characteristics();
-};
-
-VARIANT_ENUM_CAST(RigidBody2D::FreezeMode);
-VARIANT_ENUM_CAST(RigidBody2D::CenterOfMassMode);
-VARIANT_ENUM_CAST(RigidBody2D::DampMode);
-VARIANT_ENUM_CAST(RigidBody2D::CCDMode);
-
-class CharacterBody2D : public PhysicsBody2D {
- GDCLASS(CharacterBody2D, PhysicsBody2D);
-
-public:
- enum MotionMode {
- MOTION_MODE_GROUNDED,
- MOTION_MODE_FLOATING,
- };
- enum PlatformOnLeave {
- PLATFORM_ON_LEAVE_ADD_VELOCITY,
- PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY,
- PLATFORM_ON_LEAVE_DO_NOTHING,
- };
- bool move_and_slide();
- void apply_floor_snap();
-
- const Vector2 &get_velocity() const;
- void set_velocity(const Vector2 &p_velocity);
-
- bool is_on_floor() const;
- bool is_on_floor_only() const;
- bool is_on_wall() const;
- bool is_on_wall_only() const;
- bool is_on_ceiling() const;
- bool is_on_ceiling_only() const;
- const Vector2 &get_last_motion() const;
- Vector2 get_position_delta() const;
- const Vector2 &get_floor_normal() const;
- const Vector2 &get_wall_normal() const;
- const Vector2 &get_real_velocity() const;
-
- real_t get_floor_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const;
- const Vector2 &get_platform_velocity() const;
-
- int get_slide_collision_count() const;
- PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
-
- void set_safe_margin(real_t p_margin);
- real_t get_safe_margin() const;
-
- bool is_floor_stop_on_slope_enabled() const;
- void set_floor_stop_on_slope_enabled(bool p_enabled);
-
- bool is_floor_constant_speed_enabled() const;
- void set_floor_constant_speed_enabled(bool p_enabled);
-
- bool is_floor_block_on_wall_enabled() const;
- void set_floor_block_on_wall_enabled(bool p_enabled);
-
- bool is_slide_on_ceiling_enabled() const;
- void set_slide_on_ceiling_enabled(bool p_enabled);
-
- int get_max_slides() const;
- void set_max_slides(int p_max_slides);
-
- real_t get_floor_max_angle() const;
- void set_floor_max_angle(real_t p_radians);
-
- real_t get_floor_snap_length();
- void set_floor_snap_length(real_t p_floor_snap_length);
-
- real_t get_wall_min_slide_angle() const;
- void set_wall_min_slide_angle(real_t p_radians);
-
- uint32_t get_platform_floor_layers() const;
- void set_platform_floor_layers(const uint32_t p_exclude_layer);
-
- uint32_t get_platform_wall_layers() const;
- void set_platform_wall_layers(const uint32_t p_exclude_layer);
-
- void set_motion_mode(MotionMode p_mode);
- MotionMode get_motion_mode() const;
-
- void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity);
- PlatformOnLeave get_platform_on_leave() const;
-
- CharacterBody2D();
- ~CharacterBody2D();
-
-private:
- real_t margin = 0.08;
- MotionMode motion_mode = MOTION_MODE_GROUNDED;
- PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY;
-
- bool floor_constant_speed = false;
- bool floor_stop_on_slope = true;
- bool floor_block_on_wall = true;
- bool slide_on_ceiling = true;
- int max_slides = 4;
- int platform_layer = 0;
- real_t floor_max_angle = Math::deg_to_rad((real_t)45.0);
- real_t floor_snap_length = 1;
- real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0);
- Vector2 up_direction = Vector2(0.0, -1.0);
- uint32_t platform_floor_layers = UINT32_MAX;
- uint32_t platform_wall_layers = 0;
- Vector2 velocity;
-
- Vector2 floor_normal;
- Vector2 platform_velocity;
- Vector2 wall_normal;
- Vector2 last_motion;
- Vector2 previous_position;
- Vector2 real_velocity;
-
- RID platform_rid;
- ObjectID platform_object_id;
- bool on_floor = false;
- bool on_ceiling = false;
- bool on_wall = false;
-
- Vector<PhysicsServer2D::MotionResult> motion_results;
- Vector<Ref<KinematicCollision2D>> slide_colliders;
-
- void _move_and_slide_floating(double p_delta);
- void _move_and_slide_grounded(double p_delta, bool p_was_on_floor);
-
- Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
- Ref<KinematicCollision2D> _get_last_slide_collision();
- const Vector2 &get_up_direction() const;
- bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up);
- void set_up_direction(const Vector2 &p_up_direction);
- void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
- void _set_platform_data(const PhysicsServer2D::MotionResult &p_result);
- void _apply_floor_snap(bool p_wall_as_floor = false);
- void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor = false);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
- void _validate_property(PropertyInfo &p_property) const;
-};
-
-VARIANT_ENUM_CAST(CharacterBody2D::MotionMode);
-VARIANT_ENUM_CAST(CharacterBody2D::PlatformOnLeave);
-
-class KinematicCollision2D : public RefCounted {
- GDCLASS(KinematicCollision2D, RefCounted);
-
- PhysicsBody2D *owner = nullptr;
- friend class PhysicsBody2D;
- friend class CharacterBody2D;
- PhysicsServer2D::MotionResult result;
-
-protected:
- static void _bind_methods();
-
-public:
- Vector2 get_position() const;
- Vector2 get_normal() const;
- Vector2 get_travel() const;
- Vector2 get_remainder() const;
- real_t get_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const;
- real_t get_depth() const;
- Object *get_local_shape() const;
- Object *get_collider() const;
- ObjectID get_collider_id() const;
- RID get_collider_rid() const;
- Object *get_collider_shape() const;
- int get_collider_shape_index() const;
- Vector2 get_collider_velocity() const;
-};
-
-#endif // PHYSICS_BODY_2D_H
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index 2753fee7e9..c9431f53d8 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -1625,8 +1625,11 @@ void TileMapLayer::_queue_internal_update() {
if (pending_update) {
return;
}
- pending_update = true;
- callable_mp(this, &TileMapLayer::_deferred_internal_update).call_deferred();
+ // Don't update when outside the tree, it doesn't do anything useful, and causes threading problems.
+ if (is_inside_tree()) {
+ pending_update = true;
+ callable_mp(this, &TileMapLayer::_deferred_internal_update).call_deferred();
+ }
}
void TileMapLayer::_deferred_internal_update() {
@@ -1695,7 +1698,8 @@ void TileMapLayer::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
- _queue_internal_update();
+ // Update immediately on exiting.
+ update_internals();
} break;
case TileMap::NOTIFICATION_ENTER_CANVAS: {
@@ -1705,7 +1709,8 @@ void TileMapLayer::_notification(int p_what) {
case TileMap::NOTIFICATION_EXIT_CANVAS: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
- _queue_internal_update();
+ // Update immediately on exiting.
+ update_internals();
} break;
case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
diff --git a/scene/3d/SCsub b/scene/3d/SCsub
index fc61250247..94e1ab6c96 100644
--- a/scene/3d/SCsub
+++ b/scene/3d/SCsub
@@ -3,3 +3,6 @@
Import("env")
env.add_source_files(env.scene_sources, "*.cpp")
+
+# Chain load SCsubs
+SConscript("physics/SCsub")
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 2bb376c9ab..f1f9a04ea0 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -32,9 +32,9 @@
#include "audio_stream_player_3d.compat.inc"
#include "core/config/project_settings.h"
-#include "scene/3d/area_3d.h"
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/camera_3d.h"
+#include "scene/3d/physics/area_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
#include "scene/audio/audio_stream_player_internal.h"
#include "scene/main/viewport.h"
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index a44aa54c17..e8bd498e1f 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -30,7 +30,6 @@
#include "camera_3d.h"
-#include "collision_object_3d.h"
#include "core/math/projection.h"
#include "scene/main/viewport.h"
diff --git a/scene/3d/joint_3d.h b/scene/3d/joint_3d.h
deleted file mode 100644
index 527aed4079..0000000000
--- a/scene/3d/joint_3d.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/**************************************************************************/
-/* joint_3d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef JOINT_3D_H
-#define JOINT_3D_H
-
-#include "scene/3d/node_3d.h"
-#include "scene/3d/physics_body_3d.h"
-
-class Joint3D : public Node3D {
- GDCLASS(Joint3D, Node3D);
-
- RID ba, bb;
-
- RID joint;
-
- NodePath a;
- NodePath b;
-
- int solver_priority = 1;
- bool exclude_from_collision = true;
- String warning;
- bool configured = false;
-
-protected:
- void _disconnect_signals();
- void _body_exit_tree();
- void _update_joint(bool p_only_free = false);
-
- void _notification(int p_what);
-
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
-
- static void _bind_methods();
-
- _FORCE_INLINE_ bool is_configured() const { return configured; }
-
-public:
- virtual PackedStringArray get_configuration_warnings() const override;
-
- void set_node_a(const NodePath &p_node_a);
- NodePath get_node_a() const;
-
- void set_node_b(const NodePath &p_node_b);
- NodePath get_node_b() const;
-
- void set_solver_priority(int p_priority);
- int get_solver_priority() const;
-
- void set_exclude_nodes_from_collision(bool p_enable);
- bool get_exclude_nodes_from_collision() const;
-
- RID get_rid() const { return joint; }
- Joint3D();
- ~Joint3D();
-};
-
-///////////////////////////////////////////
-
-class PinJoint3D : public Joint3D {
- GDCLASS(PinJoint3D, Joint3D);
-
-public:
- enum Param {
- PARAM_BIAS = PhysicsServer3D::PIN_JOINT_BIAS,
- PARAM_DAMPING = PhysicsServer3D::PIN_JOINT_DAMPING,
- PARAM_IMPULSE_CLAMP = PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP
- };
-
-protected:
- real_t params[3];
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_param(Param p_param, real_t p_value);
- real_t get_param(Param p_param) const;
-
- PinJoint3D();
-};
-
-VARIANT_ENUM_CAST(PinJoint3D::Param);
-
-class HingeJoint3D : public Joint3D {
- GDCLASS(HingeJoint3D, Joint3D);
-
-public:
- enum Param {
- PARAM_BIAS = PhysicsServer3D::HINGE_JOINT_BIAS,
- PARAM_LIMIT_UPPER = PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER,
- PARAM_LIMIT_LOWER = PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER,
- PARAM_LIMIT_BIAS = PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS,
- PARAM_LIMIT_SOFTNESS = PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS,
- PARAM_LIMIT_RELAXATION = PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION,
- PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY,
- PARAM_MOTOR_MAX_IMPULSE = PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE,
- PARAM_MAX = PhysicsServer3D::HINGE_JOINT_MAX
- };
-
- enum Flag {
- FLAG_USE_LIMIT = PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT,
- FLAG_ENABLE_MOTOR = PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR,
- FLAG_MAX = PhysicsServer3D::HINGE_JOINT_FLAG_MAX
- };
-
-protected:
- real_t params[PARAM_MAX];
- bool flags[FLAG_MAX];
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_param(Param p_param, real_t p_value);
- real_t get_param(Param p_param) const;
-
- void set_flag(Flag p_flag, bool p_value);
- bool get_flag(Flag p_flag) const;
-
- HingeJoint3D();
-};
-
-VARIANT_ENUM_CAST(HingeJoint3D::Param);
-VARIANT_ENUM_CAST(HingeJoint3D::Flag);
-
-class SliderJoint3D : public Joint3D {
- GDCLASS(SliderJoint3D, Joint3D);
-
-public:
- enum Param {
- PARAM_LINEAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER,
- PARAM_LINEAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER,
- PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS,
- PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION,
- PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING,
- PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS,
- PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION,
- PARAM_LINEAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING,
- PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS,
- PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION,
- PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING,
-
- PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER,
- PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER,
- PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS,
- PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION,
- PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING,
- PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS,
- PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION,
- PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING,
- PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS,
- PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION,
- PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING,
- PARAM_MAX = PhysicsServer3D::SLIDER_JOINT_MAX
-
- };
-
-protected:
- real_t params[PARAM_MAX];
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_param(Param p_param, real_t p_value);
- real_t get_param(Param p_param) const;
-
- SliderJoint3D();
-};
-
-VARIANT_ENUM_CAST(SliderJoint3D::Param);
-
-class ConeTwistJoint3D : public Joint3D {
- GDCLASS(ConeTwistJoint3D, Joint3D);
-
-public:
- enum Param {
- PARAM_SWING_SPAN,
- PARAM_TWIST_SPAN,
- PARAM_BIAS,
- PARAM_SOFTNESS,
- PARAM_RELAXATION,
- PARAM_MAX
- };
-
-protected:
- real_t params[PARAM_MAX];
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_param(Param p_param, real_t p_value);
- real_t get_param(Param p_param) const;
-
- ConeTwistJoint3D();
-};
-
-VARIANT_ENUM_CAST(ConeTwistJoint3D::Param);
-
-class Generic6DOFJoint3D : public Joint3D {
- GDCLASS(Generic6DOFJoint3D, Joint3D);
-
-public:
- enum Param {
- PARAM_LINEAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT,
- PARAM_LINEAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT,
- PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS,
- PARAM_LINEAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION,
- PARAM_LINEAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING,
- PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
- PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
- PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
- PARAM_LINEAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING,
- PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
- PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
- PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
- PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
- PARAM_ANGULAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING,
- PARAM_ANGULAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION,
- PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT,
- PARAM_ANGULAR_ERP = PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP,
- PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
- PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
- PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
- PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
- PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
- PARAM_MAX = PhysicsServer3D::G6DOF_JOINT_MAX,
- };
-
- enum Flag {
- FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
- FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
- FLAG_ENABLE_LINEAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
- FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
- FLAG_ENABLE_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR,
- FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
- FLAG_MAX = PhysicsServer3D::G6DOF_JOINT_FLAG_MAX
- };
-
-protected:
- real_t params_x[PARAM_MAX];
- bool flags_x[FLAG_MAX];
- real_t params_y[PARAM_MAX];
- bool flags_y[FLAG_MAX];
- real_t params_z[PARAM_MAX];
- bool flags_z[FLAG_MAX];
-
- virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
- static void _bind_methods();
-
-public:
- void set_param_x(Param p_param, real_t p_value);
- real_t get_param_x(Param p_param) const;
-
- void set_param_y(Param p_param, real_t p_value);
- real_t get_param_y(Param p_param) const;
-
- void set_param_z(Param p_param, real_t p_value);
- real_t get_param_z(Param p_param) const;
-
- void set_flag_x(Flag p_flag, bool p_enabled);
- bool get_flag_x(Flag p_flag) const;
-
- void set_flag_y(Flag p_flag, bool p_enabled);
- bool get_flag_y(Flag p_flag) const;
-
- void set_flag_z(Flag p_flag, bool p_enabled);
- bool get_flag_z(Flag p_flag) const;
-
- Generic6DOFJoint3D();
-};
-
-VARIANT_ENUM_CAST(Generic6DOFJoint3D::Param);
-VARIANT_ENUM_CAST(Generic6DOFJoint3D::Flag);
-
-#endif // JOINT_3D_H
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index eeb41573f7..8635240655 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -30,8 +30,9 @@
#include "mesh_instance_3d.h"
-#include "collision_shape_3d.h"
-#include "physics_body_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
+#include "scene/3d/skeleton_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
#include "scene/resources/3d/convex_polygon_shape_3d.h"
diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp
index 98cd5efef2..82450927d3 100644
--- a/scene/3d/navigation_obstacle_3d.cpp
+++ b/scene/3d/navigation_obstacle_3d.cpp
@@ -31,8 +31,6 @@
#include "navigation_obstacle_3d.h"
#include "core/math/geometry_2d.h"
-#include "scene/3d/collision_shape_3d.h"
-#include "scene/3d/physics_body_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
diff --git a/scene/3d/physics/SCsub b/scene/3d/physics/SCsub
new file mode 100644
index 0000000000..e7fd3fe643
--- /dev/null
+++ b/scene/3d/physics/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.scene_sources, "*.cpp")
+
+# Chain load SCsubs
+SConscript("joints/SCsub")
diff --git a/scene/3d/physics/animatable_body_3d.cpp b/scene/3d/physics/animatable_body_3d.cpp
new file mode 100644
index 0000000000..407e23a57e
--- /dev/null
+++ b/scene/3d/physics/animatable_body_3d.cpp
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/* animatable_body_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "animatable_body_3d.h"
+
+Vector3 AnimatableBody3D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+Vector3 AnimatableBody3D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void AnimatableBody3D::set_sync_to_physics(bool p_enable) {
+ if (sync_to_physics == p_enable) {
+ return;
+ }
+
+ sync_to_physics = p_enable;
+
+ _update_kinematic_motion();
+}
+
+bool AnimatableBody3D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void AnimatableBody3D::_update_kinematic_motion() {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+
+ if (sync_to_physics) {
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ }
+}
+
+void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
+ linear_velocity = p_state->get_linear_velocity();
+ angular_velocity = p_state->get_angular_velocity();
+
+ if (!sync_to_physics) {
+ return;
+ }
+
+ last_valid_transform = p_state->get_transform();
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ _on_transform_changed();
+}
+
+void AnimatableBody3D::_notification(int p_what) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+#endif
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ last_valid_transform = get_global_transform();
+ _update_kinematic_motion();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ // Used by sync to physics, send the new transform to the physics...
+ Transform3D new_transform = get_global_transform();
+
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+
+ // ... but then revert changes.
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ _on_transform_changed();
+ } break;
+ }
+}
+
+void AnimatableBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody3D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody3D::is_sync_to_physics_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
+}
+
+AnimatableBody3D::AnimatableBody3D() :
+ StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody3D::_body_state_changed));
+}
diff --git a/scene/3d/physics/animatable_body_3d.h b/scene/3d/physics/animatable_body_3d.h
new file mode 100644
index 0000000000..715b6917c0
--- /dev/null
+++ b/scene/3d/physics/animatable_body_3d.h
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* animatable_body_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef ANIMATABLE_BODY_3D_H
+#define ANIMATABLE_BODY_3D_H
+
+#include "scene/3d/physics/static_body_3d.h"
+
+class AnimatableBody3D : public StaticBody3D {
+ GDCLASS(AnimatableBody3D, StaticBody3D);
+
+private:
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+
+ bool sync_to_physics = true;
+
+ Transform3D last_valid_transform;
+
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState3D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ virtual Vector3 get_linear_velocity() const override;
+ virtual Vector3 get_angular_velocity() const override;
+
+ AnimatableBody3D();
+
+private:
+ void _update_kinematic_motion();
+
+ void set_sync_to_physics(bool p_enable);
+ bool is_sync_to_physics_enabled() const;
+};
+
+#endif // ANIMATABLE_BODY_3D_H
diff --git a/scene/3d/area_3d.cpp b/scene/3d/physics/area_3d.cpp
index 014c33cad0..014c33cad0 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/physics/area_3d.cpp
diff --git a/scene/3d/area_3d.h b/scene/3d/physics/area_3d.h
index 05c558e8f0..41382b6128 100644
--- a/scene/3d/area_3d.h
+++ b/scene/3d/physics/area_3d.h
@@ -32,7 +32,7 @@
#define AREA_3D_H
#include "core/templates/vset.h"
-#include "scene/3d/collision_object_3d.h"
+#include "scene/3d/physics/collision_object_3d.h"
#include "scene/scene_string_names.h"
class Area3D : public CollisionObject3D {
diff --git a/scene/3d/physics/character_body_3d.cpp b/scene/3d/physics/character_body_3d.cpp
new file mode 100644
index 0000000000..b71b9519a9
--- /dev/null
+++ b/scene/3d/physics/character_body_3d.cpp
@@ -0,0 +1,939 @@
+/**************************************************************************/
+/* character_body_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "character_body_3d.h"
+
+//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
+#define FLOOR_ANGLE_THRESHOLD 0.01
+
+bool CharacterBody3D::move_and_slide() {
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
+ double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
+
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ velocity[i] = 0.0;
+ }
+ }
+
+ Transform3D gt = get_global_transform();
+ previous_position = gt.origin;
+
+ Vector3 current_platform_velocity = platform_velocity;
+
+ if ((collision_state.floor || collision_state.wall) && platform_rid.is_valid()) {
+ bool excluded = false;
+ if (collision_state.floor) {
+ excluded = (platform_floor_layers & platform_layer) == 0;
+ } else if (collision_state.wall) {
+ excluded = (platform_wall_layers & platform_layer) == 0;
+ }
+ if (!excluded) {
+ //this approach makes sure there is less delay between the actual body velocity and the one we saved
+ PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(platform_rid);
+ if (bs) {
+ Vector3 local_position = gt.origin - bs->get_transform().origin;
+ current_platform_velocity = bs->get_velocity_at_local_position(local_position);
+ } else {
+ // Body is removed or destroyed, invalidate floor.
+ current_platform_velocity = Vector3();
+ platform_rid = RID();
+ }
+ } else {
+ current_platform_velocity = Vector3();
+ }
+ }
+
+ motion_results.clear();
+
+ bool was_on_floor = collision_state.floor;
+ collision_state.state = 0;
+
+ last_motion = Vector3();
+
+ if (!current_platform_velocity.is_zero_approx()) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
+ parameters.exclude_bodies.insert(platform_rid);
+ if (platform_object_id.is_valid()) {
+ parameters.exclude_objects.insert(platform_object_id);
+ }
+
+ PhysicsServer3D::MotionResult floor_result;
+ if (move_and_collide(parameters, floor_result, false, false)) {
+ motion_results.push_back(floor_result);
+
+ CollisionState result_state;
+ _set_collision_direction(floor_result, result_state);
+ }
+ }
+
+ if (motion_mode == MOTION_MODE_GROUNDED) {
+ _move_and_slide_grounded(delta, was_on_floor);
+ } else {
+ _move_and_slide_floating(delta);
+ }
+
+ // Compute real velocity.
+ real_velocity = get_position_delta() / delta;
+
+ if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) {
+ // Add last platform velocity when just left a moving platform.
+ if (!collision_state.floor && !collision_state.wall) {
+ if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) {
+ current_platform_velocity = current_platform_velocity.slide(up_direction);
+ }
+ velocity += current_platform_velocity;
+ }
+ }
+
+ return motion_results.size() > 0;
+}
+
+void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
+ Vector3 motion = velocity * p_delta;
+ Vector3 motion_slide_up = motion.slide(up_direction);
+ Vector3 prev_floor_normal = floor_normal;
+
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ platform_velocity = Vector3();
+ platform_angular_velocity = Vector3();
+ platform_ceiling_velocity = Vector3();
+ floor_normal = Vector3();
+ wall_normal = Vector3();
+ ceiling_normal = Vector3();
+
+ // No sliding on first attempt to keep floor motion stable when possible,
+ // When stop on slope is enabled or when there is no up direction.
+ bool sliding_enabled = !floor_stop_on_slope;
+ // Constant speed can be applied only the first time sliding is enabled.
+ bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
+ bool first_slide = true;
+ bool vel_dir_facing_up = velocity.dot(up_direction) > 0;
+ Vector3 total_travel;
+
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.max_collisions = 6; // There can be 4 collisions between 2 walls + 2 more for the floor.
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
+ PhysicsServer3D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
+
+ last_motion = result.travel;
+
+ if (collided) {
+ motion_results.push_back(result);
+
+ CollisionState previous_state = collision_state;
+
+ CollisionState result_state;
+ _set_collision_direction(result, result_state);
+
+ // If we hit a ceiling platform, we set the vertical velocity to at least the platform one.
+ if (collision_state.ceiling && platform_ceiling_velocity != Vector3() && platform_ceiling_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (ceiling_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector3 ceiling_vertical_velocity = up_direction * up_direction.dot(platform_ceiling_velocity);
+ Vector3 motion_vertical_velocity = up_direction * up_direction.dot(velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
+ }
+ }
+ }
+
+ if (collision_state.floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
+ Transform3D gt = get_global_transform();
+ if (result.travel.length() <= margin + CMP_EPSILON) {
+ gt.origin -= result.travel;
+ }
+ set_global_transform(gt);
+ velocity = Vector3();
+ motion = Vector3();
+ last_motion = Vector3();
+ break;
+ }
+
+ if (result.remainder.is_zero_approx()) {
+ motion = Vector3();
+ break;
+ }
+
+ // Apply regular sliding by default.
+ bool apply_default_sliding = true;
+
+ // Wall collision checks.
+ if (result_state.wall && (motion_slide_up.dot(wall_normal) <= 0)) {
+ // Move on floor only checks.
+ if (floor_block_on_wall) {
+ // Needs horizontal motion from current motion instead of motion_slide_up
+ // to properly test the angle and avoid standing on slopes
+ Vector3 horizontal_motion = motion.slide(up_direction);
+ Vector3 horizontal_normal = wall_normal.slide(up_direction).normalized();
+ real_t motion_angle = Math::abs(Math::acos(-horizontal_normal.dot(horizontal_motion.normalized())));
+
+ // Avoid to move forward on a wall if floor_block_on_wall is true.
+ // Applies only when the motion angle is under 90 degrees,
+ // in order to avoid blocking lateral motion along a wall.
+ if (motion_angle < .5 * Math_PI) {
+ apply_default_sliding = false;
+ if (p_was_on_floor && !vel_dir_facing_up) {
+ // Cancel the motion.
+ Transform3D gt = get_global_transform();
+ real_t travel_total = result.travel.length();
+ real_t cancel_dist_max = MIN(0.1, margin * 20);
+ if (travel_total <= margin + CMP_EPSILON) {
+ gt.origin -= result.travel;
+ result.travel = Vector3(); // Cancel for constant speed computation.
+ } else if (travel_total < cancel_dist_max) { // If the movement is large the body can be prevented from reaching the walls.
+ gt.origin -= result.travel.slide(up_direction);
+ // Keep remaining motion in sync with amount canceled.
+ motion = motion.slide(up_direction);
+ result.travel = Vector3();
+ } else {
+ // Travel is too high to be safely canceled, we take it into account.
+ result.travel = result.travel.slide(up_direction);
+ motion = motion.normalized() * result.travel.length();
+ }
+ set_global_transform(gt);
+ // Determines if you are on the ground, and limits the possibility of climbing on the walls because of the approximations.
+ _snap_on_floor(true, false);
+ } else {
+ // If the movement is not canceled we only keep the remaining.
+ motion = result.remainder;
+ }
+
+ // Apply slide on forward in order to allow only lateral motion on next step.
+ Vector3 forward = wall_normal.slide(up_direction).normalized();
+ motion = motion.slide(forward);
+
+ // Scales the horizontal velocity according to the wall slope.
+ if (vel_dir_facing_up) {
+ Vector3 slide_motion = velocity.slide(result.collisions[0].normal);
+ // Keeps the vertical motion from velocity and add the horizontal motion of the projection.
+ velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
+ } else {
+ velocity = velocity.slide(forward);
+ }
+
+ // Allow only lateral motion along previous floor when already on floor.
+ // Fixes slowing down when moving in diagonal against an inclined wall.
+ if (p_was_on_floor && !vel_dir_facing_up && (motion.dot(up_direction) > 0.0)) {
+ // Slide along the corner between the wall and previous floor.
+ Vector3 floor_side = prev_floor_normal.cross(wall_normal);
+ if (floor_side != Vector3()) {
+ motion = floor_side * motion.dot(floor_side);
+ }
+ }
+
+ // Stop all motion when a second wall is hit (unless sliding down or jumping),
+ // in order to avoid jittering in corner cases.
+ bool stop_all_motion = previous_state.wall && !vel_dir_facing_up;
+
+ // Allow sliding when the body falls.
+ if (!collision_state.floor && motion.dot(up_direction) < 0) {
+ Vector3 slide_motion = motion.slide(wall_normal);
+ // Test again to allow sliding only if the result goes downwards.
+ // Fixes jittering issues at the bottom of inclined walls.
+ if (slide_motion.dot(up_direction) < 0) {
+ stop_all_motion = false;
+ motion = slide_motion;
+ }
+ }
+
+ if (stop_all_motion) {
+ motion = Vector3();
+ velocity = Vector3();
+ }
+ }
+ }
+
+ // Stop horizontal motion when under wall slide threshold.
+ if (p_was_on_floor && (wall_min_slide_angle > 0.0) && result_state.wall) {
+ Vector3 horizontal_normal = wall_normal.slide(up_direction).normalized();
+ real_t motion_angle = Math::abs(Math::acos(-horizontal_normal.dot(motion_slide_up.normalized())));
+ if (motion_angle < wall_min_slide_angle) {
+ motion = up_direction * motion.dot(up_direction);
+ velocity = up_direction * velocity.dot(up_direction);
+
+ apply_default_sliding = false;
+ }
+ }
+ }
+
+ if (apply_default_sliding) {
+ // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
+ if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
+ const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
+
+ Vector3 slide_motion = result.remainder.slide(collision.normal);
+ if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_zero_approx()) {
+ // Slide using the intersection between the motion plane and the floor plane,
+ // in order to keep the direction intact.
+ real_t motion_length = slide_motion.length();
+ slide_motion = up_direction.cross(result.remainder).cross(floor_normal);
+
+ // Keep the length from default slide to change speed in slopes by default,
+ // when constant speed is not enabled.
+ slide_motion.normalize();
+ slide_motion *= motion_length;
+ }
+
+ if (slide_motion.dot(velocity) > 0.0) {
+ motion = slide_motion;
+ } else {
+ motion = Vector3();
+ }
+
+ if (slide_on_ceiling && result_state.ceiling) {
+ // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
+ if (vel_dir_facing_up) {
+ velocity = velocity.slide(collision.normal);
+ } else {
+ // Avoid acceleration in slope when falling.
+ velocity = up_direction * up_direction.dot(velocity);
+ }
+ }
+ }
+ // No sliding on first attempt to keep floor motion stable when possible.
+ else {
+ motion = result.remainder;
+ if (result_state.ceiling && !slide_on_ceiling && vel_dir_facing_up) {
+ velocity = velocity.slide(up_direction);
+ motion = motion.slide(up_direction);
+ }
+ }
+ }
+
+ total_travel += result.travel;
+
+ // Apply Constant Speed.
+ if (p_was_on_floor && floor_constant_speed && can_apply_constant_speed && collision_state.floor && !motion.is_zero_approx()) {
+ Vector3 travel_slide_up = total_travel.slide(up_direction);
+ motion = motion.normalized() * MAX(0, (motion_slide_up.length() - travel_slide_up.length()));
+ }
+ }
+ // When you move forward in a downward slope you don’t collide because you will be in the air.
+ // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
+ else if (floor_constant_speed && first_slide && _on_floor_if_snapped(p_was_on_floor, vel_dir_facing_up)) {
+ can_apply_constant_speed = false;
+ sliding_enabled = true;
+ Transform3D gt = get_global_transform();
+ gt.origin = gt.origin - result.travel;
+ set_global_transform(gt);
+
+ // Slide using the intersection between the motion plane and the floor plane,
+ // in order to keep the direction intact.
+ Vector3 motion_slide_norm = up_direction.cross(motion).cross(prev_floor_normal);
+ motion_slide_norm.normalize();
+
+ motion = motion_slide_norm * (motion_slide_up.length());
+ collided = true;
+ }
+
+ if (!collided || motion.is_zero_approx()) {
+ break;
+ }
+
+ can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
+ sliding_enabled = true;
+ first_slide = false;
+ }
+
+ _snap_on_floor(p_was_on_floor, vel_dir_facing_up);
+
+ // Reset the gravity accumulation when touching the ground.
+ if (collision_state.floor && !vel_dir_facing_up) {
+ velocity = velocity.slide(up_direction);
+ }
+}
+
+void CharacterBody3D::_move_and_slide_floating(double p_delta) {
+ Vector3 motion = velocity * p_delta;
+
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ floor_normal = Vector3();
+ platform_velocity = Vector3();
+ platform_angular_velocity = Vector3();
+
+ bool first_slide = true;
+ for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
+ PhysicsServer3D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, false);
+
+ last_motion = result.travel;
+
+ if (collided) {
+ motion_results.push_back(result);
+
+ CollisionState result_state;
+ _set_collision_direction(result, result_state);
+
+ if (result.remainder.is_zero_approx()) {
+ motion = Vector3();
+ break;
+ }
+
+ if (wall_min_slide_angle != 0 && Math::acos(wall_normal.dot(-velocity.normalized())) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) {
+ motion = Vector3();
+ if (result.travel.length() < margin + CMP_EPSILON) {
+ Transform3D gt = get_global_transform();
+ gt.origin -= result.travel;
+ set_global_transform(gt);
+ }
+ } else if (first_slide) {
+ Vector3 motion_slide_norm = result.remainder.slide(wall_normal).normalized();
+ motion = motion_slide_norm * (motion.length() - result.travel.length());
+ } else {
+ motion = result.remainder.slide(wall_normal);
+ }
+
+ if (motion.dot(velocity) <= 0.0) {
+ motion = Vector3();
+ }
+ }
+
+ if (!collided || motion.is_zero_approx()) {
+ break;
+ }
+
+ first_slide = false;
+ }
+}
+
+void CharacterBody3D::apply_floor_snap() {
+ if (collision_state.floor) {
+ return;
+ }
+
+ // Snap by at least collision margin to keep floor state consistent.
+ real_t length = MAX(floor_snap_length, margin);
+
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.max_collisions = 4;
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+ parameters.collide_separation_ray = true;
+
+ PhysicsServer3D::MotionResult result;
+ if (move_and_collide(parameters, result, true, false)) {
+ CollisionState result_state;
+ // Apply direction for floor only.
+ _set_collision_direction(result, result_state, CollisionState(true, false, false));
+
+ if (result_state.floor) {
+ if (floor_stop_on_slope) {
+ // move and collide may stray the object a bit because of pre un-stucking,
+ // so only ensure that motion happens on floor direction in this case.
+ if (result.travel.length() > margin) {
+ result.travel = up_direction * up_direction.dot(result.travel);
+ } else {
+ result.travel = Vector3();
+ }
+ }
+
+ parameters.from.origin += result.travel;
+ set_global_transform(parameters.from);
+ }
+ }
+}
+
+void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up) {
+ if (collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) {
+ return;
+ }
+
+ apply_floor_snap();
+}
+
+bool CharacterBody3D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) {
+ if (up_direction == Vector3() || collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) {
+ return false;
+ }
+
+ // Snap by at least collision margin to keep floor state consistent.
+ real_t length = MAX(floor_snap_length, margin);
+
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.max_collisions = 4;
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+ parameters.collide_separation_ray = true;
+
+ PhysicsServer3D::MotionResult result;
+ if (move_and_collide(parameters, result, true, false)) {
+ CollisionState result_state;
+ // Don't apply direction for any type.
+ _set_collision_direction(result, result_state, CollisionState());
+
+ return result_state.floor;
+ }
+
+ return false;
+}
+
+void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResult &p_result, CollisionState &r_state, CollisionState p_apply_state) {
+ r_state.state = 0;
+
+ real_t wall_depth = -1.0;
+ real_t floor_depth = -1.0;
+
+ bool was_on_wall = collision_state.wall;
+ Vector3 prev_wall_normal = wall_normal;
+ int wall_collision_count = 0;
+ Vector3 combined_wall_normal;
+ Vector3 tmp_wall_col; // Avoid duplicate on average calculation.
+
+ for (int i = p_result.collision_count - 1; i >= 0; i--) {
+ const PhysicsServer3D::MotionCollision &collision = p_result.collisions[i];
+
+ if (motion_mode == MOTION_MODE_GROUNDED) {
+ // Check if any collision is floor.
+ real_t floor_angle = collision.get_angle(up_direction);
+ if (floor_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ r_state.floor = true;
+ if (p_apply_state.floor && collision.depth > floor_depth) {
+ collision_state.floor = true;
+ floor_normal = collision.normal;
+ floor_depth = collision.depth;
+ _set_platform_data(collision);
+ }
+ continue;
+ }
+
+ // Check if any collision is ceiling.
+ real_t ceiling_angle = collision.get_angle(-up_direction);
+ if (ceiling_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ r_state.ceiling = true;
+ if (p_apply_state.ceiling) {
+ platform_ceiling_velocity = collision.collider_velocity;
+ ceiling_normal = collision.normal;
+ collision_state.ceiling = true;
+ }
+ continue;
+ }
+ }
+
+ // Collision is wall by default.
+ r_state.wall = true;
+
+ if (p_apply_state.wall && collision.depth > wall_depth) {
+ collision_state.wall = true;
+ wall_depth = collision.depth;
+ wall_normal = collision.normal;
+
+ // Don't apply wall velocity when the collider is a CharacterBody3D.
+ if (Object::cast_to<CharacterBody3D>(ObjectDB::get_instance(collision.collider_id)) == nullptr) {
+ _set_platform_data(collision);
+ }
+ }
+
+ // Collect normal for calculating average.
+ if (!collision.normal.is_equal_approx(tmp_wall_col)) {
+ tmp_wall_col = collision.normal;
+ combined_wall_normal += collision.normal;
+ wall_collision_count++;
+ }
+ }
+
+ if (r_state.wall) {
+ if (wall_collision_count > 1 && !r_state.floor) {
+ // Check if wall normals cancel out to floor support.
+ if (!r_state.floor && motion_mode == MOTION_MODE_GROUNDED) {
+ combined_wall_normal.normalize();
+ real_t floor_angle = Math::acos(combined_wall_normal.dot(up_direction));
+ if (floor_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ r_state.floor = true;
+ r_state.wall = false;
+ if (p_apply_state.floor) {
+ collision_state.floor = true;
+ floor_normal = combined_wall_normal;
+ }
+ if (p_apply_state.wall) {
+ collision_state.wall = was_on_wall;
+ wall_normal = prev_wall_normal;
+ }
+ return;
+ }
+ }
+ }
+ }
+}
+
+void CharacterBody3D::_set_platform_data(const PhysicsServer3D::MotionCollision &p_collision) {
+ platform_rid = p_collision.collider;
+ platform_object_id = p_collision.collider_id;
+ platform_velocity = p_collision.collider_velocity;
+ platform_angular_velocity = p_collision.collider_angular_velocity;
+ platform_layer = PhysicsServer3D::get_singleton()->body_get_collision_layer(platform_rid);
+}
+
+void CharacterBody3D::set_safe_margin(real_t p_margin) {
+ margin = p_margin;
+}
+
+real_t CharacterBody3D::get_safe_margin() const {
+ return margin;
+}
+
+const Vector3 &CharacterBody3D::get_velocity() const {
+ return velocity;
+}
+
+void CharacterBody3D::set_velocity(const Vector3 &p_velocity) {
+ velocity = p_velocity;
+}
+
+bool CharacterBody3D::is_on_floor() const {
+ return collision_state.floor;
+}
+
+bool CharacterBody3D::is_on_floor_only() const {
+ return collision_state.floor && !collision_state.wall && !collision_state.ceiling;
+}
+
+bool CharacterBody3D::is_on_wall() const {
+ return collision_state.wall;
+}
+
+bool CharacterBody3D::is_on_wall_only() const {
+ return collision_state.wall && !collision_state.floor && !collision_state.ceiling;
+}
+
+bool CharacterBody3D::is_on_ceiling() const {
+ return collision_state.ceiling;
+}
+
+bool CharacterBody3D::is_on_ceiling_only() const {
+ return collision_state.ceiling && !collision_state.floor && !collision_state.wall;
+}
+
+const Vector3 &CharacterBody3D::get_floor_normal() const {
+ return floor_normal;
+}
+
+const Vector3 &CharacterBody3D::get_wall_normal() const {
+ return wall_normal;
+}
+
+const Vector3 &CharacterBody3D::get_last_motion() const {
+ return last_motion;
+}
+
+Vector3 CharacterBody3D::get_position_delta() const {
+ return get_global_transform().origin - previous_position;
+}
+
+const Vector3 &CharacterBody3D::get_real_velocity() const {
+ return real_velocity;
+}
+
+real_t CharacterBody3D::get_floor_angle(const Vector3 &p_up_direction) const {
+ ERR_FAIL_COND_V(p_up_direction == Vector3(), 0);
+ return Math::acos(floor_normal.dot(p_up_direction));
+}
+
+const Vector3 &CharacterBody3D::get_platform_velocity() const {
+ return platform_velocity;
+}
+
+const Vector3 &CharacterBody3D::get_platform_angular_velocity() const {
+ return platform_angular_velocity;
+}
+
+Vector3 CharacterBody3D::get_linear_velocity() const {
+ return get_real_velocity();
+}
+
+int CharacterBody3D::get_slide_collision_count() const {
+ return motion_results.size();
+}
+
+PhysicsServer3D::MotionResult CharacterBody3D::get_slide_collision(int p_bounce) const {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer3D::MotionResult());
+ return motion_results[p_bounce];
+}
+
+Ref<KinematicCollision3D> CharacterBody3D::_get_slide_collision(int p_bounce) {
+ ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision3D>());
+ if (p_bounce >= slide_colliders.size()) {
+ slide_colliders.resize(p_bounce + 1);
+ }
+
+ // Create a new instance when the cached reference is invalid or still in use in script.
+ if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) {
+ slide_colliders.write[p_bounce].instantiate();
+ slide_colliders.write[p_bounce]->owner = this;
+ }
+
+ slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
+ return slide_colliders[p_bounce];
+}
+
+Ref<KinematicCollision3D> CharacterBody3D::_get_last_slide_collision() {
+ if (motion_results.size() == 0) {
+ return Ref<KinematicCollision3D>();
+ }
+ return _get_slide_collision(motion_results.size() - 1);
+}
+
+bool CharacterBody3D::is_floor_stop_on_slope_enabled() const {
+ return floor_stop_on_slope;
+}
+
+void CharacterBody3D::set_floor_stop_on_slope_enabled(bool p_enabled) {
+ floor_stop_on_slope = p_enabled;
+}
+
+bool CharacterBody3D::is_floor_constant_speed_enabled() const {
+ return floor_constant_speed;
+}
+
+void CharacterBody3D::set_floor_constant_speed_enabled(bool p_enabled) {
+ floor_constant_speed = p_enabled;
+}
+
+bool CharacterBody3D::is_floor_block_on_wall_enabled() const {
+ return floor_block_on_wall;
+}
+
+void CharacterBody3D::set_floor_block_on_wall_enabled(bool p_enabled) {
+ floor_block_on_wall = p_enabled;
+}
+
+bool CharacterBody3D::is_slide_on_ceiling_enabled() const {
+ return slide_on_ceiling;
+}
+
+void CharacterBody3D::set_slide_on_ceiling_enabled(bool p_enabled) {
+ slide_on_ceiling = p_enabled;
+}
+
+uint32_t CharacterBody3D::get_platform_floor_layers() const {
+ return platform_floor_layers;
+}
+
+void CharacterBody3D::set_platform_floor_layers(uint32_t p_exclude_layers) {
+ platform_floor_layers = p_exclude_layers;
+}
+
+uint32_t CharacterBody3D::get_platform_wall_layers() const {
+ return platform_wall_layers;
+}
+
+void CharacterBody3D::set_platform_wall_layers(uint32_t p_exclude_layers) {
+ platform_wall_layers = p_exclude_layers;
+}
+
+void CharacterBody3D::set_motion_mode(MotionMode p_mode) {
+ motion_mode = p_mode;
+}
+
+CharacterBody3D::MotionMode CharacterBody3D::get_motion_mode() const {
+ return motion_mode;
+}
+
+void CharacterBody3D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) {
+ platform_on_leave = p_on_leave_apply_velocity;
+}
+
+CharacterBody3D::PlatformOnLeave CharacterBody3D::get_platform_on_leave() const {
+ return platform_on_leave;
+}
+
+int CharacterBody3D::get_max_slides() const {
+ return max_slides;
+}
+
+void CharacterBody3D::set_max_slides(int p_max_slides) {
+ ERR_FAIL_COND(p_max_slides < 1);
+ max_slides = p_max_slides;
+}
+
+real_t CharacterBody3D::get_floor_max_angle() const {
+ return floor_max_angle;
+}
+
+void CharacterBody3D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody3D::get_floor_snap_length() {
+ return floor_snap_length;
+}
+
+void CharacterBody3D::set_floor_snap_length(real_t p_floor_snap_length) {
+ ERR_FAIL_COND(p_floor_snap_length < 0);
+ floor_snap_length = p_floor_snap_length;
+}
+
+real_t CharacterBody3D::get_wall_min_slide_angle() const {
+ return wall_min_slide_angle;
+}
+
+void CharacterBody3D::set_wall_min_slide_angle(real_t p_radians) {
+ wall_min_slide_angle = p_radians;
+}
+
+const Vector3 &CharacterBody3D::get_up_direction() const {
+ return up_direction;
+}
+
+void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) {
+ ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Floating motion mode instead.");
+ up_direction = p_up_direction.normalized();
+}
+
+void CharacterBody3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ // Reset move_and_slide() data.
+ collision_state.state = 0;
+ platform_rid = RID();
+ platform_object_id = ObjectID();
+ motion_results.clear();
+ platform_velocity = Vector3();
+ platform_angular_velocity = Vector3();
+ } break;
+ }
+}
+
+void CharacterBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody3D::move_and_slide);
+ ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody3D::apply_floor_snap);
+
+ ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody3D::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody3D::get_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "margin"), &CharacterBody3D::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody3D::get_safe_margin);
+ ClassDB::bind_method(D_METHOD("is_floor_stop_on_slope_enabled"), &CharacterBody3D::is_floor_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_stop_on_slope_enabled", "enabled"), &CharacterBody3D::set_floor_stop_on_slope_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_constant_speed_enabled", "enabled"), &CharacterBody3D::set_floor_constant_speed_enabled);
+ ClassDB::bind_method(D_METHOD("is_floor_constant_speed_enabled"), &CharacterBody3D::is_floor_constant_speed_enabled);
+ ClassDB::bind_method(D_METHOD("set_floor_block_on_wall_enabled", "enabled"), &CharacterBody3D::set_floor_block_on_wall_enabled);
+ ClassDB::bind_method(D_METHOD("is_floor_block_on_wall_enabled"), &CharacterBody3D::is_floor_block_on_wall_enabled);
+ ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody3D::set_slide_on_ceiling_enabled);
+ ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody3D::is_slide_on_ceiling_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody3D::set_platform_floor_layers);
+ ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody3D::get_platform_floor_layers);
+ ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody3D::set_platform_wall_layers);
+ ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody3D::get_platform_wall_layers);
+
+ ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody3D::get_max_slides);
+ ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody3D::get_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody3D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody3D::get_floor_snap_length);
+ ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody3D::set_floor_snap_length);
+ ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody3D::get_wall_min_slide_angle);
+ ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody3D::set_wall_min_slide_angle);
+ ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody3D::get_up_direction);
+ ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody3D::set_up_direction);
+ ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody3D::set_motion_mode);
+ ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody3D::get_motion_mode);
+ ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody3D::set_platform_on_leave);
+ ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody3D::get_platform_on_leave);
+
+ ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody3D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody3D::is_on_floor_only);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody3D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody3D::is_on_ceiling_only);
+ ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody3D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody3D::is_on_wall_only);
+ ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody3D::get_floor_normal);
+ ClassDB::bind_method(D_METHOD("get_wall_normal"), &CharacterBody3D::get_wall_normal);
+ ClassDB::bind_method(D_METHOD("get_last_motion"), &CharacterBody3D::get_last_motion);
+ ClassDB::bind_method(D_METHOD("get_position_delta"), &CharacterBody3D::get_position_delta);
+ ClassDB::bind_method(D_METHOD("get_real_velocity"), &CharacterBody3D::get_real_velocity);
+ ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &CharacterBody3D::get_floor_angle, DEFVAL(Vector3(0.0, 1.0, 0.0)));
+ ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody3D::get_platform_velocity);
+ ClassDB::bind_method(D_METHOD("get_platform_angular_velocity"), &CharacterBody3D::get_platform_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_slide_collision_count"), &CharacterBody3D::get_slide_collision_count);
+ ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision);
+ ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody3D::_get_last_slide_collision);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "velocity", PROPERTY_HINT_NONE, "suffix:m/s", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle");
+
+ ADD_GROUP("Floor", "floor_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees"), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,suffix:m"), "set_floor_snap_length", "get_floor_snap_length");
+
+ ADD_GROUP("Moving Platform", "platform_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
+
+ ADD_GROUP("Collision", "");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:m"), "set_safe_margin", "get_safe_margin");
+
+ BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED);
+ BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING);
+
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY);
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY);
+ BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING);
+}
+
+void CharacterBody3D::_validate_property(PropertyInfo &p_property) const {
+ if (motion_mode == MOTION_MODE_FLOATING) {
+ if (p_property.name.begins_with("floor_") || p_property.name == "up_direction" || p_property.name == "slide_on_ceiling") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+}
+
+CharacterBody3D::CharacterBody3D() :
+ PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
+}
+
+CharacterBody3D::~CharacterBody3D() {
+ for (int i = 0; i < slide_colliders.size(); i++) {
+ if (slide_colliders[i].is_valid()) {
+ slide_colliders.write[i]->owner = nullptr;
+ }
+ }
+}
diff --git a/scene/3d/physics/character_body_3d.h b/scene/3d/physics/character_body_3d.h
new file mode 100644
index 0000000000..cffc0f8e63
--- /dev/null
+++ b/scene/3d/physics/character_body_3d.h
@@ -0,0 +1,190 @@
+/**************************************************************************/
+/* character_body_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef CHARACTER_BODY_3D_H
+#define CHARACTER_BODY_3D_H
+
+#include "scene/3d/physics/kinematic_collision_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+
+class CharacterBody3D : public PhysicsBody3D {
+ GDCLASS(CharacterBody3D, PhysicsBody3D);
+
+public:
+ enum MotionMode {
+ MOTION_MODE_GROUNDED,
+ MOTION_MODE_FLOATING,
+ };
+ enum PlatformOnLeave {
+ PLATFORM_ON_LEAVE_ADD_VELOCITY,
+ PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY,
+ PLATFORM_ON_LEAVE_DO_NOTHING,
+ };
+ bool move_and_slide();
+ void apply_floor_snap();
+
+ const Vector3 &get_velocity() const;
+ void set_velocity(const Vector3 &p_velocity);
+
+ bool is_on_floor() const;
+ bool is_on_floor_only() const;
+ bool is_on_wall() const;
+ bool is_on_wall_only() const;
+ bool is_on_ceiling() const;
+ bool is_on_ceiling_only() const;
+ const Vector3 &get_last_motion() const;
+ Vector3 get_position_delta() const;
+ const Vector3 &get_floor_normal() const;
+ const Vector3 &get_wall_normal() const;
+ const Vector3 &get_real_velocity() const;
+ real_t get_floor_angle(const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const;
+ const Vector3 &get_platform_velocity() const;
+ const Vector3 &get_platform_angular_velocity() const;
+
+ virtual Vector3 get_linear_velocity() const override;
+
+ int get_slide_collision_count() const;
+ PhysicsServer3D::MotionResult get_slide_collision(int p_bounce) const;
+
+ void set_safe_margin(real_t p_margin);
+ real_t get_safe_margin() const;
+
+ bool is_floor_stop_on_slope_enabled() const;
+ void set_floor_stop_on_slope_enabled(bool p_enabled);
+
+ bool is_floor_constant_speed_enabled() const;
+ void set_floor_constant_speed_enabled(bool p_enabled);
+
+ bool is_floor_block_on_wall_enabled() const;
+ void set_floor_block_on_wall_enabled(bool p_enabled);
+
+ bool is_slide_on_ceiling_enabled() const;
+ void set_slide_on_ceiling_enabled(bool p_enabled);
+
+ int get_max_slides() const;
+ void set_max_slides(int p_max_slides);
+
+ real_t get_floor_max_angle() const;
+ void set_floor_max_angle(real_t p_radians);
+
+ real_t get_floor_snap_length();
+ void set_floor_snap_length(real_t p_floor_snap_length);
+
+ real_t get_wall_min_slide_angle() const;
+ void set_wall_min_slide_angle(real_t p_radians);
+
+ uint32_t get_platform_floor_layers() const;
+ void set_platform_floor_layers(const uint32_t p_exclude_layer);
+
+ uint32_t get_platform_wall_layers() const;
+ void set_platform_wall_layers(const uint32_t p_exclude_layer);
+
+ void set_motion_mode(MotionMode p_mode);
+ MotionMode get_motion_mode() const;
+
+ void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity);
+ PlatformOnLeave get_platform_on_leave() const;
+
+ CharacterBody3D();
+ ~CharacterBody3D();
+
+private:
+ real_t margin = 0.001;
+ MotionMode motion_mode = MOTION_MODE_GROUNDED;
+ PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY;
+ union CollisionState {
+ uint32_t state = 0;
+ struct {
+ bool floor;
+ bool wall;
+ bool ceiling;
+ };
+
+ CollisionState() {
+ }
+
+ CollisionState(bool p_floor, bool p_wall, bool p_ceiling) {
+ floor = p_floor;
+ wall = p_wall;
+ ceiling = p_ceiling;
+ }
+ };
+
+ CollisionState collision_state;
+ bool floor_constant_speed = false;
+ bool floor_stop_on_slope = true;
+ bool floor_block_on_wall = true;
+ bool slide_on_ceiling = true;
+ int max_slides = 6;
+ int platform_layer = 0;
+ RID platform_rid;
+ ObjectID platform_object_id;
+ uint32_t platform_floor_layers = UINT32_MAX;
+ uint32_t platform_wall_layers = 0;
+ real_t floor_snap_length = 0.1;
+ real_t floor_max_angle = Math::deg_to_rad((real_t)45.0);
+ real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0);
+ Vector3 up_direction = Vector3(0.0, 1.0, 0.0);
+ Vector3 velocity;
+ Vector3 floor_normal;
+ Vector3 wall_normal;
+ Vector3 ceiling_normal;
+ Vector3 last_motion;
+ Vector3 platform_velocity;
+ Vector3 platform_angular_velocity;
+ Vector3 platform_ceiling_velocity;
+ Vector3 previous_position;
+ Vector3 real_velocity;
+
+ Vector<PhysicsServer3D::MotionResult> motion_results;
+ Vector<Ref<KinematicCollision3D>> slide_colliders;
+
+ void _move_and_slide_floating(double p_delta);
+ void _move_and_slide_grounded(double p_delta, bool p_was_on_floor);
+
+ Ref<KinematicCollision3D> _get_slide_collision(int p_bounce);
+ Ref<KinematicCollision3D> _get_last_slide_collision();
+ const Vector3 &get_up_direction() const;
+ bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up);
+ void set_up_direction(const Vector3 &p_up_direction);
+ void _set_collision_direction(const PhysicsServer3D::MotionResult &p_result, CollisionState &r_state, CollisionState p_apply_state = CollisionState(true, true, true));
+ void _set_platform_data(const PhysicsServer3D::MotionCollision &p_collision);
+ void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
+};
+
+VARIANT_ENUM_CAST(CharacterBody3D::MotionMode);
+VARIANT_ENUM_CAST(CharacterBody3D::PlatformOnLeave);
+
+#endif // CHARACTER_BODY_3D_H
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/physics/collision_object_3d.cpp
index bbd2ef2fb8..bbd2ef2fb8 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/physics/collision_object_3d.cpp
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/physics/collision_object_3d.h
index b51423f021..b51423f021 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/physics/collision_object_3d.h
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/physics/collision_polygon_3d.cpp
index abde05778d..76cd4db779 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/physics/collision_polygon_3d.cpp
@@ -30,8 +30,8 @@
#include "collision_polygon_3d.h"
-#include "collision_object_3d.h"
#include "core/math/geometry_2d.h"
+#include "scene/3d/physics/collision_object_3d.h"
#include "scene/resources/3d/convex_polygon_shape_3d.h"
void CollisionPolygon3D::_build_polygon() {
diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/physics/collision_polygon_3d.h
index fe4cf40ee3..fe4cf40ee3 100644
--- a/scene/3d/collision_polygon_3d.h
+++ b/scene/3d/physics/collision_polygon_3d.h
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/physics/collision_shape_3d.cpp
index 08fc62ae4f..f3492a3cf3 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/physics/collision_shape_3d.cpp
@@ -30,12 +30,13 @@
#include "collision_shape_3d.h"
-#include "mesh_instance_3d.h"
-#include "physics_body_3d.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/physics/character_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/vehicle_body_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
#include "scene/resources/3d/convex_polygon_shape_3d.h"
#include "scene/resources/3d/world_boundary_shape_3d.h"
-#include "vehicle_body_3d.h"
void CollisionShape3D::make_convex_from_siblings() {
Node *p = get_parent();
diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/physics/collision_shape_3d.h
index 15f6ef73cb..15f6ef73cb 100644
--- a/scene/3d/collision_shape_3d.h
+++ b/scene/3d/physics/collision_shape_3d.h
diff --git a/scene/3d/physics/joints/SCsub b/scene/3d/physics/joints/SCsub
new file mode 100644
index 0000000000..fc61250247
--- /dev/null
+++ b/scene/3d/physics/joints/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.scene_sources, "*.cpp")
diff --git a/scene/3d/physics/joints/cone_twist_joint_3d.cpp b/scene/3d/physics/joints/cone_twist_joint_3d.cpp
new file mode 100644
index 0000000000..404c074911
--- /dev/null
+++ b/scene/3d/physics/joints/cone_twist_joint_3d.cpp
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/* cone_twist_joint_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "cone_twist_joint_3d.h"
+
+#include "scene/scene_string_names.h"
+
+void ConeTwistJoint3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ConeTwistJoint3D::set_param);
+ ClassDB::bind_method(D_METHOD("get_param", "param"), &ConeTwistJoint3D::get_param);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_SWING_SPAN);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_TWIST_SPAN);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_RELAXATION);
+
+ BIND_ENUM_CONSTANT(PARAM_SWING_SPAN);
+ BIND_ENUM_CONSTANT(PARAM_TWIST_SPAN);
+ BIND_ENUM_CONSTANT(PARAM_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_RELAXATION);
+ BIND_ENUM_CONSTANT(PARAM_MAX);
+}
+
+void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
+ ERR_FAIL_INDEX(p_param, PARAM_MAX);
+ params[p_param] = p_value;
+ if (is_configured()) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_rid(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
+ }
+
+ update_gizmos();
+}
+
+real_t ConeTwistJoint3D::get_param(Param p_param) const {
+ ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
+ return params[p_param];
+}
+
+void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+ Transform3D gt = get_global_transform();
+
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
+
+ Transform3D local_a = ainv * gt;
+ local_a.orthonormalize();
+ Transform3D local_b = gt;
+
+ if (body_b) {
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
+ local_b = binv * gt;
+ }
+
+ local_b.orthonormalize();
+
+ PhysicsServer3D::get_singleton()->joint_make_cone_twist(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ for (int i = 0; i < PARAM_MAX; i++) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(p_joint, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
+ }
+}
+
+ConeTwistJoint3D::ConeTwistJoint3D() {
+ params[PARAM_SWING_SPAN] = Math_PI * 0.25;
+ params[PARAM_TWIST_SPAN] = Math_PI;
+ params[PARAM_BIAS] = 0.3;
+ params[PARAM_SOFTNESS] = 0.8;
+ params[PARAM_RELAXATION] = 1.0;
+}
diff --git a/scene/3d/physics/joints/cone_twist_joint_3d.h b/scene/3d/physics/joints/cone_twist_joint_3d.h
new file mode 100644
index 0000000000..a24c805390
--- /dev/null
+++ b/scene/3d/physics/joints/cone_twist_joint_3d.h
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/* cone_twist_joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef CONE_TWIST_JOINT_3D_H
+#define CONE_TWIST_JOINT_3D_H
+
+#include "scene/3d/physics/joints/joint_3d.h"
+
+class ConeTwistJoint3D : public Joint3D {
+ GDCLASS(ConeTwistJoint3D, Joint3D);
+
+public:
+ enum Param {
+ PARAM_SWING_SPAN,
+ PARAM_TWIST_SPAN,
+ PARAM_BIAS,
+ PARAM_SOFTNESS,
+ PARAM_RELAXATION,
+ PARAM_MAX
+ };
+
+protected:
+ real_t params[PARAM_MAX];
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_param(Param p_param, real_t p_value);
+ real_t get_param(Param p_param) const;
+
+ ConeTwistJoint3D();
+};
+
+VARIANT_ENUM_CAST(ConeTwistJoint3D::Param);
+
+#endif // CONE_TWIST_JOINT_3D_H
diff --git a/scene/3d/joint_3d.cpp b/scene/3d/physics/joints/generic_6dof_joint_3d.cpp
index 1e4e50182c..9f440b65cc 100644
--- a/scene/3d/joint_3d.cpp
+++ b/scene/3d/physics/joints/generic_6dof_joint_3d.cpp
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* joint_3d.cpp */
+/* generic_6dof_joint_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,562 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include "joint_3d.h"
-
-#include "scene/scene_string_names.h"
-
-void Joint3D::_disconnect_signals() {
- Node *node_a = get_node_or_null(a);
- PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
- if (body_a) {
- body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
- }
-
- Node *node_b = get_node_or_null(b);
- PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
- if (body_b) {
- body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
- }
-}
-
-void Joint3D::_body_exit_tree() {
- _disconnect_signals();
- _update_joint(true);
- update_configuration_warnings();
-}
-
-void Joint3D::_update_joint(bool p_only_free) {
- if (ba.is_valid() && bb.is_valid()) {
- PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
- PhysicsServer3D::get_singleton()->body_remove_collision_exception(bb, ba);
- }
-
- ba = RID();
- bb = RID();
-
- configured = false;
-
- if (p_only_free || !is_inside_tree()) {
- PhysicsServer3D::get_singleton()->joint_clear(joint);
- warning = String();
- return;
- }
-
- Node *node_a = get_node_or_null(a);
- Node *node_b = get_node_or_null(b);
-
- PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
- PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
-
- if (node_a && !body_a && node_b && !body_b) {
- warning = RTR("Node A and Node B must be PhysicsBody3Ds");
- } else if (node_a && !body_a) {
- warning = RTR("Node A must be a PhysicsBody3D");
- } else if (node_b && !body_b) {
- warning = RTR("Node B must be a PhysicsBody3D");
- } else if (!body_a && !body_b) {
- warning = RTR("Joint is not connected to any PhysicsBody3Ds");
- } else if (body_a == body_b) {
- warning = RTR("Node A and Node B must be different PhysicsBody3Ds");
- } else {
- warning = String();
- }
-
- update_configuration_warnings();
-
- if (!warning.is_empty()) {
- PhysicsServer3D::get_singleton()->joint_clear(joint);
- return;
- }
-
- configured = true;
-
- if (body_a) {
- _configure_joint(joint, body_a, body_b);
- } else if (body_b) {
- _configure_joint(joint, body_b, nullptr);
- }
-
- PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
-
- if (body_a) {
- ba = body_a->get_rid();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
- }
-
- if (body_b) {
- bb = body_b->get_rid();
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
- }
-
- PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
-}
-
-void Joint3D::set_node_a(const NodePath &p_node_a) {
- if (a == p_node_a) {
- return;
- }
-
- if (is_configured()) {
- _disconnect_signals();
- }
-
- a = p_node_a;
- _update_joint();
-}
-
-NodePath Joint3D::get_node_a() const {
- return a;
-}
-
-void Joint3D::set_node_b(const NodePath &p_node_b) {
- if (b == p_node_b) {
- return;
- }
-
- if (is_configured()) {
- _disconnect_signals();
- }
-
- b = p_node_b;
- _update_joint();
-}
-
-NodePath Joint3D::get_node_b() const {
- return b;
-}
-
-void Joint3D::set_solver_priority(int p_priority) {
- solver_priority = p_priority;
- if (joint.is_valid()) {
- PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
- }
-}
-
-int Joint3D::get_solver_priority() const {
- return solver_priority;
-}
-
-void Joint3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_POST_ENTER_TREE: {
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint();
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint(true);
- } break;
- }
-}
-
-void Joint3D::set_exclude_nodes_from_collision(bool p_enable) {
- if (exclude_from_collision == p_enable) {
- return;
- }
- if (is_configured()) {
- _disconnect_signals();
- }
- _update_joint(true);
- exclude_from_collision = p_enable;
- _update_joint();
-}
-
-bool Joint3D::get_exclude_nodes_from_collision() const {
- return exclude_from_collision;
-}
-
-PackedStringArray Joint3D::get_configuration_warnings() const {
- PackedStringArray warnings = Node3D::get_configuration_warnings();
-
- if (!warning.is_empty()) {
- warnings.push_back(warning);
- }
-
- return warnings;
-}
-
-void Joint3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint3D::set_node_a);
- ClassDB::bind_method(D_METHOD("get_node_a"), &Joint3D::get_node_a);
-
- ClassDB::bind_method(D_METHOD("set_node_b", "node"), &Joint3D::set_node_b);
- ClassDB::bind_method(D_METHOD("get_node_b"), &Joint3D::get_node_b);
-
- ClassDB::bind_method(D_METHOD("set_solver_priority", "priority"), &Joint3D::set_solver_priority);
- ClassDB::bind_method(D_METHOD("get_solver_priority"), &Joint3D::get_solver_priority);
-
- ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint3D::set_exclude_nodes_from_collision);
- ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint3D::get_exclude_nodes_from_collision);
-
- ClassDB::bind_method(D_METHOD("get_rid"), &Joint3D::get_rid);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_a", "get_node_a");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_b", "get_node_b");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "solver_priority", PROPERTY_HINT_RANGE, "1,8,1"), "set_solver_priority", "get_solver_priority");
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_nodes_from_collision"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
-}
-
-Joint3D::Joint3D() {
- set_notify_transform(true);
- joint = PhysicsServer3D::get_singleton()->joint_create();
-}
-
-Joint3D::~Joint3D() {
- ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
- PhysicsServer3D::get_singleton()->free(joint);
-}
-
-///////////////////////////////////
-
-void PinJoint3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &PinJoint3D::set_param);
- ClassDB::bind_method(D_METHOD("get_param", "param"), &PinJoint3D::get_param);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"), "set_param", "get_param", PARAM_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"), "set_param", "get_param", PARAM_IMPULSE_CLAMP);
-
- BIND_ENUM_CONSTANT(PARAM_BIAS);
- BIND_ENUM_CONSTANT(PARAM_DAMPING);
- BIND_ENUM_CONSTANT(PARAM_IMPULSE_CLAMP);
-}
-
-void PinJoint3D::set_param(Param p_param, real_t p_value) {
- ERR_FAIL_INDEX(p_param, 3);
- params[p_param] = p_value;
- if (is_configured()) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer3D::PinJointParam(p_param), p_value);
- }
-}
-
-real_t PinJoint3D::get_param(Param p_param) const {
- ERR_FAIL_INDEX_V(p_param, 3, 0);
- return params[p_param];
-}
-
-void PinJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Vector3 pinpos = get_global_transform().origin;
- Vector3 local_a = body_a->to_local(pinpos);
- Vector3 local_b;
-
- if (body_b) {
- local_b = body_b->to_local(pinpos);
- } else {
- local_b = pinpos;
- }
-
- PhysicsServer3D::get_singleton()->joint_make_pin(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
- for (int i = 0; i < 3; i++) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer3D::PinJointParam(i), params[i]);
- }
-}
-
-PinJoint3D::PinJoint3D() {
- params[PARAM_BIAS] = 0.3;
- params[PARAM_DAMPING] = 1;
- params[PARAM_IMPULSE_CLAMP] = 0;
-}
-
-/////////////////////////////////////////////////
-
-///////////////////////////////////
-
-void HingeJoint3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &HingeJoint3D::set_param);
- ClassDB::bind_method(D_METHOD("get_param", "param"), &HingeJoint3D::get_param);
-
- ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &HingeJoint3D::set_flag);
- ClassDB::bind_method(D_METHOD("get_flag", "flag"), &HingeJoint3D::get_flag);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.00,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit/enable"), "set_flag", "get_flag", FLAG_USE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_LIMIT_UPPER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_LIMIT_LOWER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_LIMIT_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "motor/enable"), "set_flag", "get_flag", FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/target_velocity", PROPERTY_HINT_RANGE, U"-200,200,0.01,or_greater,or_less,radians_as_degrees,suffix:\u00B0/s"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE);
-
- BIND_ENUM_CONSTANT(PARAM_BIAS);
- BIND_ENUM_CONSTANT(PARAM_LIMIT_UPPER);
- BIND_ENUM_CONSTANT(PARAM_LIMIT_LOWER);
- BIND_ENUM_CONSTANT(PARAM_LIMIT_BIAS);
- BIND_ENUM_CONSTANT(PARAM_LIMIT_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_LIMIT_RELAXATION);
- BIND_ENUM_CONSTANT(PARAM_MOTOR_TARGET_VELOCITY);
- BIND_ENUM_CONSTANT(PARAM_MOTOR_MAX_IMPULSE);
- BIND_ENUM_CONSTANT(PARAM_MAX);
-
- BIND_ENUM_CONSTANT(FLAG_USE_LIMIT);
- BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR);
- BIND_ENUM_CONSTANT(FLAG_MAX);
-}
-
-void HingeJoint3D::set_param(Param p_param, real_t p_value) {
- ERR_FAIL_INDEX(p_param, PARAM_MAX);
- params[p_param] = p_value;
- if (is_configured()) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_rid(), PhysicsServer3D::HingeJointParam(p_param), p_value);
- }
-
- update_gizmos();
-}
-
-real_t HingeJoint3D::get_param(Param p_param) const {
- ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
- return params[p_param];
-}
-
-void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
- ERR_FAIL_INDEX(p_flag, FLAG_MAX);
- flags[p_flag] = p_value;
- if (is_configured()) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_rid(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
- }
-
- update_gizmos();
-}
-
-bool HingeJoint3D::get_flag(Flag p_flag) const {
- ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
- return flags[p_flag];
-}
-
-void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform3D gt = get_global_transform();
- Transform3D ainv = body_a->get_global_transform().affine_inverse();
-
- Transform3D local_a = ainv * gt;
- local_a.orthonormalize();
- Transform3D local_b = gt;
-
- if (body_b) {
- Transform3D binv = body_b->get_global_transform().affine_inverse();
- local_b = binv * gt;
- }
-
- local_b.orthonormalize();
-
- PhysicsServer3D::get_singleton()->joint_make_hinge(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
- for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(p_joint, PhysicsServer3D::HingeJointParam(i), params[i]);
- }
- for (int i = 0; i < FLAG_MAX; i++) {
- set_flag(Flag(i), flags[i]);
- PhysicsServer3D::get_singleton()->hinge_joint_set_flag(p_joint, PhysicsServer3D::HingeJointFlag(i), flags[i]);
- }
-}
-
-HingeJoint3D::HingeJoint3D() {
- params[PARAM_BIAS] = 0.3;
- params[PARAM_LIMIT_UPPER] = Math_PI * 0.5;
- params[PARAM_LIMIT_LOWER] = -Math_PI * 0.5;
- params[PARAM_LIMIT_BIAS] = 0.3;
- params[PARAM_LIMIT_SOFTNESS] = 0.9;
- params[PARAM_LIMIT_RELAXATION] = 1.0;
- params[PARAM_MOTOR_TARGET_VELOCITY] = 1;
- params[PARAM_MOTOR_MAX_IMPULSE] = 1;
-
- flags[FLAG_USE_LIMIT] = false;
- flags[FLAG_ENABLE_MOTOR] = false;
-}
-
-/////////////////////////////////////////////////
-
-void SliderJoint3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &SliderJoint3D::set_param);
- ClassDB::bind_method(D_METHOD("get_param", "param"), &SliderJoint3D::get_param);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_DAMPING);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_UPPER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_LOWER);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_DAMPING);
-
- BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_UPPER);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_LOWER);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_DAMPING);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_DAMPING);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_DAMPING);
-
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_UPPER);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_LOWER);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_DAMPING);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_DAMPING);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
- BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_DAMPING);
-
- BIND_ENUM_CONSTANT(PARAM_MAX);
-}
-
-void SliderJoint3D::set_param(Param p_param, real_t p_value) {
- ERR_FAIL_INDEX(p_param, PARAM_MAX);
- params[p_param] = p_value;
- if (is_configured()) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(get_rid(), PhysicsServer3D::SliderJointParam(p_param), p_value);
- }
- update_gizmos();
-}
-
-real_t SliderJoint3D::get_param(Param p_param) const {
- ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
- return params[p_param];
-}
-
-void SliderJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform3D gt = get_global_transform();
- Transform3D ainv = body_a->get_global_transform().affine_inverse();
-
- Transform3D local_a = ainv * gt;
- local_a.orthonormalize();
- Transform3D local_b = gt;
-
- if (body_b) {
- Transform3D binv = body_b->get_global_transform().affine_inverse();
- local_b = binv * gt;
- }
-
- local_b.orthonormalize();
-
- PhysicsServer3D::get_singleton()->joint_make_slider(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
- for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(p_joint, PhysicsServer3D::SliderJointParam(i), params[i]);
- }
-}
-
-SliderJoint3D::SliderJoint3D() {
- params[PARAM_LINEAR_LIMIT_UPPER] = 1.0;
- params[PARAM_LINEAR_LIMIT_LOWER] = -1.0;
- params[PARAM_LINEAR_LIMIT_SOFTNESS] = 1.0;
- params[PARAM_LINEAR_LIMIT_RESTITUTION] = 0.7;
- params[PARAM_LINEAR_LIMIT_DAMPING] = 1.0;
- params[PARAM_LINEAR_MOTION_SOFTNESS] = 1.0;
- params[PARAM_LINEAR_MOTION_RESTITUTION] = 0.7;
- params[PARAM_LINEAR_MOTION_DAMPING] = 0; //1.0;
- params[PARAM_LINEAR_ORTHOGONAL_SOFTNESS] = 1.0;
- params[PARAM_LINEAR_ORTHOGONAL_RESTITUTION] = 0.7;
- params[PARAM_LINEAR_ORTHOGONAL_DAMPING] = 1.0;
-
- params[PARAM_ANGULAR_LIMIT_UPPER] = 0;
- params[PARAM_ANGULAR_LIMIT_LOWER] = 0;
- params[PARAM_ANGULAR_LIMIT_SOFTNESS] = 1.0;
- params[PARAM_ANGULAR_LIMIT_RESTITUTION] = 0.7;
- params[PARAM_ANGULAR_LIMIT_DAMPING] = 0; //1.0;
- params[PARAM_ANGULAR_MOTION_SOFTNESS] = 1.0;
- params[PARAM_ANGULAR_MOTION_RESTITUTION] = 0.7;
- params[PARAM_ANGULAR_MOTION_DAMPING] = 1.0;
- params[PARAM_ANGULAR_ORTHOGONAL_SOFTNESS] = 1.0;
- params[PARAM_ANGULAR_ORTHOGONAL_RESTITUTION] = 0.7;
- params[PARAM_ANGULAR_ORTHOGONAL_DAMPING] = 1.0;
-}
-
-//////////////////////////////////
-
-void ConeTwistJoint3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ConeTwistJoint3D::set_param);
- ClassDB::bind_method(D_METHOD("get_param", "param"), &ConeTwistJoint3D::get_param);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_SWING_SPAN);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_TWIST_SPAN);
-
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_RELAXATION);
-
- BIND_ENUM_CONSTANT(PARAM_SWING_SPAN);
- BIND_ENUM_CONSTANT(PARAM_TWIST_SPAN);
- BIND_ENUM_CONSTANT(PARAM_BIAS);
- BIND_ENUM_CONSTANT(PARAM_SOFTNESS);
- BIND_ENUM_CONSTANT(PARAM_RELAXATION);
- BIND_ENUM_CONSTANT(PARAM_MAX);
-}
-
-void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
- ERR_FAIL_INDEX(p_param, PARAM_MAX);
- params[p_param] = p_value;
- if (is_configured()) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_rid(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
- }
-
- update_gizmos();
-}
-
-real_t ConeTwistJoint3D::get_param(Param p_param) const {
- ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
- return params[p_param];
-}
-
-void ConeTwistJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
- Transform3D gt = get_global_transform();
-
- Transform3D ainv = body_a->get_global_transform().affine_inverse();
-
- Transform3D local_a = ainv * gt;
- local_a.orthonormalize();
- Transform3D local_b = gt;
-
- if (body_b) {
- Transform3D binv = body_b->get_global_transform().affine_inverse();
- local_b = binv * gt;
- }
-
- local_b.orthonormalize();
-
- PhysicsServer3D::get_singleton()->joint_make_cone_twist(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
- for (int i = 0; i < PARAM_MAX; i++) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(p_joint, PhysicsServer3D::ConeTwistJointParam(i), params[i]);
- }
-}
-
-ConeTwistJoint3D::ConeTwistJoint3D() {
- params[PARAM_SWING_SPAN] = Math_PI * 0.25;
- params[PARAM_TWIST_SPAN] = Math_PI;
- params[PARAM_BIAS] = 0.3;
- params[PARAM_SOFTNESS] = 0.8;
- params[PARAM_RELAXATION] = 1.0;
-}
-
-/////////////////////////////////////////////////////////////////////
+#include "generic_6dof_joint_3d.h"
void Generic6DOFJoint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_param_x", "param", "value"), &Generic6DOFJoint3D::set_param_x);
diff --git a/scene/3d/physics/joints/generic_6dof_joint_3d.h b/scene/3d/physics/joints/generic_6dof_joint_3d.h
new file mode 100644
index 0000000000..9b3e4c01b3
--- /dev/null
+++ b/scene/3d/physics/joints/generic_6dof_joint_3d.h
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/* generic_6dof_joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef GENERIC_6DOF_JOINT_3D_H
+#define GENERIC_6DOF_JOINT_3D_H
+
+#include "scene/3d/physics/joints/joint_3d.h"
+
+class Generic6DOFJoint3D : public Joint3D {
+ GDCLASS(Generic6DOFJoint3D, Joint3D);
+
+public:
+ enum Param {
+ PARAM_LINEAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT,
+ PARAM_LINEAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT,
+ PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS,
+ PARAM_LINEAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION,
+ PARAM_LINEAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING,
+ PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
+ PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
+ PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS,
+ PARAM_LINEAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING,
+ PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT,
+ PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
+ PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
+ PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
+ PARAM_ANGULAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING,
+ PARAM_ANGULAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION,
+ PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT,
+ PARAM_ANGULAR_ERP = PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP,
+ PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY,
+ PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT,
+ PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS,
+ PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING,
+ PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT,
+ PARAM_MAX = PhysicsServer3D::G6DOF_JOINT_MAX,
+ };
+
+ enum Flag {
+ FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
+ FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
+ FLAG_ENABLE_LINEAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING,
+ FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING,
+ FLAG_ENABLE_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR,
+ FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
+ FLAG_MAX = PhysicsServer3D::G6DOF_JOINT_FLAG_MAX
+ };
+
+protected:
+ real_t params_x[PARAM_MAX];
+ bool flags_x[FLAG_MAX];
+ real_t params_y[PARAM_MAX];
+ bool flags_y[FLAG_MAX];
+ real_t params_z[PARAM_MAX];
+ bool flags_z[FLAG_MAX];
+
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_param_x(Param p_param, real_t p_value);
+ real_t get_param_x(Param p_param) const;
+
+ void set_param_y(Param p_param, real_t p_value);
+ real_t get_param_y(Param p_param) const;
+
+ void set_param_z(Param p_param, real_t p_value);
+ real_t get_param_z(Param p_param) const;
+
+ void set_flag_x(Flag p_flag, bool p_enabled);
+ bool get_flag_x(Flag p_flag) const;
+
+ void set_flag_y(Flag p_flag, bool p_enabled);
+ bool get_flag_y(Flag p_flag) const;
+
+ void set_flag_z(Flag p_flag, bool p_enabled);
+ bool get_flag_z(Flag p_flag) const;
+
+ Generic6DOFJoint3D();
+};
+
+VARIANT_ENUM_CAST(Generic6DOFJoint3D::Param);
+VARIANT_ENUM_CAST(Generic6DOFJoint3D::Flag);
+
+#endif // GENERIC_6DOF_JOINT_3D_H
diff --git a/scene/3d/physics/joints/hinge_joint_3d.cpp b/scene/3d/physics/joints/hinge_joint_3d.cpp
new file mode 100644
index 0000000000..92472a45e4
--- /dev/null
+++ b/scene/3d/physics/joints/hinge_joint_3d.cpp
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* hinge_joint_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "hinge_joint_3d.h"
+
+void HingeJoint3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &HingeJoint3D::set_param);
+ ClassDB::bind_method(D_METHOD("get_param", "param"), &HingeJoint3D::get_param);
+
+ ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &HingeJoint3D::set_flag);
+ ClassDB::bind_method(D_METHOD("get_flag", "flag"), &HingeJoint3D::get_flag);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.00,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit/enable"), "set_flag", "get_flag", FLAG_USE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_LIMIT_UPPER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_LIMIT_LOWER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_LIMIT_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "motor/enable"), "set_flag", "get_flag", FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/target_velocity", PROPERTY_HINT_RANGE, U"-200,200,0.01,or_greater,or_less,radians_as_degrees,suffix:\u00B0/s"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE);
+
+ BIND_ENUM_CONSTANT(PARAM_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_LIMIT_UPPER);
+ BIND_ENUM_CONSTANT(PARAM_LIMIT_LOWER);
+ BIND_ENUM_CONSTANT(PARAM_LIMIT_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_LIMIT_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_LIMIT_RELAXATION);
+ BIND_ENUM_CONSTANT(PARAM_MOTOR_TARGET_VELOCITY);
+ BIND_ENUM_CONSTANT(PARAM_MOTOR_MAX_IMPULSE);
+ BIND_ENUM_CONSTANT(PARAM_MAX);
+
+ BIND_ENUM_CONSTANT(FLAG_USE_LIMIT);
+ BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR);
+ BIND_ENUM_CONSTANT(FLAG_MAX);
+}
+
+void HingeJoint3D::set_param(Param p_param, real_t p_value) {
+ ERR_FAIL_INDEX(p_param, PARAM_MAX);
+ params[p_param] = p_value;
+ if (is_configured()) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_rid(), PhysicsServer3D::HingeJointParam(p_param), p_value);
+ }
+
+ update_gizmos();
+}
+
+real_t HingeJoint3D::get_param(Param p_param) const {
+ ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
+ return params[p_param];
+}
+
+void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
+ ERR_FAIL_INDEX(p_flag, FLAG_MAX);
+ flags[p_flag] = p_value;
+ if (is_configured()) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_rid(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
+ }
+
+ update_gizmos();
+}
+
+bool HingeJoint3D::get_flag(Flag p_flag) const {
+ ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
+ return flags[p_flag];
+}
+
+void HingeJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+ Transform3D gt = get_global_transform();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
+
+ Transform3D local_a = ainv * gt;
+ local_a.orthonormalize();
+ Transform3D local_b = gt;
+
+ if (body_b) {
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
+ local_b = binv * gt;
+ }
+
+ local_b.orthonormalize();
+
+ PhysicsServer3D::get_singleton()->joint_make_hinge(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ for (int i = 0; i < PARAM_MAX; i++) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(p_joint, PhysicsServer3D::HingeJointParam(i), params[i]);
+ }
+ for (int i = 0; i < FLAG_MAX; i++) {
+ set_flag(Flag(i), flags[i]);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_flag(p_joint, PhysicsServer3D::HingeJointFlag(i), flags[i]);
+ }
+}
+
+HingeJoint3D::HingeJoint3D() {
+ params[PARAM_BIAS] = 0.3;
+ params[PARAM_LIMIT_UPPER] = Math_PI * 0.5;
+ params[PARAM_LIMIT_LOWER] = -Math_PI * 0.5;
+ params[PARAM_LIMIT_BIAS] = 0.3;
+ params[PARAM_LIMIT_SOFTNESS] = 0.9;
+ params[PARAM_LIMIT_RELAXATION] = 1.0;
+ params[PARAM_MOTOR_TARGET_VELOCITY] = 1;
+ params[PARAM_MOTOR_MAX_IMPULSE] = 1;
+
+ flags[FLAG_USE_LIMIT] = false;
+ flags[FLAG_ENABLE_MOTOR] = false;
+}
diff --git a/scene/3d/physics/joints/hinge_joint_3d.h b/scene/3d/physics/joints/hinge_joint_3d.h
new file mode 100644
index 0000000000..cd19a8771f
--- /dev/null
+++ b/scene/3d/physics/joints/hinge_joint_3d.h
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* hinge_joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef HINGE_JOINT_3D_H
+#define HINGE_JOINT_3D_H
+
+#include "scene/3d/physics/joints/joint_3d.h"
+
+class HingeJoint3D : public Joint3D {
+ GDCLASS(HingeJoint3D, Joint3D);
+
+public:
+ enum Param {
+ PARAM_BIAS = PhysicsServer3D::HINGE_JOINT_BIAS,
+ PARAM_LIMIT_UPPER = PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER,
+ PARAM_LIMIT_LOWER = PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER,
+ PARAM_LIMIT_BIAS = PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS,
+ PARAM_LIMIT_SOFTNESS = PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS,
+ PARAM_LIMIT_RELAXATION = PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION,
+ PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY,
+ PARAM_MOTOR_MAX_IMPULSE = PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE,
+ PARAM_MAX = PhysicsServer3D::HINGE_JOINT_MAX
+ };
+
+ enum Flag {
+ FLAG_USE_LIMIT = PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT,
+ FLAG_ENABLE_MOTOR = PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR,
+ FLAG_MAX = PhysicsServer3D::HINGE_JOINT_FLAG_MAX
+ };
+
+protected:
+ real_t params[PARAM_MAX];
+ bool flags[FLAG_MAX];
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_param(Param p_param, real_t p_value);
+ real_t get_param(Param p_param) const;
+
+ void set_flag(Flag p_flag, bool p_value);
+ bool get_flag(Flag p_flag) const;
+
+ HingeJoint3D();
+};
+
+VARIANT_ENUM_CAST(HingeJoint3D::Param);
+VARIANT_ENUM_CAST(HingeJoint3D::Flag);
+
+#endif // HINGE_JOINT_3D_H
diff --git a/scene/3d/physics/joints/joint_3d.cpp b/scene/3d/physics/joints/joint_3d.cpp
new file mode 100644
index 0000000000..a9c2526bd0
--- /dev/null
+++ b/scene/3d/physics/joints/joint_3d.cpp
@@ -0,0 +1,241 @@
+/**************************************************************************/
+/* joint_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "joint_3d.h"
+
+#include "scene/scene_string_names.h"
+
+void Joint3D::_disconnect_signals() {
+ Node *node_a = get_node_or_null(a);
+ PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
+ if (body_a) {
+ body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ }
+
+ Node *node_b = get_node_or_null(b);
+ PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
+ if (body_b) {
+ body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ }
+}
+
+void Joint3D::_body_exit_tree() {
+ _disconnect_signals();
+ _update_joint(true);
+ update_configuration_warnings();
+}
+
+void Joint3D::_update_joint(bool p_only_free) {
+ if (ba.is_valid() && bb.is_valid()) {
+ PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb);
+ PhysicsServer3D::get_singleton()->body_remove_collision_exception(bb, ba);
+ }
+
+ ba = RID();
+ bb = RID();
+
+ configured = false;
+
+ if (p_only_free || !is_inside_tree()) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
+ warning = String();
+ return;
+ }
+
+ Node *node_a = get_node_or_null(a);
+ Node *node_b = get_node_or_null(b);
+
+ PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
+ PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
+
+ if (node_a && !body_a && node_b && !body_b) {
+ warning = RTR("Node A and Node B must be PhysicsBody3Ds");
+ } else if (node_a && !body_a) {
+ warning = RTR("Node A must be a PhysicsBody3D");
+ } else if (node_b && !body_b) {
+ warning = RTR("Node B must be a PhysicsBody3D");
+ } else if (!body_a && !body_b) {
+ warning = RTR("Joint is not connected to any PhysicsBody3Ds");
+ } else if (body_a == body_b) {
+ warning = RTR("Node A and Node B must be different PhysicsBody3Ds");
+ } else {
+ warning = String();
+ }
+
+ update_configuration_warnings();
+
+ if (!warning.is_empty()) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
+ return;
+ }
+
+ configured = true;
+
+ if (body_a) {
+ _configure_joint(joint, body_a, body_b);
+ } else if (body_b) {
+ _configure_joint(joint, body_b, nullptr);
+ }
+
+ PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
+
+ if (body_a) {
+ ba = body_a->get_rid();
+ body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ }
+
+ if (body_b) {
+ bb = body_b->get_rid();
+ body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ }
+
+ PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
+}
+
+void Joint3D::set_node_a(const NodePath &p_node_a) {
+ if (a == p_node_a) {
+ return;
+ }
+
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+
+ a = p_node_a;
+ _update_joint();
+}
+
+NodePath Joint3D::get_node_a() const {
+ return a;
+}
+
+void Joint3D::set_node_b(const NodePath &p_node_b) {
+ if (b == p_node_b) {
+ return;
+ }
+
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+
+ b = p_node_b;
+ _update_joint();
+}
+
+NodePath Joint3D::get_node_b() const {
+ return b;
+}
+
+void Joint3D::set_solver_priority(int p_priority) {
+ solver_priority = p_priority;
+ if (joint.is_valid()) {
+ PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
+ }
+}
+
+int Joint3D::get_solver_priority() const {
+ return solver_priority;
+}
+
+void Joint3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_POST_ENTER_TREE: {
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint();
+ } break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint(true);
+ } break;
+ }
+}
+
+void Joint3D::set_exclude_nodes_from_collision(bool p_enable) {
+ if (exclude_from_collision == p_enable) {
+ return;
+ }
+ if (is_configured()) {
+ _disconnect_signals();
+ }
+ _update_joint(true);
+ exclude_from_collision = p_enable;
+ _update_joint();
+}
+
+bool Joint3D::get_exclude_nodes_from_collision() const {
+ return exclude_from_collision;
+}
+
+PackedStringArray Joint3D::get_configuration_warnings() const {
+ PackedStringArray warnings = Node3D::get_configuration_warnings();
+
+ if (!warning.is_empty()) {
+ warnings.push_back(warning);
+ }
+
+ return warnings;
+}
+
+void Joint3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint3D::set_node_a);
+ ClassDB::bind_method(D_METHOD("get_node_a"), &Joint3D::get_node_a);
+
+ ClassDB::bind_method(D_METHOD("set_node_b", "node"), &Joint3D::set_node_b);
+ ClassDB::bind_method(D_METHOD("get_node_b"), &Joint3D::get_node_b);
+
+ ClassDB::bind_method(D_METHOD("set_solver_priority", "priority"), &Joint3D::set_solver_priority);
+ ClassDB::bind_method(D_METHOD("get_solver_priority"), &Joint3D::get_solver_priority);
+
+ ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint3D::set_exclude_nodes_from_collision);
+ ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint3D::get_exclude_nodes_from_collision);
+
+ ClassDB::bind_method(D_METHOD("get_rid"), &Joint3D::get_rid);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_a", "get_node_a");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_b", "get_node_b");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "solver_priority", PROPERTY_HINT_RANGE, "1,8,1"), "set_solver_priority", "get_solver_priority");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_nodes_from_collision"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
+}
+
+Joint3D::Joint3D() {
+ set_notify_transform(true);
+ joint = PhysicsServer3D::get_singleton()->joint_create();
+}
+
+Joint3D::~Joint3D() {
+ ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
+ PhysicsServer3D::get_singleton()->free(joint);
+}
diff --git a/scene/3d/physics/joints/joint_3d.h b/scene/3d/physics/joints/joint_3d.h
new file mode 100644
index 0000000000..ed502ab245
--- /dev/null
+++ b/scene/3d/physics/joints/joint_3d.h
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef JOINT_3D_H
+#define JOINT_3D_H
+
+#include "scene/3d/node_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+
+class Joint3D : public Node3D {
+ GDCLASS(Joint3D, Node3D);
+
+ RID ba, bb;
+
+ RID joint;
+
+ NodePath a;
+ NodePath b;
+
+ int solver_priority = 1;
+ bool exclude_from_collision = true;
+ String warning;
+ bool configured = false;
+
+protected:
+ void _disconnect_signals();
+ void _body_exit_tree();
+ void _update_joint(bool p_only_free = false);
+
+ void _notification(int p_what);
+
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0;
+
+ static void _bind_methods();
+
+ _FORCE_INLINE_ bool is_configured() const { return configured; }
+
+public:
+ virtual PackedStringArray get_configuration_warnings() const override;
+
+ void set_node_a(const NodePath &p_node_a);
+ NodePath get_node_a() const;
+
+ void set_node_b(const NodePath &p_node_b);
+ NodePath get_node_b() const;
+
+ void set_solver_priority(int p_priority);
+ int get_solver_priority() const;
+
+ void set_exclude_nodes_from_collision(bool p_enable);
+ bool get_exclude_nodes_from_collision() const;
+
+ RID get_rid() const { return joint; }
+ Joint3D();
+ ~Joint3D();
+};
+
+#endif // JOINT_3D_H
diff --git a/scene/3d/physics/joints/pin_joint_3d.cpp b/scene/3d/physics/joints/pin_joint_3d.cpp
new file mode 100644
index 0000000000..8e367c5ef6
--- /dev/null
+++ b/scene/3d/physics/joints/pin_joint_3d.cpp
@@ -0,0 +1,80 @@
+/**************************************************************************/
+/* pin_joint_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "pin_joint_3d.h"
+
+void PinJoint3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &PinJoint3D::set_param);
+ ClassDB::bind_method(D_METHOD("get_param", "param"), &PinJoint3D::get_param);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_BIAS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01"), "set_param", "get_param", PARAM_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "params/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01"), "set_param", "get_param", PARAM_IMPULSE_CLAMP);
+
+ BIND_ENUM_CONSTANT(PARAM_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_IMPULSE_CLAMP);
+}
+
+void PinJoint3D::set_param(Param p_param, real_t p_value) {
+ ERR_FAIL_INDEX(p_param, 3);
+ params[p_param] = p_value;
+ if (is_configured()) {
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(get_rid(), PhysicsServer3D::PinJointParam(p_param), p_value);
+ }
+}
+
+real_t PinJoint3D::get_param(Param p_param) const {
+ ERR_FAIL_INDEX_V(p_param, 3, 0);
+ return params[p_param];
+}
+
+void PinJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+ Vector3 pinpos = get_global_transform().origin;
+ Vector3 local_a = body_a->to_local(pinpos);
+ Vector3 local_b;
+
+ if (body_b) {
+ local_b = body_b->to_local(pinpos);
+ } else {
+ local_b = pinpos;
+ }
+
+ PhysicsServer3D::get_singleton()->joint_make_pin(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ for (int i = 0; i < 3; i++) {
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(p_joint, PhysicsServer3D::PinJointParam(i), params[i]);
+ }
+}
+
+PinJoint3D::PinJoint3D() {
+ params[PARAM_BIAS] = 0.3;
+ params[PARAM_DAMPING] = 1;
+ params[PARAM_IMPULSE_CLAMP] = 0;
+}
diff --git a/scene/3d/physics/joints/pin_joint_3d.h b/scene/3d/physics/joints/pin_joint_3d.h
new file mode 100644
index 0000000000..34c8db2890
--- /dev/null
+++ b/scene/3d/physics/joints/pin_joint_3d.h
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/* pin_joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PIN_JOINT_3D_H
+#define PIN_JOINT_3D_H
+
+#include "scene/3d/physics/joints/joint_3d.h"
+
+class PinJoint3D : public Joint3D {
+ GDCLASS(PinJoint3D, Joint3D);
+
+public:
+ enum Param {
+ PARAM_BIAS = PhysicsServer3D::PIN_JOINT_BIAS,
+ PARAM_DAMPING = PhysicsServer3D::PIN_JOINT_DAMPING,
+ PARAM_IMPULSE_CLAMP = PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP
+ };
+
+protected:
+ real_t params[3];
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_param(Param p_param, real_t p_value);
+ real_t get_param(Param p_param) const;
+
+ PinJoint3D();
+};
+
+VARIANT_ENUM_CAST(PinJoint3D::Param);
+
+#endif // PIN_JOINT_3D_H
diff --git a/scene/3d/physics/joints/slider_joint_3d.cpp b/scene/3d/physics/joints/slider_joint_3d.cpp
new file mode 100644
index 0000000000..2e87ae1e83
--- /dev/null
+++ b/scene/3d/physics/joints/slider_joint_3d.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************/
+/* slider_joint_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "slider_joint_3d.h"
+
+#include "scene/scene_string_names.h"
+
+void SliderJoint3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &SliderJoint3D::set_param);
+ ClassDB::bind_method(D_METHOD("get_param", "param"), &SliderJoint3D::get_param);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01,suffix:m"), "set_param", "get_param", PARAM_LINEAR_LIMIT_LOWER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_MOTION_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_LINEAR_ORTHOGONAL_DAMPING);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_UPPER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1,radians_as_degrees"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_LOWER);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_LIMIT_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motion/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_MOTION_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_ortho/damping", PROPERTY_HINT_RANGE, "0,16.0,0.01"), "set_param", "get_param", PARAM_ANGULAR_ORTHOGONAL_DAMPING);
+
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_UPPER);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_LOWER);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTION_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_ORTHOGONAL_DAMPING);
+
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_UPPER);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_LOWER);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTION_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
+ BIND_ENUM_CONSTANT(PARAM_ANGULAR_ORTHOGONAL_DAMPING);
+
+ BIND_ENUM_CONSTANT(PARAM_MAX);
+}
+
+void SliderJoint3D::set_param(Param p_param, real_t p_value) {
+ ERR_FAIL_INDEX(p_param, PARAM_MAX);
+ params[p_param] = p_value;
+ if (is_configured()) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(get_rid(), PhysicsServer3D::SliderJointParam(p_param), p_value);
+ }
+ update_gizmos();
+}
+
+real_t SliderJoint3D::get_param(Param p_param) const {
+ ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
+ return params[p_param];
+}
+
+void SliderJoint3D::_configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) {
+ Transform3D gt = get_global_transform();
+ Transform3D ainv = body_a->get_global_transform().affine_inverse();
+
+ Transform3D local_a = ainv * gt;
+ local_a.orthonormalize();
+ Transform3D local_b = gt;
+
+ if (body_b) {
+ Transform3D binv = body_b->get_global_transform().affine_inverse();
+ local_b = binv * gt;
+ }
+
+ local_b.orthonormalize();
+
+ PhysicsServer3D::get_singleton()->joint_make_slider(p_joint, body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b);
+ for (int i = 0; i < PARAM_MAX; i++) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(p_joint, PhysicsServer3D::SliderJointParam(i), params[i]);
+ }
+}
+
+SliderJoint3D::SliderJoint3D() {
+ params[PARAM_LINEAR_LIMIT_UPPER] = 1.0;
+ params[PARAM_LINEAR_LIMIT_LOWER] = -1.0;
+ params[PARAM_LINEAR_LIMIT_SOFTNESS] = 1.0;
+ params[PARAM_LINEAR_LIMIT_RESTITUTION] = 0.7;
+ params[PARAM_LINEAR_LIMIT_DAMPING] = 1.0;
+ params[PARAM_LINEAR_MOTION_SOFTNESS] = 1.0;
+ params[PARAM_LINEAR_MOTION_RESTITUTION] = 0.7;
+ params[PARAM_LINEAR_MOTION_DAMPING] = 0; //1.0;
+ params[PARAM_LINEAR_ORTHOGONAL_SOFTNESS] = 1.0;
+ params[PARAM_LINEAR_ORTHOGONAL_RESTITUTION] = 0.7;
+ params[PARAM_LINEAR_ORTHOGONAL_DAMPING] = 1.0;
+
+ params[PARAM_ANGULAR_LIMIT_UPPER] = 0;
+ params[PARAM_ANGULAR_LIMIT_LOWER] = 0;
+ params[PARAM_ANGULAR_LIMIT_SOFTNESS] = 1.0;
+ params[PARAM_ANGULAR_LIMIT_RESTITUTION] = 0.7;
+ params[PARAM_ANGULAR_LIMIT_DAMPING] = 0; //1.0;
+ params[PARAM_ANGULAR_MOTION_SOFTNESS] = 1.0;
+ params[PARAM_ANGULAR_MOTION_RESTITUTION] = 0.7;
+ params[PARAM_ANGULAR_MOTION_DAMPING] = 1.0;
+ params[PARAM_ANGULAR_ORTHOGONAL_SOFTNESS] = 1.0;
+ params[PARAM_ANGULAR_ORTHOGONAL_RESTITUTION] = 0.7;
+ params[PARAM_ANGULAR_ORTHOGONAL_DAMPING] = 1.0;
+}
diff --git a/scene/3d/physics/joints/slider_joint_3d.h b/scene/3d/physics/joints/slider_joint_3d.h
new file mode 100644
index 0000000000..e0b059e6e3
--- /dev/null
+++ b/scene/3d/physics/joints/slider_joint_3d.h
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/* slider_joint_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef SLIDER_JOINT_3D_H
+#define SLIDER_JOINT_3D_H
+
+#include "scene/3d/physics/joints/joint_3d.h"
+
+class SliderJoint3D : public Joint3D {
+ GDCLASS(SliderJoint3D, Joint3D);
+
+public:
+ enum Param {
+ PARAM_LINEAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER,
+ PARAM_LINEAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER,
+ PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS,
+ PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION,
+ PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING,
+ PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS,
+ PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION,
+ PARAM_LINEAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING,
+ PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS,
+ PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION,
+ PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING,
+
+ PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER,
+ PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER,
+ PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS,
+ PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION,
+ PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING,
+ PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS,
+ PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION,
+ PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING,
+ PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS,
+ PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION,
+ PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING,
+ PARAM_MAX = PhysicsServer3D::SLIDER_JOINT_MAX
+
+ };
+
+protected:
+ real_t params[PARAM_MAX];
+ virtual void _configure_joint(RID p_joint, PhysicsBody3D *body_a, PhysicsBody3D *body_b) override;
+ static void _bind_methods();
+
+public:
+ void set_param(Param p_param, real_t p_value);
+ real_t get_param(Param p_param) const;
+
+ SliderJoint3D();
+};
+
+VARIANT_ENUM_CAST(SliderJoint3D::Param);
+
+#endif // SLIDER_JOINT_3D_H
diff --git a/scene/3d/physics/kinematic_collision_3d.cpp b/scene/3d/physics/kinematic_collision_3d.cpp
new file mode 100644
index 0000000000..54371425bc
--- /dev/null
+++ b/scene/3d/physics/kinematic_collision_3d.cpp
@@ -0,0 +1,134 @@
+/**************************************************************************/
+/* kinematic_collision_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "kinematic_collision_3d.h"
+
+#include "scene/3d/physics/character_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+
+Vector3 KinematicCollision3D::get_travel() const {
+ return result.travel;
+}
+
+Vector3 KinematicCollision3D::get_remainder() const {
+ return result.remainder;
+}
+
+int KinematicCollision3D::get_collision_count() const {
+ return result.collision_count;
+}
+
+real_t KinematicCollision3D::get_depth() const {
+ return result.collision_depth;
+}
+
+Vector3 KinematicCollision3D::get_position(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].position;
+}
+
+Vector3 KinematicCollision3D::get_normal(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].normal;
+}
+
+real_t KinematicCollision3D::get_angle(int p_collision_index, const Vector3 &p_up_direction) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0.0);
+ ERR_FAIL_COND_V(p_up_direction == Vector3(), 0);
+ return result.collisions[p_collision_index].get_angle(p_up_direction);
+}
+
+Object *KinematicCollision3D::get_local_shape(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
+ if (!owner) {
+ return nullptr;
+ }
+ uint32_t ownerid = owner->shape_find_owner(result.collisions[p_collision_index].local_shape);
+ return owner->shape_owner_get_owner(ownerid);
+}
+
+Object *KinematicCollision3D::get_collider(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
+ if (result.collisions[p_collision_index].collider_id.is_valid()) {
+ return ObjectDB::get_instance(result.collisions[p_collision_index].collider_id);
+ }
+
+ return nullptr;
+}
+
+ObjectID KinematicCollision3D::get_collider_id(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, ObjectID());
+ return result.collisions[p_collision_index].collider_id;
+}
+
+RID KinematicCollision3D::get_collider_rid(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, RID());
+ return result.collisions[p_collision_index].collider;
+}
+
+Object *KinematicCollision3D::get_collider_shape(int p_collision_index) const {
+ Object *collider = get_collider(p_collision_index);
+ if (collider) {
+ CollisionObject3D *obj2d = Object::cast_to<CollisionObject3D>(collider);
+ if (obj2d) {
+ uint32_t ownerid = obj2d->shape_find_owner(result.collisions[p_collision_index].collider_shape);
+ return obj2d->shape_owner_get_owner(ownerid);
+ }
+ }
+
+ return nullptr;
+}
+
+int KinematicCollision3D::get_collider_shape_index(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0);
+ return result.collisions[p_collision_index].collider_shape;
+}
+
+Vector3 KinematicCollision3D::get_collider_velocity(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
+ return result.collisions[p_collision_index].collider_velocity;
+}
+
+void KinematicCollision3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision3D::get_travel);
+ ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision3D::get_remainder);
+ ClassDB::bind_method(D_METHOD("get_depth"), &KinematicCollision3D::get_depth);
+ ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicCollision3D::get_collision_count);
+ ClassDB::bind_method(D_METHOD("get_position", "collision_index"), &KinematicCollision3D::get_position, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_normal", "collision_index"), &KinematicCollision3D::get_normal, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_angle", "collision_index", "up_direction"), &KinematicCollision3D::get_angle, DEFVAL(0), DEFVAL(Vector3(0.0, 1.0, 0.0)));
+ ClassDB::bind_method(D_METHOD("get_local_shape", "collision_index"), &KinematicCollision3D::get_local_shape, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider", "collision_index"), &KinematicCollision3D::get_collider, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_id", "collision_index"), &KinematicCollision3D::get_collider_id, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_rid", "collision_index"), &KinematicCollision3D::get_collider_rid, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &KinematicCollision3D::get_collider_shape, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_shape_index", "collision_index"), &KinematicCollision3D::get_collider_shape_index, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collider_velocity", "collision_index"), &KinematicCollision3D::get_collider_velocity, DEFVAL(0));
+}
diff --git a/scene/3d/physics/kinematic_collision_3d.h b/scene/3d/physics/kinematic_collision_3d.h
new file mode 100644
index 0000000000..656531c82b
--- /dev/null
+++ b/scene/3d/physics/kinematic_collision_3d.h
@@ -0,0 +1,68 @@
+/**************************************************************************/
+/* kinematic_collision_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef KINEMATIC_COLLISION_3D_H
+#define KINEMATIC_COLLISION_3D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/physics_server_3d.h"
+
+class CharacterBody3D;
+class PhysicsBody3D;
+
+class KinematicCollision3D : public RefCounted {
+ GDCLASS(KinematicCollision3D, RefCounted);
+
+ PhysicsBody3D *owner = nullptr;
+ friend class PhysicsBody3D;
+ friend class CharacterBody3D;
+ PhysicsServer3D::MotionResult result;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Vector3 get_travel() const;
+ Vector3 get_remainder() const;
+ int get_collision_count() const;
+ real_t get_depth() const;
+ Vector3 get_position(int p_collision_index = 0) const;
+ Vector3 get_normal(int p_collision_index = 0) const;
+ real_t get_angle(int p_collision_index = 0, const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const;
+ Object *get_local_shape(int p_collision_index = 0) const;
+ Object *get_collider(int p_collision_index = 0) const;
+ ObjectID get_collider_id(int p_collision_index = 0) const;
+ RID get_collider_rid(int p_collision_index = 0) const;
+ Object *get_collider_shape(int p_collision_index = 0) const;
+ int get_collider_shape_index(int p_collision_index = 0) const;
+ Vector3 get_collider_velocity(int p_collision_index = 0) const;
+};
+
+#endif // KINEMATIC_COLLISION_3D_H
diff --git a/scene/3d/physics/physical_bone_3d.cpp b/scene/3d/physics/physical_bone_3d.cpp
new file mode 100644
index 0000000000..10c1fceb94
--- /dev/null
+++ b/scene/3d/physics/physical_bone_3d.cpp
@@ -0,0 +1,1346 @@
+/**************************************************************************/
+/* physical_bone_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "physical_bone_3d.h"
+
+bool PhysicalBone3D::JointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ return false;
+}
+
+bool PhysicalBone3D::JointData::_get(const StringName &p_name, Variant &r_ret) const {
+ return false;
+}
+
+void PhysicalBone3D::JointData::_get_property_list(List<PropertyInfo> *p_list) const {
+}
+
+void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) {
+ PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
+}
+
+void PhysicalBone3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
+}
+
+void PhysicalBone3D::set_linear_velocity(const Vector3 &p_velocity) {
+ linear_velocity = p_velocity;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+}
+
+Vector3 PhysicalBone3D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+void PhysicalBone3D::set_angular_velocity(const Vector3 &p_velocity) {
+ angular_velocity = p_velocity;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
+}
+
+Vector3 PhysicalBone3D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void PhysicalBone3D::set_use_custom_integrator(bool p_enable) {
+ if (custom_integrator == p_enable) {
+ return;
+ }
+
+ custom_integrator = p_enable;
+ PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
+}
+
+bool PhysicalBone3D::is_using_custom_integrator() {
+ return custom_integrator;
+}
+
+void PhysicalBone3D::reset_physics_simulation_state() {
+ if (simulate_physics) {
+ _start_physics_simulation();
+ } else {
+ _stop_physics_simulation();
+ }
+}
+
+void PhysicalBone3D::reset_to_rest_position() {
+ if (parent_skeleton) {
+ Transform3D new_transform = parent_skeleton->get_global_transform();
+ if (bone_id == -1) {
+ new_transform *= body_offset;
+ } else {
+ new_transform *= parent_skeleton->get_bone_global_pose(bone_id) * body_offset;
+ }
+ new_transform.orthonormalize();
+ set_global_transform(new_transform);
+ }
+}
+
+bool PhysicalBone3D::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ if (JointData::_set(p_name, p_value, j)) {
+ return true;
+ }
+
+ bool is_valid_pin = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_PIN;
+ if ("joint_constraints/bias" == p_name) {
+ bias = p_value;
+ if (is_valid_pin) {
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_BIAS, bias);
+ }
+
+ } else if ("joint_constraints/damping" == p_name) {
+ damping = p_value;
+ if (is_valid_pin) {
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_DAMPING, damping);
+ }
+
+ } else if ("joint_constraints/impulse_clamp" == p_name) {
+ impulse_clamp = p_value;
+ if (is_valid_pin) {
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp);
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhysicalBone3D::PinJointData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (JointData::_get(p_name, r_ret)) {
+ return true;
+ }
+
+ if ("joint_constraints/bias" == p_name) {
+ r_ret = bias;
+ } else if ("joint_constraints/damping" == p_name) {
+ r_ret = damping;
+ } else if ("joint_constraints/impulse_clamp" == p_name) {
+ r_ret = impulse_clamp;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void PhysicalBone3D::PinJointData::_get_property_list(List<PropertyInfo> *p_list) const {
+ JointData::_get_property_list(p_list);
+
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/bias"), PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/damping"), PROPERTY_HINT_RANGE, "0.01,8.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/impulse_clamp"), PROPERTY_HINT_RANGE, "0.0,64.0,0.01"));
+}
+
+bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ if (JointData::_set(p_name, p_value, j)) {
+ return true;
+ }
+
+ bool is_valid_cone = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_CONE_TWIST;
+ if ("joint_constraints/swing_span" == p_name) {
+ swing_span = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_cone) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span);
+ }
+
+ } else if ("joint_constraints/twist_span" == p_name) {
+ twist_span = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_cone) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span);
+ }
+
+ } else if ("joint_constraints/bias" == p_name) {
+ bias = p_value;
+ if (is_valid_cone) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, bias);
+ }
+
+ } else if ("joint_constraints/softness" == p_name) {
+ softness = p_value;
+ if (is_valid_cone) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, softness);
+ }
+
+ } else if ("joint_constraints/relaxation" == p_name) {
+ relaxation = p_value;
+ if (is_valid_cone) {
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, relaxation);
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhysicalBone3D::ConeJointData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (JointData::_get(p_name, r_ret)) {
+ return true;
+ }
+
+ if ("joint_constraints/swing_span" == p_name) {
+ r_ret = Math::rad_to_deg(swing_span);
+ } else if ("joint_constraints/twist_span" == p_name) {
+ r_ret = Math::rad_to_deg(twist_span);
+ } else if ("joint_constraints/bias" == p_name) {
+ r_ret = bias;
+ } else if ("joint_constraints/softness" == p_name) {
+ r_ret = softness;
+ } else if ("joint_constraints/relaxation" == p_name) {
+ r_ret = relaxation;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void PhysicalBone3D::ConeJointData::_get_property_list(List<PropertyInfo> *p_list) const {
+ JointData::_get_property_list(p_list);
+
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/swing_span"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/twist_span"), PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_less,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/bias"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/relaxation"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+}
+
+bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ if (JointData::_set(p_name, p_value, j)) {
+ return true;
+ }
+
+ bool is_valid_hinge = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_HINGE;
+ if ("joint_constraints/angular_limit_enabled" == p_name) {
+ angular_limit_enabled = p_value;
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled);
+ }
+
+ } else if ("joint_constraints/angular_limit_upper" == p_name) {
+ angular_limit_upper = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper);
+ }
+
+ } else if ("joint_constraints/angular_limit_lower" == p_name) {
+ angular_limit_lower = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower);
+ }
+
+ } else if ("joint_constraints/angular_limit_bias" == p_name) {
+ angular_limit_bias = p_value;
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias);
+ }
+
+ } else if ("joint_constraints/angular_limit_softness" == p_name) {
+ angular_limit_softness = p_value;
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness);
+ }
+
+ } else if ("joint_constraints/angular_limit_relaxation" == p_name) {
+ angular_limit_relaxation = p_value;
+ if (is_valid_hinge) {
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation);
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhysicalBone3D::HingeJointData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (JointData::_get(p_name, r_ret)) {
+ return true;
+ }
+
+ if ("joint_constraints/angular_limit_enabled" == p_name) {
+ r_ret = angular_limit_enabled;
+ } else if ("joint_constraints/angular_limit_upper" == p_name) {
+ r_ret = Math::rad_to_deg(angular_limit_upper);
+ } else if ("joint_constraints/angular_limit_lower" == p_name) {
+ r_ret = Math::rad_to_deg(angular_limit_lower);
+ } else if ("joint_constraints/angular_limit_bias" == p_name) {
+ r_ret = angular_limit_bias;
+ } else if ("joint_constraints/angular_limit_softness" == p_name) {
+ r_ret = angular_limit_softness;
+ } else if ("joint_constraints/angular_limit_relaxation" == p_name) {
+ r_ret = angular_limit_relaxation;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void PhysicalBone3D::HingeJointData::_get_property_list(List<PropertyInfo> *p_list) const {
+ JointData::_get_property_list(p_list);
+
+ p_list->push_back(PropertyInfo(Variant::BOOL, PNAME("joint_constraints/angular_limit_enabled")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_bias"), PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_relaxation"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+}
+
+bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ if (JointData::_set(p_name, p_value, j)) {
+ return true;
+ }
+
+ bool is_valid_slider = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_SLIDER;
+ if ("joint_constraints/linear_limit_upper" == p_name) {
+ linear_limit_upper = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper);
+ }
+
+ } else if ("joint_constraints/linear_limit_lower" == p_name) {
+ linear_limit_lower = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower);
+ }
+
+ } else if ("joint_constraints/linear_limit_softness" == p_name) {
+ linear_limit_softness = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness);
+ }
+
+ } else if ("joint_constraints/linear_limit_restitution" == p_name) {
+ linear_limit_restitution = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution);
+ }
+
+ } else if ("joint_constraints/linear_limit_damping" == p_name) {
+ linear_limit_damping = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution);
+ }
+
+ } else if ("joint_constraints/angular_limit_upper" == p_name) {
+ angular_limit_upper = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper);
+ }
+
+ } else if ("joint_constraints/angular_limit_lower" == p_name) {
+ angular_limit_lower = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower);
+ }
+
+ } else if ("joint_constraints/angular_limit_softness" == p_name) {
+ angular_limit_softness = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
+ }
+
+ } else if ("joint_constraints/angular_limit_restitution" == p_name) {
+ angular_limit_restitution = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
+ }
+
+ } else if ("joint_constraints/angular_limit_damping" == p_name) {
+ angular_limit_damping = p_value;
+ if (is_valid_slider) {
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping);
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhysicalBone3D::SliderJointData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (JointData::_get(p_name, r_ret)) {
+ return true;
+ }
+
+ if ("joint_constraints/linear_limit_upper" == p_name) {
+ r_ret = linear_limit_upper;
+ } else if ("joint_constraints/linear_limit_lower" == p_name) {
+ r_ret = linear_limit_lower;
+ } else if ("joint_constraints/linear_limit_softness" == p_name) {
+ r_ret = linear_limit_softness;
+ } else if ("joint_constraints/linear_limit_restitution" == p_name) {
+ r_ret = linear_limit_restitution;
+ } else if ("joint_constraints/linear_limit_damping" == p_name) {
+ r_ret = linear_limit_damping;
+ } else if ("joint_constraints/angular_limit_upper" == p_name) {
+ r_ret = Math::rad_to_deg(angular_limit_upper);
+ } else if ("joint_constraints/angular_limit_lower" == p_name) {
+ r_ret = Math::rad_to_deg(angular_limit_lower);
+ } else if ("joint_constraints/angular_limit_softness" == p_name) {
+ r_ret = angular_limit_softness;
+ } else if ("joint_constraints/angular_limit_restitution" == p_name) {
+ r_ret = angular_limit_restitution;
+ } else if ("joint_constraints/angular_limit_damping" == p_name) {
+ r_ret = angular_limit_damping;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void PhysicalBone3D::SliderJointData::_get_property_list(List<PropertyInfo> *p_list) const {
+ JointData::_get_property_list(p_list);
+
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_upper")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_lower")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_restitution"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_damping"), PROPERTY_HINT_RANGE, "0,16.0,0.01"));
+
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_restitution"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_damping"), PROPERTY_HINT_RANGE, "0,16.0,0.01"));
+}
+
+bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
+ if (JointData::_set(p_name, p_value, j)) {
+ return true;
+ }
+
+ String path = p_name;
+
+ if (!path.begins_with("joint_constraints/")) {
+ return false;
+ }
+
+ Vector3::Axis axis;
+ {
+ const String axis_s = path.get_slicec('/', 1);
+ if ("x" == axis_s) {
+ axis = Vector3::AXIS_X;
+ } else if ("y" == axis_s) {
+ axis = Vector3::AXIS_Y;
+ } else if ("z" == axis_s) {
+ axis = Vector3::AXIS_Z;
+ } else {
+ return false;
+ }
+ }
+
+ String var_name = path.get_slicec('/', 2);
+ bool is_valid_6dof = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_6DOF;
+ if ("linear_limit_enabled" == var_name) {
+ axis_data[axis].linear_limit_enabled = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled);
+ }
+
+ } else if ("linear_limit_upper" == var_name) {
+ axis_data[axis].linear_limit_upper = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper);
+ }
+
+ } else if ("linear_limit_lower" == var_name) {
+ axis_data[axis].linear_limit_lower = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower);
+ }
+
+ } else if ("linear_limit_softness" == var_name) {
+ axis_data[axis].linear_limit_softness = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
+ }
+
+ } else if ("linear_spring_enabled" == var_name) {
+ axis_data[axis].linear_spring_enabled = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
+ }
+
+ } else if ("linear_spring_stiffness" == var_name) {
+ axis_data[axis].linear_spring_stiffness = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
+ }
+
+ } else if ("linear_spring_damping" == var_name) {
+ axis_data[axis].linear_spring_damping = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
+ }
+
+ } else if ("linear_equilibrium_point" == var_name) {
+ axis_data[axis].linear_equilibrium_point = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
+ }
+
+ } else if ("linear_restitution" == var_name) {
+ axis_data[axis].linear_restitution = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution);
+ }
+
+ } else if ("linear_damping" == var_name) {
+ axis_data[axis].linear_damping = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping);
+ }
+
+ } else if ("angular_limit_enabled" == var_name) {
+ axis_data[axis].angular_limit_enabled = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled);
+ }
+
+ } else if ("angular_limit_upper" == var_name) {
+ axis_data[axis].angular_limit_upper = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper);
+ }
+
+ } else if ("angular_limit_lower" == var_name) {
+ axis_data[axis].angular_limit_lower = Math::deg_to_rad(real_t(p_value));
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower);
+ }
+
+ } else if ("angular_limit_softness" == var_name) {
+ axis_data[axis].angular_limit_softness = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness);
+ }
+
+ } else if ("angular_restitution" == var_name) {
+ axis_data[axis].angular_restitution = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution);
+ }
+
+ } else if ("angular_damping" == var_name) {
+ axis_data[axis].angular_damping = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping);
+ }
+
+ } else if ("erp" == var_name) {
+ axis_data[axis].erp = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
+ }
+
+ } else if ("angular_spring_enabled" == var_name) {
+ axis_data[axis].angular_spring_enabled = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
+ }
+
+ } else if ("angular_spring_stiffness" == var_name) {
+ axis_data[axis].angular_spring_stiffness = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
+ }
+
+ } else if ("angular_spring_damping" == var_name) {
+ axis_data[axis].angular_spring_damping = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
+ }
+
+ } else if ("angular_equilibrium_point" == var_name) {
+ axis_data[axis].angular_equilibrium_point = p_value;
+ if (is_valid_6dof) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhysicalBone3D::SixDOFJointData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (JointData::_get(p_name, r_ret)) {
+ return true;
+ }
+
+ String path = p_name;
+
+ if (!path.begins_with("joint_constraints/")) {
+ return false;
+ }
+
+ int axis;
+ {
+ const String axis_s = path.get_slicec('/', 1);
+ if ("x" == axis_s) {
+ axis = 0;
+ } else if ("y" == axis_s) {
+ axis = 1;
+ } else if ("z" == axis_s) {
+ axis = 2;
+ } else {
+ return false;
+ }
+ }
+
+ String var_name = path.get_slicec('/', 2);
+
+ if ("linear_limit_enabled" == var_name) {
+ r_ret = axis_data[axis].linear_limit_enabled;
+ } else if ("linear_limit_upper" == var_name) {
+ r_ret = axis_data[axis].linear_limit_upper;
+ } else if ("linear_limit_lower" == var_name) {
+ r_ret = axis_data[axis].linear_limit_lower;
+ } else if ("linear_limit_softness" == var_name) {
+ r_ret = axis_data[axis].linear_limit_softness;
+ } else if ("linear_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].linear_spring_enabled;
+ } else if ("linear_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].linear_spring_stiffness;
+ } else if ("linear_spring_damping" == var_name) {
+ r_ret = axis_data[axis].linear_spring_damping;
+ } else if ("linear_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].linear_equilibrium_point;
+ } else if ("linear_restitution" == var_name) {
+ r_ret = axis_data[axis].linear_restitution;
+ } else if ("linear_damping" == var_name) {
+ r_ret = axis_data[axis].linear_damping;
+ } else if ("angular_limit_enabled" == var_name) {
+ r_ret = axis_data[axis].angular_limit_enabled;
+ } else if ("angular_limit_upper" == var_name) {
+ r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_upper);
+ } else if ("angular_limit_lower" == var_name) {
+ r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_lower);
+ } else if ("angular_limit_softness" == var_name) {
+ r_ret = axis_data[axis].angular_limit_softness;
+ } else if ("angular_restitution" == var_name) {
+ r_ret = axis_data[axis].angular_restitution;
+ } else if ("angular_damping" == var_name) {
+ r_ret = axis_data[axis].angular_damping;
+ } else if ("erp" == var_name) {
+ r_ret = axis_data[axis].erp;
+ } else if ("angular_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].angular_spring_enabled;
+ } else if ("angular_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].angular_spring_stiffness;
+ } else if ("angular_spring_damping" == var_name) {
+ r_ret = axis_data[axis].angular_spring_damping;
+ } else if ("angular_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].angular_equilibrium_point;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+void PhysicalBone3D::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_list) const {
+ const StringName axis_names[] = { PNAME("x"), PNAME("y"), PNAME("z") };
+ for (int i = 0; i < 3; ++i) {
+ const String prefix = vformat("%s/%s/", PNAME("joint_constraints"), axis_names[i]);
+ p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("linear_limit_enabled")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_upper")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_lower")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("linear_spring_enabled")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_spring_stiffness")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_spring_damping")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_equilibrium_point")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_restitution"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_damping"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("angular_limit_enabled")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_restitution"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_damping"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("erp")));
+ p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("angular_spring_enabled")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_spring_stiffness")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_spring_damping")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_equilibrium_point")));
+ }
+}
+
+bool PhysicalBone3D::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "bone_name") {
+ set_bone_name(p_value);
+ return true;
+ }
+
+ if (joint_data) {
+ if (joint_data->_set(p_name, p_value, joint)) {
+#ifdef TOOLS_ENABLED
+ update_gizmos();
+#endif
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool PhysicalBone3D::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "bone_name") {
+ r_ret = get_bone_name();
+ return true;
+ }
+
+ if (joint_data) {
+ return joint_data->_get(p_name, r_ret);
+ }
+
+ return false;
+}
+
+void PhysicalBone3D::_get_property_list(List<PropertyInfo> *p_list) const {
+ Skeleton3D *parent = find_skeleton_parent(get_parent());
+
+ if (parent) {
+ String names;
+ for (int i = 0; i < parent->get_bone_count(); i++) {
+ if (i > 0) {
+ names += ",";
+ }
+ names += parent->get_bone_name(i);
+ }
+
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name"), PROPERTY_HINT_ENUM, names));
+ } else {
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name")));
+ }
+
+ if (joint_data) {
+ joint_data->_get_property_list(p_list);
+ }
+}
+
+void PhysicalBone3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ parent_skeleton = find_skeleton_parent(get_parent());
+ update_bone_id();
+ reset_to_rest_position();
+ reset_physics_simulation_state();
+ if (joint_data) {
+ _reload_joint();
+ }
+ break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ if (parent_skeleton) {
+ if (-1 != bone_id) {
+ parent_skeleton->unbind_physical_bone_from_bone(bone_id);
+ bone_id = -1;
+ }
+ }
+ parent_skeleton = nullptr;
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
+ } break;
+
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_offset();
+ }
+ } break;
+ }
+}
+
+void PhysicalBone3D::_sync_body_state(PhysicsDirectBodyState3D *p_state) {
+ set_ignore_transform_notification(true);
+ set_global_transform(p_state->get_transform());
+ set_ignore_transform_notification(false);
+
+ linear_velocity = p_state->get_linear_velocity();
+ angular_velocity = p_state->get_angular_velocity();
+}
+
+void PhysicalBone3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
+ if (!simulate_physics || !_internal_simulate_physics) {
+ return;
+ }
+
+ if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
+ _sync_body_state(p_state);
+
+ Transform3D old_transform = get_global_transform();
+ GDVIRTUAL_CALL(_integrate_forces, p_state);
+ Transform3D new_transform = get_global_transform();
+
+ if (new_transform != old_transform) {
+ // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+ }
+ }
+
+ _sync_body_state(p_state);
+ _on_transform_changed();
+
+ Transform3D global_transform(p_state->get_transform());
+
+ // Update skeleton
+ if (parent_skeleton) {
+ if (-1 != bone_id) {
+ parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1.0, true);
+ }
+ }
+}
+
+void PhysicalBone3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse);
+ ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3());
+
+ ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone3D::set_joint_type);
+ ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone3D::get_joint_type);
+
+ ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone3D::set_joint_offset);
+ ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone3D::get_joint_offset);
+ ClassDB::bind_method(D_METHOD("set_joint_rotation", "euler"), &PhysicalBone3D::set_joint_rotation);
+ ClassDB::bind_method(D_METHOD("get_joint_rotation"), &PhysicalBone3D::get_joint_rotation);
+
+ ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone3D::set_body_offset);
+ ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone3D::get_body_offset);
+
+ ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone3D::get_simulate_physics);
+
+ ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone3D::is_simulating_physics);
+
+ ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone3D::get_bone_id);
+
+ ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone3D::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone3D::get_mass);
+
+ ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone3D::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone3D::get_friction);
+
+ ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &PhysicalBone3D::set_bounce);
+ ClassDB::bind_method(D_METHOD("get_bounce"), &PhysicalBone3D::get_bounce);
+
+ ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone3D::set_gravity_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone3D::get_gravity_scale);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &PhysicalBone3D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &PhysicalBone3D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &PhysicalBone3D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &PhysicalBone3D::get_angular_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &PhysicalBone3D::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"), &PhysicalBone3D::get_linear_damp);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &PhysicalBone3D::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"), &PhysicalBone3D::get_angular_damp);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &PhysicalBone3D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicalBone3D::get_linear_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &PhysicalBone3D::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"), &PhysicalBone3D::get_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &PhysicalBone3D::set_use_custom_integrator);
+ ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &PhysicalBone3D::is_using_custom_integrator);
+
+ ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &PhysicalBone3D::set_can_sleep);
+ ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &PhysicalBone3D::is_able_to_sleep);
+
+ GDVIRTUAL_BIND(_integrate_forces, "state");
+
+ ADD_GROUP("Joint", "joint_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "joint_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_joint_offset", "get_joint_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_RANGE, "-360,360,0.01,or_less,or_greater,radians_as_degrees"), "set_joint_rotation", "get_joint_rotation");
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_body_offset", "get_body_offset");
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
+
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+
+ BIND_ENUM_CONSTANT(JOINT_TYPE_NONE);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_CONE);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER);
+ BIND_ENUM_CONSTANT(JOINT_TYPE_6DOF);
+}
+
+Skeleton3D *PhysicalBone3D::find_skeleton_parent(Node *p_parent) {
+ if (!p_parent) {
+ return nullptr;
+ }
+ Skeleton3D *s = Object::cast_to<Skeleton3D>(p_parent);
+ return s ? s : find_skeleton_parent(p_parent->get_parent());
+}
+
+void PhysicalBone3D::_update_joint_offset() {
+ _fix_joint_offset();
+
+ set_ignore_transform_notification(true);
+ reset_to_rest_position();
+ set_ignore_transform_notification(false);
+
+#ifdef TOOLS_ENABLED
+ update_gizmos();
+#endif
+}
+
+void PhysicalBone3D::_fix_joint_offset() {
+ // Clamp joint origin to bone origin
+ if (parent_skeleton) {
+ joint_offset.origin = body_offset.affine_inverse().origin;
+ }
+}
+
+void PhysicalBone3D::_reload_joint() {
+ if (!parent_skeleton) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
+ return;
+ }
+
+ PhysicalBone3D *body_a = parent_skeleton->get_physical_bone_parent(bone_id);
+ if (!body_a) {
+ PhysicsServer3D::get_singleton()->joint_clear(joint);
+ return;
+ }
+
+ Transform3D joint_transf = get_global_transform() * joint_offset;
+ Transform3D local_a = body_a->get_global_transform().affine_inverse() * joint_transf;
+ local_a.orthonormalize();
+
+ switch (get_joint_type()) {
+ case JOINT_TYPE_PIN: {
+ PhysicsServer3D::get_singleton()->joint_make_pin(joint, body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
+ const PinJointData *pjd(static_cast<const PinJointData *>(joint_data));
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias);
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping);
+ PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp);
+
+ } break;
+ case JOINT_TYPE_CONE: {
+ PhysicsServer3D::get_singleton()->joint_make_cone_twist(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
+ const ConeJointData *cjd(static_cast<const ConeJointData *>(joint_data));
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span);
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span);
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, cjd->bias);
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, cjd->softness);
+ PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation);
+
+ } break;
+ case JOINT_TYPE_HINGE: {
+ PhysicsServer3D::get_singleton()->joint_make_hinge(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
+ const HingeJointData *hjd(static_cast<const HingeJointData *>(joint_data));
+ PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness);
+ PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation);
+
+ } break;
+ case JOINT_TYPE_SLIDER: {
+ PhysicsServer3D::get_singleton()->joint_make_slider(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
+ const SliderJointData *sjd(static_cast<const SliderJointData *>(joint_data));
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness);
+ PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping);
+
+ } break;
+ case JOINT_TYPE_6DOF: {
+ PhysicsServer3D::get_singleton()->joint_make_generic_6dof(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
+ const SixDOFJointData *g6dofjd(static_cast<const SixDOFJointData *>(joint_data));
+ for (int axis = 0; axis < 3; ++axis) {
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping);
+ PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point);
+ }
+
+ } break;
+ case JOINT_TYPE_NONE: {
+ } break;
+ }
+}
+
+void PhysicalBone3D::_on_bone_parent_changed() {
+ _reload_joint();
+}
+
+#ifdef TOOLS_ENABLED
+void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) {
+ gizmo_move_joint = p_move_joint;
+}
+
+Transform3D PhysicalBone3D::get_global_gizmo_transform() const {
+ return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform();
+}
+
+Transform3D PhysicalBone3D::get_local_gizmo_transform() const {
+ return gizmo_move_joint ? get_transform() * joint_offset : get_transform();
+}
+#endif
+
+const PhysicalBone3D::JointData *PhysicalBone3D::get_joint_data() const {
+ return joint_data;
+}
+
+Skeleton3D *PhysicalBone3D::find_skeleton_parent() {
+ return find_skeleton_parent(this);
+}
+
+void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
+ if (p_joint_type == get_joint_type()) {
+ return;
+ }
+
+ if (joint_data) {
+ memdelete(joint_data);
+ }
+ joint_data = nullptr;
+ switch (p_joint_type) {
+ case JOINT_TYPE_PIN:
+ joint_data = memnew(PinJointData);
+ break;
+ case JOINT_TYPE_CONE:
+ joint_data = memnew(ConeJointData);
+ break;
+ case JOINT_TYPE_HINGE:
+ joint_data = memnew(HingeJointData);
+ break;
+ case JOINT_TYPE_SLIDER:
+ joint_data = memnew(SliderJointData);
+ break;
+ case JOINT_TYPE_6DOF:
+ joint_data = memnew(SixDOFJointData);
+ break;
+ case JOINT_TYPE_NONE:
+ break;
+ }
+
+ _reload_joint();
+
+#ifdef TOOLS_ENABLED
+ notify_property_list_changed();
+ update_gizmos();
+#endif
+}
+
+PhysicalBone3D::JointType PhysicalBone3D::get_joint_type() const {
+ return joint_data ? joint_data->get_joint_type() : JOINT_TYPE_NONE;
+}
+
+void PhysicalBone3D::set_joint_offset(const Transform3D &p_offset) {
+ joint_offset = p_offset;
+
+ _update_joint_offset();
+}
+
+const Transform3D &PhysicalBone3D::get_joint_offset() const {
+ return joint_offset;
+}
+
+void PhysicalBone3D::set_joint_rotation(const Vector3 &p_euler_rad) {
+ joint_offset.basis.set_euler_scale(p_euler_rad, joint_offset.basis.get_scale());
+
+ _update_joint_offset();
+}
+
+Vector3 PhysicalBone3D::get_joint_rotation() const {
+ return joint_offset.basis.get_euler_normalized();
+}
+
+const Transform3D &PhysicalBone3D::get_body_offset() const {
+ return body_offset;
+}
+
+void PhysicalBone3D::set_body_offset(const Transform3D &p_offset) {
+ body_offset = p_offset;
+ body_offset_inverse = body_offset.affine_inverse();
+
+ _update_joint_offset();
+}
+
+void PhysicalBone3D::set_simulate_physics(bool p_simulate) {
+ if (simulate_physics == p_simulate) {
+ return;
+ }
+
+ simulate_physics = p_simulate;
+ reset_physics_simulation_state();
+}
+
+bool PhysicalBone3D::get_simulate_physics() {
+ return simulate_physics;
+}
+
+bool PhysicalBone3D::is_simulating_physics() {
+ return _internal_simulate_physics;
+}
+
+void PhysicalBone3D::set_bone_name(const String &p_name) {
+ bone_name = p_name;
+ bone_id = -1;
+
+ update_bone_id();
+ reset_to_rest_position();
+}
+
+const String &PhysicalBone3D::get_bone_name() const {
+ return bone_name;
+}
+
+void PhysicalBone3D::set_mass(real_t p_mass) {
+ ERR_FAIL_COND(p_mass <= 0);
+ mass = p_mass;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
+}
+
+real_t PhysicalBone3D::get_mass() const {
+ return mass;
+}
+
+void PhysicalBone3D::set_friction(real_t p_friction) {
+ ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
+
+ friction = p_friction;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, friction);
+}
+
+real_t PhysicalBone3D::get_friction() const {
+ return friction;
+}
+
+void PhysicalBone3D::set_bounce(real_t p_bounce) {
+ ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
+
+ bounce = p_bounce;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, bounce);
+}
+
+real_t PhysicalBone3D::get_bounce() const {
+ return bounce;
+}
+
+void PhysicalBone3D::set_gravity_scale(real_t p_gravity_scale) {
+ gravity_scale = p_gravity_scale;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
+}
+
+real_t PhysicalBone3D::get_gravity_scale() const {
+ return gravity_scale;
+}
+
+void PhysicalBone3D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+PhysicalBone3D::DampMode PhysicalBone3D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void PhysicalBone3D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+PhysicalBone3D::DampMode PhysicalBone3D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
+void PhysicalBone3D::set_linear_damp(real_t p_linear_damp) {
+ ERR_FAIL_COND(p_linear_damp < 0);
+
+ linear_damp = p_linear_damp;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
+}
+
+real_t PhysicalBone3D::get_linear_damp() const {
+ return linear_damp;
+}
+
+void PhysicalBone3D::set_angular_damp(real_t p_angular_damp) {
+ ERR_FAIL_COND(p_angular_damp < 0);
+
+ angular_damp = p_angular_damp;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
+}
+
+real_t PhysicalBone3D::get_angular_damp() const {
+ return angular_damp;
+}
+
+void PhysicalBone3D::set_can_sleep(bool p_active) {
+ can_sleep = p_active;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active);
+}
+
+bool PhysicalBone3D::is_able_to_sleep() const {
+ return can_sleep;
+}
+
+PhysicalBone3D::PhysicalBone3D() :
+ PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
+ joint = PhysicsServer3D::get_singleton()->joint_create();
+ reset_physics_simulation_state();
+}
+
+PhysicalBone3D::~PhysicalBone3D() {
+ if (joint_data) {
+ memdelete(joint_data);
+ }
+ ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
+ PhysicsServer3D::get_singleton()->free(joint);
+}
+
+void PhysicalBone3D::update_bone_id() {
+ if (!parent_skeleton) {
+ return;
+ }
+
+ const int new_bone_id = parent_skeleton->find_bone(bone_name);
+
+ if (new_bone_id != bone_id) {
+ if (-1 != bone_id) {
+ // Assert the unbind from old node
+ parent_skeleton->unbind_physical_bone_from_bone(bone_id);
+ }
+
+ bone_id = new_bone_id;
+
+ parent_skeleton->bind_physical_bone_to_bone(bone_id, this);
+
+ _fix_joint_offset();
+ reset_physics_simulation_state();
+ }
+}
+
+void PhysicalBone3D::update_offset() {
+#ifdef TOOLS_ENABLED
+ if (parent_skeleton) {
+ Transform3D bone_transform(parent_skeleton->get_global_transform());
+ if (-1 != bone_id) {
+ bone_transform *= parent_skeleton->get_bone_global_pose(bone_id);
+ }
+
+ if (gizmo_move_joint) {
+ bone_transform *= body_offset;
+ set_joint_offset(bone_transform.affine_inverse() * get_global_transform());
+ } else {
+ set_body_offset(bone_transform.affine_inverse() * get_global_transform());
+ }
+ }
+#endif
+}
+
+void PhysicalBone3D::_start_physics_simulation() {
+ if (_internal_simulate_physics || !parent_skeleton) {
+ return;
+ }
+ reset_to_rest_position();
+ set_body_mode(PhysicsServer3D::BODY_MODE_RIGID);
+ PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
+ PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
+ PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_body_state_changed));
+ set_as_top_level(true);
+ _internal_simulate_physics = true;
+}
+
+void PhysicalBone3D::_stop_physics_simulation() {
+ if (!parent_skeleton) {
+ return;
+ }
+ if (parent_skeleton->get_animate_physical_bones()) {
+ set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
+ PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
+ PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
+ PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());
+ } else {
+ set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
+ PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0);
+ PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
+ PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), 1.0);
+ }
+ if (_internal_simulate_physics) {
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
+ parent_skeleton->set_bone_global_pose_override(bone_id, Transform3D(), 0.0, false);
+ set_as_top_level(false);
+ _internal_simulate_physics = false;
+ }
+}
diff --git a/scene/3d/physics/physical_bone_3d.h b/scene/3d/physics/physical_bone_3d.h
new file mode 100644
index 0000000000..953400da2f
--- /dev/null
+++ b/scene/3d/physics/physical_bone_3d.h
@@ -0,0 +1,306 @@
+/**************************************************************************/
+/* physical_bone_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PHYSICAL_BONE_3D_H
+#define PHYSICAL_BONE_3D_H
+
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/skeleton_3d.h"
+
+class PhysicalBone3D : public PhysicsBody3D {
+ GDCLASS(PhysicalBone3D, PhysicsBody3D);
+
+public:
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
+ enum JointType {
+ JOINT_TYPE_NONE,
+ JOINT_TYPE_PIN,
+ JOINT_TYPE_CONE,
+ JOINT_TYPE_HINGE,
+ JOINT_TYPE_SLIDER,
+ JOINT_TYPE_6DOF
+ };
+
+ struct JointData {
+ virtual JointType get_joint_type() { return JOINT_TYPE_NONE; }
+
+ /// "j" is used to set the parameter inside the PhysicsServer3D
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ virtual ~JointData() {}
+ };
+
+ struct PinJointData : public JointData {
+ virtual JointType get_joint_type() { return JOINT_TYPE_PIN; }
+
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ real_t bias = 0.3;
+ real_t damping = 1.0;
+ real_t impulse_clamp = 0.0;
+ };
+
+ struct ConeJointData : public JointData {
+ virtual JointType get_joint_type() { return JOINT_TYPE_CONE; }
+
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ real_t swing_span = Math_PI * 0.25;
+ real_t twist_span = Math_PI;
+ real_t bias = 0.3;
+ real_t softness = 0.8;
+ real_t relaxation = 1.;
+ };
+
+ struct HingeJointData : public JointData {
+ virtual JointType get_joint_type() { return JOINT_TYPE_HINGE; }
+
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ bool angular_limit_enabled = false;
+ real_t angular_limit_upper = Math_PI * 0.5;
+ real_t angular_limit_lower = -Math_PI * 0.5;
+ real_t angular_limit_bias = 0.3;
+ real_t angular_limit_softness = 0.9;
+ real_t angular_limit_relaxation = 1.;
+ };
+
+ struct SliderJointData : public JointData {
+ virtual JointType get_joint_type() { return JOINT_TYPE_SLIDER; }
+
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ real_t linear_limit_upper = 1.0;
+ real_t linear_limit_lower = -1.0;
+ real_t linear_limit_softness = 1.0;
+ real_t linear_limit_restitution = 0.7;
+ real_t linear_limit_damping = 1.0;
+ real_t angular_limit_upper = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_softness = 1.0;
+ real_t angular_limit_restitution = 0.7;
+ real_t angular_limit_damping = 1.0;
+ };
+
+ struct SixDOFJointData : public JointData {
+ struct SixDOFAxisData {
+ bool linear_limit_enabled = true;
+ real_t linear_limit_upper = 0.0;
+ real_t linear_limit_lower = 0.0;
+ real_t linear_limit_softness = 0.7;
+ real_t linear_restitution = 0.5;
+ real_t linear_damping = 1.0;
+ bool linear_spring_enabled = false;
+ real_t linear_spring_stiffness = 0.0;
+ real_t linear_spring_damping = 0.0;
+ real_t linear_equilibrium_point = 0.0;
+ bool angular_limit_enabled = true;
+ real_t angular_limit_upper = 0.0;
+ real_t angular_limit_lower = 0.0;
+ real_t angular_limit_softness = 0.5;
+ real_t angular_restitution = 0.0;
+ real_t angular_damping = 1.0;
+ real_t erp = 0.5;
+ bool angular_spring_enabled = false;
+ real_t angular_spring_stiffness = 0.0;
+ real_t angular_spring_damping = 0.0;
+ real_t angular_equilibrium_point = 0.0;
+ };
+
+ virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
+
+ virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
+ virtual bool _get(const StringName &p_name, Variant &r_ret) const;
+ virtual void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ SixDOFAxisData axis_data[3];
+
+ SixDOFJointData() {}
+ };
+
+private:
+#ifdef TOOLS_ENABLED
+ // if false gizmo move body
+ bool gizmo_move_joint = false;
+#endif
+
+ JointData *joint_data = nullptr;
+ Transform3D joint_offset;
+ RID joint;
+
+ Skeleton3D *parent_skeleton = nullptr;
+ Transform3D body_offset;
+ Transform3D body_offset_inverse;
+ bool simulate_physics = false;
+ bool _internal_simulate_physics = false;
+ int bone_id = -1;
+
+ String bone_name;
+ real_t bounce = 0.0;
+ real_t mass = 1.0;
+ real_t friction = 1.0;
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+ real_t gravity_scale = 1.0;
+ bool can_sleep = true;
+
+ bool custom_integrator = false;
+
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _notification(int p_what);
+ GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *)
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState3D *p_state);
+
+ static void _bind_methods();
+
+private:
+ void _sync_body_state(PhysicsDirectBodyState3D *p_state);
+ static Skeleton3D *find_skeleton_parent(Node *p_parent);
+
+ void _update_joint_offset();
+ void _fix_joint_offset();
+ void _reload_joint();
+
+public:
+ void _on_bone_parent_changed();
+
+ void set_linear_velocity(const Vector3 &p_velocity);
+ Vector3 get_linear_velocity() const override;
+
+ void set_angular_velocity(const Vector3 &p_velocity);
+ Vector3 get_angular_velocity() const override;
+
+ void set_use_custom_integrator(bool p_enable);
+ bool is_using_custom_integrator();
+
+#ifdef TOOLS_ENABLED
+ void _set_gizmo_move_joint(bool p_move_joint);
+ virtual Transform3D get_global_gizmo_transform() const override;
+ virtual Transform3D get_local_gizmo_transform() const override;
+#endif
+
+ const JointData *get_joint_data() const;
+ Skeleton3D *find_skeleton_parent();
+
+ int get_bone_id() const {
+ return bone_id;
+ }
+
+ void set_joint_type(JointType p_joint_type);
+ JointType get_joint_type() const;
+
+ void set_joint_offset(const Transform3D &p_offset);
+ const Transform3D &get_joint_offset() const;
+
+ void set_joint_rotation(const Vector3 &p_euler_rad);
+ Vector3 get_joint_rotation() const;
+
+ void set_body_offset(const Transform3D &p_offset);
+ const Transform3D &get_body_offset() const;
+
+ void set_simulate_physics(bool p_simulate);
+ bool get_simulate_physics();
+ bool is_simulating_physics();
+
+ void set_bone_name(const String &p_name);
+ const String &get_bone_name() const;
+
+ void set_mass(real_t p_mass);
+ real_t get_mass() const;
+
+ void set_friction(real_t p_friction);
+ real_t get_friction() const;
+
+ void set_bounce(real_t p_bounce);
+ real_t get_bounce() const;
+
+ void set_gravity_scale(real_t p_gravity_scale);
+ real_t get_gravity_scale() const;
+
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
+ void set_linear_damp(real_t p_linear_damp);
+ real_t get_linear_damp() const;
+
+ void set_angular_damp(real_t p_angular_damp);
+ real_t get_angular_damp() const;
+
+ void set_can_sleep(bool p_active);
+ bool is_able_to_sleep() const;
+
+ void apply_central_impulse(const Vector3 &p_impulse);
+ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
+
+ void reset_physics_simulation_state();
+ void reset_to_rest_position();
+
+ PhysicalBone3D();
+ ~PhysicalBone3D();
+
+private:
+ void update_bone_id();
+ void update_offset();
+
+ void _start_physics_simulation();
+ void _stop_physics_simulation();
+};
+
+VARIANT_ENUM_CAST(PhysicalBone3D::JointType);
+VARIANT_ENUM_CAST(PhysicalBone3D::DampMode);
+
+#endif // PHYSICAL_BONE_3D_H
diff --git a/scene/3d/physics/physics_body_3d.cpp b/scene/3d/physics/physics_body_3d.cpp
new file mode 100644
index 0000000000..711ca60a81
--- /dev/null
+++ b/scene/3d/physics/physics_body_3d.cpp
@@ -0,0 +1,228 @@
+/**************************************************************************/
+/* physics_body_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "physics_body_3d.h"
+
+#include "scene/scene_string_names.h"
+
+void PhysicsBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("get_gravity"), &PhysicsBody3D::get_gravity);
+
+ ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
+ ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
+
+ ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody3D::get_collision_exceptions);
+ ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody3D::add_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody3D::remove_collision_exception_with);
+
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z);
+}
+
+PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
+ CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
+ set_body_mode(p_mode);
+}
+
+PhysicsBody3D::~PhysicsBody3D() {
+ if (motion_cache.is_valid()) {
+ motion_cache->owner = nullptr;
+ }
+}
+
+TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
+ List<RID> exceptions;
+ PhysicsServer3D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
+ Array ret;
+ for (const RID &body : exceptions) {
+ ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body);
+ Object *obj = ObjectDB::get_instance(instance_id);
+ PhysicsBody3D *physics_body = Object::cast_to<PhysicsBody3D>(obj);
+ ret.append(physics_body);
+ }
+ return ret;
+}
+
+void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
+ ERR_FAIL_NULL(p_node);
+ CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
+ ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
+ PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid());
+}
+
+void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
+ ERR_FAIL_NULL(p_node);
+ CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
+ ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
+ PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
+}
+
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
+ parameters.max_collisions = p_max_collisions;
+ parameters.recovery_as_collision = p_recovery_as_collision;
+
+ PhysicsServer3D::MotionResult result;
+
+ if (move_and_collide(parameters, result, p_test_only)) {
+ // Create a new instance when the cached reference is invalid or still in use in script.
+ if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) {
+ motion_cache.instantiate();
+ motion_cache->owner = this;
+ }
+
+ motion_cache->result = result;
+
+ return motion_cache;
+ }
+
+ return Ref<KinematicCollision3D>();
+}
+
+bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
+ bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
+
+ // Restore direction of motion to be along original motion,
+ // in order to avoid sliding due to recovery,
+ // but only if collision depth is low enough to avoid tunneling.
+ if (p_cancel_sliding) {
+ real_t motion_length = p_parameters.motion.length();
+ real_t precision = 0.001;
+
+ if (colliding) {
+ // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
+ // so even in normal resting cases the depth can be a bit more than the margin.
+ precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
+
+ if (r_result.collisions[0].depth > p_parameters.margin + precision) {
+ p_cancel_sliding = false;
+ }
+ }
+
+ if (p_cancel_sliding) {
+ // When motion is null, recovery is the resulting motion.
+ Vector3 motion_normal;
+ if (motion_length > CMP_EPSILON) {
+ motion_normal = p_parameters.motion / motion_length;
+ }
+
+ // Check depth of recovery.
+ real_t projected_length = r_result.travel.dot(motion_normal);
+ Vector3 recovery = r_result.travel - motion_normal * projected_length;
+ real_t recovery_length = recovery.length();
+ // Fixes cases where canceling slide causes the motion to go too deep into the ground,
+ // because we're only taking rest information into account and not general recovery.
+ if (recovery_length < p_parameters.margin + precision) {
+ // Apply adjustment to motion.
+ r_result.travel = motion_normal * projected_length;
+ r_result.remainder = p_parameters.motion - r_result.travel;
+ }
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ r_result.travel[i] = 0;
+ }
+ }
+
+ if (!p_test_only) {
+ Transform3D gt = p_parameters.from;
+ gt.origin += r_result.travel;
+ set_global_transform(gt);
+ }
+
+ return colliding;
+}
+
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+
+ PhysicsServer3D::MotionResult *r = nullptr;
+ PhysicsServer3D::MotionResult temp_result;
+ if (r_collision.is_valid()) {
+ // Needs const_cast because method bindings don't support non-const Ref.
+ r = const_cast<PhysicsServer3D::MotionResult *>(&r_collision->result);
+ } else {
+ r = &temp_result;
+ }
+
+ PhysicsServer3D::MotionParameters parameters(p_from, p_motion, p_margin);
+ parameters.recovery_as_collision = p_recovery_as_collision;
+ parameters.max_collisions = p_max_collisions;
+
+ return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
+}
+
+Vector3 PhysicsBody3D::get_gravity() const {
+ PhysicsDirectBodyState3D *state = PhysicsServer3D::get_singleton()->body_get_direct_state(get_rid());
+ ERR_FAIL_NULL_V(state, Vector3());
+ return state->get_total_gravity();
+}
+
+void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
+ if (p_lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= (~p_axis);
+ }
+ PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
+}
+
+bool PhysicsBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
+ return (locked_axis & p_axis);
+}
+
+Vector3 PhysicsBody3D::get_linear_velocity() const {
+ return Vector3();
+}
+
+Vector3 PhysicsBody3D::get_angular_velocity() const {
+ return Vector3();
+}
+
+real_t PhysicsBody3D::get_inverse_mass() const {
+ return 0;
+}
+
+///////////////////////////////////////
+
+//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
+
+///////////////////////////////////////
+
+///////////////////////////////////////
diff --git a/scene/3d/physics/physics_body_3d.h b/scene/3d/physics/physics_body_3d.h
new file mode 100644
index 0000000000..92b3850085
--- /dev/null
+++ b/scene/3d/physics/physics_body_3d.h
@@ -0,0 +1,72 @@
+/**************************************************************************/
+/* physics_body_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PHYSICS_BODY_3D_H
+#define PHYSICS_BODY_3D_H
+
+#include "core/templates/vset.h"
+#include "scene/3d/physics/collision_object_3d.h"
+#include "scene/3d/physics/kinematic_collision_3d.h"
+#include "scene/resources/physics_material.h"
+#include "servers/physics_server_3d.h"
+
+class PhysicsBody3D : public CollisionObject3D {
+ GDCLASS(PhysicsBody3D, CollisionObject3D);
+
+protected:
+ static void _bind_methods();
+ PhysicsBody3D(PhysicsServer3D::BodyMode p_mode);
+
+ Ref<KinematicCollision3D> motion_cache;
+
+ uint16_t locked_axis = 0;
+
+ Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+
+public:
+ bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ Vector3 get_gravity() const;
+
+ void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
+ bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
+
+ virtual Vector3 get_linear_velocity() const;
+ virtual Vector3 get_angular_velocity() const;
+ virtual real_t get_inverse_mass() const;
+
+ TypedArray<PhysicsBody3D> get_collision_exceptions();
+ void add_collision_exception_with(Node *p_node); //must be physicsbody
+ void remove_collision_exception_with(Node *p_node);
+
+ virtual ~PhysicsBody3D();
+};
+
+#endif // PHYSICS_BODY_3D_H
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/physics/ray_cast_3d.cpp
index b821181d29..0cb722a77e 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/physics/ray_cast_3d.cpp
@@ -30,8 +30,8 @@
#include "ray_cast_3d.h"
-#include "collision_object_3d.h"
-#include "mesh_instance_3d.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/physics/collision_object_3d.h"
void RayCast3D::set_target_position(const Vector3 &p_point) {
target_position = p_point;
@@ -41,7 +41,7 @@ void RayCast3D::set_target_position(const Vector3 &p_point) {
if (is_inside_tree()) {
_update_debug_shape_vertices();
}
- } else if (debug_shape) {
+ } else if (debug_instance.is_valid()) {
_update_debug_shape();
}
}
@@ -186,11 +186,17 @@ void RayCast3D::_notification(int p_what) {
set_physics_process_internal(false);
}
- if (debug_shape) {
+ if (debug_instance.is_valid()) {
_clear_debug_shape();
}
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+ }
+ } break;
+
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (!enabled) {
break;
@@ -200,6 +206,9 @@ void RayCast3D::_notification(int p_what) {
_update_raycast_state();
if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) {
_update_debug_shape_material(true);
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
}
} break;
}
@@ -416,7 +425,7 @@ void RayCast3D::set_debug_shape_thickness(const int p_debug_shape_thickness) {
if (is_inside_tree()) {
_update_debug_shape_vertices();
}
- } else if (debug_shape) {
+ } else if (debug_instance.is_valid()) {
_update_debug_shape();
}
}
@@ -448,13 +457,13 @@ const Color &RayCast3D::get_debug_shape_custom_color() const {
void RayCast3D::_create_debug_shape() {
_update_debug_shape_material();
- Ref<ArrayMesh> mesh = memnew(ArrayMesh);
-
- MeshInstance3D *mi = memnew(MeshInstance3D);
- mi->set_mesh(mesh);
+ if (!debug_instance.is_valid()) {
+ debug_instance = RenderingServer::get_singleton()->instance_create();
+ }
- add_child(mi);
- debug_shape = mi;
+ if (debug_mesh.is_null()) {
+ debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ }
}
void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
@@ -494,19 +503,17 @@ void RayCast3D::_update_debug_shape() {
return;
}
- if (!debug_shape) {
+ if (!debug_instance.is_valid()) {
_create_debug_shape();
}
- MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- Ref<ArrayMesh> mesh = mi->get_mesh();
- if (!mesh.is_valid()) {
+ if (!debug_instance.is_valid() || debug_mesh.is_null()) {
return;
}
_update_debug_shape_vertices();
- mesh->clear_surfaces();
+ debug_mesh->clear_surfaces();
Array a;
a.resize(Mesh::ARRAY_MAX);
@@ -516,32 +523,36 @@ void RayCast3D::_update_debug_shape() {
if (!debug_line_vertices.is_empty()) {
a[Mesh::ARRAY_VERTEX] = debug_line_vertices;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
- mesh->surface_set_material(surface_count, debug_material);
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ debug_mesh->surface_set_material(surface_count, debug_material);
++surface_count;
}
if (!debug_shape_vertices.is_empty()) {
a[Mesh::ARRAY_VERTEX] = debug_shape_vertices;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_STRIP, a, Array(), Dictionary(), flags);
- mesh->surface_set_material(surface_count, debug_material);
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_STRIP, a, Array(), Dictionary(), flags);
+ debug_mesh->surface_set_material(surface_count, debug_material);
++surface_count;
}
+
+ RenderingServer::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
+ RenderingServer::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+ RenderingServer::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
}
void RayCast3D::_clear_debug_shape() {
- if (!debug_shape) {
- return;
+ ERR_FAIL_NULL(RenderingServer::get_singleton());
+ if (debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_instance);
+ debug_instance = RID();
}
-
- MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- if (mi->is_inside_tree()) {
- mi->queue_free();
- } else {
- memdelete(mi);
+ if (debug_mesh.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_mesh->get_rid());
+ debug_mesh = Ref<ArrayMesh>();
}
-
- debug_shape = nullptr;
}
RayCast3D::RayCast3D() {
diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/physics/ray_cast_3d.h
index 7b7f698114..40f2223602 100644
--- a/scene/3d/ray_cast_3d.h
+++ b/scene/3d/physics/ray_cast_3d.h
@@ -53,7 +53,6 @@ class RayCast3D : public Node3D {
uint32_t collision_mask = 1;
bool exclude_parent_body = true;
- Node *debug_shape = nullptr;
Ref<Material> debug_material;
Color debug_shape_custom_color = Color(0.0, 0.0, 0.0);
int debug_shape_thickness = 2;
@@ -72,6 +71,9 @@ class RayCast3D : public Node3D {
bool hit_from_inside = false;
bool hit_back_faces = true;
+ RID debug_instance;
+ Ref<ArrayMesh> debug_mesh;
+
protected:
void _notification(int p_what);
void _update_raycast_state();
diff --git a/scene/3d/physics/rigid_body_3d.cpp b/scene/3d/physics/rigid_body_3d.cpp
new file mode 100644
index 0000000000..54bd1c0d25
--- /dev/null
+++ b/scene/3d/physics/rigid_body_3d.cpp
@@ -0,0 +1,825 @@
+/**************************************************************************/
+/* rigid_body_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "rigid_body_3d.h"
+
+#include "scene/scene_string_names.h"
+
+void RigidBody3D::_body_enter_tree(ObjectID p_id) {
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_FAIL_NULL(node);
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(E->value.in_tree);
+
+ E->value.in_tree = true;
+
+ contact_monitor->locked = true;
+
+ emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+
+ for (int i = 0; i < E->value.shapes.size(); i++) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+}
+
+void RigidBody3D::_body_exit_tree(ObjectID p_id) {
+ Object *obj = ObjectDB::get_instance(p_id);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_FAIL_NULL(node);
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
+ ERR_FAIL_COND(!E);
+ ERR_FAIL_COND(!E->value.in_tree);
+ E->value.in_tree = false;
+
+ contact_monitor->locked = true;
+
+ emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+
+ for (int i = 0; i < E->value.shapes.size(); i++) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+}
+
+void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
+ bool body_in = p_status == 1;
+ ObjectID objid = p_instance;
+
+ Object *obj = ObjectDB::get_instance(objid);
+ Node *node = Object::cast_to<Node>(obj);
+
+ ERR_FAIL_NULL(contact_monitor);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
+
+ ERR_FAIL_COND(!body_in && !E);
+
+ if (body_in) {
+ if (!E) {
+ E = contact_monitor->body_map.insert(objid, BodyState());
+ E->value.rid = p_body;
+ //E->value.rc=0;
+ E->value.in_tree = node && node->is_inside_tree();
+ if (node) {
+ node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid));
+ if (E->value.in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ }
+ }
+ }
+ //E->value.rc++;
+ if (node) {
+ E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
+ }
+
+ if (E->value.in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
+ }
+
+ } else {
+ //E->value.rc--;
+
+ if (node) {
+ E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
+ }
+
+ bool in_tree = E->value.in_tree;
+
+ if (E->value.shapes.is_empty()) {
+ if (node) {
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
+ if (in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ }
+ }
+
+ contact_monitor->body_map.remove(E);
+ }
+ if (node && in_tree) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape);
+ }
+ }
+}
+
+struct _RigidBodyInOut {
+ RID rid;
+ ObjectID id;
+ int shape = 0;
+ int local_shape = 0;
+};
+
+void RigidBody3D::_sync_body_state(PhysicsDirectBodyState3D *p_state) {
+ set_ignore_transform_notification(true);
+ set_global_transform(p_state->get_transform());
+ set_ignore_transform_notification(false);
+
+ linear_velocity = p_state->get_linear_velocity();
+ angular_velocity = p_state->get_angular_velocity();
+
+ inverse_inertia_tensor = p_state->get_inverse_inertia_tensor();
+
+ contact_count = p_state->get_contact_count();
+
+ if (sleeping != p_state->is_sleeping()) {
+ sleeping = p_state->is_sleeping();
+ emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
+ }
+}
+
+void RigidBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
+ lock_callback();
+
+ if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
+ _sync_body_state(p_state);
+
+ Transform3D old_transform = get_global_transform();
+ GDVIRTUAL_CALL(_integrate_forces, p_state);
+ Transform3D new_transform = get_global_transform();
+
+ if (new_transform != old_transform) {
+ // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
+ }
+ }
+
+ _sync_body_state(p_state);
+ _on_transform_changed();
+
+ if (contact_monitor) {
+ contact_monitor->locked = true;
+
+ //untag all
+ int rc = 0;
+ for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ for (int i = 0; i < E.value.shapes.size(); i++) {
+ E.value.shapes[i].tagged = false;
+ rc++;
+ }
+ }
+
+ _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBodyInOut));
+ int toadd_count = 0;
+ RigidBody3D_RemoveAction *toremove = (RigidBody3D_RemoveAction *)alloca(rc * sizeof(RigidBody3D_RemoveAction));
+ int toremove_count = 0;
+
+ //put the ones to add
+
+ for (int i = 0; i < p_state->get_contact_count(); i++) {
+ RID col_rid = p_state->get_contact_collider(i);
+ ObjectID col_obj = p_state->get_contact_collider_id(i);
+ int local_shape = p_state->get_contact_local_shape(i);
+ int col_shape = p_state->get_contact_collider_shape(i);
+
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
+ if (!E) {
+ toadd[toadd_count].rid = col_rid;
+ toadd[toadd_count].local_shape = local_shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
+ toadd_count++;
+ continue;
+ }
+
+ ShapePair sp(col_shape, local_shape);
+ int idx = E->value.shapes.find(sp);
+ if (idx == -1) {
+ toadd[toadd_count].rid = col_rid;
+ toadd[toadd_count].local_shape = local_shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
+ toadd_count++;
+ continue;
+ }
+
+ E->value.shapes[idx].tagged = true;
+ }
+
+ //put the ones to remove
+
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ for (int i = 0; i < E.value.shapes.size(); i++) {
+ if (!E.value.shapes[i].tagged) {
+ toremove[toremove_count].rid = E.value.rid;
+ toremove[toremove_count].body_id = E.key;
+ toremove[toremove_count].pair = E.value.shapes[i];
+ toremove_count++;
+ }
+ }
+ }
+
+ //process removals
+
+ for (int i = 0; i < toremove_count; i++) {
+ _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
+ }
+
+ //process additions
+
+ for (int i = 0; i < toadd_count; i++) {
+ _body_inout(1, toremove[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
+ }
+
+ contact_monitor->locked = false;
+ }
+
+ unlock_callback();
+}
+
+void RigidBody3D::_notification(int p_what) {
+#ifdef TOOLS_ENABLED
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ set_notify_local_transform(true); // Used for warnings and only in editor.
+ }
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ update_configuration_warnings();
+ } break;
+ }
+#endif
+}
+
+void RigidBody3D::_apply_body_mode() {
+ if (freeze) {
+ switch (freeze_mode) {
+ case FREEZE_MODE_STATIC: {
+ set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
+ } break;
+ case FREEZE_MODE_KINEMATIC: {
+ set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
+ } break;
+ }
+ } else if (lock_rotation) {
+ set_body_mode(PhysicsServer3D::BODY_MODE_RIGID_LINEAR);
+ } else {
+ set_body_mode(PhysicsServer3D::BODY_MODE_RIGID);
+ }
+}
+
+void RigidBody3D::set_lock_rotation_enabled(bool p_lock_rotation) {
+ if (p_lock_rotation == lock_rotation) {
+ return;
+ }
+
+ lock_rotation = p_lock_rotation;
+ _apply_body_mode();
+}
+
+bool RigidBody3D::is_lock_rotation_enabled() const {
+ return lock_rotation;
+}
+
+void RigidBody3D::set_freeze_enabled(bool p_freeze) {
+ if (p_freeze == freeze) {
+ return;
+ }
+
+ freeze = p_freeze;
+ _apply_body_mode();
+}
+
+bool RigidBody3D::is_freeze_enabled() const {
+ return freeze;
+}
+
+void RigidBody3D::set_freeze_mode(FreezeMode p_freeze_mode) {
+ if (p_freeze_mode == freeze_mode) {
+ return;
+ }
+
+ freeze_mode = p_freeze_mode;
+ _apply_body_mode();
+}
+
+RigidBody3D::FreezeMode RigidBody3D::get_freeze_mode() const {
+ return freeze_mode;
+}
+
+void RigidBody3D::set_mass(real_t p_mass) {
+ ERR_FAIL_COND(p_mass <= 0);
+ mass = p_mass;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
+}
+
+real_t RigidBody3D::get_mass() const {
+ return mass;
+}
+
+void RigidBody3D::set_inertia(const Vector3 &p_inertia) {
+ ERR_FAIL_COND(p_inertia.x < 0);
+ ERR_FAIL_COND(p_inertia.y < 0);
+ ERR_FAIL_COND(p_inertia.z < 0);
+
+ inertia = p_inertia;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
+}
+
+const Vector3 &RigidBody3D::get_inertia() const {
+ return inertia;
+}
+
+void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
+ if (center_of_mass_mode == p_mode) {
+ return;
+ }
+
+ center_of_mass_mode = p_mode;
+
+ switch (center_of_mass_mode) {
+ case CENTER_OF_MASS_MODE_AUTO: {
+ center_of_mass = Vector3();
+ PhysicsServer3D::get_singleton()->body_reset_mass_properties(get_rid());
+ if (inertia != Vector3()) {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
+ }
+ } break;
+
+ case CENTER_OF_MASS_MODE_CUSTOM: {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+ } break;
+ }
+}
+
+RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const {
+ return center_of_mass_mode;
+}
+
+void RigidBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) {
+ if (center_of_mass == p_center_of_mass) {
+ return;
+ }
+
+ ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
+ center_of_mass = p_center_of_mass;
+
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+}
+
+const Vector3 &RigidBody3D::get_center_of_mass() const {
+ return center_of_mass;
+}
+
+void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
+ if (physics_material_override.is_valid()) {
+ physics_material_override->disconnect_changed(callable_mp(this, &RigidBody3D::_reload_physics_characteristics));
+ }
+
+ physics_material_override = p_physics_material_override;
+
+ if (physics_material_override.is_valid()) {
+ physics_material_override->connect_changed(callable_mp(this, &RigidBody3D::_reload_physics_characteristics));
+ }
+ _reload_physics_characteristics();
+}
+
+Ref<PhysicsMaterial> RigidBody3D::get_physics_material_override() const {
+ return physics_material_override;
+}
+
+void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) {
+ gravity_scale = p_gravity_scale;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
+}
+
+real_t RigidBody3D::get_gravity_scale() const {
+ return gravity_scale;
+}
+
+void RigidBody3D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+RigidBody3D::DampMode RigidBody3D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void RigidBody3D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+RigidBody3D::DampMode RigidBody3D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
+void RigidBody3D::set_linear_damp(real_t p_linear_damp) {
+ ERR_FAIL_COND(p_linear_damp < 0.0);
+ linear_damp = p_linear_damp;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
+}
+
+real_t RigidBody3D::get_linear_damp() const {
+ return linear_damp;
+}
+
+void RigidBody3D::set_angular_damp(real_t p_angular_damp) {
+ ERR_FAIL_COND(p_angular_damp < 0.0);
+ angular_damp = p_angular_damp;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
+}
+
+real_t RigidBody3D::get_angular_damp() const {
+ return angular_damp;
+}
+
+void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) {
+ Vector3 axis = p_axis.normalized();
+ linear_velocity -= axis * axis.dot(linear_velocity);
+ linear_velocity += p_axis;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+}
+
+void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) {
+ linear_velocity = p_velocity;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
+}
+
+Vector3 RigidBody3D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) {
+ angular_velocity = p_velocity;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
+}
+
+Vector3 RigidBody3D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+Basis RigidBody3D::get_inverse_inertia_tensor() const {
+ return inverse_inertia_tensor;
+}
+
+void RigidBody3D::set_use_custom_integrator(bool p_enable) {
+ if (custom_integrator == p_enable) {
+ return;
+ }
+
+ custom_integrator = p_enable;
+ PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
+}
+
+bool RigidBody3D::is_using_custom_integrator() {
+ return custom_integrator;
+}
+
+void RigidBody3D::set_sleeping(bool p_sleeping) {
+ sleeping = p_sleeping;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping);
+}
+
+void RigidBody3D::set_can_sleep(bool p_active) {
+ can_sleep = p_active;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active);
+}
+
+bool RigidBody3D::is_able_to_sleep() const {
+ return can_sleep;
+}
+
+bool RigidBody3D::is_sleeping() const {
+ return sleeping;
+}
+
+void RigidBody3D::set_max_contacts_reported(int p_amount) {
+ max_contacts_reported = p_amount;
+ PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
+}
+
+int RigidBody3D::get_max_contacts_reported() const {
+ return max_contacts_reported;
+}
+
+int RigidBody3D::get_contact_count() const {
+ return contact_count;
+}
+
+void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) {
+ PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
+}
+
+void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+ singleton->body_apply_impulse(get_rid(), p_impulse, p_position);
+}
+
+void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
+ PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse);
+}
+
+void RigidBody3D::apply_central_force(const Vector3 &p_force) {
+ PhysicsServer3D::get_singleton()->body_apply_central_force(get_rid(), p_force);
+}
+
+void RigidBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) {
+ PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+ singleton->body_apply_force(get_rid(), p_force, p_position);
+}
+
+void RigidBody3D::apply_torque(const Vector3 &p_torque) {
+ PhysicsServer3D::get_singleton()->body_apply_torque(get_rid(), p_torque);
+}
+
+void RigidBody3D::add_constant_central_force(const Vector3 &p_force) {
+ PhysicsServer3D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
+}
+
+void RigidBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) {
+ PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+ singleton->body_add_constant_force(get_rid(), p_force, p_position);
+}
+
+void RigidBody3D::add_constant_torque(const Vector3 &p_torque) {
+ PhysicsServer3D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
+}
+
+void RigidBody3D::set_constant_force(const Vector3 &p_force) {
+ PhysicsServer3D::get_singleton()->body_set_constant_force(get_rid(), p_force);
+}
+
+Vector3 RigidBody3D::get_constant_force() const {
+ return PhysicsServer3D::get_singleton()->body_get_constant_force(get_rid());
+}
+
+void RigidBody3D::set_constant_torque(const Vector3 &p_torque) {
+ PhysicsServer3D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
+}
+
+Vector3 RigidBody3D::get_constant_torque() const {
+ return PhysicsServer3D::get_singleton()->body_get_constant_torque(get_rid());
+}
+
+void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) {
+ ccd = p_enable;
+ PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable);
+}
+
+bool RigidBody3D::is_using_continuous_collision_detection() const {
+ return ccd;
+}
+
+void RigidBody3D::set_contact_monitor(bool p_enabled) {
+ if (p_enabled == is_contact_monitor_enabled()) {
+ return;
+ }
+
+ if (!p_enabled) {
+ ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
+
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ //clean up mess
+ Object *obj = ObjectDB::get_instance(E.key);
+ Node *node = Object::cast_to<Node>(obj);
+
+ if (node) {
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
+ node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
+ }
+ }
+
+ memdelete(contact_monitor);
+ contact_monitor = nullptr;
+ } else {
+ contact_monitor = memnew(ContactMonitor);
+ contact_monitor->locked = false;
+ }
+}
+
+bool RigidBody3D::is_contact_monitor_enabled() const {
+ return contact_monitor != nullptr;
+}
+
+TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const {
+ ERR_FAIL_NULL_V(contact_monitor, TypedArray<Node3D>());
+
+ TypedArray<Node3D> ret;
+ ret.resize(contact_monitor->body_map.size());
+ int idx = 0;
+ for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
+ Object *obj = ObjectDB::get_instance(E.key);
+ if (!obj) {
+ ret.resize(ret.size() - 1); //ops
+ } else {
+ ret[idx++] = obj;
+ }
+ }
+
+ return ret;
+}
+
+void RigidBody3D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
+ }
+}
+
+PackedStringArray RigidBody3D::get_configuration_warnings() const {
+ PackedStringArray warnings = CollisionObject3D::get_configuration_warnings();
+
+ Vector3 scale = get_transform().get_basis().get_scale();
+ if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) {
+ warnings.push_back(RTR("Scale changes to RigidBody3D will be overridden by the physics engine when running.\nPlease change the size in children collision shapes instead."));
+ }
+
+ return warnings;
+}
+
+void RigidBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass);
+
+ ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody3D::set_inertia);
+ ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody3D::get_inertia);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody3D::set_center_of_mass_mode);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody3D::get_center_of_mass_mode);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody3D::set_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody3D::get_center_of_mass);
+
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody3D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody3D::get_linear_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody3D::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody3D::get_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidBody3D::get_inverse_inertia_tensor);
+
+ ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody3D::set_gravity_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody3D::get_gravity_scale);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody3D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody3D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody3D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody3D::get_angular_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody3D::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody3D::get_linear_damp);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody3D::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody3D::get_angular_damp);
+
+ ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody3D::set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody3D::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody3D::get_contact_count);
+
+ ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody3D::set_use_custom_integrator);
+ ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody3D::is_using_custom_integrator);
+
+ ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody3D::set_contact_monitor);
+ ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody3D::is_contact_monitor_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidBody3D::set_use_continuous_collision_detection);
+ ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody3D::is_using_continuous_collision_detection);
+
+ ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity);
+
+ ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse);
+ ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3());
+ ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse);
+
+ ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody3D::apply_central_force);
+ ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody3D::apply_force, Vector3());
+ ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody3D::apply_torque);
+
+ ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody3D::add_constant_central_force);
+ ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody3D::add_constant_force, Vector3());
+ ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody3D::add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody3D::set_constant_force);
+ ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody3D::get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody3D::set_constant_torque);
+ ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody3D::get_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping);
+ ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody3D::is_sleeping);
+
+ ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep);
+ ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep);
+
+ ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody3D::set_lock_rotation_enabled);
+ ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody3D::is_lock_rotation_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody3D::set_freeze_enabled);
+ ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody3D::is_freeze_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody3D::set_freeze_mode);
+ ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody3D::get_freeze_mode);
+
+ ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies);
+
+ GDVIRTUAL_BIND(_integrate_forces, "state");
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
+ ADD_GROUP("Mass Distribution", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:m"), "set_center_of_mass", "get_center_of_mass");
+ ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5m\u00B2"), "set_inertia", "get_inertia");
+ ADD_GROUP("Deactivation", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
+ ADD_GROUP("Solver", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
+ ADD_GROUP("Linear", "linear_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_GROUP("Angular", "angular_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_GROUP("Constant Forces", "constant_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m/s\u00B2 (N)"), "set_constant_force", "get_constant_force");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
+
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
+
+ BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
+ BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
+
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+}
+
+void RigidBody3D::_validate_property(PropertyInfo &p_property) const {
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
+ if (p_property.name == "center_of_mass") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+}
+
+RigidBody3D::RigidBody3D() :
+ PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody3D::_body_state_changed));
+}
+
+RigidBody3D::~RigidBody3D() {
+ if (contact_monitor) {
+ memdelete(contact_monitor);
+ }
+}
diff --git a/scene/3d/physics/rigid_body_3d.h b/scene/3d/physics/rigid_body_3d.h
new file mode 100644
index 0000000000..ec051e5e0f
--- /dev/null
+++ b/scene/3d/physics/rigid_body_3d.h
@@ -0,0 +1,248 @@
+/**************************************************************************/
+/* rigid_body_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef RIGID_BODY_3D_H
+#define RIGID_BODY_3D_H
+
+#include "scene/3d/physics/static_body_3d.h"
+
+class RigidBody3D : public PhysicsBody3D {
+ GDCLASS(RigidBody3D, PhysicsBody3D);
+
+public:
+ enum FreezeMode {
+ FREEZE_MODE_STATIC,
+ FREEZE_MODE_KINEMATIC,
+ };
+
+ enum CenterOfMassMode {
+ CENTER_OF_MASS_MODE_AUTO,
+ CENTER_OF_MASS_MODE_CUSTOM,
+ };
+
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
+private:
+ bool can_sleep = true;
+ bool lock_rotation = false;
+ bool freeze = false;
+ FreezeMode freeze_mode = FREEZE_MODE_STATIC;
+
+ real_t mass = 1.0;
+ Vector3 inertia;
+ CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
+ Vector3 center_of_mass;
+
+ Ref<PhysicsMaterial> physics_material_override;
+
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+ Basis inverse_inertia_tensor;
+ real_t gravity_scale = 1.0;
+
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
+ bool sleeping = false;
+ bool ccd = false;
+
+ int max_contacts_reported = 0;
+ int contact_count = 0;
+
+ bool custom_integrator = false;
+
+ struct ShapePair {
+ int body_shape = 0;
+ int local_shape = 0;
+ bool tagged = false;
+ bool operator<(const ShapePair &p_sp) const {
+ if (body_shape == p_sp.body_shape) {
+ return local_shape < p_sp.local_shape;
+ } else {
+ return body_shape < p_sp.body_shape;
+ }
+ }
+
+ ShapePair() {}
+ ShapePair(int p_bs, int p_ls) {
+ body_shape = p_bs;
+ local_shape = p_ls;
+ tagged = false;
+ }
+ };
+ struct RigidBody3D_RemoveAction {
+ RID rid;
+ ObjectID body_id;
+ ShapePair pair;
+ };
+ struct BodyState {
+ RID rid;
+ //int rc;
+ bool in_tree = false;
+ VSet<ShapePair> shapes;
+ };
+
+ struct ContactMonitor {
+ bool locked = false;
+ HashMap<ObjectID, BodyState> body_map;
+ };
+
+ ContactMonitor *contact_monitor = nullptr;
+ void _body_enter_tree(ObjectID p_id);
+ void _body_exit_tree(ObjectID p_id);
+
+ void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
+
+ void _sync_body_state(PhysicsDirectBodyState3D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+ void _validate_property(PropertyInfo &p_property) const;
+
+ GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *)
+
+ virtual void _body_state_changed(PhysicsDirectBodyState3D *p_state);
+
+ void _apply_body_mode();
+
+public:
+ void set_lock_rotation_enabled(bool p_lock_rotation);
+ bool is_lock_rotation_enabled() const;
+
+ void set_freeze_enabled(bool p_freeze);
+ bool is_freeze_enabled() const;
+
+ void set_freeze_mode(FreezeMode p_freeze_mode);
+ FreezeMode get_freeze_mode() const;
+
+ void set_mass(real_t p_mass);
+ real_t get_mass() const;
+
+ virtual real_t get_inverse_mass() const override { return 1.0 / mass; }
+
+ void set_inertia(const Vector3 &p_inertia);
+ const Vector3 &get_inertia() const;
+
+ void set_center_of_mass_mode(CenterOfMassMode p_mode);
+ CenterOfMassMode get_center_of_mass_mode() const;
+
+ void set_center_of_mass(const Vector3 &p_center_of_mass);
+ const Vector3 &get_center_of_mass() const;
+
+ void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
+ Ref<PhysicsMaterial> get_physics_material_override() const;
+
+ void set_linear_velocity(const Vector3 &p_velocity);
+ Vector3 get_linear_velocity() const override;
+
+ void set_axis_velocity(const Vector3 &p_axis);
+
+ void set_angular_velocity(const Vector3 &p_velocity);
+ Vector3 get_angular_velocity() const override;
+
+ Basis get_inverse_inertia_tensor() const;
+
+ void set_gravity_scale(real_t p_gravity_scale);
+ real_t get_gravity_scale() const;
+
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
+ void set_linear_damp(real_t p_linear_damp);
+ real_t get_linear_damp() const;
+
+ void set_angular_damp(real_t p_angular_damp);
+ real_t get_angular_damp() const;
+
+ void set_use_custom_integrator(bool p_enable);
+ bool is_using_custom_integrator();
+
+ void set_sleeping(bool p_sleeping);
+ bool is_sleeping() const;
+
+ void set_can_sleep(bool p_active);
+ bool is_able_to_sleep() const;
+
+ void set_contact_monitor(bool p_enabled);
+ bool is_contact_monitor_enabled() const;
+
+ void set_max_contacts_reported(int p_amount);
+ int get_max_contacts_reported() const;
+ int get_contact_count() const;
+
+ void set_use_continuous_collision_detection(bool p_enable);
+ bool is_using_continuous_collision_detection() const;
+
+ TypedArray<Node3D> get_colliding_bodies() const;
+
+ void apply_central_impulse(const Vector3 &p_impulse);
+ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
+ void apply_torque_impulse(const Vector3 &p_impulse);
+
+ void apply_central_force(const Vector3 &p_force);
+ void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
+ void apply_torque(const Vector3 &p_torque);
+
+ void add_constant_central_force(const Vector3 &p_force);
+ void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
+ void add_constant_torque(const Vector3 &p_torque);
+
+ void set_constant_force(const Vector3 &p_force);
+ Vector3 get_constant_force() const;
+
+ void set_constant_torque(const Vector3 &p_torque);
+ Vector3 get_constant_torque() const;
+
+ virtual PackedStringArray get_configuration_warnings() const override;
+
+ RigidBody3D();
+ ~RigidBody3D();
+
+private:
+ void _reload_physics_characteristics();
+};
+
+VARIANT_ENUM_CAST(RigidBody3D::FreezeMode);
+VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode);
+VARIANT_ENUM_CAST(RigidBody3D::DampMode);
+
+#endif // RIGID_BODY_3D_H
diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/physics/shape_cast_3d.cpp
index 2da5f52928..ada238c7f2 100644
--- a/scene/3d/shape_cast_3d.cpp
+++ b/scene/3d/physics/shape_cast_3d.cpp
@@ -30,8 +30,8 @@
#include "shape_cast_3d.h"
-#include "scene/3d/collision_object_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/physics/collision_object_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
void ShapeCast3D::_notification(int p_what) {
@@ -64,11 +64,17 @@ void ShapeCast3D::_notification(int p_what) {
set_physics_process_internal(false);
}
- if (debug_shape) {
+ if (debug_instance.is_valid()) {
_clear_debug_shape();
}
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+ }
+ } break;
+
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (!enabled) {
break;
@@ -86,6 +92,9 @@ void ShapeCast3D::_notification(int p_what) {
if (prev_collision_state == collided && !collided) {
_update_debug_shape();
}
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
}
} break;
}
@@ -217,7 +226,7 @@ void ShapeCast3D::set_target_position(const Vector3 &p_point) {
if (is_inside_tree()) {
_update_debug_shape_vertices();
}
- } else if (debug_shape) {
+ } else if (debug_instance.is_valid()) {
_update_debug_shape();
}
}
@@ -532,13 +541,13 @@ const Color &ShapeCast3D::get_debug_shape_custom_color() const {
void ShapeCast3D::_create_debug_shape() {
_update_debug_shape_material();
- Ref<ArrayMesh> mesh = memnew(ArrayMesh);
-
- MeshInstance3D *mi = memnew(MeshInstance3D);
- mi->set_mesh(mesh);
+ if (!debug_instance.is_valid()) {
+ debug_instance = RenderingServer::get_singleton()->instance_create();
+ }
- add_child(mi);
- debug_shape = mi;
+ if (debug_mesh.is_null()) {
+ debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ }
}
void ShapeCast3D::_update_debug_shape_material(bool p_check_collision) {
@@ -578,7 +587,7 @@ void ShapeCast3D::_update_debug_shape() {
return;
}
- if (!debug_shape) {
+ if (!debug_instance.is_valid()) {
_create_debug_shape();
}
@@ -588,13 +597,11 @@ void ShapeCast3D::_update_debug_shape() {
return;
}
- MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- Ref<ArrayMesh> mesh = mi->get_mesh();
- if (!mesh.is_valid()) {
+ if (!debug_instance.is_valid() || debug_mesh.is_null()) {
return;
}
- mesh->clear_surfaces();
+ debug_mesh->clear_surfaces();
Array a;
a.resize(Mesh::ARRAY_MAX);
@@ -604,30 +611,34 @@ void ShapeCast3D::_update_debug_shape() {
if (!debug_shape_vertices.is_empty()) {
a[Mesh::ARRAY_VERTEX] = debug_shape_vertices;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
- mesh->surface_set_material(surface_count, debug_material);
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ debug_mesh->surface_set_material(surface_count, debug_material);
++surface_count;
}
if (!debug_line_vertices.is_empty()) {
a[Mesh::ARRAY_VERTEX] = debug_line_vertices;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
- mesh->surface_set_material(surface_count, debug_material);
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ debug_mesh->surface_set_material(surface_count, debug_material);
++surface_count;
}
+
+ RenderingServer::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
+ RenderingServer::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+ RenderingServer::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
}
void ShapeCast3D::_clear_debug_shape() {
- if (!debug_shape) {
- return;
+ ERR_FAIL_NULL(RenderingServer::get_singleton());
+ if (debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_instance);
+ debug_instance = RID();
}
-
- MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- if (mi->is_inside_tree()) {
- mi->queue_free();
- } else {
- memdelete(mi);
+ if (debug_mesh.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_mesh->get_rid());
+ debug_mesh = Ref<ArrayMesh>();
}
-
- debug_shape = nullptr;
}
diff --git a/scene/3d/shape_cast_3d.h b/scene/3d/physics/shape_cast_3d.h
index 9052db9046..19b73e3f72 100644
--- a/scene/3d/shape_cast_3d.h
+++ b/scene/3d/physics/shape_cast_3d.h
@@ -55,7 +55,6 @@ class ShapeCast3D : public Node3D {
bool collide_with_areas = false;
bool collide_with_bodies = true;
- Node *debug_shape = nullptr;
Ref<Material> debug_material;
Color debug_shape_custom_color = Color(0.0, 0.0, 0.0);
Vector<Vector3> debug_shape_vertices;
@@ -76,6 +75,9 @@ class ShapeCast3D : public Node3D {
Array _get_collision_result() const;
+ RID debug_instance;
+ Ref<ArrayMesh> debug_mesh;
+
protected:
void _notification(int p_what);
void _update_shapecast_state();
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/physics/spring_arm_3d.cpp
index 8d2f10310c..8d2f10310c 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/physics/spring_arm_3d.cpp
diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/physics/spring_arm_3d.h
index c7e1da35f0..c7e1da35f0 100644
--- a/scene/3d/spring_arm_3d.h
+++ b/scene/3d/physics/spring_arm_3d.h
diff --git a/scene/3d/physics/static_body_3d.cpp b/scene/3d/physics/static_body_3d.cpp
new file mode 100644
index 0000000000..30e796f92e
--- /dev/null
+++ b/scene/3d/physics/static_body_3d.cpp
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/* static_body_3d.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "static_body_3d.h"
+
+void StaticBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
+ if (physics_material_override.is_valid()) {
+ physics_material_override->disconnect_changed(callable_mp(this, &StaticBody3D::_reload_physics_characteristics));
+ }
+
+ physics_material_override = p_physics_material_override;
+
+ if (physics_material_override.is_valid()) {
+ physics_material_override->connect_changed(callable_mp(this, &StaticBody3D::_reload_physics_characteristics));
+ }
+ _reload_physics_characteristics();
+}
+
+Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
+ return physics_material_override;
+}
+
+void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
+ constant_linear_velocity = p_vel;
+
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+}
+
+void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
+ constant_angular_velocity = p_vel;
+
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+}
+
+Vector3 StaticBody3D::get_constant_linear_velocity() const {
+ return constant_linear_velocity;
+}
+
+Vector3 StaticBody3D::get_constant_angular_velocity() const {
+ return constant_angular_velocity;
+}
+
+void StaticBody3D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
+ }
+}
+
+void StaticBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+}
+
+StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) :
+ PhysicsBody3D(p_mode) {
+}
diff --git a/scene/3d/physics/static_body_3d.h b/scene/3d/physics/static_body_3d.h
new file mode 100644
index 0000000000..7d7f7a4acc
--- /dev/null
+++ b/scene/3d/physics/static_body_3d.h
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* static_body_3d.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef STATIC_BODY_3D_H
+#define STATIC_BODY_3D_H
+
+#include "scene/3d/physics/physics_body_3d.h"
+
+class StaticBody3D : public PhysicsBody3D {
+ GDCLASS(StaticBody3D, PhysicsBody3D);
+
+private:
+ Vector3 constant_linear_velocity;
+ Vector3 constant_angular_velocity;
+
+ Ref<PhysicsMaterial> physics_material_override;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
+ Ref<PhysicsMaterial> get_physics_material_override() const;
+
+ void set_constant_linear_velocity(const Vector3 &p_vel);
+ void set_constant_angular_velocity(const Vector3 &p_vel);
+
+ Vector3 get_constant_linear_velocity() const;
+ Vector3 get_constant_angular_velocity() const;
+
+ StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC);
+
+private:
+ void _reload_physics_characteristics();
+};
+
+#endif // STATIC_BODY_3D_H
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/physics/vehicle_body_3d.cpp
index c23032d3b9..c23032d3b9 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/physics/vehicle_body_3d.cpp
diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/physics/vehicle_body_3d.h
index ce913f152d..def9984440 100644
--- a/scene/3d/vehicle_body_3d.h
+++ b/scene/3d/physics/vehicle_body_3d.h
@@ -31,7 +31,8 @@
#ifndef VEHICLE_BODY_3D_H
#define VEHICLE_BODY_3D_H
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/rigid_body_3d.h"
class VehicleBody3D;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
deleted file mode 100644
index 67a7f76d7d..0000000000
--- a/scene/3d/physics_body_3d.cpp
+++ /dev/null
@@ -1,3503 +0,0 @@
-/**************************************************************************/
-/* physics_body_3d.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "physics_body_3d.h"
-
-#include "scene/scene_string_names.h"
-
-void PhysicsBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("get_gravity"), &PhysicsBody3D::get_gravity);
-
- ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
- ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
-
- ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody3D::get_collision_exceptions);
- ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody3D::add_collision_exception_with);
- ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody3D::remove_collision_exception_with);
-
- ADD_GROUP("Axis Lock", "axis_lock_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z);
-}
-
-PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
- CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
- set_body_mode(p_mode);
-}
-
-PhysicsBody3D::~PhysicsBody3D() {
- if (motion_cache.is_valid()) {
- motion_cache->owner = nullptr;
- }
-}
-
-TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
- List<RID> exceptions;
- PhysicsServer3D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
- Array ret;
- for (const RID &body : exceptions) {
- ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body);
- Object *obj = ObjectDB::get_instance(instance_id);
- PhysicsBody3D *physics_body = Object::cast_to<PhysicsBody3D>(obj);
- ret.append(physics_body);
- }
- return ret;
-}
-
-void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
- ERR_FAIL_NULL(p_node);
- CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
- PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid());
-}
-
-void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
- ERR_FAIL_NULL(p_node);
- CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_NULL_MSG(collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
- PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
-}
-
-Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
- parameters.max_collisions = p_max_collisions;
- parameters.recovery_as_collision = p_recovery_as_collision;
-
- PhysicsServer3D::MotionResult result;
-
- if (move_and_collide(parameters, result, p_test_only)) {
- // Create a new instance when the cached reference is invalid or still in use in script.
- if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) {
- motion_cache.instantiate();
- motion_cache->owner = this;
- }
-
- motion_cache->result = result;
-
- return motion_cache;
- }
-
- return Ref<KinematicCollision3D>();
-}
-
-bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
- bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
-
- // Restore direction of motion to be along original motion,
- // in order to avoid sliding due to recovery,
- // but only if collision depth is low enough to avoid tunneling.
- if (p_cancel_sliding) {
- real_t motion_length = p_parameters.motion.length();
- real_t precision = 0.001;
-
- if (colliding) {
- // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
- // so even in normal resting cases the depth can be a bit more than the margin.
- precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
-
- if (r_result.collisions[0].depth > p_parameters.margin + precision) {
- p_cancel_sliding = false;
- }
- }
-
- if (p_cancel_sliding) {
- // When motion is null, recovery is the resulting motion.
- Vector3 motion_normal;
- if (motion_length > CMP_EPSILON) {
- motion_normal = p_parameters.motion / motion_length;
- }
-
- // Check depth of recovery.
- real_t projected_length = r_result.travel.dot(motion_normal);
- Vector3 recovery = r_result.travel - motion_normal * projected_length;
- real_t recovery_length = recovery.length();
- // Fixes cases where canceling slide causes the motion to go too deep into the ground,
- // because we're only taking rest information into account and not general recovery.
- if (recovery_length < p_parameters.margin + precision) {
- // Apply adjustment to motion.
- r_result.travel = motion_normal * projected_length;
- r_result.remainder = p_parameters.motion - r_result.travel;
- }
- }
- }
-
- for (int i = 0; i < 3; i++) {
- if (locked_axis & (1 << i)) {
- r_result.travel[i] = 0;
- }
- }
-
- if (!p_test_only) {
- Transform3D gt = p_parameters.from;
- gt.origin += r_result.travel;
- set_global_transform(gt);
- }
-
- return colliding;
-}
-
-bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
-
- PhysicsServer3D::MotionResult *r = nullptr;
- PhysicsServer3D::MotionResult temp_result;
- if (r_collision.is_valid()) {
- // Needs const_cast because method bindings don't support non-const Ref.
- r = const_cast<PhysicsServer3D::MotionResult *>(&r_collision->result);
- } else {
- r = &temp_result;
- }
-
- PhysicsServer3D::MotionParameters parameters(p_from, p_motion, p_margin);
- parameters.recovery_as_collision = p_recovery_as_collision;
- parameters.max_collisions = p_max_collisions;
-
- return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
-}
-
-Vector3 PhysicsBody3D::get_gravity() const {
- PhysicsDirectBodyState3D *state = PhysicsServer3D::get_singleton()->body_get_direct_state(get_rid());
- ERR_FAIL_NULL_V(state, Vector3());
- return state->get_total_gravity();
-}
-
-void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
- if (p_lock) {
- locked_axis |= p_axis;
- } else {
- locked_axis &= (~p_axis);
- }
- PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
-}
-
-bool PhysicsBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const {
- return (locked_axis & p_axis);
-}
-
-Vector3 PhysicsBody3D::get_linear_velocity() const {
- return Vector3();
-}
-
-Vector3 PhysicsBody3D::get_angular_velocity() const {
- return Vector3();
-}
-
-real_t PhysicsBody3D::get_inverse_mass() const {
- return 0;
-}
-
-void StaticBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
- if (physics_material_override.is_valid()) {
- physics_material_override->disconnect_changed(callable_mp(this, &StaticBody3D::_reload_physics_characteristics));
- }
-
- physics_material_override = p_physics_material_override;
-
- if (physics_material_override.is_valid()) {
- physics_material_override->connect_changed(callable_mp(this, &StaticBody3D::_reload_physics_characteristics));
- }
- _reload_physics_characteristics();
-}
-
-Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
- return physics_material_override;
-}
-
-void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
- constant_linear_velocity = p_vel;
-
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
-}
-
-void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
- constant_angular_velocity = p_vel;
-
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
-}
-
-Vector3 StaticBody3D::get_constant_linear_velocity() const {
- return constant_linear_velocity;
-}
-
-Vector3 StaticBody3D::get_constant_angular_velocity() const {
- return constant_angular_velocity;
-}
-
-void StaticBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
-}
-
-StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) :
- PhysicsBody3D(p_mode) {
-}
-
-void StaticBody3D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-Vector3 AnimatableBody3D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-Vector3 AnimatableBody3D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-void AnimatableBody3D::set_sync_to_physics(bool p_enable) {
- if (sync_to_physics == p_enable) {
- return;
- }
-
- sync_to_physics = p_enable;
-
- _update_kinematic_motion();
-}
-
-bool AnimatableBody3D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void AnimatableBody3D::_update_kinematic_motion() {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
-
- if (sync_to_physics) {
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-}
-
-void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
- linear_velocity = p_state->get_linear_velocity();
- angular_velocity = p_state->get_angular_velocity();
-
- if (!sync_to_physics) {
- return;
- }
-
- last_valid_transform = p_state->get_transform();
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
- _on_transform_changed();
-}
-
-void AnimatableBody3D::_notification(int p_what) {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- last_valid_transform = get_global_transform();
- _update_kinematic_motion();
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- } break;
-
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- // Used by sync to physics, send the new transform to the physics...
- Transform3D new_transform = get_global_transform();
-
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
-
- // ... but then revert changes.
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
- _on_transform_changed();
- } break;
- }
-}
-
-void AnimatableBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody3D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody3D::is_sync_to_physics_enabled);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
-}
-
-AnimatableBody3D::AnimatableBody3D() :
- StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody3D::_body_state_changed));
-}
-
-void RigidBody3D::_body_enter_tree(ObjectID p_id) {
- Object *obj = ObjectDB::get_instance(p_id);
- Node *node = Object::cast_to<Node>(obj);
- ERR_FAIL_NULL(node);
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
- ERR_FAIL_COND(!E);
- ERR_FAIL_COND(E->value.in_tree);
-
- E->value.in_tree = true;
-
- contact_monitor->locked = true;
-
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
-
- for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
- }
-
- contact_monitor->locked = false;
-}
-
-void RigidBody3D::_body_exit_tree(ObjectID p_id) {
- Object *obj = ObjectDB::get_instance(p_id);
- Node *node = Object::cast_to<Node>(obj);
- ERR_FAIL_NULL(node);
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
- ERR_FAIL_COND(!E);
- ERR_FAIL_COND(!E->value.in_tree);
- E->value.in_tree = false;
-
- contact_monitor->locked = true;
-
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
-
- for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
- }
-
- contact_monitor->locked = false;
-}
-
-void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
- bool body_in = p_status == 1;
- ObjectID objid = p_instance;
-
- Object *obj = ObjectDB::get_instance(objid);
- Node *node = Object::cast_to<Node>(obj);
-
- ERR_FAIL_NULL(contact_monitor);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
-
- ERR_FAIL_COND(!body_in && !E);
-
- if (body_in) {
- if (!E) {
- E = contact_monitor->body_map.insert(objid, BodyState());
- E->value.rid = p_body;
- //E->value.rc=0;
- E->value.in_tree = node && node->is_inside_tree();
- if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid));
- if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
- }
- }
- }
- //E->value.rc++;
- if (node) {
- E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
- }
-
- if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
- }
-
- } else {
- //E->value.rc--;
-
- if (node) {
- E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
- }
-
- bool in_tree = E->value.in_tree;
-
- if (E->value.shapes.is_empty()) {
- if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
- if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
- }
- }
-
- contact_monitor->body_map.remove(E);
- }
- if (node && in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape);
- }
- }
-}
-
-struct _RigidBodyInOut {
- RID rid;
- ObjectID id;
- int shape = 0;
- int local_shape = 0;
-};
-
-void RigidBody3D::_sync_body_state(PhysicsDirectBodyState3D *p_state) {
- set_ignore_transform_notification(true);
- set_global_transform(p_state->get_transform());
- set_ignore_transform_notification(false);
-
- linear_velocity = p_state->get_linear_velocity();
- angular_velocity = p_state->get_angular_velocity();
-
- inverse_inertia_tensor = p_state->get_inverse_inertia_tensor();
-
- contact_count = p_state->get_contact_count();
-
- if (sleeping != p_state->is_sleeping()) {
- sleeping = p_state->is_sleeping();
- emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
- }
-}
-
-void RigidBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
- lock_callback();
-
- if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
- _sync_body_state(p_state);
-
- Transform3D old_transform = get_global_transform();
- GDVIRTUAL_CALL(_integrate_forces, p_state);
- Transform3D new_transform = get_global_transform();
-
- if (new_transform != old_transform) {
- // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
- }
- }
-
- _sync_body_state(p_state);
- _on_transform_changed();
-
- if (contact_monitor) {
- contact_monitor->locked = true;
-
- //untag all
- int rc = 0;
- for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- for (int i = 0; i < E.value.shapes.size(); i++) {
- E.value.shapes[i].tagged = false;
- rc++;
- }
- }
-
- _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBodyInOut));
- int toadd_count = 0;
- RigidBody3D_RemoveAction *toremove = (RigidBody3D_RemoveAction *)alloca(rc * sizeof(RigidBody3D_RemoveAction));
- int toremove_count = 0;
-
- //put the ones to add
-
- for (int i = 0; i < p_state->get_contact_count(); i++) {
- RID col_rid = p_state->get_contact_collider(i);
- ObjectID col_obj = p_state->get_contact_collider_id(i);
- int local_shape = p_state->get_contact_local_shape(i);
- int col_shape = p_state->get_contact_collider_shape(i);
-
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
- if (!E) {
- toadd[toadd_count].rid = col_rid;
- toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = col_obj;
- toadd[toadd_count].shape = col_shape;
- toadd_count++;
- continue;
- }
-
- ShapePair sp(col_shape, local_shape);
- int idx = E->value.shapes.find(sp);
- if (idx == -1) {
- toadd[toadd_count].rid = col_rid;
- toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = col_obj;
- toadd[toadd_count].shape = col_shape;
- toadd_count++;
- continue;
- }
-
- E->value.shapes[idx].tagged = true;
- }
-
- //put the ones to remove
-
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- for (int i = 0; i < E.value.shapes.size(); i++) {
- if (!E.value.shapes[i].tagged) {
- toremove[toremove_count].rid = E.value.rid;
- toremove[toremove_count].body_id = E.key;
- toremove[toremove_count].pair = E.value.shapes[i];
- toremove_count++;
- }
- }
- }
-
- //process removals
-
- for (int i = 0; i < toremove_count; i++) {
- _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
- }
-
- //process additions
-
- for (int i = 0; i < toadd_count; i++) {
- _body_inout(1, toremove[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
- }
-
- contact_monitor->locked = false;
- }
-
- unlock_callback();
-}
-
-void RigidBody3D::_notification(int p_what) {
-#ifdef TOOLS_ENABLED
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (Engine::get_singleton()->is_editor_hint()) {
- set_notify_local_transform(true); // Used for warnings and only in editor.
- }
- } break;
-
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- update_configuration_warnings();
- } break;
- }
-#endif
-}
-
-void RigidBody3D::_apply_body_mode() {
- if (freeze) {
- switch (freeze_mode) {
- case FREEZE_MODE_STATIC: {
- set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
- } break;
- case FREEZE_MODE_KINEMATIC: {
- set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
- } break;
- }
- } else if (lock_rotation) {
- set_body_mode(PhysicsServer3D::BODY_MODE_RIGID_LINEAR);
- } else {
- set_body_mode(PhysicsServer3D::BODY_MODE_RIGID);
- }
-}
-
-void RigidBody3D::set_lock_rotation_enabled(bool p_lock_rotation) {
- if (p_lock_rotation == lock_rotation) {
- return;
- }
-
- lock_rotation = p_lock_rotation;
- _apply_body_mode();
-}
-
-bool RigidBody3D::is_lock_rotation_enabled() const {
- return lock_rotation;
-}
-
-void RigidBody3D::set_freeze_enabled(bool p_freeze) {
- if (p_freeze == freeze) {
- return;
- }
-
- freeze = p_freeze;
- _apply_body_mode();
-}
-
-bool RigidBody3D::is_freeze_enabled() const {
- return freeze;
-}
-
-void RigidBody3D::set_freeze_mode(FreezeMode p_freeze_mode) {
- if (p_freeze_mode == freeze_mode) {
- return;
- }
-
- freeze_mode = p_freeze_mode;
- _apply_body_mode();
-}
-
-RigidBody3D::FreezeMode RigidBody3D::get_freeze_mode() const {
- return freeze_mode;
-}
-
-void RigidBody3D::set_mass(real_t p_mass) {
- ERR_FAIL_COND(p_mass <= 0);
- mass = p_mass;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
-}
-
-real_t RigidBody3D::get_mass() const {
- return mass;
-}
-
-void RigidBody3D::set_inertia(const Vector3 &p_inertia) {
- ERR_FAIL_COND(p_inertia.x < 0);
- ERR_FAIL_COND(p_inertia.y < 0);
- ERR_FAIL_COND(p_inertia.z < 0);
-
- inertia = p_inertia;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
-}
-
-const Vector3 &RigidBody3D::get_inertia() const {
- return inertia;
-}
-
-void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
- if (center_of_mass_mode == p_mode) {
- return;
- }
-
- center_of_mass_mode = p_mode;
-
- switch (center_of_mass_mode) {
- case CENTER_OF_MASS_MODE_AUTO: {
- center_of_mass = Vector3();
- PhysicsServer3D::get_singleton()->body_reset_mass_properties(get_rid());
- if (inertia != Vector3()) {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
- }
- } break;
-
- case CENTER_OF_MASS_MODE_CUSTOM: {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
- } break;
- }
-}
-
-RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const {
- return center_of_mass_mode;
-}
-
-void RigidBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) {
- if (center_of_mass == p_center_of_mass) {
- return;
- }
-
- ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
- center_of_mass = p_center_of_mass;
-
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
-}
-
-const Vector3 &RigidBody3D::get_center_of_mass() const {
- return center_of_mass;
-}
-
-void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
- if (physics_material_override.is_valid()) {
- physics_material_override->disconnect_changed(callable_mp(this, &RigidBody3D::_reload_physics_characteristics));
- }
-
- physics_material_override = p_physics_material_override;
-
- if (physics_material_override.is_valid()) {
- physics_material_override->connect_changed(callable_mp(this, &RigidBody3D::_reload_physics_characteristics));
- }
- _reload_physics_characteristics();
-}
-
-Ref<PhysicsMaterial> RigidBody3D::get_physics_material_override() const {
- return physics_material_override;
-}
-
-void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) {
- gravity_scale = p_gravity_scale;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
-}
-
-real_t RigidBody3D::get_gravity_scale() const {
- return gravity_scale;
-}
-
-void RigidBody3D::set_linear_damp_mode(DampMode p_mode) {
- linear_damp_mode = p_mode;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
-}
-
-RigidBody3D::DampMode RigidBody3D::get_linear_damp_mode() const {
- return linear_damp_mode;
-}
-
-void RigidBody3D::set_angular_damp_mode(DampMode p_mode) {
- angular_damp_mode = p_mode;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
-}
-
-RigidBody3D::DampMode RigidBody3D::get_angular_damp_mode() const {
- return angular_damp_mode;
-}
-
-void RigidBody3D::set_linear_damp(real_t p_linear_damp) {
- ERR_FAIL_COND(p_linear_damp < 0.0);
- linear_damp = p_linear_damp;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
-}
-
-real_t RigidBody3D::get_linear_damp() const {
- return linear_damp;
-}
-
-void RigidBody3D::set_angular_damp(real_t p_angular_damp) {
- ERR_FAIL_COND(p_angular_damp < 0.0);
- angular_damp = p_angular_damp;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
-}
-
-real_t RigidBody3D::get_angular_damp() const {
- return angular_damp;
-}
-
-void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) {
- Vector3 axis = p_axis.normalized();
- linear_velocity -= axis * axis.dot(linear_velocity);
- linear_velocity += p_axis;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
-}
-
-void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) {
- linear_velocity = p_velocity;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
-}
-
-Vector3 RigidBody3D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) {
- angular_velocity = p_velocity;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
-}
-
-Vector3 RigidBody3D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-Basis RigidBody3D::get_inverse_inertia_tensor() const {
- return inverse_inertia_tensor;
-}
-
-void RigidBody3D::set_use_custom_integrator(bool p_enable) {
- if (custom_integrator == p_enable) {
- return;
- }
-
- custom_integrator = p_enable;
- PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
-}
-
-bool RigidBody3D::is_using_custom_integrator() {
- return custom_integrator;
-}
-
-void RigidBody3D::set_sleeping(bool p_sleeping) {
- sleeping = p_sleeping;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping);
-}
-
-void RigidBody3D::set_can_sleep(bool p_active) {
- can_sleep = p_active;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active);
-}
-
-bool RigidBody3D::is_able_to_sleep() const {
- return can_sleep;
-}
-
-bool RigidBody3D::is_sleeping() const {
- return sleeping;
-}
-
-void RigidBody3D::set_max_contacts_reported(int p_amount) {
- max_contacts_reported = p_amount;
- PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
-}
-
-int RigidBody3D::get_max_contacts_reported() const {
- return max_contacts_reported;
-}
-
-int RigidBody3D::get_contact_count() const {
- return contact_count;
-}
-
-void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) {
- PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
-}
-
-void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
- PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
- singleton->body_apply_impulse(get_rid(), p_impulse, p_position);
-}
-
-void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
- PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse);
-}
-
-void RigidBody3D::apply_central_force(const Vector3 &p_force) {
- PhysicsServer3D::get_singleton()->body_apply_central_force(get_rid(), p_force);
-}
-
-void RigidBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) {
- PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
- singleton->body_apply_force(get_rid(), p_force, p_position);
-}
-
-void RigidBody3D::apply_torque(const Vector3 &p_torque) {
- PhysicsServer3D::get_singleton()->body_apply_torque(get_rid(), p_torque);
-}
-
-void RigidBody3D::add_constant_central_force(const Vector3 &p_force) {
- PhysicsServer3D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
-}
-
-void RigidBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) {
- PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
- singleton->body_add_constant_force(get_rid(), p_force, p_position);
-}
-
-void RigidBody3D::add_constant_torque(const Vector3 &p_torque) {
- PhysicsServer3D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
-}
-
-void RigidBody3D::set_constant_force(const Vector3 &p_force) {
- PhysicsServer3D::get_singleton()->body_set_constant_force(get_rid(), p_force);
-}
-
-Vector3 RigidBody3D::get_constant_force() const {
- return PhysicsServer3D::get_singleton()->body_get_constant_force(get_rid());
-}
-
-void RigidBody3D::set_constant_torque(const Vector3 &p_torque) {
- PhysicsServer3D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
-}
-
-Vector3 RigidBody3D::get_constant_torque() const {
- return PhysicsServer3D::get_singleton()->body_get_constant_torque(get_rid());
-}
-
-void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) {
- ccd = p_enable;
- PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable);
-}
-
-bool RigidBody3D::is_using_continuous_collision_detection() const {
- return ccd;
-}
-
-void RigidBody3D::set_contact_monitor(bool p_enabled) {
- if (p_enabled == is_contact_monitor_enabled()) {
- return;
- }
-
- if (!p_enabled) {
- ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
-
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- //clean up mess
- Object *obj = ObjectDB::get_instance(E.key);
- Node *node = Object::cast_to<Node>(obj);
-
- if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
- }
- }
-
- memdelete(contact_monitor);
- contact_monitor = nullptr;
- } else {
- contact_monitor = memnew(ContactMonitor);
- contact_monitor->locked = false;
- }
-}
-
-bool RigidBody3D::is_contact_monitor_enabled() const {
- return contact_monitor != nullptr;
-}
-
-TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const {
- ERR_FAIL_NULL_V(contact_monitor, TypedArray<Node3D>());
-
- TypedArray<Node3D> ret;
- ret.resize(contact_monitor->body_map.size());
- int idx = 0;
- for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
- Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
- }
- }
-
- return ret;
-}
-
-PackedStringArray RigidBody3D::get_configuration_warnings() const {
- PackedStringArray warnings = CollisionObject3D::get_configuration_warnings();
-
- Vector3 scale = get_transform().get_basis().get_scale();
- if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) {
- warnings.push_back(RTR("Scale changes to RigidBody3D will be overridden by the physics engine when running.\nPlease change the size in children collision shapes instead."));
- }
-
- return warnings;
-}
-
-void RigidBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass);
- ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass);
-
- ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody3D::set_inertia);
- ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody3D::get_inertia);
-
- ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody3D::set_center_of_mass_mode);
- ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody3D::get_center_of_mass_mode);
-
- ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody3D::set_center_of_mass);
- ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody3D::get_center_of_mass);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override);
-
- ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody3D::set_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody3D::get_linear_velocity);
-
- ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody3D::set_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody3D::get_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidBody3D::get_inverse_inertia_tensor);
-
- ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody3D::set_gravity_scale);
- ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody3D::get_gravity_scale);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody3D::set_linear_damp_mode);
- ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody3D::get_linear_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody3D::set_angular_damp_mode);
- ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody3D::get_angular_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody3D::set_linear_damp);
- ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody3D::get_linear_damp);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody3D::set_angular_damp);
- ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody3D::get_angular_damp);
-
- ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody3D::set_max_contacts_reported);
- ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody3D::get_max_contacts_reported);
- ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody3D::get_contact_count);
-
- ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody3D::set_use_custom_integrator);
- ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody3D::is_using_custom_integrator);
-
- ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody3D::set_contact_monitor);
- ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody3D::is_contact_monitor_enabled);
-
- ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidBody3D::set_use_continuous_collision_detection);
- ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody3D::is_using_continuous_collision_detection);
-
- ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity);
-
- ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse);
- ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3());
- ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse);
-
- ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody3D::apply_central_force);
- ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody3D::apply_force, Vector3());
- ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody3D::apply_torque);
-
- ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody3D::add_constant_central_force);
- ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody3D::add_constant_force, Vector3());
- ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody3D::add_constant_torque);
-
- ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody3D::set_constant_force);
- ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody3D::get_constant_force);
-
- ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody3D::set_constant_torque);
- ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody3D::get_constant_torque);
-
- ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping);
- ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody3D::is_sleeping);
-
- ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep);
- ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep);
-
- ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody3D::set_lock_rotation_enabled);
- ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody3D::is_lock_rotation_enabled);
-
- ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody3D::set_freeze_enabled);
- ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody3D::is_freeze_enabled);
-
- ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody3D::set_freeze_mode);
- ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody3D::get_freeze_mode);
-
- ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies);
-
- GDVIRTUAL_BIND(_integrate_forces, "state");
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
- ADD_GROUP("Mass Distribution", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:m"), "set_center_of_mass", "get_center_of_mass");
- ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5m\u00B2"), "set_inertia", "get_inertia");
- ADD_GROUP("Deactivation", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
- ADD_GROUP("Solver", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
- ADD_GROUP("Linear", "linear_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
- ADD_GROUP("Angular", "angular_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_GROUP("Constant Forces", "constant_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m/s\u00B2 (N)"), "set_constant_force", "get_constant_force");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
-
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
-
- BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
- BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
-
- BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
- BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
-
- BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
- BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
-}
-
-void RigidBody3D::_validate_property(PropertyInfo &p_property) const {
- if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
- if (p_property.name == "center_of_mass") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
- }
-}
-
-RigidBody3D::RigidBody3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody3D::_body_state_changed));
-}
-
-RigidBody3D::~RigidBody3D() {
- if (contact_monitor) {
- memdelete(contact_monitor);
- }
-}
-
-void RigidBody3D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-///////////////////////////////////////
-
-//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
-#define FLOOR_ANGLE_THRESHOLD 0.01
-
-bool CharacterBody3D::move_and_slide() {
- // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
-
- for (int i = 0; i < 3; i++) {
- if (locked_axis & (1 << i)) {
- velocity[i] = 0.0;
- }
- }
-
- Transform3D gt = get_global_transform();
- previous_position = gt.origin;
-
- Vector3 current_platform_velocity = platform_velocity;
-
- if ((collision_state.floor || collision_state.wall) && platform_rid.is_valid()) {
- bool excluded = false;
- if (collision_state.floor) {
- excluded = (platform_floor_layers & platform_layer) == 0;
- } else if (collision_state.wall) {
- excluded = (platform_wall_layers & platform_layer) == 0;
- }
- if (!excluded) {
- //this approach makes sure there is less delay between the actual body velocity and the one we saved
- PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(platform_rid);
- if (bs) {
- Vector3 local_position = gt.origin - bs->get_transform().origin;
- current_platform_velocity = bs->get_velocity_at_local_position(local_position);
- } else {
- // Body is removed or destroyed, invalidate floor.
- current_platform_velocity = Vector3();
- platform_rid = RID();
- }
- } else {
- current_platform_velocity = Vector3();
- }
- }
-
- motion_results.clear();
-
- bool was_on_floor = collision_state.floor;
- collision_state.state = 0;
-
- last_motion = Vector3();
-
- if (!current_platform_velocity.is_zero_approx()) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
-
- parameters.exclude_bodies.insert(platform_rid);
- if (platform_object_id.is_valid()) {
- parameters.exclude_objects.insert(platform_object_id);
- }
-
- PhysicsServer3D::MotionResult floor_result;
- if (move_and_collide(parameters, floor_result, false, false)) {
- motion_results.push_back(floor_result);
-
- CollisionState result_state;
- _set_collision_direction(floor_result, result_state);
- }
- }
-
- if (motion_mode == MOTION_MODE_GROUNDED) {
- _move_and_slide_grounded(delta, was_on_floor);
- } else {
- _move_and_slide_floating(delta);
- }
-
- // Compute real velocity.
- real_velocity = get_position_delta() / delta;
-
- if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) {
- // Add last platform velocity when just left a moving platform.
- if (!collision_state.floor && !collision_state.wall) {
- if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) {
- current_platform_velocity = current_platform_velocity.slide(up_direction);
- }
- velocity += current_platform_velocity;
- }
- }
-
- return motion_results.size() > 0;
-}
-
-void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
- Vector3 motion = velocity * p_delta;
- Vector3 motion_slide_up = motion.slide(up_direction);
- Vector3 prev_floor_normal = floor_normal;
-
- platform_rid = RID();
- platform_object_id = ObjectID();
- platform_velocity = Vector3();
- platform_angular_velocity = Vector3();
- platform_ceiling_velocity = Vector3();
- floor_normal = Vector3();
- wall_normal = Vector3();
- ceiling_normal = Vector3();
-
- // No sliding on first attempt to keep floor motion stable when possible,
- // When stop on slope is enabled or when there is no up direction.
- bool sliding_enabled = !floor_stop_on_slope;
- // Constant speed can be applied only the first time sliding is enabled.
- bool can_apply_constant_speed = sliding_enabled;
- // If the platform's ceiling push down the body.
- bool apply_ceiling_velocity = false;
- bool first_slide = true;
- bool vel_dir_facing_up = velocity.dot(up_direction) > 0;
- Vector3 total_travel;
-
- for (int iteration = 0; iteration < max_slides; ++iteration) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
- parameters.max_collisions = 6; // There can be 4 collisions between 2 walls + 2 more for the floor.
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
-
- PhysicsServer3D::MotionResult result;
- bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
-
- last_motion = result.travel;
-
- if (collided) {
- motion_results.push_back(result);
-
- CollisionState previous_state = collision_state;
-
- CollisionState result_state;
- _set_collision_direction(result, result_state);
-
- // If we hit a ceiling platform, we set the vertical velocity to at least the platform one.
- if (collision_state.ceiling && platform_ceiling_velocity != Vector3() && platform_ceiling_velocity.dot(up_direction) < 0) {
- // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
- if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (ceiling_normal + up_direction).length() < 0.01) {
- apply_ceiling_velocity = true;
- Vector3 ceiling_vertical_velocity = up_direction * up_direction.dot(platform_ceiling_velocity);
- Vector3 motion_vertical_velocity = up_direction * up_direction.dot(velocity);
- if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
- velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
- }
- }
- }
-
- if (collision_state.floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
- Transform3D gt = get_global_transform();
- if (result.travel.length() <= margin + CMP_EPSILON) {
- gt.origin -= result.travel;
- }
- set_global_transform(gt);
- velocity = Vector3();
- motion = Vector3();
- last_motion = Vector3();
- break;
- }
-
- if (result.remainder.is_zero_approx()) {
- motion = Vector3();
- break;
- }
-
- // Apply regular sliding by default.
- bool apply_default_sliding = true;
-
- // Wall collision checks.
- if (result_state.wall && (motion_slide_up.dot(wall_normal) <= 0)) {
- // Move on floor only checks.
- if (floor_block_on_wall) {
- // Needs horizontal motion from current motion instead of motion_slide_up
- // to properly test the angle and avoid standing on slopes
- Vector3 horizontal_motion = motion.slide(up_direction);
- Vector3 horizontal_normal = wall_normal.slide(up_direction).normalized();
- real_t motion_angle = Math::abs(Math::acos(-horizontal_normal.dot(horizontal_motion.normalized())));
-
- // Avoid to move forward on a wall if floor_block_on_wall is true.
- // Applies only when the motion angle is under 90 degrees,
- // in order to avoid blocking lateral motion along a wall.
- if (motion_angle < .5 * Math_PI) {
- apply_default_sliding = false;
- if (p_was_on_floor && !vel_dir_facing_up) {
- // Cancel the motion.
- Transform3D gt = get_global_transform();
- real_t travel_total = result.travel.length();
- real_t cancel_dist_max = MIN(0.1, margin * 20);
- if (travel_total <= margin + CMP_EPSILON) {
- gt.origin -= result.travel;
- result.travel = Vector3(); // Cancel for constant speed computation.
- } else if (travel_total < cancel_dist_max) { // If the movement is large the body can be prevented from reaching the walls.
- gt.origin -= result.travel.slide(up_direction);
- // Keep remaining motion in sync with amount canceled.
- motion = motion.slide(up_direction);
- result.travel = Vector3();
- } else {
- // Travel is too high to be safely canceled, we take it into account.
- result.travel = result.travel.slide(up_direction);
- motion = motion.normalized() * result.travel.length();
- }
- set_global_transform(gt);
- // Determines if you are on the ground, and limits the possibility of climbing on the walls because of the approximations.
- _snap_on_floor(true, false);
- } else {
- // If the movement is not canceled we only keep the remaining.
- motion = result.remainder;
- }
-
- // Apply slide on forward in order to allow only lateral motion on next step.
- Vector3 forward = wall_normal.slide(up_direction).normalized();
- motion = motion.slide(forward);
-
- // Scales the horizontal velocity according to the wall slope.
- if (vel_dir_facing_up) {
- Vector3 slide_motion = velocity.slide(result.collisions[0].normal);
- // Keeps the vertical motion from velocity and add the horizontal motion of the projection.
- velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
- } else {
- velocity = velocity.slide(forward);
- }
-
- // Allow only lateral motion along previous floor when already on floor.
- // Fixes slowing down when moving in diagonal against an inclined wall.
- if (p_was_on_floor && !vel_dir_facing_up && (motion.dot(up_direction) > 0.0)) {
- // Slide along the corner between the wall and previous floor.
- Vector3 floor_side = prev_floor_normal.cross(wall_normal);
- if (floor_side != Vector3()) {
- motion = floor_side * motion.dot(floor_side);
- }
- }
-
- // Stop all motion when a second wall is hit (unless sliding down or jumping),
- // in order to avoid jittering in corner cases.
- bool stop_all_motion = previous_state.wall && !vel_dir_facing_up;
-
- // Allow sliding when the body falls.
- if (!collision_state.floor && motion.dot(up_direction) < 0) {
- Vector3 slide_motion = motion.slide(wall_normal);
- // Test again to allow sliding only if the result goes downwards.
- // Fixes jittering issues at the bottom of inclined walls.
- if (slide_motion.dot(up_direction) < 0) {
- stop_all_motion = false;
- motion = slide_motion;
- }
- }
-
- if (stop_all_motion) {
- motion = Vector3();
- velocity = Vector3();
- }
- }
- }
-
- // Stop horizontal motion when under wall slide threshold.
- if (p_was_on_floor && (wall_min_slide_angle > 0.0) && result_state.wall) {
- Vector3 horizontal_normal = wall_normal.slide(up_direction).normalized();
- real_t motion_angle = Math::abs(Math::acos(-horizontal_normal.dot(motion_slide_up.normalized())));
- if (motion_angle < wall_min_slide_angle) {
- motion = up_direction * motion.dot(up_direction);
- velocity = up_direction * velocity.dot(up_direction);
-
- apply_default_sliding = false;
- }
- }
- }
-
- if (apply_default_sliding) {
- // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
- const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
-
- Vector3 slide_motion = result.remainder.slide(collision.normal);
- if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_zero_approx()) {
- // Slide using the intersection between the motion plane and the floor plane,
- // in order to keep the direction intact.
- real_t motion_length = slide_motion.length();
- slide_motion = up_direction.cross(result.remainder).cross(floor_normal);
-
- // Keep the length from default slide to change speed in slopes by default,
- // when constant speed is not enabled.
- slide_motion.normalize();
- slide_motion *= motion_length;
- }
-
- if (slide_motion.dot(velocity) > 0.0) {
- motion = slide_motion;
- } else {
- motion = Vector3();
- }
-
- if (slide_on_ceiling && result_state.ceiling) {
- // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
- if (vel_dir_facing_up) {
- velocity = velocity.slide(collision.normal);
- } else {
- // Avoid acceleration in slope when falling.
- velocity = up_direction * up_direction.dot(velocity);
- }
- }
- }
- // No sliding on first attempt to keep floor motion stable when possible.
- else {
- motion = result.remainder;
- if (result_state.ceiling && !slide_on_ceiling && vel_dir_facing_up) {
- velocity = velocity.slide(up_direction);
- motion = motion.slide(up_direction);
- }
- }
- }
-
- total_travel += result.travel;
-
- // Apply Constant Speed.
- if (p_was_on_floor && floor_constant_speed && can_apply_constant_speed && collision_state.floor && !motion.is_zero_approx()) {
- Vector3 travel_slide_up = total_travel.slide(up_direction);
- motion = motion.normalized() * MAX(0, (motion_slide_up.length() - travel_slide_up.length()));
- }
- }
- // When you move forward in a downward slope you don’t collide because you will be in the air.
- // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
- else if (floor_constant_speed && first_slide && _on_floor_if_snapped(p_was_on_floor, vel_dir_facing_up)) {
- can_apply_constant_speed = false;
- sliding_enabled = true;
- Transform3D gt = get_global_transform();
- gt.origin = gt.origin - result.travel;
- set_global_transform(gt);
-
- // Slide using the intersection between the motion plane and the floor plane,
- // in order to keep the direction intact.
- Vector3 motion_slide_norm = up_direction.cross(motion).cross(prev_floor_normal);
- motion_slide_norm.normalize();
-
- motion = motion_slide_norm * (motion_slide_up.length());
- collided = true;
- }
-
- if (!collided || motion.is_zero_approx()) {
- break;
- }
-
- can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
- sliding_enabled = true;
- first_slide = false;
- }
-
- _snap_on_floor(p_was_on_floor, vel_dir_facing_up);
-
- // Reset the gravity accumulation when touching the ground.
- if (collision_state.floor && !vel_dir_facing_up) {
- velocity = velocity.slide(up_direction);
- }
-}
-
-void CharacterBody3D::_move_and_slide_floating(double p_delta) {
- Vector3 motion = velocity * p_delta;
-
- platform_rid = RID();
- platform_object_id = ObjectID();
- floor_normal = Vector3();
- platform_velocity = Vector3();
- platform_angular_velocity = Vector3();
-
- bool first_slide = true;
- for (int iteration = 0; iteration < max_slides; ++iteration) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
-
- PhysicsServer3D::MotionResult result;
- bool collided = move_and_collide(parameters, result, false, false);
-
- last_motion = result.travel;
-
- if (collided) {
- motion_results.push_back(result);
-
- CollisionState result_state;
- _set_collision_direction(result, result_state);
-
- if (result.remainder.is_zero_approx()) {
- motion = Vector3();
- break;
- }
-
- if (wall_min_slide_angle != 0 && Math::acos(wall_normal.dot(-velocity.normalized())) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) {
- motion = Vector3();
- if (result.travel.length() < margin + CMP_EPSILON) {
- Transform3D gt = get_global_transform();
- gt.origin -= result.travel;
- set_global_transform(gt);
- }
- } else if (first_slide) {
- Vector3 motion_slide_norm = result.remainder.slide(wall_normal).normalized();
- motion = motion_slide_norm * (motion.length() - result.travel.length());
- } else {
- motion = result.remainder.slide(wall_normal);
- }
-
- if (motion.dot(velocity) <= 0.0) {
- motion = Vector3();
- }
- }
-
- if (!collided || motion.is_zero_approx()) {
- break;
- }
-
- first_slide = false;
- }
-}
-
-void CharacterBody3D::apply_floor_snap() {
- if (collision_state.floor) {
- return;
- }
-
- // Snap by at least collision margin to keep floor state consistent.
- real_t length = MAX(floor_snap_length, margin);
-
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.max_collisions = 4;
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
- parameters.collide_separation_ray = true;
-
- PhysicsServer3D::MotionResult result;
- if (move_and_collide(parameters, result, true, false)) {
- CollisionState result_state;
- // Apply direction for floor only.
- _set_collision_direction(result, result_state, CollisionState(true, false, false));
-
- if (result_state.floor) {
- if (floor_stop_on_slope) {
- // move and collide may stray the object a bit because of pre un-stucking,
- // so only ensure that motion happens on floor direction in this case.
- if (result.travel.length() > margin) {
- result.travel = up_direction * up_direction.dot(result.travel);
- } else {
- result.travel = Vector3();
- }
- }
-
- parameters.from.origin += result.travel;
- set_global_transform(parameters.from);
- }
- }
-}
-
-void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up) {
- if (collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) {
- return;
- }
-
- apply_floor_snap();
-}
-
-bool CharacterBody3D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) {
- if (up_direction == Vector3() || collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) {
- return false;
- }
-
- // Snap by at least collision margin to keep floor state consistent.
- real_t length = MAX(floor_snap_length, margin);
-
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.max_collisions = 4;
- parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
- parameters.collide_separation_ray = true;
-
- PhysicsServer3D::MotionResult result;
- if (move_and_collide(parameters, result, true, false)) {
- CollisionState result_state;
- // Don't apply direction for any type.
- _set_collision_direction(result, result_state, CollisionState());
-
- return result_state.floor;
- }
-
- return false;
-}
-
-void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResult &p_result, CollisionState &r_state, CollisionState p_apply_state) {
- r_state.state = 0;
-
- real_t wall_depth = -1.0;
- real_t floor_depth = -1.0;
-
- bool was_on_wall = collision_state.wall;
- Vector3 prev_wall_normal = wall_normal;
- int wall_collision_count = 0;
- Vector3 combined_wall_normal;
- Vector3 tmp_wall_col; // Avoid duplicate on average calculation.
-
- for (int i = p_result.collision_count - 1; i >= 0; i--) {
- const PhysicsServer3D::MotionCollision &collision = p_result.collisions[i];
-
- if (motion_mode == MOTION_MODE_GROUNDED) {
- // Check if any collision is floor.
- real_t floor_angle = collision.get_angle(up_direction);
- if (floor_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
- r_state.floor = true;
- if (p_apply_state.floor && collision.depth > floor_depth) {
- collision_state.floor = true;
- floor_normal = collision.normal;
- floor_depth = collision.depth;
- _set_platform_data(collision);
- }
- continue;
- }
-
- // Check if any collision is ceiling.
- real_t ceiling_angle = collision.get_angle(-up_direction);
- if (ceiling_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
- r_state.ceiling = true;
- if (p_apply_state.ceiling) {
- platform_ceiling_velocity = collision.collider_velocity;
- ceiling_normal = collision.normal;
- collision_state.ceiling = true;
- }
- continue;
- }
- }
-
- // Collision is wall by default.
- r_state.wall = true;
-
- if (p_apply_state.wall && collision.depth > wall_depth) {
- collision_state.wall = true;
- wall_depth = collision.depth;
- wall_normal = collision.normal;
-
- // Don't apply wall velocity when the collider is a CharacterBody3D.
- if (Object::cast_to<CharacterBody3D>(ObjectDB::get_instance(collision.collider_id)) == nullptr) {
- _set_platform_data(collision);
- }
- }
-
- // Collect normal for calculating average.
- if (!collision.normal.is_equal_approx(tmp_wall_col)) {
- tmp_wall_col = collision.normal;
- combined_wall_normal += collision.normal;
- wall_collision_count++;
- }
- }
-
- if (r_state.wall) {
- if (wall_collision_count > 1 && !r_state.floor) {
- // Check if wall normals cancel out to floor support.
- if (!r_state.floor && motion_mode == MOTION_MODE_GROUNDED) {
- combined_wall_normal.normalize();
- real_t floor_angle = Math::acos(combined_wall_normal.dot(up_direction));
- if (floor_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
- r_state.floor = true;
- r_state.wall = false;
- if (p_apply_state.floor) {
- collision_state.floor = true;
- floor_normal = combined_wall_normal;
- }
- if (p_apply_state.wall) {
- collision_state.wall = was_on_wall;
- wall_normal = prev_wall_normal;
- }
- return;
- }
- }
- }
- }
-}
-
-void CharacterBody3D::_set_platform_data(const PhysicsServer3D::MotionCollision &p_collision) {
- platform_rid = p_collision.collider;
- platform_object_id = p_collision.collider_id;
- platform_velocity = p_collision.collider_velocity;
- platform_angular_velocity = p_collision.collider_angular_velocity;
- platform_layer = PhysicsServer3D::get_singleton()->body_get_collision_layer(platform_rid);
-}
-
-void CharacterBody3D::set_safe_margin(real_t p_margin) {
- margin = p_margin;
-}
-
-real_t CharacterBody3D::get_safe_margin() const {
- return margin;
-}
-
-const Vector3 &CharacterBody3D::get_velocity() const {
- return velocity;
-}
-
-void CharacterBody3D::set_velocity(const Vector3 &p_velocity) {
- velocity = p_velocity;
-}
-
-bool CharacterBody3D::is_on_floor() const {
- return collision_state.floor;
-}
-
-bool CharacterBody3D::is_on_floor_only() const {
- return collision_state.floor && !collision_state.wall && !collision_state.ceiling;
-}
-
-bool CharacterBody3D::is_on_wall() const {
- return collision_state.wall;
-}
-
-bool CharacterBody3D::is_on_wall_only() const {
- return collision_state.wall && !collision_state.floor && !collision_state.ceiling;
-}
-
-bool CharacterBody3D::is_on_ceiling() const {
- return collision_state.ceiling;
-}
-
-bool CharacterBody3D::is_on_ceiling_only() const {
- return collision_state.ceiling && !collision_state.floor && !collision_state.wall;
-}
-
-const Vector3 &CharacterBody3D::get_floor_normal() const {
- return floor_normal;
-}
-
-const Vector3 &CharacterBody3D::get_wall_normal() const {
- return wall_normal;
-}
-
-const Vector3 &CharacterBody3D::get_last_motion() const {
- return last_motion;
-}
-
-Vector3 CharacterBody3D::get_position_delta() const {
- return get_global_transform().origin - previous_position;
-}
-
-const Vector3 &CharacterBody3D::get_real_velocity() const {
- return real_velocity;
-}
-
-real_t CharacterBody3D::get_floor_angle(const Vector3 &p_up_direction) const {
- ERR_FAIL_COND_V(p_up_direction == Vector3(), 0);
- return Math::acos(floor_normal.dot(p_up_direction));
-}
-
-const Vector3 &CharacterBody3D::get_platform_velocity() const {
- return platform_velocity;
-}
-
-const Vector3 &CharacterBody3D::get_platform_angular_velocity() const {
- return platform_angular_velocity;
-}
-
-Vector3 CharacterBody3D::get_linear_velocity() const {
- return get_real_velocity();
-}
-
-int CharacterBody3D::get_slide_collision_count() const {
- return motion_results.size();
-}
-
-PhysicsServer3D::MotionResult CharacterBody3D::get_slide_collision(int p_bounce) const {
- ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer3D::MotionResult());
- return motion_results[p_bounce];
-}
-
-Ref<KinematicCollision3D> CharacterBody3D::_get_slide_collision(int p_bounce) {
- ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision3D>());
- if (p_bounce >= slide_colliders.size()) {
- slide_colliders.resize(p_bounce + 1);
- }
-
- // Create a new instance when the cached reference is invalid or still in use in script.
- if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) {
- slide_colliders.write[p_bounce].instantiate();
- slide_colliders.write[p_bounce]->owner = this;
- }
-
- slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
- return slide_colliders[p_bounce];
-}
-
-Ref<KinematicCollision3D> CharacterBody3D::_get_last_slide_collision() {
- if (motion_results.size() == 0) {
- return Ref<KinematicCollision3D>();
- }
- return _get_slide_collision(motion_results.size() - 1);
-}
-
-bool CharacterBody3D::is_floor_stop_on_slope_enabled() const {
- return floor_stop_on_slope;
-}
-
-void CharacterBody3D::set_floor_stop_on_slope_enabled(bool p_enabled) {
- floor_stop_on_slope = p_enabled;
-}
-
-bool CharacterBody3D::is_floor_constant_speed_enabled() const {
- return floor_constant_speed;
-}
-
-void CharacterBody3D::set_floor_constant_speed_enabled(bool p_enabled) {
- floor_constant_speed = p_enabled;
-}
-
-bool CharacterBody3D::is_floor_block_on_wall_enabled() const {
- return floor_block_on_wall;
-}
-
-void CharacterBody3D::set_floor_block_on_wall_enabled(bool p_enabled) {
- floor_block_on_wall = p_enabled;
-}
-
-bool CharacterBody3D::is_slide_on_ceiling_enabled() const {
- return slide_on_ceiling;
-}
-
-void CharacterBody3D::set_slide_on_ceiling_enabled(bool p_enabled) {
- slide_on_ceiling = p_enabled;
-}
-
-uint32_t CharacterBody3D::get_platform_floor_layers() const {
- return platform_floor_layers;
-}
-
-void CharacterBody3D::set_platform_floor_layers(uint32_t p_exclude_layers) {
- platform_floor_layers = p_exclude_layers;
-}
-
-uint32_t CharacterBody3D::get_platform_wall_layers() const {
- return platform_wall_layers;
-}
-
-void CharacterBody3D::set_platform_wall_layers(uint32_t p_exclude_layers) {
- platform_wall_layers = p_exclude_layers;
-}
-
-void CharacterBody3D::set_motion_mode(MotionMode p_mode) {
- motion_mode = p_mode;
-}
-
-CharacterBody3D::MotionMode CharacterBody3D::get_motion_mode() const {
- return motion_mode;
-}
-
-void CharacterBody3D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) {
- platform_on_leave = p_on_leave_apply_velocity;
-}
-
-CharacterBody3D::PlatformOnLeave CharacterBody3D::get_platform_on_leave() const {
- return platform_on_leave;
-}
-
-int CharacterBody3D::get_max_slides() const {
- return max_slides;
-}
-
-void CharacterBody3D::set_max_slides(int p_max_slides) {
- ERR_FAIL_COND(p_max_slides < 1);
- max_slides = p_max_slides;
-}
-
-real_t CharacterBody3D::get_floor_max_angle() const {
- return floor_max_angle;
-}
-
-void CharacterBody3D::set_floor_max_angle(real_t p_radians) {
- floor_max_angle = p_radians;
-}
-
-real_t CharacterBody3D::get_floor_snap_length() {
- return floor_snap_length;
-}
-
-void CharacterBody3D::set_floor_snap_length(real_t p_floor_snap_length) {
- ERR_FAIL_COND(p_floor_snap_length < 0);
- floor_snap_length = p_floor_snap_length;
-}
-
-real_t CharacterBody3D::get_wall_min_slide_angle() const {
- return wall_min_slide_angle;
-}
-
-void CharacterBody3D::set_wall_min_slide_angle(real_t p_radians) {
- wall_min_slide_angle = p_radians;
-}
-
-const Vector3 &CharacterBody3D::get_up_direction() const {
- return up_direction;
-}
-
-void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) {
- ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Floating motion mode instead.");
- up_direction = p_up_direction.normalized();
-}
-
-void CharacterBody3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- // Reset move_and_slide() data.
- collision_state.state = 0;
- platform_rid = RID();
- platform_object_id = ObjectID();
- motion_results.clear();
- platform_velocity = Vector3();
- platform_angular_velocity = Vector3();
- } break;
- }
-}
-
-void CharacterBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody3D::move_and_slide);
- ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody3D::apply_floor_snap);
-
- ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody3D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody3D::get_velocity);
-
- ClassDB::bind_method(D_METHOD("set_safe_margin", "margin"), &CharacterBody3D::set_safe_margin);
- ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody3D::get_safe_margin);
- ClassDB::bind_method(D_METHOD("is_floor_stop_on_slope_enabled"), &CharacterBody3D::is_floor_stop_on_slope_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_stop_on_slope_enabled", "enabled"), &CharacterBody3D::set_floor_stop_on_slope_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_constant_speed_enabled", "enabled"), &CharacterBody3D::set_floor_constant_speed_enabled);
- ClassDB::bind_method(D_METHOD("is_floor_constant_speed_enabled"), &CharacterBody3D::is_floor_constant_speed_enabled);
- ClassDB::bind_method(D_METHOD("set_floor_block_on_wall_enabled", "enabled"), &CharacterBody3D::set_floor_block_on_wall_enabled);
- ClassDB::bind_method(D_METHOD("is_floor_block_on_wall_enabled"), &CharacterBody3D::is_floor_block_on_wall_enabled);
- ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody3D::set_slide_on_ceiling_enabled);
- ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody3D::is_slide_on_ceiling_enabled);
-
- ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody3D::set_platform_floor_layers);
- ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody3D::get_platform_floor_layers);
- ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody3D::set_platform_wall_layers);
- ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody3D::get_platform_wall_layers);
-
- ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody3D::get_max_slides);
- ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides);
- ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody3D::get_floor_max_angle);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody3D::set_floor_max_angle);
- ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody3D::get_floor_snap_length);
- ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody3D::set_floor_snap_length);
- ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody3D::get_wall_min_slide_angle);
- ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody3D::set_wall_min_slide_angle);
- ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody3D::get_up_direction);
- ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody3D::set_up_direction);
- ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody3D::set_motion_mode);
- ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody3D::get_motion_mode);
- ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody3D::set_platform_on_leave);
- ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody3D::get_platform_on_leave);
-
- ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody3D::is_on_floor);
- ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody3D::is_on_floor_only);
- ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody3D::is_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody3D::is_on_ceiling_only);
- ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody3D::is_on_wall);
- ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody3D::is_on_wall_only);
- ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody3D::get_floor_normal);
- ClassDB::bind_method(D_METHOD("get_wall_normal"), &CharacterBody3D::get_wall_normal);
- ClassDB::bind_method(D_METHOD("get_last_motion"), &CharacterBody3D::get_last_motion);
- ClassDB::bind_method(D_METHOD("get_position_delta"), &CharacterBody3D::get_position_delta);
- ClassDB::bind_method(D_METHOD("get_real_velocity"), &CharacterBody3D::get_real_velocity);
- ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &CharacterBody3D::get_floor_angle, DEFVAL(Vector3(0.0, 1.0, 0.0)));
- ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody3D::get_platform_velocity);
- ClassDB::bind_method(D_METHOD("get_platform_angular_velocity"), &CharacterBody3D::get_platform_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_slide_collision_count"), &CharacterBody3D::get_slide_collision_count);
- ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision);
- ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody3D::_get_last_slide_collision);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "velocity", PROPERTY_HINT_NONE, "suffix:m/s", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle");
-
- ADD_GROUP("Floor", "floor_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians_as_degrees"), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,suffix:m"), "set_floor_snap_length", "get_floor_snap_length");
-
- ADD_GROUP("Moving Platform", "platform_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
-
- ADD_GROUP("Collision", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:m"), "set_safe_margin", "get_safe_margin");
-
- BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED);
- BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING);
-
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY);
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY);
- BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING);
-}
-
-void CharacterBody3D::_validate_property(PropertyInfo &p_property) const {
- if (motion_mode == MOTION_MODE_FLOATING) {
- if (p_property.name.begins_with("floor_") || p_property.name == "up_direction" || p_property.name == "slide_on_ceiling") {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
- }
-}
-
-CharacterBody3D::CharacterBody3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
-}
-
-CharacterBody3D::~CharacterBody3D() {
- for (int i = 0; i < slide_colliders.size(); i++) {
- if (slide_colliders[i].is_valid()) {
- slide_colliders.write[i]->owner = nullptr;
- }
- }
-}
-
-///////////////////////////////////////
-
-Vector3 KinematicCollision3D::get_travel() const {
- return result.travel;
-}
-
-Vector3 KinematicCollision3D::get_remainder() const {
- return result.remainder;
-}
-
-int KinematicCollision3D::get_collision_count() const {
- return result.collision_count;
-}
-
-real_t KinematicCollision3D::get_depth() const {
- return result.collision_depth;
-}
-
-Vector3 KinematicCollision3D::get_position(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
- return result.collisions[p_collision_index].position;
-}
-
-Vector3 KinematicCollision3D::get_normal(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
- return result.collisions[p_collision_index].normal;
-}
-
-real_t KinematicCollision3D::get_angle(int p_collision_index, const Vector3 &p_up_direction) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0.0);
- ERR_FAIL_COND_V(p_up_direction == Vector3(), 0);
- return result.collisions[p_collision_index].get_angle(p_up_direction);
-}
-
-Object *KinematicCollision3D::get_local_shape(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
- if (!owner) {
- return nullptr;
- }
- uint32_t ownerid = owner->shape_find_owner(result.collisions[p_collision_index].local_shape);
- return owner->shape_owner_get_owner(ownerid);
-}
-
-Object *KinematicCollision3D::get_collider(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, nullptr);
- if (result.collisions[p_collision_index].collider_id.is_valid()) {
- return ObjectDB::get_instance(result.collisions[p_collision_index].collider_id);
- }
-
- return nullptr;
-}
-
-ObjectID KinematicCollision3D::get_collider_id(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, ObjectID());
- return result.collisions[p_collision_index].collider_id;
-}
-
-RID KinematicCollision3D::get_collider_rid(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, RID());
- return result.collisions[p_collision_index].collider;
-}
-
-Object *KinematicCollision3D::get_collider_shape(int p_collision_index) const {
- Object *collider = get_collider(p_collision_index);
- if (collider) {
- CollisionObject3D *obj2d = Object::cast_to<CollisionObject3D>(collider);
- if (obj2d) {
- uint32_t ownerid = obj2d->shape_find_owner(result.collisions[p_collision_index].collider_shape);
- return obj2d->shape_owner_get_owner(ownerid);
- }
- }
-
- return nullptr;
-}
-
-int KinematicCollision3D::get_collider_shape_index(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0);
- return result.collisions[p_collision_index].collider_shape;
-}
-
-Vector3 KinematicCollision3D::get_collider_velocity(int p_collision_index) const {
- ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, Vector3());
- return result.collisions[p_collision_index].collider_velocity;
-}
-
-void KinematicCollision3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision3D::get_travel);
- ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision3D::get_remainder);
- ClassDB::bind_method(D_METHOD("get_depth"), &KinematicCollision3D::get_depth);
- ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicCollision3D::get_collision_count);
- ClassDB::bind_method(D_METHOD("get_position", "collision_index"), &KinematicCollision3D::get_position, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_normal", "collision_index"), &KinematicCollision3D::get_normal, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_angle", "collision_index", "up_direction"), &KinematicCollision3D::get_angle, DEFVAL(0), DEFVAL(Vector3(0.0, 1.0, 0.0)));
- ClassDB::bind_method(D_METHOD("get_local_shape", "collision_index"), &KinematicCollision3D::get_local_shape, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider", "collision_index"), &KinematicCollision3D::get_collider, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider_id", "collision_index"), &KinematicCollision3D::get_collider_id, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider_rid", "collision_index"), &KinematicCollision3D::get_collider_rid, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &KinematicCollision3D::get_collider_shape, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider_shape_index", "collision_index"), &KinematicCollision3D::get_collider_shape_index, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_collider_velocity", "collision_index"), &KinematicCollision3D::get_collider_velocity, DEFVAL(0));
-}
-
-///////////////////////////////////////
-
-bool PhysicalBone3D::JointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- return false;
-}
-
-bool PhysicalBone3D::JointData::_get(const StringName &p_name, Variant &r_ret) const {
- return false;
-}
-
-void PhysicalBone3D::JointData::_get_property_list(List<PropertyInfo> *p_list) const {
-}
-
-void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) {
- PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
-}
-
-void PhysicalBone3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
- PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
-}
-
-void PhysicalBone3D::set_linear_velocity(const Vector3 &p_velocity) {
- linear_velocity = p_velocity;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
-}
-
-Vector3 PhysicalBone3D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-void PhysicalBone3D::set_angular_velocity(const Vector3 &p_velocity) {
- angular_velocity = p_velocity;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
-}
-
-Vector3 PhysicalBone3D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-void PhysicalBone3D::set_use_custom_integrator(bool p_enable) {
- if (custom_integrator == p_enable) {
- return;
- }
-
- custom_integrator = p_enable;
- PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
-}
-
-bool PhysicalBone3D::is_using_custom_integrator() {
- return custom_integrator;
-}
-
-void PhysicalBone3D::reset_physics_simulation_state() {
- if (simulate_physics) {
- _start_physics_simulation();
- } else {
- _stop_physics_simulation();
- }
-}
-
-void PhysicalBone3D::reset_to_rest_position() {
- if (parent_skeleton) {
- Transform3D new_transform = parent_skeleton->get_global_transform();
- if (bone_id == -1) {
- new_transform *= body_offset;
- } else {
- new_transform *= parent_skeleton->get_bone_global_pose(bone_id) * body_offset;
- }
- new_transform.orthonormalize();
- set_global_transform(new_transform);
- }
-}
-
-bool PhysicalBone3D::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- if (JointData::_set(p_name, p_value, j)) {
- return true;
- }
-
- bool is_valid_pin = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_PIN;
- if ("joint_constraints/bias" == p_name) {
- bias = p_value;
- if (is_valid_pin) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_BIAS, bias);
- }
-
- } else if ("joint_constraints/damping" == p_name) {
- damping = p_value;
- if (is_valid_pin) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_DAMPING, damping);
- }
-
- } else if ("joint_constraints/impulse_clamp" == p_name) {
- impulse_clamp = p_value;
- if (is_valid_pin) {
- PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp);
- }
-
- } else {
- return false;
- }
-
- return true;
-}
-
-bool PhysicalBone3D::PinJointData::_get(const StringName &p_name, Variant &r_ret) const {
- if (JointData::_get(p_name, r_ret)) {
- return true;
- }
-
- if ("joint_constraints/bias" == p_name) {
- r_ret = bias;
- } else if ("joint_constraints/damping" == p_name) {
- r_ret = damping;
- } else if ("joint_constraints/impulse_clamp" == p_name) {
- r_ret = impulse_clamp;
- } else {
- return false;
- }
-
- return true;
-}
-
-void PhysicalBone3D::PinJointData::_get_property_list(List<PropertyInfo> *p_list) const {
- JointData::_get_property_list(p_list);
-
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/bias"), PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/damping"), PROPERTY_HINT_RANGE, "0.01,8.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/impulse_clamp"), PROPERTY_HINT_RANGE, "0.0,64.0,0.01"));
-}
-
-bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- if (JointData::_set(p_name, p_value, j)) {
- return true;
- }
-
- bool is_valid_cone = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_CONE_TWIST;
- if ("joint_constraints/swing_span" == p_name) {
- swing_span = Math::deg_to_rad(real_t(p_value));
- if (is_valid_cone) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span);
- }
-
- } else if ("joint_constraints/twist_span" == p_name) {
- twist_span = Math::deg_to_rad(real_t(p_value));
- if (is_valid_cone) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span);
- }
-
- } else if ("joint_constraints/bias" == p_name) {
- bias = p_value;
- if (is_valid_cone) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, bias);
- }
-
- } else if ("joint_constraints/softness" == p_name) {
- softness = p_value;
- if (is_valid_cone) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, softness);
- }
-
- } else if ("joint_constraints/relaxation" == p_name) {
- relaxation = p_value;
- if (is_valid_cone) {
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, relaxation);
- }
-
- } else {
- return false;
- }
-
- return true;
-}
-
-bool PhysicalBone3D::ConeJointData::_get(const StringName &p_name, Variant &r_ret) const {
- if (JointData::_get(p_name, r_ret)) {
- return true;
- }
-
- if ("joint_constraints/swing_span" == p_name) {
- r_ret = Math::rad_to_deg(swing_span);
- } else if ("joint_constraints/twist_span" == p_name) {
- r_ret = Math::rad_to_deg(twist_span);
- } else if ("joint_constraints/bias" == p_name) {
- r_ret = bias;
- } else if ("joint_constraints/softness" == p_name) {
- r_ret = softness;
- } else if ("joint_constraints/relaxation" == p_name) {
- r_ret = relaxation;
- } else {
- return false;
- }
-
- return true;
-}
-
-void PhysicalBone3D::ConeJointData::_get_property_list(List<PropertyInfo> *p_list) const {
- JointData::_get_property_list(p_list);
-
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/swing_span"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/twist_span"), PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_less,or_greater"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/bias"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/relaxation"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
-}
-
-bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- if (JointData::_set(p_name, p_value, j)) {
- return true;
- }
-
- bool is_valid_hinge = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_HINGE;
- if ("joint_constraints/angular_limit_enabled" == p_name) {
- angular_limit_enabled = p_value;
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled);
- }
-
- } else if ("joint_constraints/angular_limit_upper" == p_name) {
- angular_limit_upper = Math::deg_to_rad(real_t(p_value));
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper);
- }
-
- } else if ("joint_constraints/angular_limit_lower" == p_name) {
- angular_limit_lower = Math::deg_to_rad(real_t(p_value));
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower);
- }
-
- } else if ("joint_constraints/angular_limit_bias" == p_name) {
- angular_limit_bias = p_value;
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias);
- }
-
- } else if ("joint_constraints/angular_limit_softness" == p_name) {
- angular_limit_softness = p_value;
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness);
- }
-
- } else if ("joint_constraints/angular_limit_relaxation" == p_name) {
- angular_limit_relaxation = p_value;
- if (is_valid_hinge) {
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation);
- }
-
- } else {
- return false;
- }
-
- return true;
-}
-
-bool PhysicalBone3D::HingeJointData::_get(const StringName &p_name, Variant &r_ret) const {
- if (JointData::_get(p_name, r_ret)) {
- return true;
- }
-
- if ("joint_constraints/angular_limit_enabled" == p_name) {
- r_ret = angular_limit_enabled;
- } else if ("joint_constraints/angular_limit_upper" == p_name) {
- r_ret = Math::rad_to_deg(angular_limit_upper);
- } else if ("joint_constraints/angular_limit_lower" == p_name) {
- r_ret = Math::rad_to_deg(angular_limit_lower);
- } else if ("joint_constraints/angular_limit_bias" == p_name) {
- r_ret = angular_limit_bias;
- } else if ("joint_constraints/angular_limit_softness" == p_name) {
- r_ret = angular_limit_softness;
- } else if ("joint_constraints/angular_limit_relaxation" == p_name) {
- r_ret = angular_limit_relaxation;
- } else {
- return false;
- }
-
- return true;
-}
-
-void PhysicalBone3D::HingeJointData::_get_property_list(List<PropertyInfo> *p_list) const {
- JointData::_get_property_list(p_list);
-
- p_list->push_back(PropertyInfo(Variant::BOOL, PNAME("joint_constraints/angular_limit_enabled")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_bias"), PROPERTY_HINT_RANGE, "0.01,0.99,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_relaxation"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
-}
-
-bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- if (JointData::_set(p_name, p_value, j)) {
- return true;
- }
-
- bool is_valid_slider = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_SLIDER;
- if ("joint_constraints/linear_limit_upper" == p_name) {
- linear_limit_upper = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper);
- }
-
- } else if ("joint_constraints/linear_limit_lower" == p_name) {
- linear_limit_lower = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower);
- }
-
- } else if ("joint_constraints/linear_limit_softness" == p_name) {
- linear_limit_softness = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness);
- }
-
- } else if ("joint_constraints/linear_limit_restitution" == p_name) {
- linear_limit_restitution = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution);
- }
-
- } else if ("joint_constraints/linear_limit_damping" == p_name) {
- linear_limit_damping = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution);
- }
-
- } else if ("joint_constraints/angular_limit_upper" == p_name) {
- angular_limit_upper = Math::deg_to_rad(real_t(p_value));
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper);
- }
-
- } else if ("joint_constraints/angular_limit_lower" == p_name) {
- angular_limit_lower = Math::deg_to_rad(real_t(p_value));
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower);
- }
-
- } else if ("joint_constraints/angular_limit_softness" == p_name) {
- angular_limit_softness = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
- }
-
- } else if ("joint_constraints/angular_limit_restitution" == p_name) {
- angular_limit_restitution = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness);
- }
-
- } else if ("joint_constraints/angular_limit_damping" == p_name) {
- angular_limit_damping = p_value;
- if (is_valid_slider) {
- PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping);
- }
-
- } else {
- return false;
- }
-
- return true;
-}
-
-bool PhysicalBone3D::SliderJointData::_get(const StringName &p_name, Variant &r_ret) const {
- if (JointData::_get(p_name, r_ret)) {
- return true;
- }
-
- if ("joint_constraints/linear_limit_upper" == p_name) {
- r_ret = linear_limit_upper;
- } else if ("joint_constraints/linear_limit_lower" == p_name) {
- r_ret = linear_limit_lower;
- } else if ("joint_constraints/linear_limit_softness" == p_name) {
- r_ret = linear_limit_softness;
- } else if ("joint_constraints/linear_limit_restitution" == p_name) {
- r_ret = linear_limit_restitution;
- } else if ("joint_constraints/linear_limit_damping" == p_name) {
- r_ret = linear_limit_damping;
- } else if ("joint_constraints/angular_limit_upper" == p_name) {
- r_ret = Math::rad_to_deg(angular_limit_upper);
- } else if ("joint_constraints/angular_limit_lower" == p_name) {
- r_ret = Math::rad_to_deg(angular_limit_lower);
- } else if ("joint_constraints/angular_limit_softness" == p_name) {
- r_ret = angular_limit_softness;
- } else if ("joint_constraints/angular_limit_restitution" == p_name) {
- r_ret = angular_limit_restitution;
- } else if ("joint_constraints/angular_limit_damping" == p_name) {
- r_ret = angular_limit_damping;
- } else {
- return false;
- }
-
- return true;
-}
-
-void PhysicalBone3D::SliderJointData::_get_property_list(List<PropertyInfo> *p_list) const {
- JointData::_get_property_list(p_list);
-
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_upper")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_lower")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_restitution"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/linear_limit_damping"), PROPERTY_HINT_RANGE, "0,16.0,0.01"));
-
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_restitution"), PROPERTY_HINT_RANGE, "0.01,16.0,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("joint_constraints/angular_limit_damping"), PROPERTY_HINT_RANGE, "0,16.0,0.01"));
-}
-
-bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Variant &p_value, RID j) {
- if (JointData::_set(p_name, p_value, j)) {
- return true;
- }
-
- String path = p_name;
-
- if (!path.begins_with("joint_constraints/")) {
- return false;
- }
-
- Vector3::Axis axis;
- {
- const String axis_s = path.get_slicec('/', 1);
- if ("x" == axis_s) {
- axis = Vector3::AXIS_X;
- } else if ("y" == axis_s) {
- axis = Vector3::AXIS_Y;
- } else if ("z" == axis_s) {
- axis = Vector3::AXIS_Z;
- } else {
- return false;
- }
- }
-
- String var_name = path.get_slicec('/', 2);
- bool is_valid_6dof = j.is_valid() && PhysicsServer3D::get_singleton()->joint_get_type(j) == PhysicsServer3D::JOINT_TYPE_6DOF;
- if ("linear_limit_enabled" == var_name) {
- axis_data[axis].linear_limit_enabled = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled);
- }
-
- } else if ("linear_limit_upper" == var_name) {
- axis_data[axis].linear_limit_upper = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper);
- }
-
- } else if ("linear_limit_lower" == var_name) {
- axis_data[axis].linear_limit_lower = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower);
- }
-
- } else if ("linear_limit_softness" == var_name) {
- axis_data[axis].linear_limit_softness = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
- }
-
- } else if ("linear_spring_enabled" == var_name) {
- axis_data[axis].linear_spring_enabled = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
- }
-
- } else if ("linear_spring_stiffness" == var_name) {
- axis_data[axis].linear_spring_stiffness = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
- }
-
- } else if ("linear_spring_damping" == var_name) {
- axis_data[axis].linear_spring_damping = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
- }
-
- } else if ("linear_equilibrium_point" == var_name) {
- axis_data[axis].linear_equilibrium_point = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
- }
-
- } else if ("linear_restitution" == var_name) {
- axis_data[axis].linear_restitution = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution);
- }
-
- } else if ("linear_damping" == var_name) {
- axis_data[axis].linear_damping = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping);
- }
-
- } else if ("angular_limit_enabled" == var_name) {
- axis_data[axis].angular_limit_enabled = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled);
- }
-
- } else if ("angular_limit_upper" == var_name) {
- axis_data[axis].angular_limit_upper = Math::deg_to_rad(real_t(p_value));
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper);
- }
-
- } else if ("angular_limit_lower" == var_name) {
- axis_data[axis].angular_limit_lower = Math::deg_to_rad(real_t(p_value));
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower);
- }
-
- } else if ("angular_limit_softness" == var_name) {
- axis_data[axis].angular_limit_softness = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness);
- }
-
- } else if ("angular_restitution" == var_name) {
- axis_data[axis].angular_restitution = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution);
- }
-
- } else if ("angular_damping" == var_name) {
- axis_data[axis].angular_damping = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping);
- }
-
- } else if ("erp" == var_name) {
- axis_data[axis].erp = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
- }
-
- } else if ("angular_spring_enabled" == var_name) {
- axis_data[axis].angular_spring_enabled = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
- }
-
- } else if ("angular_spring_stiffness" == var_name) {
- axis_data[axis].angular_spring_stiffness = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
- }
-
- } else if ("angular_spring_damping" == var_name) {
- axis_data[axis].angular_spring_damping = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
- }
-
- } else if ("angular_equilibrium_point" == var_name) {
- axis_data[axis].angular_equilibrium_point = p_value;
- if (is_valid_6dof) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
- }
-
- } else {
- return false;
- }
-
- return true;
-}
-
-bool PhysicalBone3D::SixDOFJointData::_get(const StringName &p_name, Variant &r_ret) const {
- if (JointData::_get(p_name, r_ret)) {
- return true;
- }
-
- String path = p_name;
-
- if (!path.begins_with("joint_constraints/")) {
- return false;
- }
-
- int axis;
- {
- const String axis_s = path.get_slicec('/', 1);
- if ("x" == axis_s) {
- axis = 0;
- } else if ("y" == axis_s) {
- axis = 1;
- } else if ("z" == axis_s) {
- axis = 2;
- } else {
- return false;
- }
- }
-
- String var_name = path.get_slicec('/', 2);
-
- if ("linear_limit_enabled" == var_name) {
- r_ret = axis_data[axis].linear_limit_enabled;
- } else if ("linear_limit_upper" == var_name) {
- r_ret = axis_data[axis].linear_limit_upper;
- } else if ("linear_limit_lower" == var_name) {
- r_ret = axis_data[axis].linear_limit_lower;
- } else if ("linear_limit_softness" == var_name) {
- r_ret = axis_data[axis].linear_limit_softness;
- } else if ("linear_spring_enabled" == var_name) {
- r_ret = axis_data[axis].linear_spring_enabled;
- } else if ("linear_spring_stiffness" == var_name) {
- r_ret = axis_data[axis].linear_spring_stiffness;
- } else if ("linear_spring_damping" == var_name) {
- r_ret = axis_data[axis].linear_spring_damping;
- } else if ("linear_equilibrium_point" == var_name) {
- r_ret = axis_data[axis].linear_equilibrium_point;
- } else if ("linear_restitution" == var_name) {
- r_ret = axis_data[axis].linear_restitution;
- } else if ("linear_damping" == var_name) {
- r_ret = axis_data[axis].linear_damping;
- } else if ("angular_limit_enabled" == var_name) {
- r_ret = axis_data[axis].angular_limit_enabled;
- } else if ("angular_limit_upper" == var_name) {
- r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_upper);
- } else if ("angular_limit_lower" == var_name) {
- r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_lower);
- } else if ("angular_limit_softness" == var_name) {
- r_ret = axis_data[axis].angular_limit_softness;
- } else if ("angular_restitution" == var_name) {
- r_ret = axis_data[axis].angular_restitution;
- } else if ("angular_damping" == var_name) {
- r_ret = axis_data[axis].angular_damping;
- } else if ("erp" == var_name) {
- r_ret = axis_data[axis].erp;
- } else if ("angular_spring_enabled" == var_name) {
- r_ret = axis_data[axis].angular_spring_enabled;
- } else if ("angular_spring_stiffness" == var_name) {
- r_ret = axis_data[axis].angular_spring_stiffness;
- } else if ("angular_spring_damping" == var_name) {
- r_ret = axis_data[axis].angular_spring_damping;
- } else if ("angular_equilibrium_point" == var_name) {
- r_ret = axis_data[axis].angular_equilibrium_point;
- } else {
- return false;
- }
-
- return true;
-}
-
-void PhysicalBone3D::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_list) const {
- const StringName axis_names[] = { PNAME("x"), PNAME("y"), PNAME("z") };
- for (int i = 0; i < 3; ++i) {
- const String prefix = vformat("%s/%s/", PNAME("joint_constraints"), axis_names[i]);
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("linear_limit_enabled")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_upper")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_lower")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("linear_spring_enabled")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_spring_stiffness")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_spring_damping")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_equilibrium_point")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_restitution"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("linear_damping"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("angular_limit_enabled")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_upper"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_lower"), PROPERTY_HINT_RANGE, "-180,180,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_limit_softness"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_restitution"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_damping"), PROPERTY_HINT_RANGE, "0.01,16,0.01"));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("erp")));
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix + PNAME("angular_spring_enabled")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_spring_stiffness")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_spring_damping")));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + PNAME("angular_equilibrium_point")));
- }
-}
-
-bool PhysicalBone3D::_set(const StringName &p_name, const Variant &p_value) {
- if (p_name == "bone_name") {
- set_bone_name(p_value);
- return true;
- }
-
- if (joint_data) {
- if (joint_data->_set(p_name, p_value, joint)) {
-#ifdef TOOLS_ENABLED
- update_gizmos();
-#endif
- return true;
- }
- }
-
- return false;
-}
-
-bool PhysicalBone3D::_get(const StringName &p_name, Variant &r_ret) const {
- if (p_name == "bone_name") {
- r_ret = get_bone_name();
- return true;
- }
-
- if (joint_data) {
- return joint_data->_get(p_name, r_ret);
- }
-
- return false;
-}
-
-void PhysicalBone3D::_get_property_list(List<PropertyInfo> *p_list) const {
- Skeleton3D *parent = find_skeleton_parent(get_parent());
-
- if (parent) {
- String names;
- for (int i = 0; i < parent->get_bone_count(); i++) {
- if (i > 0) {
- names += ",";
- }
- names += parent->get_bone_name(i);
- }
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name"), PROPERTY_HINT_ENUM, names));
- } else {
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name")));
- }
-
- if (joint_data) {
- joint_data->_get_property_list(p_list);
- }
-}
-
-void PhysicalBone3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
- parent_skeleton = find_skeleton_parent(get_parent());
- update_bone_id();
- reset_to_rest_position();
- reset_physics_simulation_state();
- if (joint_data) {
- _reload_joint();
- }
- break;
-
- case NOTIFICATION_EXIT_TREE: {
- if (parent_skeleton) {
- if (-1 != bone_id) {
- parent_skeleton->unbind_physical_bone_from_bone(bone_id);
- bone_id = -1;
- }
- }
- parent_skeleton = nullptr;
- PhysicsServer3D::get_singleton()->joint_clear(joint);
- } break;
-
- case NOTIFICATION_TRANSFORM_CHANGED: {
- if (Engine::get_singleton()->is_editor_hint()) {
- update_offset();
- }
- } break;
- }
-}
-
-void PhysicalBone3D::_sync_body_state(PhysicsDirectBodyState3D *p_state) {
- set_ignore_transform_notification(true);
- set_global_transform(p_state->get_transform());
- set_ignore_transform_notification(false);
-
- linear_velocity = p_state->get_linear_velocity();
- angular_velocity = p_state->get_angular_velocity();
-}
-
-void PhysicalBone3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
- if (!simulate_physics || !_internal_simulate_physics) {
- return;
- }
-
- if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
- _sync_body_state(p_state);
-
- Transform3D old_transform = get_global_transform();
- GDVIRTUAL_CALL(_integrate_forces, p_state);
- Transform3D new_transform = get_global_transform();
-
- if (new_transform != old_transform) {
- // Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
- }
- }
-
- _sync_body_state(p_state);
- _on_transform_changed();
-
- Transform3D global_transform(p_state->get_transform());
-
- // Update skeleton
- if (parent_skeleton) {
- if (-1 != bone_id) {
- parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1.0, true);
- }
- }
-}
-
-void PhysicalBone3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse);
- ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3());
-
- ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone3D::set_joint_type);
- ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone3D::get_joint_type);
-
- ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone3D::set_joint_offset);
- ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone3D::get_joint_offset);
- ClassDB::bind_method(D_METHOD("set_joint_rotation", "euler"), &PhysicalBone3D::set_joint_rotation);
- ClassDB::bind_method(D_METHOD("get_joint_rotation"), &PhysicalBone3D::get_joint_rotation);
-
- ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone3D::set_body_offset);
- ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone3D::get_body_offset);
-
- ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone3D::get_simulate_physics);
-
- ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone3D::is_simulating_physics);
-
- ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone3D::get_bone_id);
-
- ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone3D::set_mass);
- ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone3D::get_mass);
-
- ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone3D::set_friction);
- ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone3D::get_friction);
-
- ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &PhysicalBone3D::set_bounce);
- ClassDB::bind_method(D_METHOD("get_bounce"), &PhysicalBone3D::get_bounce);
-
- ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone3D::set_gravity_scale);
- ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone3D::get_gravity_scale);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &PhysicalBone3D::set_linear_damp_mode);
- ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &PhysicalBone3D::get_linear_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &PhysicalBone3D::set_angular_damp_mode);
- ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &PhysicalBone3D::get_angular_damp_mode);
-
- ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &PhysicalBone3D::set_linear_damp);
- ClassDB::bind_method(D_METHOD("get_linear_damp"), &PhysicalBone3D::get_linear_damp);
-
- ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &PhysicalBone3D::set_angular_damp);
- ClassDB::bind_method(D_METHOD("get_angular_damp"), &PhysicalBone3D::get_angular_damp);
-
- ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &PhysicalBone3D::set_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicalBone3D::get_linear_velocity);
-
- ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &PhysicalBone3D::set_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_angular_velocity"), &PhysicalBone3D::get_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &PhysicalBone3D::set_use_custom_integrator);
- ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &PhysicalBone3D::is_using_custom_integrator);
-
- ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &PhysicalBone3D::set_can_sleep);
- ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &PhysicalBone3D::is_able_to_sleep);
-
- GDVIRTUAL_BIND(_integrate_forces, "state");
-
- ADD_GROUP("Joint", "joint_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "joint_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_joint_offset", "get_joint_offset");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_RANGE, "-360,360,0.01,or_less,or_greater,radians_as_degrees"), "set_joint_rotation", "get_joint_rotation");
-
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_body_offset", "get_body_offset");
-
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity", PROPERTY_HINT_NONE, "suffix:m/s"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
-
- BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
- BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
-
- BIND_ENUM_CONSTANT(JOINT_TYPE_NONE);
- BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
- BIND_ENUM_CONSTANT(JOINT_TYPE_CONE);
- BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE);
- BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER);
- BIND_ENUM_CONSTANT(JOINT_TYPE_6DOF);
-}
-
-Skeleton3D *PhysicalBone3D::find_skeleton_parent(Node *p_parent) {
- if (!p_parent) {
- return nullptr;
- }
- Skeleton3D *s = Object::cast_to<Skeleton3D>(p_parent);
- return s ? s : find_skeleton_parent(p_parent->get_parent());
-}
-
-void PhysicalBone3D::_update_joint_offset() {
- _fix_joint_offset();
-
- set_ignore_transform_notification(true);
- reset_to_rest_position();
- set_ignore_transform_notification(false);
-
-#ifdef TOOLS_ENABLED
- update_gizmos();
-#endif
-}
-
-void PhysicalBone3D::_fix_joint_offset() {
- // Clamp joint origin to bone origin
- if (parent_skeleton) {
- joint_offset.origin = body_offset.affine_inverse().origin;
- }
-}
-
-void PhysicalBone3D::_reload_joint() {
- if (!parent_skeleton) {
- PhysicsServer3D::get_singleton()->joint_clear(joint);
- return;
- }
-
- PhysicalBone3D *body_a = parent_skeleton->get_physical_bone_parent(bone_id);
- if (!body_a) {
- PhysicsServer3D::get_singleton()->joint_clear(joint);
- return;
- }
-
- Transform3D joint_transf = get_global_transform() * joint_offset;
- Transform3D local_a = body_a->get_global_transform().affine_inverse() * joint_transf;
- local_a.orthonormalize();
-
- switch (get_joint_type()) {
- case JOINT_TYPE_PIN: {
- PhysicsServer3D::get_singleton()->joint_make_pin(joint, body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin);
- const PinJointData *pjd(static_cast<const PinJointData *>(joint_data));
- PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias);
- PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping);
- PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp);
-
- } break;
- case JOINT_TYPE_CONE: {
- PhysicsServer3D::get_singleton()->joint_make_cone_twist(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
- const ConeJointData *cjd(static_cast<const ConeJointData *>(joint_data));
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span);
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span);
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, cjd->bias);
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, cjd->softness);
- PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation);
-
- } break;
- case JOINT_TYPE_HINGE: {
- PhysicsServer3D::get_singleton()->joint_make_hinge(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
- const HingeJointData *hjd(static_cast<const HingeJointData *>(joint_data));
- PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled);
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper);
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower);
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias);
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness);
- PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation);
-
- } break;
- case JOINT_TYPE_SLIDER: {
- PhysicsServer3D::get_singleton()->joint_make_slider(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
- const SliderJointData *sjd(static_cast<const SliderJointData *>(joint_data));
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness);
- PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping);
-
- } break;
- case JOINT_TYPE_6DOF: {
- PhysicsServer3D::get_singleton()->joint_make_generic_6dof(joint, body_a->get_rid(), local_a, get_rid(), joint_offset);
- const SixDOFJointData *g6dofjd(static_cast<const SixDOFJointData *>(joint_data));
- for (int axis = 0; axis < 3; ++axis) {
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping);
- PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point);
- }
-
- } break;
- case JOINT_TYPE_NONE: {
- } break;
- }
-}
-
-void PhysicalBone3D::_on_bone_parent_changed() {
- _reload_joint();
-}
-
-#ifdef TOOLS_ENABLED
-void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) {
- gizmo_move_joint = p_move_joint;
-}
-
-Transform3D PhysicalBone3D::get_global_gizmo_transform() const {
- return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform();
-}
-
-Transform3D PhysicalBone3D::get_local_gizmo_transform() const {
- return gizmo_move_joint ? get_transform() * joint_offset : get_transform();
-}
-#endif
-
-const PhysicalBone3D::JointData *PhysicalBone3D::get_joint_data() const {
- return joint_data;
-}
-
-Skeleton3D *PhysicalBone3D::find_skeleton_parent() {
- return find_skeleton_parent(this);
-}
-
-void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
- if (p_joint_type == get_joint_type()) {
- return;
- }
-
- if (joint_data) {
- memdelete(joint_data);
- }
- joint_data = nullptr;
- switch (p_joint_type) {
- case JOINT_TYPE_PIN:
- joint_data = memnew(PinJointData);
- break;
- case JOINT_TYPE_CONE:
- joint_data = memnew(ConeJointData);
- break;
- case JOINT_TYPE_HINGE:
- joint_data = memnew(HingeJointData);
- break;
- case JOINT_TYPE_SLIDER:
- joint_data = memnew(SliderJointData);
- break;
- case JOINT_TYPE_6DOF:
- joint_data = memnew(SixDOFJointData);
- break;
- case JOINT_TYPE_NONE:
- break;
- }
-
- _reload_joint();
-
-#ifdef TOOLS_ENABLED
- notify_property_list_changed();
- update_gizmos();
-#endif
-}
-
-PhysicalBone3D::JointType PhysicalBone3D::get_joint_type() const {
- return joint_data ? joint_data->get_joint_type() : JOINT_TYPE_NONE;
-}
-
-void PhysicalBone3D::set_joint_offset(const Transform3D &p_offset) {
- joint_offset = p_offset;
-
- _update_joint_offset();
-}
-
-const Transform3D &PhysicalBone3D::get_joint_offset() const {
- return joint_offset;
-}
-
-void PhysicalBone3D::set_joint_rotation(const Vector3 &p_euler_rad) {
- joint_offset.basis.set_euler_scale(p_euler_rad, joint_offset.basis.get_scale());
-
- _update_joint_offset();
-}
-
-Vector3 PhysicalBone3D::get_joint_rotation() const {
- return joint_offset.basis.get_euler_normalized();
-}
-
-const Transform3D &PhysicalBone3D::get_body_offset() const {
- return body_offset;
-}
-
-void PhysicalBone3D::set_body_offset(const Transform3D &p_offset) {
- body_offset = p_offset;
- body_offset_inverse = body_offset.affine_inverse();
-
- _update_joint_offset();
-}
-
-void PhysicalBone3D::set_simulate_physics(bool p_simulate) {
- if (simulate_physics == p_simulate) {
- return;
- }
-
- simulate_physics = p_simulate;
- reset_physics_simulation_state();
-}
-
-bool PhysicalBone3D::get_simulate_physics() {
- return simulate_physics;
-}
-
-bool PhysicalBone3D::is_simulating_physics() {
- return _internal_simulate_physics;
-}
-
-void PhysicalBone3D::set_bone_name(const String &p_name) {
- bone_name = p_name;
- bone_id = -1;
-
- update_bone_id();
- reset_to_rest_position();
-}
-
-const String &PhysicalBone3D::get_bone_name() const {
- return bone_name;
-}
-
-void PhysicalBone3D::set_mass(real_t p_mass) {
- ERR_FAIL_COND(p_mass <= 0);
- mass = p_mass;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass);
-}
-
-real_t PhysicalBone3D::get_mass() const {
- return mass;
-}
-
-void PhysicalBone3D::set_friction(real_t p_friction) {
- ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
-
- friction = p_friction;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, friction);
-}
-
-real_t PhysicalBone3D::get_friction() const {
- return friction;
-}
-
-void PhysicalBone3D::set_bounce(real_t p_bounce) {
- ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
-
- bounce = p_bounce;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, bounce);
-}
-
-real_t PhysicalBone3D::get_bounce() const {
- return bounce;
-}
-
-void PhysicalBone3D::set_gravity_scale(real_t p_gravity_scale) {
- gravity_scale = p_gravity_scale;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
-}
-
-real_t PhysicalBone3D::get_gravity_scale() const {
- return gravity_scale;
-}
-
-void PhysicalBone3D::set_linear_damp_mode(DampMode p_mode) {
- linear_damp_mode = p_mode;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
-}
-
-PhysicalBone3D::DampMode PhysicalBone3D::get_linear_damp_mode() const {
- return linear_damp_mode;
-}
-
-void PhysicalBone3D::set_angular_damp_mode(DampMode p_mode) {
- angular_damp_mode = p_mode;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
-}
-
-PhysicalBone3D::DampMode PhysicalBone3D::get_angular_damp_mode() const {
- return angular_damp_mode;
-}
-
-void PhysicalBone3D::set_linear_damp(real_t p_linear_damp) {
- ERR_FAIL_COND(p_linear_damp < 0);
-
- linear_damp = p_linear_damp;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
-}
-
-real_t PhysicalBone3D::get_linear_damp() const {
- return linear_damp;
-}
-
-void PhysicalBone3D::set_angular_damp(real_t p_angular_damp) {
- ERR_FAIL_COND(p_angular_damp < 0);
-
- angular_damp = p_angular_damp;
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
-}
-
-real_t PhysicalBone3D::get_angular_damp() const {
- return angular_damp;
-}
-
-void PhysicalBone3D::set_can_sleep(bool p_active) {
- can_sleep = p_active;
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active);
-}
-
-bool PhysicalBone3D::is_able_to_sleep() const {
- return can_sleep;
-}
-
-PhysicalBone3D::PhysicalBone3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
- joint = PhysicsServer3D::get_singleton()->joint_create();
- reset_physics_simulation_state();
-}
-
-PhysicalBone3D::~PhysicalBone3D() {
- if (joint_data) {
- memdelete(joint_data);
- }
- ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
- PhysicsServer3D::get_singleton()->free(joint);
-}
-
-void PhysicalBone3D::update_bone_id() {
- if (!parent_skeleton) {
- return;
- }
-
- const int new_bone_id = parent_skeleton->find_bone(bone_name);
-
- if (new_bone_id != bone_id) {
- if (-1 != bone_id) {
- // Assert the unbind from old node
- parent_skeleton->unbind_physical_bone_from_bone(bone_id);
- }
-
- bone_id = new_bone_id;
-
- parent_skeleton->bind_physical_bone_to_bone(bone_id, this);
-
- _fix_joint_offset();
- reset_physics_simulation_state();
- }
-}
-
-void PhysicalBone3D::update_offset() {
-#ifdef TOOLS_ENABLED
- if (parent_skeleton) {
- Transform3D bone_transform(parent_skeleton->get_global_transform());
- if (-1 != bone_id) {
- bone_transform *= parent_skeleton->get_bone_global_pose(bone_id);
- }
-
- if (gizmo_move_joint) {
- bone_transform *= body_offset;
- set_joint_offset(bone_transform.affine_inverse() * get_global_transform());
- } else {
- set_body_offset(bone_transform.affine_inverse() * get_global_transform());
- }
- }
-#endif
-}
-
-void PhysicalBone3D::_start_physics_simulation() {
- if (_internal_simulate_physics || !parent_skeleton) {
- return;
- }
- reset_to_rest_position();
- set_body_mode(PhysicsServer3D::BODY_MODE_RIGID);
- PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
- PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
- PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_body_state_changed));
- set_as_top_level(true);
- _internal_simulate_physics = true;
-}
-
-void PhysicalBone3D::_stop_physics_simulation() {
- if (!parent_skeleton) {
- return;
- }
- if (parent_skeleton->get_animate_physical_bones()) {
- set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
- PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
- PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
- PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());
- } else {
- set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
- PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0);
- PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
- PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), 1.0);
- }
- if (_internal_simulate_physics) {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
- parent_skeleton->set_bone_global_pose_override(bone_id, Transform3D(), 0.0, false);
- set_as_top_level(false);
- _internal_simulate_physics = false;
- }
-}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
deleted file mode 100644
index b84b7c4f02..0000000000
--- a/scene/3d/physics_body_3d.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/**************************************************************************/
-/* physics_body_3d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef PHYSICS_BODY_3D_H
-#define PHYSICS_BODY_3D_H
-
-#include "core/templates/vset.h"
-#include "scene/3d/collision_object_3d.h"
-#include "scene/resources/physics_material.h"
-#include "servers/physics_server_3d.h"
-#include "skeleton_3d.h"
-
-class KinematicCollision3D;
-
-class PhysicsBody3D : public CollisionObject3D {
- GDCLASS(PhysicsBody3D, CollisionObject3D);
-
-protected:
- static void _bind_methods();
- PhysicsBody3D(PhysicsServer3D::BodyMode p_mode);
-
- Ref<KinematicCollision3D> motion_cache;
-
- uint16_t locked_axis = 0;
-
- Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
-
-public:
- bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
- Vector3 get_gravity() const;
-
- void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
- bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
-
- virtual Vector3 get_linear_velocity() const;
- virtual Vector3 get_angular_velocity() const;
- virtual real_t get_inverse_mass() const;
-
- TypedArray<PhysicsBody3D> get_collision_exceptions();
- void add_collision_exception_with(Node *p_node); //must be physicsbody
- void remove_collision_exception_with(Node *p_node);
-
- virtual ~PhysicsBody3D();
-};
-
-class StaticBody3D : public PhysicsBody3D {
- GDCLASS(StaticBody3D, PhysicsBody3D);
-
-private:
- Vector3 constant_linear_velocity;
- Vector3 constant_angular_velocity;
-
- Ref<PhysicsMaterial> physics_material_override;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
- Ref<PhysicsMaterial> get_physics_material_override() const;
-
- void set_constant_linear_velocity(const Vector3 &p_vel);
- void set_constant_angular_velocity(const Vector3 &p_vel);
-
- Vector3 get_constant_linear_velocity() const;
- Vector3 get_constant_angular_velocity() const;
-
- StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC);
-
-private:
- void _reload_physics_characteristics();
-};
-
-class AnimatableBody3D : public StaticBody3D {
- GDCLASS(AnimatableBody3D, StaticBody3D);
-
-private:
- Vector3 linear_velocity;
- Vector3 angular_velocity;
-
- bool sync_to_physics = true;
-
- Transform3D last_valid_transform;
-
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
- void _body_state_changed(PhysicsDirectBodyState3D *p_state);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- virtual Vector3 get_linear_velocity() const override;
- virtual Vector3 get_angular_velocity() const override;
-
- AnimatableBody3D();
-
-private:
- void _update_kinematic_motion();
-
- void set_sync_to_physics(bool p_enable);
- bool is_sync_to_physics_enabled() const;
-};
-
-class RigidBody3D : public PhysicsBody3D {
- GDCLASS(RigidBody3D, PhysicsBody3D);
-
-public:
- enum FreezeMode {
- FREEZE_MODE_STATIC,
- FREEZE_MODE_KINEMATIC,
- };
-
- enum CenterOfMassMode {
- CENTER_OF_MASS_MODE_AUTO,
- CENTER_OF_MASS_MODE_CUSTOM,
- };
-
- enum DampMode {
- DAMP_MODE_COMBINE,
- DAMP_MODE_REPLACE,
- };
-
-private:
- bool can_sleep = true;
- bool lock_rotation = false;
- bool freeze = false;
- FreezeMode freeze_mode = FREEZE_MODE_STATIC;
-
- real_t mass = 1.0;
- Vector3 inertia;
- CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
- Vector3 center_of_mass;
-
- Ref<PhysicsMaterial> physics_material_override;
-
- Vector3 linear_velocity;
- Vector3 angular_velocity;
- Basis inverse_inertia_tensor;
- real_t gravity_scale = 1.0;
-
- DampMode linear_damp_mode = DAMP_MODE_COMBINE;
- DampMode angular_damp_mode = DAMP_MODE_COMBINE;
-
- real_t linear_damp = 0.0;
- real_t angular_damp = 0.0;
-
- bool sleeping = false;
- bool ccd = false;
-
- int max_contacts_reported = 0;
- int contact_count = 0;
-
- bool custom_integrator = false;
-
- struct ShapePair {
- int body_shape = 0;
- int local_shape = 0;
- bool tagged = false;
- bool operator<(const ShapePair &p_sp) const {
- if (body_shape == p_sp.body_shape) {
- return local_shape < p_sp.local_shape;
- } else {
- return body_shape < p_sp.body_shape;
- }
- }
-
- ShapePair() {}
- ShapePair(int p_bs, int p_ls) {
- body_shape = p_bs;
- local_shape = p_ls;
- tagged = false;
- }
- };
- struct RigidBody3D_RemoveAction {
- RID rid;
- ObjectID body_id;
- ShapePair pair;
- };
- struct BodyState {
- RID rid;
- //int rc;
- bool in_tree = false;
- VSet<ShapePair> shapes;
- };
-
- struct ContactMonitor {
- bool locked = false;
- HashMap<ObjectID, BodyState> body_map;
- };
-
- ContactMonitor *contact_monitor = nullptr;
- void _body_enter_tree(ObjectID p_id);
- void _body_exit_tree(ObjectID p_id);
-
- void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape);
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
-
- void _sync_body_state(PhysicsDirectBodyState3D *p_state);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
- void _validate_property(PropertyInfo &p_property) const;
-
- GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *)
-
- virtual void _body_state_changed(PhysicsDirectBodyState3D *p_state);
-
- void _apply_body_mode();
-
-public:
- void set_lock_rotation_enabled(bool p_lock_rotation);
- bool is_lock_rotation_enabled() const;
-
- void set_freeze_enabled(bool p_freeze);
- bool is_freeze_enabled() const;
-
- void set_freeze_mode(FreezeMode p_freeze_mode);
- FreezeMode get_freeze_mode() const;
-
- void set_mass(real_t p_mass);
- real_t get_mass() const;
-
- virtual real_t get_inverse_mass() const override { return 1.0 / mass; }
-
- void set_inertia(const Vector3 &p_inertia);
- const Vector3 &get_inertia() const;
-
- void set_center_of_mass_mode(CenterOfMassMode p_mode);
- CenterOfMassMode get_center_of_mass_mode() const;
-
- void set_center_of_mass(const Vector3 &p_center_of_mass);
- const Vector3 &get_center_of_mass() const;
-
- void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
- Ref<PhysicsMaterial> get_physics_material_override() const;
-
- void set_linear_velocity(const Vector3 &p_velocity);
- Vector3 get_linear_velocity() const override;
-
- void set_axis_velocity(const Vector3 &p_axis);
-
- void set_angular_velocity(const Vector3 &p_velocity);
- Vector3 get_angular_velocity() const override;
-
- Basis get_inverse_inertia_tensor() const;
-
- void set_gravity_scale(real_t p_gravity_scale);
- real_t get_gravity_scale() const;
-
- void set_linear_damp_mode(DampMode p_mode);
- DampMode get_linear_damp_mode() const;
-
- void set_angular_damp_mode(DampMode p_mode);
- DampMode get_angular_damp_mode() const;
-
- void set_linear_damp(real_t p_linear_damp);
- real_t get_linear_damp() const;
-
- void set_angular_damp(real_t p_angular_damp);
- real_t get_angular_damp() const;
-
- void set_use_custom_integrator(bool p_enable);
- bool is_using_custom_integrator();
-
- void set_sleeping(bool p_sleeping);
- bool is_sleeping() const;
-
- void set_can_sleep(bool p_active);
- bool is_able_to_sleep() const;
-
- void set_contact_monitor(bool p_enabled);
- bool is_contact_monitor_enabled() const;
-
- void set_max_contacts_reported(int p_amount);
- int get_max_contacts_reported() const;
- int get_contact_count() const;
-
- void set_use_continuous_collision_detection(bool p_enable);
- bool is_using_continuous_collision_detection() const;
-
- TypedArray<Node3D> get_colliding_bodies() const;
-
- void apply_central_impulse(const Vector3 &p_impulse);
- void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
- void apply_torque_impulse(const Vector3 &p_impulse);
-
- void apply_central_force(const Vector3 &p_force);
- void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
- void apply_torque(const Vector3 &p_torque);
-
- void add_constant_central_force(const Vector3 &p_force);
- void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
- void add_constant_torque(const Vector3 &p_torque);
-
- void set_constant_force(const Vector3 &p_force);
- Vector3 get_constant_force() const;
-
- void set_constant_torque(const Vector3 &p_torque);
- Vector3 get_constant_torque() const;
-
- virtual PackedStringArray get_configuration_warnings() const override;
-
- RigidBody3D();
- ~RigidBody3D();
-
-private:
- void _reload_physics_characteristics();
-};
-
-VARIANT_ENUM_CAST(RigidBody3D::FreezeMode);
-VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode);
-VARIANT_ENUM_CAST(RigidBody3D::DampMode);
-
-class KinematicCollision3D;
-
-class CharacterBody3D : public PhysicsBody3D {
- GDCLASS(CharacterBody3D, PhysicsBody3D);
-
-public:
- enum MotionMode {
- MOTION_MODE_GROUNDED,
- MOTION_MODE_FLOATING,
- };
- enum PlatformOnLeave {
- PLATFORM_ON_LEAVE_ADD_VELOCITY,
- PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY,
- PLATFORM_ON_LEAVE_DO_NOTHING,
- };
- bool move_and_slide();
- void apply_floor_snap();
-
- const Vector3 &get_velocity() const;
- void set_velocity(const Vector3 &p_velocity);
-
- bool is_on_floor() const;
- bool is_on_floor_only() const;
- bool is_on_wall() const;
- bool is_on_wall_only() const;
- bool is_on_ceiling() const;
- bool is_on_ceiling_only() const;
- const Vector3 &get_last_motion() const;
- Vector3 get_position_delta() const;
- const Vector3 &get_floor_normal() const;
- const Vector3 &get_wall_normal() const;
- const Vector3 &get_real_velocity() const;
- real_t get_floor_angle(const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const;
- const Vector3 &get_platform_velocity() const;
- const Vector3 &get_platform_angular_velocity() const;
-
- virtual Vector3 get_linear_velocity() const override;
-
- int get_slide_collision_count() const;
- PhysicsServer3D::MotionResult get_slide_collision(int p_bounce) const;
-
- void set_safe_margin(real_t p_margin);
- real_t get_safe_margin() const;
-
- bool is_floor_stop_on_slope_enabled() const;
- void set_floor_stop_on_slope_enabled(bool p_enabled);
-
- bool is_floor_constant_speed_enabled() const;
- void set_floor_constant_speed_enabled(bool p_enabled);
-
- bool is_floor_block_on_wall_enabled() const;
- void set_floor_block_on_wall_enabled(bool p_enabled);
-
- bool is_slide_on_ceiling_enabled() const;
- void set_slide_on_ceiling_enabled(bool p_enabled);
-
- int get_max_slides() const;
- void set_max_slides(int p_max_slides);
-
- real_t get_floor_max_angle() const;
- void set_floor_max_angle(real_t p_radians);
-
- real_t get_floor_snap_length();
- void set_floor_snap_length(real_t p_floor_snap_length);
-
- real_t get_wall_min_slide_angle() const;
- void set_wall_min_slide_angle(real_t p_radians);
-
- uint32_t get_platform_floor_layers() const;
- void set_platform_floor_layers(const uint32_t p_exclude_layer);
-
- uint32_t get_platform_wall_layers() const;
- void set_platform_wall_layers(const uint32_t p_exclude_layer);
-
- void set_motion_mode(MotionMode p_mode);
- MotionMode get_motion_mode() const;
-
- void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity);
- PlatformOnLeave get_platform_on_leave() const;
-
- CharacterBody3D();
- ~CharacterBody3D();
-
-private:
- real_t margin = 0.001;
- MotionMode motion_mode = MOTION_MODE_GROUNDED;
- PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY;
- union CollisionState {
- uint32_t state = 0;
- struct {
- bool floor;
- bool wall;
- bool ceiling;
- };
-
- CollisionState() {
- }
-
- CollisionState(bool p_floor, bool p_wall, bool p_ceiling) {
- floor = p_floor;
- wall = p_wall;
- ceiling = p_ceiling;
- }
- };
-
- CollisionState collision_state;
- bool floor_constant_speed = false;
- bool floor_stop_on_slope = true;
- bool floor_block_on_wall = true;
- bool slide_on_ceiling = true;
- int max_slides = 6;
- int platform_layer = 0;
- RID platform_rid;
- ObjectID platform_object_id;
- uint32_t platform_floor_layers = UINT32_MAX;
- uint32_t platform_wall_layers = 0;
- real_t floor_snap_length = 0.1;
- real_t floor_max_angle = Math::deg_to_rad((real_t)45.0);
- real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0);
- Vector3 up_direction = Vector3(0.0, 1.0, 0.0);
- Vector3 velocity;
- Vector3 floor_normal;
- Vector3 wall_normal;
- Vector3 ceiling_normal;
- Vector3 last_motion;
- Vector3 platform_velocity;
- Vector3 platform_angular_velocity;
- Vector3 platform_ceiling_velocity;
- Vector3 previous_position;
- Vector3 real_velocity;
-
- Vector<PhysicsServer3D::MotionResult> motion_results;
- Vector<Ref<KinematicCollision3D>> slide_colliders;
-
- void _move_and_slide_floating(double p_delta);
- void _move_and_slide_grounded(double p_delta, bool p_was_on_floor);
-
- Ref<KinematicCollision3D> _get_slide_collision(int p_bounce);
- Ref<KinematicCollision3D> _get_last_slide_collision();
- const Vector3 &get_up_direction() const;
- bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up);
- void set_up_direction(const Vector3 &p_up_direction);
- void _set_collision_direction(const PhysicsServer3D::MotionResult &p_result, CollisionState &r_state, CollisionState p_apply_state = CollisionState(true, true, true));
- void _set_platform_data(const PhysicsServer3D::MotionCollision &p_collision);
- void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
- void _validate_property(PropertyInfo &p_property) const;
-};
-
-VARIANT_ENUM_CAST(CharacterBody3D::MotionMode);
-VARIANT_ENUM_CAST(CharacterBody3D::PlatformOnLeave);
-
-class KinematicCollision3D : public RefCounted {
- GDCLASS(KinematicCollision3D, RefCounted);
-
- PhysicsBody3D *owner = nullptr;
- friend class PhysicsBody3D;
- friend class CharacterBody3D;
- PhysicsServer3D::MotionResult result;
-
-protected:
- static void _bind_methods();
-
-public:
- Vector3 get_travel() const;
- Vector3 get_remainder() const;
- int get_collision_count() const;
- real_t get_depth() const;
- Vector3 get_position(int p_collision_index = 0) const;
- Vector3 get_normal(int p_collision_index = 0) const;
- real_t get_angle(int p_collision_index = 0, const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const;
- Object *get_local_shape(int p_collision_index = 0) const;
- Object *get_collider(int p_collision_index = 0) const;
- ObjectID get_collider_id(int p_collision_index = 0) const;
- RID get_collider_rid(int p_collision_index = 0) const;
- Object *get_collider_shape(int p_collision_index = 0) const;
- int get_collider_shape_index(int p_collision_index = 0) const;
- Vector3 get_collider_velocity(int p_collision_index = 0) const;
-};
-
-class PhysicalBone3D : public PhysicsBody3D {
- GDCLASS(PhysicalBone3D, PhysicsBody3D);
-
-public:
- enum DampMode {
- DAMP_MODE_COMBINE,
- DAMP_MODE_REPLACE,
- };
-
- enum JointType {
- JOINT_TYPE_NONE,
- JOINT_TYPE_PIN,
- JOINT_TYPE_CONE,
- JOINT_TYPE_HINGE,
- JOINT_TYPE_SLIDER,
- JOINT_TYPE_6DOF
- };
-
- struct JointData {
- virtual JointType get_joint_type() { return JOINT_TYPE_NONE; }
-
- /// "j" is used to set the parameter inside the PhysicsServer3D
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- virtual ~JointData() {}
- };
-
- struct PinJointData : public JointData {
- virtual JointType get_joint_type() { return JOINT_TYPE_PIN; }
-
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- real_t bias = 0.3;
- real_t damping = 1.0;
- real_t impulse_clamp = 0.0;
- };
-
- struct ConeJointData : public JointData {
- virtual JointType get_joint_type() { return JOINT_TYPE_CONE; }
-
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- real_t swing_span = Math_PI * 0.25;
- real_t twist_span = Math_PI;
- real_t bias = 0.3;
- real_t softness = 0.8;
- real_t relaxation = 1.;
- };
-
- struct HingeJointData : public JointData {
- virtual JointType get_joint_type() { return JOINT_TYPE_HINGE; }
-
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- bool angular_limit_enabled = false;
- real_t angular_limit_upper = Math_PI * 0.5;
- real_t angular_limit_lower = -Math_PI * 0.5;
- real_t angular_limit_bias = 0.3;
- real_t angular_limit_softness = 0.9;
- real_t angular_limit_relaxation = 1.;
- };
-
- struct SliderJointData : public JointData {
- virtual JointType get_joint_type() { return JOINT_TYPE_SLIDER; }
-
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- real_t linear_limit_upper = 1.0;
- real_t linear_limit_lower = -1.0;
- real_t linear_limit_softness = 1.0;
- real_t linear_limit_restitution = 0.7;
- real_t linear_limit_damping = 1.0;
- real_t angular_limit_upper = 0.0;
- real_t angular_limit_lower = 0.0;
- real_t angular_limit_softness = 1.0;
- real_t angular_limit_restitution = 0.7;
- real_t angular_limit_damping = 1.0;
- };
-
- struct SixDOFJointData : public JointData {
- struct SixDOFAxisData {
- bool linear_limit_enabled = true;
- real_t linear_limit_upper = 0.0;
- real_t linear_limit_lower = 0.0;
- real_t linear_limit_softness = 0.7;
- real_t linear_restitution = 0.5;
- real_t linear_damping = 1.0;
- bool linear_spring_enabled = false;
- real_t linear_spring_stiffness = 0.0;
- real_t linear_spring_damping = 0.0;
- real_t linear_equilibrium_point = 0.0;
- bool angular_limit_enabled = true;
- real_t angular_limit_upper = 0.0;
- real_t angular_limit_lower = 0.0;
- real_t angular_limit_softness = 0.5;
- real_t angular_restitution = 0.0;
- real_t angular_damping = 1.0;
- real_t erp = 0.5;
- bool angular_spring_enabled = false;
- real_t angular_spring_stiffness = 0.0;
- real_t angular_spring_damping = 0.0;
- real_t angular_equilibrium_point = 0.0;
- };
-
- virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
-
- virtual bool _set(const StringName &p_name, const Variant &p_value, RID j);
- virtual bool _get(const StringName &p_name, Variant &r_ret) const;
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
-
- SixDOFAxisData axis_data[3];
-
- SixDOFJointData() {}
- };
-
-private:
-#ifdef TOOLS_ENABLED
- // if false gizmo move body
- bool gizmo_move_joint = false;
-#endif
-
- JointData *joint_data = nullptr;
- Transform3D joint_offset;
- RID joint;
-
- Skeleton3D *parent_skeleton = nullptr;
- Transform3D body_offset;
- Transform3D body_offset_inverse;
- bool simulate_physics = false;
- bool _internal_simulate_physics = false;
- int bone_id = -1;
-
- String bone_name;
- real_t bounce = 0.0;
- real_t mass = 1.0;
- real_t friction = 1.0;
- Vector3 linear_velocity;
- Vector3 angular_velocity;
- real_t gravity_scale = 1.0;
- bool can_sleep = true;
-
- bool custom_integrator = false;
-
- DampMode linear_damp_mode = DAMP_MODE_COMBINE;
- DampMode angular_damp_mode = DAMP_MODE_COMBINE;
-
- real_t linear_damp = 0.0;
- real_t angular_damp = 0.0;
-
-protected:
- bool _set(const StringName &p_name, const Variant &p_value);
- bool _get(const StringName &p_name, Variant &r_ret) const;
- void _get_property_list(List<PropertyInfo> *p_list) const;
- void _notification(int p_what);
- GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *)
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
- void _body_state_changed(PhysicsDirectBodyState3D *p_state);
-
- static void _bind_methods();
-
-private:
- void _sync_body_state(PhysicsDirectBodyState3D *p_state);
- static Skeleton3D *find_skeleton_parent(Node *p_parent);
-
- void _update_joint_offset();
- void _fix_joint_offset();
- void _reload_joint();
-
-public:
- void _on_bone_parent_changed();
-
- void set_linear_velocity(const Vector3 &p_velocity);
- Vector3 get_linear_velocity() const override;
-
- void set_angular_velocity(const Vector3 &p_velocity);
- Vector3 get_angular_velocity() const override;
-
- void set_use_custom_integrator(bool p_enable);
- bool is_using_custom_integrator();
-
-#ifdef TOOLS_ENABLED
- void _set_gizmo_move_joint(bool p_move_joint);
- virtual Transform3D get_global_gizmo_transform() const override;
- virtual Transform3D get_local_gizmo_transform() const override;
-#endif
-
- const JointData *get_joint_data() const;
- Skeleton3D *find_skeleton_parent();
-
- int get_bone_id() const {
- return bone_id;
- }
-
- void set_joint_type(JointType p_joint_type);
- JointType get_joint_type() const;
-
- void set_joint_offset(const Transform3D &p_offset);
- const Transform3D &get_joint_offset() const;
-
- void set_joint_rotation(const Vector3 &p_euler_rad);
- Vector3 get_joint_rotation() const;
-
- void set_body_offset(const Transform3D &p_offset);
- const Transform3D &get_body_offset() const;
-
- void set_simulate_physics(bool p_simulate);
- bool get_simulate_physics();
- bool is_simulating_physics();
-
- void set_bone_name(const String &p_name);
- const String &get_bone_name() const;
-
- void set_mass(real_t p_mass);
- real_t get_mass() const;
-
- void set_friction(real_t p_friction);
- real_t get_friction() const;
-
- void set_bounce(real_t p_bounce);
- real_t get_bounce() const;
-
- void set_gravity_scale(real_t p_gravity_scale);
- real_t get_gravity_scale() const;
-
- void set_linear_damp_mode(DampMode p_mode);
- DampMode get_linear_damp_mode() const;
-
- void set_angular_damp_mode(DampMode p_mode);
- DampMode get_angular_damp_mode() const;
-
- void set_linear_damp(real_t p_linear_damp);
- real_t get_linear_damp() const;
-
- void set_angular_damp(real_t p_angular_damp);
- real_t get_angular_damp() const;
-
- void set_can_sleep(bool p_active);
- bool is_able_to_sleep() const;
-
- void apply_central_impulse(const Vector3 &p_impulse);
- void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
-
- void reset_physics_simulation_state();
- void reset_to_rest_position();
-
- PhysicalBone3D();
- ~PhysicalBone3D();
-
-private:
- void update_bone_id();
- void update_offset();
-
- void _start_physics_simulation();
- void _stop_physics_simulation();
-};
-
-VARIANT_ENUM_CAST(PhysicalBone3D::JointType);
-VARIANT_ENUM_CAST(PhysicalBone3D::DampMode);
-
-#endif // PHYSICS_BODY_3D_H
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index f448d1c6e2..f0ffb7b2d5 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -32,7 +32,8 @@
#include "skeleton_3d.compat.inc"
#include "core/variant/type_info.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physical_bone_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
#include "scene/resources/surface_tool.h"
#include "scene/scene_string_names.h"
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index bd03a97a36..f02cd9b700 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -30,7 +30,7 @@
#include "soft_body_3d.h"
-#include "scene/3d/physics_body_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 67f8a97212..9fe4fc88b9 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2958,17 +2958,24 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) {
remove_child(child);
if (!child->is_owned_by_parent()) {
// add the custom children to the p_node
+ Node *child_owner = child->get_owner() == this ? p_node : child->get_owner();
+ child->set_owner(nullptr);
p_node->add_child(child);
+ child->set_owner(child_owner);
}
}
p_node->set_owner(owner);
for (Node *E : owned) {
- E->set_owner(p_node);
+ if (E->data.owner != p_node) {
+ E->set_owner(p_node);
+ }
}
for (Node *E : owned_by_owner) {
- E->set_owner(owner);
+ if (E->data.owner != owner) {
+ E->set_owner(owner);
+ }
}
p_node->set_scene_file_path(get_scene_file_path());
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 0bb2688fea..1dcf9acda3 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -37,11 +37,11 @@
#include "core/templates/sort_array.h"
#include "scene/2d/audio_listener_2d.h"
#include "scene/2d/camera_2d.h"
-#include "scene/2d/collision_object_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
#ifndef _3D_DISABLED
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/camera_3d.h"
-#include "scene/3d/collision_object_3d.h"
+#include "scene/3d/physics/collision_object_3d.h"
#include "scene/3d/world_environment.h"
#endif // _3D_DISABLED
#include "scene/gui/control.h"
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b156cd0422..f1c94f53da 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -34,18 +34,14 @@
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "scene/2d/animated_sprite_2d.h"
-#include "scene/2d/area_2d.h"
#include "scene/2d/audio_listener_2d.h"
#include "scene/2d/audio_stream_player_2d.h"
#include "scene/2d/back_buffer_copy.h"
#include "scene/2d/camera_2d.h"
#include "scene/2d/canvas_group.h"
#include "scene/2d/canvas_modulate.h"
-#include "scene/2d/collision_polygon_2d.h"
-#include "scene/2d/collision_shape_2d.h"
#include "scene/2d/cpu_particles_2d.h"
#include "scene/2d/gpu_particles_2d.h"
-#include "scene/2d/joint_2d.h"
#include "scene/2d/light_2d.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/line_2d.h"
@@ -59,12 +55,24 @@
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
#include "scene/2d/path_2d.h"
-#include "scene/2d/physical_bone_2d.h"
-#include "scene/2d/physics_body_2d.h"
+#include "scene/2d/physics/animatable_body_2d.h"
+#include "scene/2d/physics/area_2d.h"
+#include "scene/2d/physics/character_body_2d.h"
+#include "scene/2d/physics/collision_polygon_2d.h"
+#include "scene/2d/physics/collision_shape_2d.h"
+#include "scene/2d/physics/joints/damped_spring_joint_2d.h"
+#include "scene/2d/physics/joints/groove_joint_2d.h"
+#include "scene/2d/physics/joints/joint_2d.h"
+#include "scene/2d/physics/joints/pin_joint_2d.h"
+#include "scene/2d/physics/kinematic_collision_2d.h"
+#include "scene/2d/physics/physical_bone_2d.h"
+#include "scene/2d/physics/physics_body_2d.h"
+#include "scene/2d/physics/ray_cast_2d.h"
+#include "scene/2d/physics/rigid_body_2d.h"
+#include "scene/2d/physics/shape_cast_2d.h"
+#include "scene/2d/physics/static_body_2d.h"
#include "scene/2d/polygon_2d.h"
-#include "scene/2d/ray_cast_2d.h"
#include "scene/2d/remote_transform_2d.h"
-#include "scene/2d/shape_cast_2d.h"
#include "scene/2d/skeleton_2d.h"
#include "scene/2d/sprite_2d.h"
#include "scene/2d/tile_map.h"
@@ -218,20 +226,16 @@
#include "scene/main/shader_globals_override.h"
#ifndef _3D_DISABLED
-#include "scene/3d/area_3d.h"
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/audio_stream_player_3d.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/camera_3d.h"
-#include "scene/3d/collision_polygon_3d.h"
-#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/cpu_particles_3d.h"
#include "scene/3d/decal.h"
#include "scene/3d/fog_volume.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
-#include "scene/3d/joint_3d.h"
#include "scene/3d/label_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
@@ -246,17 +250,32 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/occluder_instance_3d.h"
#include "scene/3d/path_3d.h"
-#include "scene/3d/physics_body_3d.h"
-#include "scene/3d/ray_cast_3d.h"
+#include "scene/3d/physics/animatable_body_3d.h"
+#include "scene/3d/physics/area_3d.h"
+#include "scene/3d/physics/character_body_3d.h"
+#include "scene/3d/physics/collision_polygon_3d.h"
+#include "scene/3d/physics/collision_shape_3d.h"
+#include "scene/3d/physics/joints/cone_twist_joint_3d.h"
+#include "scene/3d/physics/joints/generic_6dof_joint_3d.h"
+#include "scene/3d/physics/joints/hinge_joint_3d.h"
+#include "scene/3d/physics/joints/joint_3d.h"
+#include "scene/3d/physics/joints/pin_joint_3d.h"
+#include "scene/3d/physics/joints/slider_joint_3d.h"
+#include "scene/3d/physics/kinematic_collision_3d.h"
+#include "scene/3d/physics/physical_bone_3d.h"
+#include "scene/3d/physics/physics_body_3d.h"
+#include "scene/3d/physics/ray_cast_3d.h"
+#include "scene/3d/physics/rigid_body_3d.h"
+#include "scene/3d/physics/shape_cast_3d.h"
+#include "scene/3d/physics/spring_arm_3d.h"
+#include "scene/3d/physics/static_body_3d.h"
+#include "scene/3d/physics/vehicle_body_3d.h"
#include "scene/3d/reflection_probe.h"
#include "scene/3d/remote_transform_3d.h"
-#include "scene/3d/shape_cast_3d.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/3d/skeleton_ik_3d.h"
#include "scene/3d/soft_body_3d.h"
-#include "scene/3d/spring_arm_3d.h"
#include "scene/3d/sprite_3d.h"
-#include "scene/3d/vehicle_body_3d.h"
#include "scene/3d/visible_on_screen_notifier_3d.h"
#include "scene/3d/voxel_gi.h"
#include "scene/3d/world_environment.h"
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
index 88a0f7b92d..4e7563fdc3 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
@@ -31,9 +31,9 @@
#include "skeleton_modification_2d.h"
#include "scene/2d/skeleton_2d.h"
-#include "scene/2d/collision_object_2d.h"
-#include "scene/2d/collision_shape_2d.h"
-#include "scene/2d/physical_bone_2d.h"
+#include "scene/2d/physics/collision_object_2d.h"
+#include "scene/2d/physics/collision_shape_2d.h"
+#include "scene/2d/physics/physical_bone_2d.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
index e000e947cd..61e5aed150 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
@@ -29,7 +29,7 @@
/**************************************************************************/
#include "skeleton_modification_2d_physicalbones.h"
-#include "scene/2d/physical_bone_2d.h"
+#include "scene/2d/physics/physical_bone_2d.h"
#include "scene/2d/skeleton_2d.h"
bool SkeletonModification2DPhysicalBones::_set(const StringName &p_path, const Variant &p_value) {
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index d5e3427344..04a15b0381 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -32,7 +32,6 @@
#define WORLD_2D_H
#include "core/io/resource.h"
-#include "scene/resources/world_2d.h"
#include "servers/physics_server_2d.h"
class VisibleOnScreenNotifier2D;
diff --git a/scu_builders.py b/scu_builders.py
index 1a75f19b30..2579398ad6 100644
--- a/scu_builders.py
+++ b/scu_builders.py
@@ -310,7 +310,11 @@ def generate_scu_files(max_includes_per_scu):
process_folder(["modules/gdscript/language_server"])
process_folder(["scene/2d"])
+ process_folder(["scene/2d/physics"])
+ process_folder(["scene/2d/physics/joints"])
process_folder(["scene/3d"])
+ process_folder(["scene/3d/physics"])
+ process_folder(["scene/3d/physics/joints"])
process_folder(["scene/animation"])
process_folder(["scene/gui"])
process_folder(["scene/main"])
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index ce7128d564..8c88c08950 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -39,7 +39,6 @@
#include "core/templates/rid_owner.h"
#include "core/variant/typed_array.h"
#include "servers/display_server.h"
-#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_device_commons.h"
#include "servers/rendering/rendering_device_driver.h"
#include "servers/rendering/rendering_device_graph.h"
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index 9706d3219a..ee33dc103c 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -106,7 +106,7 @@ struct VersatileResourceTemplate {
template <class T>
static T *allocate(PagedAllocator<VersatileResourceTemplate> &p_allocator) {
T *obj = (T *)p_allocator.alloc();
- *obj = T();
+ memnew_placement(obj, T);
return obj;
}
diff --git a/tests/scene/test_viewport.h b/tests/scene/test_viewport.h
index e15b01ae9f..66b0f438cc 100644
--- a/tests/scene/test_viewport.h
+++ b/tests/scene/test_viewport.h
@@ -31,8 +31,8 @@
#ifndef TEST_VIEWPORT_H
#define TEST_VIEWPORT_H
-#include "scene/2d/area_2d.h"
-#include "scene/2d/collision_shape_2d.h"
+#include "scene/2d/physics/area_2d.h"
+#include "scene/2d/physics/collision_shape_2d.h"
#include "scene/gui/control.h"
#include "scene/gui/subviewport_container.h"
#include "scene/main/canvas_layer.h"