From eaae4b6408361eb34363adcb22a08046f43147f4 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 26 Mar 2020 18:49:16 -0300 Subject: Renamed 2D and 3D nodes to make their types explicit Fixes #30736. --- editor/animation_track_editor.cpp | 10 +- editor/animation_track_editor.h | 2 +- editor/animation_track_editor_plugins.cpp | 16 +- editor/debugger/script_editor_debugger.cpp | 8 +- editor/editor_inspector.cpp | 2 +- editor/editor_node.cpp | 12 +- editor/editor_node.h | 2 +- editor/editor_plugin.cpp | 38 +- editor/editor_plugin.h | 12 +- editor/icons/AnimatedSprite.svg | 1 - editor/icons/AnimatedSprite2D.svg | 1 + editor/icons/Area.svg | 1 - editor/icons/Area3D.svg | 1 + editor/icons/BoneAttachment.svg | 1 - editor/icons/BoneAttachment3D.svg | 1 + editor/icons/CPUParticles.svg | 1 - editor/icons/CPUParticles3D.svg | 1 + editor/icons/Camera.svg | 1 - editor/icons/Camera3D.svg | 1 + editor/icons/CapsuleShape.svg | 1 - editor/icons/CapsuleShape3D.svg | 1 + editor/icons/CollisionPolygon.svg | 1 - editor/icons/CollisionPolygon3D.svg | 1 + editor/icons/CollisionShape.svg | 1 - editor/icons/CollisionShape3D.svg | 1 + editor/icons/ConcavePolygonShape.svg | 1 - editor/icons/ConcavePolygonShape3D.svg | 1 + editor/icons/ConeTwistJoint.svg | 1 - editor/icons/ConeTwistJoint3D.svg | 1 + editor/icons/ConvexPolygonShape.svg | 1 - editor/icons/ConvexPolygonShape3D.svg | 1 + editor/icons/CylinderShape.svg | 1 - editor/icons/CylinderShape3D.svg | 1 + editor/icons/DirectionalLight.svg | 1 - editor/icons/DirectionalLight3D.svg | 1 + editor/icons/GPUParticles2D.svg | 1 + editor/icons/GPUParticles3D.svg | 1 + editor/icons/Generic6DOFJoint.svg | 1 - editor/icons/Generic6DOFJoint3D.svg | 1 + editor/icons/Gizmo3DSamplePlayer.svg | 1 + editor/icons/GizmoSpatialSamplePlayer.svg | 1 - editor/icons/HingeJoint.svg | 1 - editor/icons/HingeJoint3D.svg | 1 + editor/icons/ImmediateGeometry.svg | 1 - editor/icons/ImmediateGeometry3D.svg | 1 + editor/icons/KinematicBody.svg | 1 - editor/icons/KinematicBody3D.svg | 1 + editor/icons/Listener.svg | 1 - editor/icons/Listener3D.svg | 1 + editor/icons/MeshInstance.svg | 1 - editor/icons/MeshInstance3D.svg | 1 + editor/icons/MultiMeshInstance.svg | 1 - editor/icons/MultiMeshInstance3D.svg | 1 + editor/icons/Navigation.svg | 1 - editor/icons/Navigation3D.svg | 1 + editor/icons/NavigationAgent.svg | 1 - editor/icons/NavigationAgent3D.svg | 1 + editor/icons/NavigationObstacle.svg | 1 - editor/icons/NavigationObstacle3D.svg | 1 + editor/icons/NavigationRegion.svg | 1 - editor/icons/NavigationRegion3D.svg | 1 + editor/icons/Node3D.svg | 1 + editor/icons/OmniLight.svg | 1 - editor/icons/OmniLight3D.svg | 1 + editor/icons/Particles.svg | 1 - editor/icons/Particles2D.svg | 1 - editor/icons/Path.svg | 1 - editor/icons/Path3D.svg | 1 + editor/icons/PathFollow.svg | 1 - editor/icons/PathFollow3D.svg | 1 + editor/icons/PhysicalBone.svg | 1 - editor/icons/PhysicalBone3D.svg | 1 + editor/icons/PinJoint.svg | 1 - editor/icons/PinJoint3D.svg | 1 + editor/icons/ProximityGroup.svg | 1 - editor/icons/ProximityGroup3D.svg | 1 + editor/icons/RayCast.svg | 1 - editor/icons/RayCast3D.svg | 1 + editor/icons/RayShape.svg | 1 - editor/icons/RayShape3D.svg | 1 + editor/icons/RemoteTransform.svg | 1 - editor/icons/RemoteTransform3D.svg | 1 + editor/icons/RigidBody.svg | 1 - editor/icons/RigidBody3D.svg | 1 + editor/icons/Skeleton.svg | 1 - editor/icons/Skeleton3D.svg | 1 + editor/icons/SkeletonIK.svg | 1 - editor/icons/SkeletonIK3D.svg | 1 + editor/icons/SliderJoint.svg | 1 - editor/icons/SliderJoint3D.svg | 1 + editor/icons/SoftBody.svg | 1 - editor/icons/SoftBody3D.svg | 1 + editor/icons/Spatial.svg | 1 - editor/icons/SphereShape.svg | 1 - editor/icons/SphereShape3D.svg | 1 + editor/icons/SpotLight.svg | 1 - editor/icons/SpotLight3D.svg | 1 + editor/icons/SpringArm.svg | 1 - editor/icons/SpringArm3D.svg | 1 + editor/icons/Sprite.svg | 1 - editor/icons/Sprite2D.svg | 1 + editor/icons/StaticBody.svg | 1 - editor/icons/StaticBody3D.svg | 1 + editor/icons/VisibilityEnabler.svg | 1 - editor/icons/VisibilityEnabler3D.svg | 1 + editor/icons/VisibilityNotifier.svg | 1 - editor/icons/VisibilityNotifier3D.svg | 1 + editor/import/editor_import_collada.cpp | 78 +- editor/import/editor_scene_importer_gltf.cpp | 50 +- editor/import/editor_scene_importer_gltf.h | 24 +- editor/import/resource_importer_obj.cpp | 8 +- editor/import/resource_importer_scene.cpp | 122 +- editor/import/resource_importer_scene.h | 4 +- editor/inspector_dock.cpp | 2 +- .../plugins/animation_blend_tree_editor_plugin.cpp | 6 +- editor/plugins/animation_player_editor_plugin.cpp | 12 +- editor/plugins/camera_editor_plugin.cpp | 18 +- editor/plugins/camera_editor_plugin.h | 4 +- editor/plugins/canvas_item_editor_plugin.cpp | 6 +- editor/plugins/collision_polygon_editor_plugin.cpp | 20 +- editor/plugins/collision_polygon_editor_plugin.h | 16 +- editor/plugins/cpu_particles_editor_plugin.cpp | 12 +- editor/plugins/cpu_particles_editor_plugin.h | 6 +- editor/plugins/material_editor_plugin.cpp | 10 +- editor/plugins/material_editor_plugin.h | 16 +- editor/plugins/mesh_editor_plugin.cpp | 10 +- editor/plugins/mesh_editor_plugin.h | 16 +- editor/plugins/mesh_instance_editor_plugin.cpp | 48 +- editor/plugins/mesh_instance_editor_plugin.h | 8 +- editor/plugins/mesh_library_editor_plugin.cpp | 26 +- editor/plugins/multimesh_editor_plugin.cpp | 16 +- editor/plugins/multimesh_editor_plugin.h | 8 +- editor/plugins/particles_2d_editor_plugin.cpp | 2 +- editor/plugins/particles_editor_plugin.cpp | 20 +- editor/plugins/particles_editor_plugin.h | 8 +- editor/plugins/path_editor_plugin.cpp | 62 +- editor/plugins/path_editor_plugin.h | 28 +- editor/plugins/physical_bone_plugin.cpp | 10 +- editor/plugins/physical_bone_plugin.h | 10 +- editor/plugins/root_motion_editor_plugin.cpp | 6 +- editor/plugins/skeleton_editor_plugin.cpp | 30 +- editor/plugins/skeleton_editor_plugin.h | 14 +- editor/plugins/skeleton_ik_editor_plugin.cpp | 4 +- editor/plugins/skeleton_ik_editor_plugin.h | 4 +- editor/plugins/spatial_editor_plugin.cpp | 850 +++---- editor/plugins/spatial_editor_plugin.h | 180 +- editor/plugins/sprite_editor_plugin.cpp | 6 +- editor/plugins/sprite_editor_plugin.h | 6 +- editor/plugins/sprite_frames_editor_plugin.cpp | 17 +- editor/plugins/sprite_frames_editor_plugin.h | 2 +- editor/plugins/texture_region_editor_plugin.cpp | 6 +- editor/plugins/texture_region_editor_plugin.h | 6 +- editor/plugins/tile_set_editor_plugin.cpp | 8 +- editor/plugins/tile_set_editor_plugin.h | 4 +- editor/scene_tree_dock.cpp | 22 +- editor/scene_tree_editor.cpp | 12 +- editor/spatial_editor_gizmos.cpp | 908 +++---- editor/spatial_editor_gizmos.h | 290 +-- main/tests/test_gui.cpp | 4 +- modules/assimp/editor_scene_importer_assimp.cpp | 62 +- modules/assimp/editor_scene_importer_assimp.h | 18 +- modules/assimp/import_state.h | 22 +- modules/bullet/soft_body_bullet.cpp | 2 +- modules/csg/csg_gizmos.cpp | 144 +- modules/csg/csg_gizmos.h | 18 +- modules/csg/csg_shape.cpp | 500 ++-- modules/csg/csg_shape.h | 70 +- modules/csg/icons/CSGBox.svg | 6 - modules/csg/icons/CSGBox3D.svg | 6 + modules/csg/icons/CSGCapsule.svg | 6 - modules/csg/icons/CSGCapsule3D.svg | 6 + modules/csg/icons/CSGCombiner.svg | 8 - modules/csg/icons/CSGCombiner3D.svg | 8 + modules/csg/icons/CSGCylinder.svg | 6 - modules/csg/icons/CSGCylinder3D.svg | 6 + modules/csg/icons/CSGMesh.svg | 6 - modules/csg/icons/CSGMesh3D.svg | 6 + modules/csg/icons/CSGPolygon.svg | 6 - modules/csg/icons/CSGPolygon3D.svg | 6 + modules/csg/icons/CSGSphere.svg | 6 - modules/csg/icons/CSGSphere3D.svg | 6 + modules/csg/icons/CSGTorus.svg | 6 - modules/csg/icons/CSGTorus3D.svg | 6 + modules/csg/register_types.cpp | 27 +- modules/gdnavigation/nav_region.h | 2 +- .../gdnavigation/navigation_mesh_editor_plugin.cpp | 8 +- .../gdnavigation/navigation_mesh_editor_plugin.h | 6 +- modules/gdnavigation/navigation_mesh_generator.cpp | 58 +- modules/gdnavigation/navigation_mesh_generator.h | 2 +- modules/gridmap/grid_map.cpp | 8 +- modules/gridmap/grid_map.h | 10 +- modules/gridmap/grid_map_editor_plugin.cpp | 22 +- modules/gridmap/grid_map_editor_plugin.h | 10 +- modules/mono/mono_gd/gd_mono_cache.cpp | 4 +- modules/mono/mono_gd/gd_mono_cache.h | 2 +- scene/2d/animated_sprite.cpp | 772 ------ scene/2d/animated_sprite.h | 231 -- scene/2d/animated_sprite_2d.cpp | 772 ++++++ scene/2d/animated_sprite_2d.h | 231 ++ scene/2d/sprite.cpp | 539 ---- scene/2d/sprite.h | 143 -- scene/2d/sprite_2d.cpp | 539 ++++ scene/2d/sprite_2d.h | 143 ++ scene/2d/visibility_notifier_2d.cpp | 6 +- scene/3d/area.cpp | 759 ------ scene/3d/area.h | 217 -- scene/3d/area_3d.cpp | 759 ++++++ scene/3d/area_3d.h | 217 ++ scene/3d/arvr_nodes.cpp | 8 +- scene/3d/arvr_nodes.h | 20 +- scene/3d/audio_stream_player_3d.cpp | 20 +- scene/3d/audio_stream_player_3d.h | 12 +- scene/3d/bone_attachment.cpp | 127 - scene/3d/bone_attachment.h | 59 - scene/3d/bone_attachment_3d.cpp | 127 + scene/3d/bone_attachment_3d.h | 59 + scene/3d/camera.cpp | 954 ------- scene/3d/camera.h | 246 -- scene/3d/camera_3d.cpp | 954 +++++++ scene/3d/camera_3d.h | 246 ++ scene/3d/collision_object.cpp | 396 --- scene/3d/collision_object.h | 119 - scene/3d/collision_object_3d.cpp | 396 +++ scene/3d/collision_object_3d.h | 119 + scene/3d/collision_polygon.cpp | 207 -- scene/3d/collision_polygon.h | 79 - scene/3d/collision_polygon_3d.cpp | 207 ++ scene/3d/collision_polygon_3d.h | 79 + scene/3d/collision_shape.cpp | 242 -- scene/3d/collision_shape.h | 78 - scene/3d/collision_shape_3d.cpp | 242 ++ scene/3d/collision_shape_3d.h | 78 + scene/3d/cpu_particles.cpp | 1546 ------------ scene/3d/cpu_particles.h | 298 --- scene/3d/cpu_particles_3d.cpp | 1546 ++++++++++++ scene/3d/cpu_particles_3d.h | 298 +++ scene/3d/gi_probe.cpp | 10 +- scene/3d/gi_probe.h | 8 +- scene/3d/gpu_particles_3d.cpp | 441 ++++ scene/3d/gpu_particles_3d.h | 133 + scene/3d/immediate_geometry.cpp | 169 -- scene/3d/immediate_geometry.h | 73 - scene/3d/immediate_geometry_3d.cpp | 169 ++ scene/3d/immediate_geometry_3d.h | 73 + scene/3d/interpolated_camera.cpp | 155 -- scene/3d/interpolated_camera.h | 63 - scene/3d/light.cpp | 480 ---- scene/3d/light.h | 216 -- scene/3d/light_3d.cpp | 480 ++++ scene/3d/light_3d.h | 216 ++ scene/3d/listener.cpp | 178 -- scene/3d/listener.h | 78 - scene/3d/listener_3d.cpp | 178 ++ scene/3d/listener_3d.h | 78 + scene/3d/mesh_instance.cpp | 421 ---- scene/3d/mesh_instance.h | 103 - scene/3d/mesh_instance_3d.cpp | 421 ++++ scene/3d/mesh_instance_3d.h | 103 + scene/3d/multimesh_instance.cpp | 71 - scene/3d/multimesh_instance.h | 58 - scene/3d/multimesh_instance_3d.cpp | 71 + scene/3d/multimesh_instance_3d.h | 58 + scene/3d/navigation.cpp | 125 - scene/3d/navigation.h | 79 - scene/3d/navigation_3d.cpp | 125 + scene/3d/navigation_3d.h | 79 + scene/3d/navigation_agent.cpp | 362 --- scene/3d/navigation_agent.h | 162 -- scene/3d/navigation_agent_3d.cpp | 362 +++ scene/3d/navigation_agent_3d.h | 162 ++ scene/3d/navigation_obstacle.cpp | 163 -- scene/3d/navigation_obstacle.h | 71 - scene/3d/navigation_obstacle_3d.cpp | 163 ++ scene/3d/navigation_obstacle_3d.h | 71 + scene/3d/navigation_region.cpp | 258 -- scene/3d/navigation_region.h | 75 - scene/3d/navigation_region_3d.cpp | 258 ++ scene/3d/navigation_region_3d.h | 75 + scene/3d/node_3d.cpp | 848 +++++++ scene/3d/node_3d.h | 207 ++ scene/3d/particles.cpp | 441 ---- scene/3d/particles.h | 133 - scene/3d/path.cpp | 416 ---- scene/3d/path.h | 117 - scene/3d/path_3d.cpp | 416 ++++ scene/3d/path_3d.h | 117 + scene/3d/physics_body.cpp | 2596 -------------------- scene/3d/physics_body.h | 646 ----- scene/3d/physics_body_3d.cpp | 2596 ++++++++++++++++++++ scene/3d/physics_body_3d.h | 646 +++++ scene/3d/physics_joint.cpp | 1049 -------- scene/3d/physics_joint.h | 343 --- scene/3d/physics_joint_3d.cpp | 1049 ++++++++ scene/3d/physics_joint_3d.h | 343 +++ scene/3d/position_3d.h | 6 +- scene/3d/proximity_group.cpp | 214 -- scene/3d/proximity_group.h | 87 - scene/3d/proximity_group_3d.cpp | 214 ++ scene/3d/proximity_group_3d.h | 87 + scene/3d/ray_cast.cpp | 405 --- scene/3d/ray_cast.h | 106 - scene/3d/ray_cast_3d.cpp | 405 +++ scene/3d/ray_cast_3d.h | 106 + scene/3d/reflection_probe.h | 6 +- scene/3d/remote_transform.cpp | 223 -- scene/3d/remote_transform.h | 78 - scene/3d/remote_transform_3d.cpp | 223 ++ scene/3d/remote_transform_3d.h | 78 + scene/3d/skeleton.cpp | 956 ------- scene/3d/skeleton.h | 235 -- scene/3d/skeleton_3d.cpp | 956 +++++++ scene/3d/skeleton_3d.h | 235 ++ scene/3d/soft_body.cpp | 826 ------- scene/3d/soft_body.h | 202 -- scene/3d/soft_body_3d.cpp | 826 +++++++ scene/3d/soft_body_3d.h | 202 ++ scene/3d/spatial.cpp | 848 ------- scene/3d/spatial.h | 207 -- scene/3d/spatial_velocity_tracker.cpp | 136 - scene/3d/spatial_velocity_tracker.h | 61 - scene/3d/spring_arm.cpp | 173 -- scene/3d/spring_arm.h | 71 - scene/3d/spring_arm_3d.cpp | 173 ++ scene/3d/spring_arm_3d.h | 71 + scene/3d/sprite_3d.h | 8 +- scene/3d/vehicle_body.cpp | 10 +- scene/3d/vehicle_body.h | 18 +- scene/3d/velocity_tracker_3d.cpp | 136 + scene/3d/velocity_tracker_3d.h | 61 + scene/3d/visibility_notifier.cpp | 274 --- scene/3d/visibility_notifier.h | 101 - scene/3d/visibility_notifier_3d.cpp | 274 +++ scene/3d/visibility_notifier_3d.h | 101 + scene/3d/visual_instance.cpp | 335 --- scene/3d/visual_instance.h | 150 -- scene/3d/visual_instance_3d.cpp | 335 +++ scene/3d/visual_instance_3d.h | 150 ++ scene/3d/voxelizer.h | 2 +- scene/3d/world_environment.cpp | 4 +- scene/3d/world_environment.h | 2 +- scene/animation/animation_cache.cpp | 6 +- scene/animation/animation_cache.h | 6 +- scene/animation/animation_player.cpp | 12 +- scene/animation/animation_player.h | 8 +- scene/animation/animation_tree.cpp | 6 +- scene/animation/animation_tree.h | 8 +- scene/animation/root_motion_view.h | 6 +- scene/animation/skeleton_ik.cpp | 116 +- scene/animation/skeleton_ik.h | 24 +- scene/main/scene_tree.h | 2 +- scene/main/viewport.cpp | 87 +- scene/main/viewport.h | 40 +- scene/register_scene_types.cpp | 271 +- scene/resources/box_shape.cpp | 86 - scene/resources/box_shape.h | 56 - scene/resources/box_shape_3d.cpp | 86 + scene/resources/box_shape_3d.h | 56 + scene/resources/capsule_shape.cpp | 128 - scene/resources/capsule_shape.h | 59 - scene/resources/capsule_shape_3d.cpp | 128 + scene/resources/capsule_shape_3d.h | 59 + scene/resources/concave_polygon_shape.cpp | 103 - scene/resources/concave_polygon_shape.h | 75 - scene/resources/concave_polygon_shape_3d.cpp | 103 + scene/resources/concave_polygon_shape_3d.h | 75 + scene/resources/convex_polygon_shape.cpp | 96 - scene/resources/convex_polygon_shape.h | 56 - scene/resources/convex_polygon_shape_3d.cpp | 96 + scene/resources/convex_polygon_shape_3d.h | 56 + scene/resources/cylinder_shape.cpp | 121 - scene/resources/cylinder_shape.h | 58 - scene/resources/cylinder_shape_3d.cpp | 121 + scene/resources/cylinder_shape_3d.h | 58 + scene/resources/height_map_shape.cpp | 4 +- scene/resources/height_map_shape.h | 6 +- scene/resources/mesh.cpp | 24 +- scene/resources/mesh.h | 8 +- scene/resources/mesh_library.h | 6 +- scene/resources/packed_scene.cpp | 6 +- scene/resources/ray_shape.cpp | 30 +- scene/resources/ray_shape.h | 8 +- scene/resources/shape.cpp | 127 - scene/resources/shape.h | 73 - scene/resources/shape_3d.cpp | 127 + scene/resources/shape_3d.h | 73 + scene/resources/sphere_shape.cpp | 93 - scene/resources/sphere_shape.h | 56 - scene/resources/sphere_shape_3d.cpp | 93 + scene/resources/sphere_shape_3d.h | 56 + scene/resources/visual_shader.cpp | 2 +- scene/resources/world.cpp | 72 +- scene/resources/world.h | 22 +- scene/resources/world_margin_shape.cpp | 95 - scene/resources/world_margin_shape.h | 57 - scene/resources/world_margin_shape_3d.cpp | 95 + scene/resources/world_margin_shape_3d.h | 57 + servers/navigation_server.h | 2 +- 397 files changed, 25599 insertions(+), 25745 deletions(-) delete mode 100644 editor/icons/AnimatedSprite.svg create mode 100644 editor/icons/AnimatedSprite2D.svg delete mode 100644 editor/icons/Area.svg create mode 100644 editor/icons/Area3D.svg delete mode 100644 editor/icons/BoneAttachment.svg create mode 100644 editor/icons/BoneAttachment3D.svg delete mode 100644 editor/icons/CPUParticles.svg create mode 100644 editor/icons/CPUParticles3D.svg delete mode 100644 editor/icons/Camera.svg create mode 100644 editor/icons/Camera3D.svg delete mode 100644 editor/icons/CapsuleShape.svg create mode 100644 editor/icons/CapsuleShape3D.svg delete mode 100644 editor/icons/CollisionPolygon.svg create mode 100644 editor/icons/CollisionPolygon3D.svg delete mode 100644 editor/icons/CollisionShape.svg create mode 100644 editor/icons/CollisionShape3D.svg delete mode 100644 editor/icons/ConcavePolygonShape.svg create mode 100644 editor/icons/ConcavePolygonShape3D.svg delete mode 100644 editor/icons/ConeTwistJoint.svg create mode 100644 editor/icons/ConeTwistJoint3D.svg delete mode 100644 editor/icons/ConvexPolygonShape.svg create mode 100644 editor/icons/ConvexPolygonShape3D.svg delete mode 100644 editor/icons/CylinderShape.svg create mode 100644 editor/icons/CylinderShape3D.svg delete mode 100644 editor/icons/DirectionalLight.svg create mode 100644 editor/icons/DirectionalLight3D.svg create mode 100644 editor/icons/GPUParticles2D.svg create mode 100644 editor/icons/GPUParticles3D.svg delete mode 100644 editor/icons/Generic6DOFJoint.svg create mode 100644 editor/icons/Generic6DOFJoint3D.svg create mode 100644 editor/icons/Gizmo3DSamplePlayer.svg delete mode 100644 editor/icons/GizmoSpatialSamplePlayer.svg delete mode 100644 editor/icons/HingeJoint.svg create mode 100644 editor/icons/HingeJoint3D.svg delete mode 100644 editor/icons/ImmediateGeometry.svg create mode 100644 editor/icons/ImmediateGeometry3D.svg delete mode 100644 editor/icons/KinematicBody.svg create mode 100644 editor/icons/KinematicBody3D.svg delete mode 100644 editor/icons/Listener.svg create mode 100644 editor/icons/Listener3D.svg delete mode 100644 editor/icons/MeshInstance.svg create mode 100644 editor/icons/MeshInstance3D.svg delete mode 100644 editor/icons/MultiMeshInstance.svg create mode 100644 editor/icons/MultiMeshInstance3D.svg delete mode 100644 editor/icons/Navigation.svg create mode 100644 editor/icons/Navigation3D.svg delete mode 100644 editor/icons/NavigationAgent.svg create mode 100644 editor/icons/NavigationAgent3D.svg delete mode 100644 editor/icons/NavigationObstacle.svg create mode 100644 editor/icons/NavigationObstacle3D.svg delete mode 100644 editor/icons/NavigationRegion.svg create mode 100644 editor/icons/NavigationRegion3D.svg create mode 100644 editor/icons/Node3D.svg delete mode 100644 editor/icons/OmniLight.svg create mode 100644 editor/icons/OmniLight3D.svg delete mode 100644 editor/icons/Particles.svg delete mode 100644 editor/icons/Particles2D.svg delete mode 100644 editor/icons/Path.svg create mode 100644 editor/icons/Path3D.svg delete mode 100644 editor/icons/PathFollow.svg create mode 100644 editor/icons/PathFollow3D.svg delete mode 100644 editor/icons/PhysicalBone.svg create mode 100644 editor/icons/PhysicalBone3D.svg delete mode 100644 editor/icons/PinJoint.svg create mode 100644 editor/icons/PinJoint3D.svg delete mode 100644 editor/icons/ProximityGroup.svg create mode 100644 editor/icons/ProximityGroup3D.svg delete mode 100644 editor/icons/RayCast.svg create mode 100644 editor/icons/RayCast3D.svg delete mode 100644 editor/icons/RayShape.svg create mode 100644 editor/icons/RayShape3D.svg delete mode 100644 editor/icons/RemoteTransform.svg create mode 100644 editor/icons/RemoteTransform3D.svg delete mode 100644 editor/icons/RigidBody.svg create mode 100644 editor/icons/RigidBody3D.svg delete mode 100644 editor/icons/Skeleton.svg create mode 100644 editor/icons/Skeleton3D.svg delete mode 100644 editor/icons/SkeletonIK.svg create mode 100644 editor/icons/SkeletonIK3D.svg delete mode 100644 editor/icons/SliderJoint.svg create mode 100644 editor/icons/SliderJoint3D.svg delete mode 100644 editor/icons/SoftBody.svg create mode 100644 editor/icons/SoftBody3D.svg delete mode 100644 editor/icons/Spatial.svg delete mode 100644 editor/icons/SphereShape.svg create mode 100644 editor/icons/SphereShape3D.svg delete mode 100644 editor/icons/SpotLight.svg create mode 100644 editor/icons/SpotLight3D.svg delete mode 100644 editor/icons/SpringArm.svg create mode 100644 editor/icons/SpringArm3D.svg delete mode 100644 editor/icons/Sprite.svg create mode 100644 editor/icons/Sprite2D.svg delete mode 100644 editor/icons/StaticBody.svg create mode 100644 editor/icons/StaticBody3D.svg delete mode 100644 editor/icons/VisibilityEnabler.svg create mode 100644 editor/icons/VisibilityEnabler3D.svg delete mode 100644 editor/icons/VisibilityNotifier.svg create mode 100644 editor/icons/VisibilityNotifier3D.svg delete mode 100644 modules/csg/icons/CSGBox.svg create mode 100644 modules/csg/icons/CSGBox3D.svg delete mode 100644 modules/csg/icons/CSGCapsule.svg create mode 100644 modules/csg/icons/CSGCapsule3D.svg delete mode 100644 modules/csg/icons/CSGCombiner.svg create mode 100644 modules/csg/icons/CSGCombiner3D.svg delete mode 100644 modules/csg/icons/CSGCylinder.svg create mode 100644 modules/csg/icons/CSGCylinder3D.svg delete mode 100644 modules/csg/icons/CSGMesh.svg create mode 100644 modules/csg/icons/CSGMesh3D.svg delete mode 100644 modules/csg/icons/CSGPolygon.svg create mode 100644 modules/csg/icons/CSGPolygon3D.svg delete mode 100644 modules/csg/icons/CSGSphere.svg create mode 100644 modules/csg/icons/CSGSphere3D.svg delete mode 100644 modules/csg/icons/CSGTorus.svg create mode 100644 modules/csg/icons/CSGTorus3D.svg delete mode 100644 scene/2d/animated_sprite.cpp delete mode 100644 scene/2d/animated_sprite.h create mode 100644 scene/2d/animated_sprite_2d.cpp create mode 100644 scene/2d/animated_sprite_2d.h delete mode 100644 scene/2d/sprite.cpp delete mode 100644 scene/2d/sprite.h create mode 100644 scene/2d/sprite_2d.cpp create mode 100644 scene/2d/sprite_2d.h delete mode 100644 scene/3d/area.cpp delete mode 100644 scene/3d/area.h create mode 100644 scene/3d/area_3d.cpp create mode 100644 scene/3d/area_3d.h delete mode 100644 scene/3d/bone_attachment.cpp delete mode 100644 scene/3d/bone_attachment.h create mode 100644 scene/3d/bone_attachment_3d.cpp create mode 100644 scene/3d/bone_attachment_3d.h delete mode 100644 scene/3d/camera.cpp delete mode 100644 scene/3d/camera.h create mode 100644 scene/3d/camera_3d.cpp create mode 100644 scene/3d/camera_3d.h delete mode 100644 scene/3d/collision_object.cpp delete mode 100644 scene/3d/collision_object.h create mode 100644 scene/3d/collision_object_3d.cpp create mode 100644 scene/3d/collision_object_3d.h delete mode 100644 scene/3d/collision_polygon.cpp delete mode 100644 scene/3d/collision_polygon.h create mode 100644 scene/3d/collision_polygon_3d.cpp create mode 100644 scene/3d/collision_polygon_3d.h delete mode 100644 scene/3d/collision_shape.cpp delete mode 100644 scene/3d/collision_shape.h create mode 100644 scene/3d/collision_shape_3d.cpp create mode 100644 scene/3d/collision_shape_3d.h delete mode 100644 scene/3d/cpu_particles.cpp delete mode 100644 scene/3d/cpu_particles.h create mode 100644 scene/3d/cpu_particles_3d.cpp create mode 100644 scene/3d/cpu_particles_3d.h create mode 100644 scene/3d/gpu_particles_3d.cpp create mode 100644 scene/3d/gpu_particles_3d.h delete mode 100644 scene/3d/immediate_geometry.cpp delete mode 100644 scene/3d/immediate_geometry.h create mode 100644 scene/3d/immediate_geometry_3d.cpp create mode 100644 scene/3d/immediate_geometry_3d.h delete mode 100644 scene/3d/interpolated_camera.cpp delete mode 100644 scene/3d/interpolated_camera.h delete mode 100644 scene/3d/light.cpp delete mode 100644 scene/3d/light.h create mode 100644 scene/3d/light_3d.cpp create mode 100644 scene/3d/light_3d.h delete mode 100644 scene/3d/listener.cpp delete mode 100644 scene/3d/listener.h create mode 100644 scene/3d/listener_3d.cpp create mode 100644 scene/3d/listener_3d.h delete mode 100644 scene/3d/mesh_instance.cpp delete mode 100644 scene/3d/mesh_instance.h create mode 100644 scene/3d/mesh_instance_3d.cpp create mode 100644 scene/3d/mesh_instance_3d.h delete mode 100644 scene/3d/multimesh_instance.cpp delete mode 100644 scene/3d/multimesh_instance.h create mode 100644 scene/3d/multimesh_instance_3d.cpp create mode 100644 scene/3d/multimesh_instance_3d.h delete mode 100644 scene/3d/navigation.cpp delete mode 100644 scene/3d/navigation.h create mode 100644 scene/3d/navigation_3d.cpp create mode 100644 scene/3d/navigation_3d.h delete mode 100644 scene/3d/navigation_agent.cpp delete mode 100644 scene/3d/navigation_agent.h create mode 100644 scene/3d/navigation_agent_3d.cpp create mode 100644 scene/3d/navigation_agent_3d.h delete mode 100644 scene/3d/navigation_obstacle.cpp delete mode 100644 scene/3d/navigation_obstacle.h create mode 100644 scene/3d/navigation_obstacle_3d.cpp create mode 100644 scene/3d/navigation_obstacle_3d.h delete mode 100644 scene/3d/navigation_region.cpp delete mode 100644 scene/3d/navigation_region.h create mode 100644 scene/3d/navigation_region_3d.cpp create mode 100644 scene/3d/navigation_region_3d.h create mode 100644 scene/3d/node_3d.cpp create mode 100644 scene/3d/node_3d.h delete mode 100644 scene/3d/particles.cpp delete mode 100644 scene/3d/particles.h delete mode 100644 scene/3d/path.cpp delete mode 100644 scene/3d/path.h create mode 100644 scene/3d/path_3d.cpp create mode 100644 scene/3d/path_3d.h delete mode 100644 scene/3d/physics_body.cpp delete mode 100644 scene/3d/physics_body.h create mode 100644 scene/3d/physics_body_3d.cpp create mode 100644 scene/3d/physics_body_3d.h delete mode 100644 scene/3d/physics_joint.cpp delete mode 100644 scene/3d/physics_joint.h create mode 100644 scene/3d/physics_joint_3d.cpp create mode 100644 scene/3d/physics_joint_3d.h delete mode 100644 scene/3d/proximity_group.cpp delete mode 100644 scene/3d/proximity_group.h create mode 100644 scene/3d/proximity_group_3d.cpp create mode 100644 scene/3d/proximity_group_3d.h delete mode 100644 scene/3d/ray_cast.cpp delete mode 100644 scene/3d/ray_cast.h create mode 100644 scene/3d/ray_cast_3d.cpp create mode 100644 scene/3d/ray_cast_3d.h delete mode 100644 scene/3d/remote_transform.cpp delete mode 100644 scene/3d/remote_transform.h create mode 100644 scene/3d/remote_transform_3d.cpp create mode 100644 scene/3d/remote_transform_3d.h delete mode 100644 scene/3d/skeleton.cpp delete mode 100644 scene/3d/skeleton.h create mode 100644 scene/3d/skeleton_3d.cpp create mode 100644 scene/3d/skeleton_3d.h delete mode 100644 scene/3d/soft_body.cpp delete mode 100644 scene/3d/soft_body.h create mode 100644 scene/3d/soft_body_3d.cpp create mode 100644 scene/3d/soft_body_3d.h delete mode 100644 scene/3d/spatial.cpp delete mode 100644 scene/3d/spatial.h delete mode 100644 scene/3d/spatial_velocity_tracker.cpp delete mode 100644 scene/3d/spatial_velocity_tracker.h delete mode 100644 scene/3d/spring_arm.cpp delete mode 100644 scene/3d/spring_arm.h create mode 100644 scene/3d/spring_arm_3d.cpp create mode 100644 scene/3d/spring_arm_3d.h create mode 100644 scene/3d/velocity_tracker_3d.cpp create mode 100644 scene/3d/velocity_tracker_3d.h delete mode 100644 scene/3d/visibility_notifier.cpp delete mode 100644 scene/3d/visibility_notifier.h create mode 100644 scene/3d/visibility_notifier_3d.cpp create mode 100644 scene/3d/visibility_notifier_3d.h delete mode 100644 scene/3d/visual_instance.cpp delete mode 100644 scene/3d/visual_instance.h create mode 100644 scene/3d/visual_instance_3d.cpp create mode 100644 scene/3d/visual_instance_3d.h delete mode 100644 scene/resources/box_shape.cpp delete mode 100644 scene/resources/box_shape.h create mode 100644 scene/resources/box_shape_3d.cpp create mode 100644 scene/resources/box_shape_3d.h delete mode 100644 scene/resources/capsule_shape.cpp delete mode 100644 scene/resources/capsule_shape.h create mode 100644 scene/resources/capsule_shape_3d.cpp create mode 100644 scene/resources/capsule_shape_3d.h delete mode 100644 scene/resources/concave_polygon_shape.cpp delete mode 100644 scene/resources/concave_polygon_shape.h create mode 100644 scene/resources/concave_polygon_shape_3d.cpp create mode 100644 scene/resources/concave_polygon_shape_3d.h delete mode 100644 scene/resources/convex_polygon_shape.cpp delete mode 100644 scene/resources/convex_polygon_shape.h create mode 100644 scene/resources/convex_polygon_shape_3d.cpp create mode 100644 scene/resources/convex_polygon_shape_3d.h delete mode 100644 scene/resources/cylinder_shape.cpp delete mode 100644 scene/resources/cylinder_shape.h create mode 100644 scene/resources/cylinder_shape_3d.cpp create mode 100644 scene/resources/cylinder_shape_3d.h delete mode 100644 scene/resources/shape.cpp delete mode 100644 scene/resources/shape.h create mode 100644 scene/resources/shape_3d.cpp create mode 100644 scene/resources/shape_3d.h delete mode 100644 scene/resources/sphere_shape.cpp delete mode 100644 scene/resources/sphere_shape.h create mode 100644 scene/resources/sphere_shape_3d.cpp create mode 100644 scene/resources/sphere_shape_3d.h delete mode 100644 scene/resources/world_margin_shape.cpp delete mode 100644 scene/resources/world_margin_shape.h create mode 100644 scene/resources/world_margin_shape_3d.cpp create mode 100644 scene/resources/world_margin_shape_3d.h diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 182b406705..4f06a753a7 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3554,7 +3554,7 @@ void AnimationTrackEditor::_insert_delay() { insert_queue = false; } -void AnimationTrackEditor::insert_transform_key(Spatial *p_node, const String &p_sub, const Transform &p_xform) { +void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform &p_xform) { if (!keying) return; @@ -4446,8 +4446,8 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) { ERR_FAIL_COND(!node); NodePath path_to = root->get_path_to(node); - if (adding_track_type == Animation::TYPE_TRANSFORM && !node->is_class("Spatial")) { - EditorNode::get_singleton()->show_warning(TTR("Transform tracks only apply to Spatial-based nodes.")); + if (adding_track_type == Animation::TYPE_TRANSFORM && !node->is_class("Node3D")) { + EditorNode::get_singleton()->show_warning(TTR("Transform tracks only apply to 3D-based nodes.")); return; } @@ -4638,10 +4638,10 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { EditorNode::get_singleton()->show_warning(TTR("Track path is invalid, so can't add a key.")); return; } - Spatial *base = Object::cast_to(root->get_node(animation->track_get_path(p_track))); + Node3D *base = Object::cast_to(root->get_node(animation->track_get_path(p_track))); if (!base) { - EditorNode::get_singleton()->show_warning(TTR("Track is not of type Spatial, can't insert key")); + EditorNode::get_singleton()->show_warning(TTR("Track is not of type Node3D, can't insert key")); return; } diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 7f13716b67..7c4cc6db53 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -513,7 +513,7 @@ public: void set_anim_pos(float p_pos); void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false); void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance); - void insert_transform_key(Spatial *p_node, const String &p_sub, const Transform &p_xform); + void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform &p_xform); void show_select_node_warning(bool p_show); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 7effe114ca..ea0d7511fe 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -33,8 +33,8 @@ #include "editor/audio_stream_preview.h" #include "editor_resource_preview.h" #include "editor_scale.h" -#include "scene/2d/animated_sprite.h" -#include "scene/2d/sprite.h" +#include "scene/2d/animated_sprite_2d.h" +#include "scene/2d/sprite_2d.h" #include "scene/3d/sprite_3d.h" #include "scene/animation/animation_player.h" #include "servers/audio/audio_stream.h" @@ -357,7 +357,7 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se Size2 size; - if (Object::cast_to(object) || Object::cast_to(object)) { + if (Object::cast_to(object) || Object::cast_to(object)) { Ref texture = object->call("get_texture"); if (!texture.is_valid()) { @@ -379,7 +379,7 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se if (vframes > 1) { size.y /= vframes; } - } else if (Object::cast_to(object) || Object::cast_to(object)) { + } else if (Object::cast_to(object) || Object::cast_to(object)) { Ref sf = object->call("get_sprite_frames"); if (sf.is_null()) { @@ -436,7 +436,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in Ref texture; Rect2 region; - if (Object::cast_to(object) || Object::cast_to(object)) { + if (Object::cast_to(object) || Object::cast_to(object)) { texture = object->call("get_texture"); if (!texture.is_valid()) { @@ -473,7 +473,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in region.position.x += region.size.x * coords.x; region.position.y += region.size.y * coords.y; - } else if (Object::cast_to(object) || Object::cast_to(object)) { + } else if (Object::cast_to(object) || Object::cast_to(object)) { Ref sf = object->call("get_sprite_frames"); if (sf.is_null()) { @@ -1300,14 +1300,14 @@ AnimationTrackEdit *AnimationTrackEditDefaultPlugin::create_value_track_edit(Obj return audio; } - if (p_property == "frame" && (p_object->is_class("Sprite") || p_object->is_class("Sprite3D") || p_object->is_class("AnimatedSprite") || p_object->is_class("AnimatedSprite3D"))) { + if (p_property == "frame" && (p_object->is_class("Sprite2D") || p_object->is_class("Sprite3D") || p_object->is_class("AnimatedSprite2D") || p_object->is_class("AnimatedSprite3D"))) { AnimationTrackEditSpriteFrame *sprite = memnew(AnimationTrackEditSpriteFrame); sprite->set_node(p_object); return sprite; } - if (p_property == "frame_coords" && (p_object->is_class("Sprite") || p_object->is_class("Sprite3D"))) { + if (p_property == "frame_coords" && (p_object->is_class("Sprite2D") || p_object->is_class("Sprite3D"))) { AnimationTrackEditSpriteFrame *sprite = memnew(AnimationTrackEditSpriteFrame); sprite->set_as_coords(); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 7526111eef..41ba7343d2 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -45,7 +45,7 @@ #include "editor/plugins/spatial_editor_plugin.h" #include "editor/property_editor.h" #include "main/performance.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" #include "scene/debugger/scene_debugger.h" #include "scene/gui/dialogs.h" #include "scene/gui/label.h" @@ -791,12 +791,12 @@ void ScriptEditorDebugger::_notification(int p_what) { } else if (camera_override >= CameraOverride::OVERRIDE_3D_1) { int viewport_idx = camera_override - CameraOverride::OVERRIDE_3D_1; - SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(viewport_idx); - Camera *const cam = viewport->get_camera(); + Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_editor_viewport(viewport_idx); + Camera3D *const cam = viewport->get_camera(); Array msg; msg.push_back(cam->get_camera_transform()); - if (cam->get_projection() == Camera::PROJECTION_ORTHOGONAL) { + if (cam->get_projection() == Camera3D::PROJECTION_ORTHOGONAL) { msg.push_back(false); msg.push_back(cam->get_size()); } else { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index ba02f8e99f..181811207c 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -646,7 +646,7 @@ void EditorProperty::_gui_input(const Ref &p_event) { emit_signal("property_keyed", property, use_keying_next()); if (use_keying_next()) { - if (property == "frame_coords" && (object->is_class("Sprite") || object->is_class("Sprite3D"))) { + if (property == "frame_coords" && (object->is_class("Sprite2D") || object->is_class("Sprite3D"))) { Vector2 new_coords = object->get(property); new_coords.x++; if (new_coords.x >= object->get("hframes").operator int64_t()) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 86d4b76ee2..70ee45f845 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1107,7 +1107,7 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) { if (p_node->is_class("CanvasItem")) count_2d++; - else if (p_node->is_class("Spatial")) + else if (p_node->is_class("Node3D")) count_3d++; for (int i = 0; i < p_node->get_child_count(); i++) @@ -1139,7 +1139,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { if (is2d) { img = scene_root->get_texture()->get_data(); } else { - img = SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); } if (img.is_valid()) { @@ -3595,8 +3595,8 @@ void EditorNode::register_editor_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::register_virtual_class(); @@ -6571,7 +6571,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(DebuggerEditorPlugin(this, debug_menu))); add_editor_plugin(memnew(AnimationPlayerEditorPlugin(this))); add_editor_plugin(memnew(CanvasItemEditorPlugin(this))); - add_editor_plugin(memnew(SpatialEditorPlugin(this))); + add_editor_plugin(memnew(Node3DEditorPlugin(this))); add_editor_plugin(memnew(ScriptEditorPlugin(this))); EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); @@ -6851,7 +6851,7 @@ bool EditorPluginList::forward_gui_input(const Ref &p_event) { return discard; } -bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref &p_event, bool serve_when_force_input_enabled) { +bool EditorPluginList::forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event, bool serve_when_force_input_enabled) { bool discard = false; for (int i = 0; i < plugins_list.size(); i++) { diff --git a/editor/editor_node.h b/editor/editor_node.h index 21025f2a50..9d251690d2 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -894,7 +894,7 @@ public: bool forward_gui_input(const Ref &p_event); void forward_canvas_draw_over_viewport(Control *p_overlay); void forward_canvas_force_draw_over_viewport(Control *p_overlay); - bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event, bool serve_when_force_input_enabled); + bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event, bool serve_when_force_input_enabled); void forward_spatial_draw_over_viewport(Control *p_overlay); void forward_spatial_force_draw_over_viewport(Control *p_overlay); void add_plugin(EditorPlugin *p_plugin); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 07a63c39ba..2ddd86f4fb 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -39,7 +39,7 @@ #include "main/main.h" #include "plugins/canvas_item_editor_plugin.h" #include "plugins/spatial_editor_plugin.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" #include "scene/gui/popup_menu.h" #include "servers/visual_server.h" @@ -371,24 +371,24 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C case CONTAINER_SPATIAL_EDITOR_MENU: { - SpatialEditor::get_singleton()->add_control_to_menu_panel(p_control); + Node3DEditor::get_singleton()->add_control_to_menu_panel(p_control); } break; case CONTAINER_SPATIAL_EDITOR_SIDE_LEFT: { - SpatialEditor::get_singleton()->get_palette_split()->add_child(p_control); - SpatialEditor::get_singleton()->get_palette_split()->move_child(p_control, 0); + Node3DEditor::get_singleton()->get_palette_split()->add_child(p_control); + Node3DEditor::get_singleton()->get_palette_split()->move_child(p_control, 0); } break; case CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT: { - SpatialEditor::get_singleton()->get_palette_split()->add_child(p_control); - SpatialEditor::get_singleton()->get_palette_split()->move_child(p_control, 1); + Node3DEditor::get_singleton()->get_palette_split()->add_child(p_control); + Node3DEditor::get_singleton()->get_palette_split()->move_child(p_control, 1); } break; case CONTAINER_SPATIAL_EDITOR_BOTTOM: { - SpatialEditor::get_singleton()->get_shader_split()->add_child(p_control); + Node3DEditor::get_singleton()->get_shader_split()->add_child(p_control); } break; case CONTAINER_CANVAS_EDITOR_MENU: { @@ -445,18 +445,18 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati case CONTAINER_SPATIAL_EDITOR_MENU: { - SpatialEditor::get_singleton()->remove_control_from_menu_panel(p_control); + Node3DEditor::get_singleton()->remove_control_from_menu_panel(p_control); } break; case CONTAINER_SPATIAL_EDITOR_SIDE_LEFT: case CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT: { - SpatialEditor::get_singleton()->get_palette_split()->remove_child(p_control); + Node3DEditor::get_singleton()->get_palette_split()->remove_child(p_control); } break; case CONTAINER_SPATIAL_EDITOR_BOTTOM: { - SpatialEditor::get_singleton()->get_shader_split()->remove_child(p_control); + Node3DEditor::get_singleton()->get_shader_split()->remove_child(p_control); } break; case CONTAINER_CANVAS_EDITOR_MENU: { @@ -562,10 +562,10 @@ void EditorPlugin::forward_canvas_force_draw_over_viewport(Control *p_overlay) { // Updates the overlays of the 2D viewport or, if in 3D mode, of every 3D viewport. int EditorPlugin::update_overlays() const { - if (SpatialEditor::get_singleton()->is_visible()) { + if (Node3DEditor::get_singleton()->is_visible()) { int count = 0; - for (uint32_t i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { - SpatialEditorViewport *vp = SpatialEditor::get_singleton()->get_editor_viewport(i); + for (uint32_t i = 0; i < Node3DEditor::VIEWPORTS_COUNT; i++) { + Node3DEditorViewport *vp = Node3DEditor::get_singleton()->get_editor_viewport(i); if (vp->is_visible()) { vp->update_surface(); count++; @@ -579,7 +579,7 @@ int EditorPlugin::update_overlays() const { } } -bool EditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref &p_event) { +bool EditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event) { if (get_script_instance() && get_script_instance()->has_method("forward_spatial_gui_input")) { return get_script_instance()->call("forward_spatial_gui_input", p_camera, p_event); @@ -724,12 +724,12 @@ void EditorPlugin::remove_export_plugin(const Ref &p_exporte EditorExport::get_singleton()->remove_export_plugin(p_exporter); } -void EditorPlugin::add_spatial_gizmo_plugin(const Ref &p_gizmo_plugin) { - SpatialEditor::get_singleton()->add_gizmo_plugin(p_gizmo_plugin); +void EditorPlugin::add_spatial_gizmo_plugin(const Ref &p_gizmo_plugin) { + Node3DEditor::get_singleton()->add_gizmo_plugin(p_gizmo_plugin); } -void EditorPlugin::remove_spatial_gizmo_plugin(const Ref &p_gizmo_plugin) { - SpatialEditor::get_singleton()->remove_gizmo_plugin(p_gizmo_plugin); +void EditorPlugin::remove_spatial_gizmo_plugin(const Ref &p_gizmo_plugin) { + Node3DEditor::get_singleton()->remove_gizmo_plugin(p_gizmo_plugin); } void EditorPlugin::add_inspector_plugin(const Ref &p_plugin) { @@ -865,7 +865,7 @@ void EditorPlugin::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "get_plugin_icon")); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "has_main_screen")); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index cd3f4d0638..12b042d0e5 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -42,14 +42,14 @@ #include "scene/resources/texture.h" class EditorNode; -class Spatial; -class Camera; +class Node3D; +class Camera3D; class EditorSelection; class EditorExport; class EditorSettings; class EditorImportPlugin; class EditorExportPlugin; -class EditorSpatialGizmoPlugin; +class EditorNode3DGizmoPlugin; class EditorResourcePreview; class EditorFileSystem; class EditorToolAddons; @@ -185,7 +185,7 @@ public: virtual void forward_canvas_draw_over_viewport(Control *p_overlay); virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay); - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event); + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event); virtual void forward_spatial_draw_over_viewport(Control *p_overlay); virtual void forward_spatial_force_draw_over_viewport(Control *p_overlay); @@ -227,8 +227,8 @@ public: void add_export_plugin(const Ref &p_exporter); void remove_export_plugin(const Ref &p_exporter); - void add_spatial_gizmo_plugin(const Ref &p_gizmo_plugin); - void remove_spatial_gizmo_plugin(const Ref &p_gizmo_plugin); + void add_spatial_gizmo_plugin(const Ref &p_gizmo_plugin); + void remove_spatial_gizmo_plugin(const Ref &p_gizmo_plugin); void add_inspector_plugin(const Ref &p_plugin); void remove_inspector_plugin(const Ref &p_plugin); diff --git a/editor/icons/AnimatedSprite.svg b/editor/icons/AnimatedSprite.svg deleted file mode 100644 index 411ddda015..0000000000 --- a/editor/icons/AnimatedSprite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/AnimatedSprite2D.svg b/editor/icons/AnimatedSprite2D.svg new file mode 100644 index 0000000000..411ddda015 --- /dev/null +++ b/editor/icons/AnimatedSprite2D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Area.svg b/editor/icons/Area.svg deleted file mode 100644 index 21ebe3c251..0000000000 --- a/editor/icons/Area.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Area3D.svg b/editor/icons/Area3D.svg new file mode 100644 index 0000000000..21ebe3c251 --- /dev/null +++ b/editor/icons/Area3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/BoneAttachment.svg b/editor/icons/BoneAttachment.svg deleted file mode 100644 index 0b7dede0b6..0000000000 --- a/editor/icons/BoneAttachment.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/BoneAttachment3D.svg b/editor/icons/BoneAttachment3D.svg new file mode 100644 index 0000000000..0b7dede0b6 --- /dev/null +++ b/editor/icons/BoneAttachment3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/CPUParticles.svg b/editor/icons/CPUParticles.svg deleted file mode 100644 index af4115c93f..0000000000 --- a/editor/icons/CPUParticles.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/CPUParticles3D.svg b/editor/icons/CPUParticles3D.svg new file mode 100644 index 0000000000..af4115c93f --- /dev/null +++ b/editor/icons/CPUParticles3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Camera.svg b/editor/icons/Camera.svg deleted file mode 100644 index af1cb8a2e9..0000000000 --- a/editor/icons/Camera.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Camera3D.svg b/editor/icons/Camera3D.svg new file mode 100644 index 0000000000..af1cb8a2e9 --- /dev/null +++ b/editor/icons/Camera3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/CapsuleShape.svg b/editor/icons/CapsuleShape.svg deleted file mode 100644 index ba035ca196..0000000000 --- a/editor/icons/CapsuleShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/CapsuleShape3D.svg b/editor/icons/CapsuleShape3D.svg new file mode 100644 index 0000000000..ba035ca196 --- /dev/null +++ b/editor/icons/CapsuleShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/CollisionPolygon.svg b/editor/icons/CollisionPolygon.svg deleted file mode 100644 index 5e849ae4e3..0000000000 --- a/editor/icons/CollisionPolygon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/CollisionPolygon3D.svg b/editor/icons/CollisionPolygon3D.svg new file mode 100644 index 0000000000..5e849ae4e3 --- /dev/null +++ b/editor/icons/CollisionPolygon3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/CollisionShape.svg b/editor/icons/CollisionShape.svg deleted file mode 100644 index 8f14996a97..0000000000 --- a/editor/icons/CollisionShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/CollisionShape3D.svg b/editor/icons/CollisionShape3D.svg new file mode 100644 index 0000000000..8f14996a97 --- /dev/null +++ b/editor/icons/CollisionShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/ConcavePolygonShape.svg b/editor/icons/ConcavePolygonShape.svg deleted file mode 100644 index 001ab82826..0000000000 --- a/editor/icons/ConcavePolygonShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/ConcavePolygonShape3D.svg b/editor/icons/ConcavePolygonShape3D.svg new file mode 100644 index 0000000000..001ab82826 --- /dev/null +++ b/editor/icons/ConcavePolygonShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/ConeTwistJoint.svg b/editor/icons/ConeTwistJoint.svg deleted file mode 100644 index 0e5e98a17b..0000000000 --- a/editor/icons/ConeTwistJoint.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/ConeTwistJoint3D.svg b/editor/icons/ConeTwistJoint3D.svg new file mode 100644 index 0000000000..0e5e98a17b --- /dev/null +++ b/editor/icons/ConeTwistJoint3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/ConvexPolygonShape.svg b/editor/icons/ConvexPolygonShape.svg deleted file mode 100644 index bfb9230586..0000000000 --- a/editor/icons/ConvexPolygonShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/ConvexPolygonShape3D.svg b/editor/icons/ConvexPolygonShape3D.svg new file mode 100644 index 0000000000..bfb9230586 --- /dev/null +++ b/editor/icons/ConvexPolygonShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/CylinderShape.svg b/editor/icons/CylinderShape.svg deleted file mode 100644 index f0aa5833d2..0000000000 --- a/editor/icons/CylinderShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/CylinderShape3D.svg b/editor/icons/CylinderShape3D.svg new file mode 100644 index 0000000000..f0aa5833d2 --- /dev/null +++ b/editor/icons/CylinderShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/DirectionalLight.svg b/editor/icons/DirectionalLight.svg deleted file mode 100644 index faac2be134..0000000000 --- a/editor/icons/DirectionalLight.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/DirectionalLight3D.svg b/editor/icons/DirectionalLight3D.svg new file mode 100644 index 0000000000..faac2be134 --- /dev/null +++ b/editor/icons/DirectionalLight3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/GPUParticles2D.svg b/editor/icons/GPUParticles2D.svg new file mode 100644 index 0000000000..7151194e36 --- /dev/null +++ b/editor/icons/GPUParticles2D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/GPUParticles3D.svg b/editor/icons/GPUParticles3D.svg new file mode 100644 index 0000000000..f1378e3f8c --- /dev/null +++ b/editor/icons/GPUParticles3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Generic6DOFJoint.svg b/editor/icons/Generic6DOFJoint.svg deleted file mode 100644 index 30d892e7a1..0000000000 --- a/editor/icons/Generic6DOFJoint.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Generic6DOFJoint3D.svg b/editor/icons/Generic6DOFJoint3D.svg new file mode 100644 index 0000000000..30d892e7a1 --- /dev/null +++ b/editor/icons/Generic6DOFJoint3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Gizmo3DSamplePlayer.svg b/editor/icons/Gizmo3DSamplePlayer.svg new file mode 100644 index 0000000000..ee471124dc --- /dev/null +++ b/editor/icons/Gizmo3DSamplePlayer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/GizmoSpatialSamplePlayer.svg b/editor/icons/GizmoSpatialSamplePlayer.svg deleted file mode 100644 index ee471124dc..0000000000 --- a/editor/icons/GizmoSpatialSamplePlayer.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/HingeJoint.svg b/editor/icons/HingeJoint.svg deleted file mode 100644 index 21b3e29cb5..0000000000 --- a/editor/icons/HingeJoint.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/HingeJoint3D.svg b/editor/icons/HingeJoint3D.svg new file mode 100644 index 0000000000..21b3e29cb5 --- /dev/null +++ b/editor/icons/HingeJoint3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/ImmediateGeometry.svg b/editor/icons/ImmediateGeometry.svg deleted file mode 100644 index 5679d5906f..0000000000 --- a/editor/icons/ImmediateGeometry.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/ImmediateGeometry3D.svg b/editor/icons/ImmediateGeometry3D.svg new file mode 100644 index 0000000000..5679d5906f --- /dev/null +++ b/editor/icons/ImmediateGeometry3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/KinematicBody.svg b/editor/icons/KinematicBody.svg deleted file mode 100644 index 16078fbdec..0000000000 --- a/editor/icons/KinematicBody.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/KinematicBody3D.svg b/editor/icons/KinematicBody3D.svg new file mode 100644 index 0000000000..16078fbdec --- /dev/null +++ b/editor/icons/KinematicBody3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Listener.svg b/editor/icons/Listener.svg deleted file mode 100644 index 96eaeaffa9..0000000000 --- a/editor/icons/Listener.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Listener3D.svg b/editor/icons/Listener3D.svg new file mode 100644 index 0000000000..96eaeaffa9 --- /dev/null +++ b/editor/icons/Listener3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/MeshInstance.svg b/editor/icons/MeshInstance.svg deleted file mode 100644 index 68344b7dbd..0000000000 --- a/editor/icons/MeshInstance.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/MeshInstance3D.svg b/editor/icons/MeshInstance3D.svg new file mode 100644 index 0000000000..68344b7dbd --- /dev/null +++ b/editor/icons/MeshInstance3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/MultiMeshInstance.svg b/editor/icons/MultiMeshInstance.svg deleted file mode 100644 index c114a725db..0000000000 --- a/editor/icons/MultiMeshInstance.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/MultiMeshInstance3D.svg b/editor/icons/MultiMeshInstance3D.svg new file mode 100644 index 0000000000..c114a725db --- /dev/null +++ b/editor/icons/MultiMeshInstance3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Navigation.svg b/editor/icons/Navigation.svg deleted file mode 100644 index d5a8f8618b..0000000000 --- a/editor/icons/Navigation.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Navigation3D.svg b/editor/icons/Navigation3D.svg new file mode 100644 index 0000000000..d5a8f8618b --- /dev/null +++ b/editor/icons/Navigation3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/NavigationAgent.svg b/editor/icons/NavigationAgent.svg deleted file mode 100644 index 44c991d44c..0000000000 --- a/editor/icons/NavigationAgent.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/NavigationAgent3D.svg b/editor/icons/NavigationAgent3D.svg new file mode 100644 index 0000000000..44c991d44c --- /dev/null +++ b/editor/icons/NavigationAgent3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/NavigationObstacle.svg b/editor/icons/NavigationObstacle.svg deleted file mode 100644 index 42481a6067..0000000000 --- a/editor/icons/NavigationObstacle.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/NavigationObstacle3D.svg b/editor/icons/NavigationObstacle3D.svg new file mode 100644 index 0000000000..42481a6067 --- /dev/null +++ b/editor/icons/NavigationObstacle3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/NavigationRegion.svg b/editor/icons/NavigationRegion.svg deleted file mode 100644 index 61f43497b4..0000000000 --- a/editor/icons/NavigationRegion.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/NavigationRegion3D.svg b/editor/icons/NavigationRegion3D.svg new file mode 100644 index 0000000000..61f43497b4 --- /dev/null +++ b/editor/icons/NavigationRegion3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Node3D.svg b/editor/icons/Node3D.svg new file mode 100644 index 0000000000..6a469dde13 --- /dev/null +++ b/editor/icons/Node3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/OmniLight.svg b/editor/icons/OmniLight.svg deleted file mode 100644 index 6fa0454e8c..0000000000 --- a/editor/icons/OmniLight.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/OmniLight3D.svg b/editor/icons/OmniLight3D.svg new file mode 100644 index 0000000000..6fa0454e8c --- /dev/null +++ b/editor/icons/OmniLight3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Particles.svg b/editor/icons/Particles.svg deleted file mode 100644 index f1378e3f8c..0000000000 --- a/editor/icons/Particles.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Particles2D.svg b/editor/icons/Particles2D.svg deleted file mode 100644 index 7151194e36..0000000000 --- a/editor/icons/Particles2D.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Path.svg b/editor/icons/Path.svg deleted file mode 100644 index cde9a06903..0000000000 --- a/editor/icons/Path.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Path3D.svg b/editor/icons/Path3D.svg new file mode 100644 index 0000000000..cde9a06903 --- /dev/null +++ b/editor/icons/Path3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/PathFollow.svg b/editor/icons/PathFollow.svg deleted file mode 100644 index 8e904ab5a5..0000000000 --- a/editor/icons/PathFollow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/PathFollow3D.svg b/editor/icons/PathFollow3D.svg new file mode 100644 index 0000000000..8e904ab5a5 --- /dev/null +++ b/editor/icons/PathFollow3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/PhysicalBone.svg b/editor/icons/PhysicalBone.svg deleted file mode 100644 index 0a34eb6e48..0000000000 --- a/editor/icons/PhysicalBone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/PhysicalBone3D.svg b/editor/icons/PhysicalBone3D.svg new file mode 100644 index 0000000000..0a34eb6e48 --- /dev/null +++ b/editor/icons/PhysicalBone3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/PinJoint.svg b/editor/icons/PinJoint.svg deleted file mode 100644 index 147553d316..0000000000 --- a/editor/icons/PinJoint.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/PinJoint3D.svg b/editor/icons/PinJoint3D.svg new file mode 100644 index 0000000000..147553d316 --- /dev/null +++ b/editor/icons/PinJoint3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/ProximityGroup.svg b/editor/icons/ProximityGroup.svg deleted file mode 100644 index 7df1cc9093..0000000000 --- a/editor/icons/ProximityGroup.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/ProximityGroup3D.svg b/editor/icons/ProximityGroup3D.svg new file mode 100644 index 0000000000..7df1cc9093 --- /dev/null +++ b/editor/icons/ProximityGroup3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/RayCast.svg b/editor/icons/RayCast.svg deleted file mode 100644 index e782b27e9f..0000000000 --- a/editor/icons/RayCast.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/RayCast3D.svg b/editor/icons/RayCast3D.svg new file mode 100644 index 0000000000..e782b27e9f --- /dev/null +++ b/editor/icons/RayCast3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/RayShape.svg b/editor/icons/RayShape.svg deleted file mode 100644 index 37c2206740..0000000000 --- a/editor/icons/RayShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/RayShape3D.svg b/editor/icons/RayShape3D.svg new file mode 100644 index 0000000000..37c2206740 --- /dev/null +++ b/editor/icons/RayShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/RemoteTransform.svg b/editor/icons/RemoteTransform.svg deleted file mode 100644 index 2bdf8cd858..0000000000 --- a/editor/icons/RemoteTransform.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/RemoteTransform3D.svg b/editor/icons/RemoteTransform3D.svg new file mode 100644 index 0000000000..2bdf8cd858 --- /dev/null +++ b/editor/icons/RemoteTransform3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/RigidBody.svg b/editor/icons/RigidBody.svg deleted file mode 100644 index 5d766f7c3d..0000000000 --- a/editor/icons/RigidBody.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/RigidBody3D.svg b/editor/icons/RigidBody3D.svg new file mode 100644 index 0000000000..5d766f7c3d --- /dev/null +++ b/editor/icons/RigidBody3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Skeleton.svg b/editor/icons/Skeleton.svg deleted file mode 100644 index 015c842125..0000000000 --- a/editor/icons/Skeleton.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Skeleton3D.svg b/editor/icons/Skeleton3D.svg new file mode 100644 index 0000000000..015c842125 --- /dev/null +++ b/editor/icons/Skeleton3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SkeletonIK.svg b/editor/icons/SkeletonIK.svg deleted file mode 100644 index e69f6e8bf3..0000000000 --- a/editor/icons/SkeletonIK.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SkeletonIK3D.svg b/editor/icons/SkeletonIK3D.svg new file mode 100644 index 0000000000..e69f6e8bf3 --- /dev/null +++ b/editor/icons/SkeletonIK3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SliderJoint.svg b/editor/icons/SliderJoint.svg deleted file mode 100644 index fdd7487bbf..0000000000 --- a/editor/icons/SliderJoint.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SliderJoint3D.svg b/editor/icons/SliderJoint3D.svg new file mode 100644 index 0000000000..fdd7487bbf --- /dev/null +++ b/editor/icons/SliderJoint3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SoftBody.svg b/editor/icons/SoftBody.svg deleted file mode 100644 index 2c907df847..0000000000 --- a/editor/icons/SoftBody.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SoftBody3D.svg b/editor/icons/SoftBody3D.svg new file mode 100644 index 0000000000..2c907df847 --- /dev/null +++ b/editor/icons/SoftBody3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Spatial.svg b/editor/icons/Spatial.svg deleted file mode 100644 index 6a469dde13..0000000000 --- a/editor/icons/Spatial.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SphereShape.svg b/editor/icons/SphereShape.svg deleted file mode 100644 index 4da18a1a38..0000000000 --- a/editor/icons/SphereShape.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SphereShape3D.svg b/editor/icons/SphereShape3D.svg new file mode 100644 index 0000000000..4da18a1a38 --- /dev/null +++ b/editor/icons/SphereShape3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SpotLight.svg b/editor/icons/SpotLight.svg deleted file mode 100644 index 6a35ee3890..0000000000 --- a/editor/icons/SpotLight.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SpotLight3D.svg b/editor/icons/SpotLight3D.svg new file mode 100644 index 0000000000..6a35ee3890 --- /dev/null +++ b/editor/icons/SpotLight3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SpringArm.svg b/editor/icons/SpringArm.svg deleted file mode 100644 index eb0c1ebd7d..0000000000 --- a/editor/icons/SpringArm.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/SpringArm3D.svg b/editor/icons/SpringArm3D.svg new file mode 100644 index 0000000000..eb0c1ebd7d --- /dev/null +++ b/editor/icons/SpringArm3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/Sprite.svg b/editor/icons/Sprite.svg deleted file mode 100644 index 26a10625fc..0000000000 --- a/editor/icons/Sprite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/Sprite2D.svg b/editor/icons/Sprite2D.svg new file mode 100644 index 0000000000..26a10625fc --- /dev/null +++ b/editor/icons/Sprite2D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/StaticBody.svg b/editor/icons/StaticBody.svg deleted file mode 100644 index de819bd76b..0000000000 --- a/editor/icons/StaticBody.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/StaticBody3D.svg b/editor/icons/StaticBody3D.svg new file mode 100644 index 0000000000..de819bd76b --- /dev/null +++ b/editor/icons/StaticBody3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/VisibilityEnabler.svg b/editor/icons/VisibilityEnabler.svg deleted file mode 100644 index 70e4f081c2..0000000000 --- a/editor/icons/VisibilityEnabler.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/VisibilityEnabler3D.svg b/editor/icons/VisibilityEnabler3D.svg new file mode 100644 index 0000000000..70e4f081c2 --- /dev/null +++ b/editor/icons/VisibilityEnabler3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/VisibilityNotifier.svg b/editor/icons/VisibilityNotifier.svg deleted file mode 100644 index c908d5c99d..0000000000 --- a/editor/icons/VisibilityNotifier.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/editor/icons/VisibilityNotifier3D.svg b/editor/icons/VisibilityNotifier3D.svg new file mode 100644 index 0000000000..c908d5c99d --- /dev/null +++ b/editor/icons/VisibilityNotifier3D.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index f7da8c27f9..e67dd37b88 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -33,12 +33,12 @@ #include "core/os/os.h" #include "editor/editor_node.h" #include "editor/import/collada.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/path.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/path_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/packed_scene.h" @@ -47,13 +47,13 @@ struct ColladaImport { Collada collada; - Spatial *scene; + Node3D *scene; Vector> animations; struct NodeMap { //String path; - Spatial *node; + Node3D *node; int bone; List anim_tracks; @@ -76,17 +76,17 @@ struct ColladaImport { Map> mesh_cache; Map> curve_cache; Map> material_cache; - Map skeleton_map; + Map skeleton_map; - Map> skeleton_bone_map; + Map> skeleton_bone_map; Set valid_animated_nodes; Vector valid_animated_properties; Map bones_with_animation; - Error _populate_skeleton(Skeleton *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); + Error _populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); Error _create_scene_skeletons(Collada::Node *p_node); - Error _create_scene(Collada::Node *p_node, Spatial *p_parent); + Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_material(const String &p_target); Error _create_mesh_surfaces(bool p_optimize, Ref &p_mesh, const Map &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector> p_morph_meshes = Vector>(), bool p_use_compression = false, bool p_use_mesh_material = false); @@ -110,7 +110,7 @@ struct ColladaImport { } }; -Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent) { +Error ColladaImport::_populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent) { if (p_node->type != Collada::Node::TYPE_JOINT) return OK; @@ -174,7 +174,7 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { if (p_node->type == Collada::Node::TYPE_SKELETON) { - Skeleton *sk = memnew(Skeleton); + Skeleton3D *sk = memnew(Skeleton3D); int bone = 0; for (int i = 0; i < p_node->children.size(); i++) { @@ -193,15 +193,15 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { return OK; } -Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { +Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { - Spatial *node = NULL; + Node3D *node = NULL; switch (p_node->type) { case Collada::Node::TYPE_NODE: { - node = memnew(Spatial); + node = memnew(Node3D); } break; case Collada::Node::TYPE_JOINT: { @@ -223,7 +223,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (!bool(GLOBAL_DEF("collada/use_ambient", false))) return OK; //well, it's an ambient light.. - Light *l = memnew(DirectionalLight); + Light3D *l = memnew(DirectionalLight3D); //l->set_color(Light::COLOR_AMBIENT,ld.color); //l->set_color(Light::COLOR_DIFFUSE,Color(0,0,0)); //l->set_color(Light::COLOR_SPECULAR,Color(0,0,0)); @@ -232,7 +232,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else if (ld.mode == Collada::LightData::MODE_DIRECTIONAL) { //well, it's an ambient light.. - Light *l = memnew(DirectionalLight); + Light3D *l = memnew(DirectionalLight3D); /* if (found_ambient) //use it here l->set_color(Light::COLOR_AMBIENT,ambient); @@ -243,12 +243,12 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { node = l; } else { - Light *l; + Light3D *l; if (ld.mode == Collada::LightData::MODE_OMNI) - l = memnew(OmniLight); + l = memnew(OmniLight3D); else { - l = memnew(SpotLight); + l = memnew(SpotLight3D); //l->set_parameter(Light::PARAM_SPOT_ANGLE,ld.spot_angle); //l->set_parameter(Light::PARAM_SPOT_ATTENUATION,ld.spot_exp); } @@ -262,13 +262,13 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else { - node = memnew(Spatial); + node = memnew(Node3D); } } break; case Collada::Node::TYPE_CAMERA: { Collada::NodeCamera *cam = static_cast(p_node); - Camera *camera = memnew(Camera); + Camera3D *camera = memnew(Camera3D); if (collada.state.camera_data_map.has(cam->camera)) { @@ -280,12 +280,12 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (cd.orthogonal.y_mag) { - camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT); + camera->set_keep_aspect_mode(Camera3D::KEEP_HEIGHT); camera->set_orthogonal(cd.orthogonal.y_mag * 2.0, cd.z_near, cd.z_far); } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) { - camera->set_keep_aspect_mode(Camera::KEEP_WIDTH); + camera->set_keep_aspect_mode(Camera3D::KEEP_WIDTH); camera->set_orthogonal(cd.orthogonal.x_mag * 2.0, cd.z_near, cd.z_far); } @@ -314,17 +314,17 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (collada.state.curve_data_map.has(ng->source)) { - node = memnew(Path); + node = memnew(Path3D); } else { //mesh since nothing else - node = memnew(MeshInstance); + node = memnew(MeshInstance3D); //Object::cast_to(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); } } break; case Collada::Node::TYPE_SKELETON: { ERR_FAIL_COND_V(!skeleton_map.has(p_node), ERR_CANT_CREATE); - Skeleton *sk = skeleton_map[p_node]; + Skeleton3D *sk = skeleton_map[p_node]; node = sk; } break; } @@ -1010,12 +1010,12 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres if (p_node->type == Collada::Node::TYPE_GEOMETRY && node_map.has(p_node->id)) { - Spatial *node = node_map[p_node->id].node; + Node3D *node = node_map[p_node->id].node; Collada::NodeGeometry *ng = static_cast(p_node); - if (Object::cast_to(node)) { + if (Object::cast_to(node)) { - Path *path = Object::cast_to(node); + Path3D *path = Object::cast_to(node); if (curve_cache.has(ng->source)) { @@ -1083,11 +1083,11 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } } - if (Object::cast_to(node)) { + if (Object::cast_to(node)) { Collada::NodeGeometry *ng2 = static_cast(p_node); - MeshInstance *mi = Object::cast_to(node); + MeshInstance3D *mi = Object::cast_to(node); ERR_FAIL_COND_V(!mi, ERR_BUG); @@ -1114,7 +1114,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres String skname = skeletons[0]; ERR_FAIL_COND_V(!node_map.has(skname), ERR_INVALID_DATA); NodeMap nmsk = node_map[skname]; - Skeleton *sk = Object::cast_to(nmsk.node); + Skeleton3D *sk = Object::cast_to(nmsk.node); ERR_FAIL_COND_V(!sk, ERR_INVALID_DATA); ERR_FAIL_COND_V(!skeleton_bone_map.has(sk), ERR_INVALID_DATA); Map &bone_remap_map = skeleton_bone_map[sk]; @@ -1265,7 +1265,7 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t ERR_FAIL_COND_V(!collada.state.visual_scene_map.has(collada.state.root_visual_scene), ERR_INVALID_DATA); Collada::VisualScene &vs = collada.state.visual_scene_map[collada.state.root_visual_scene]; - scene = memnew(Spatial); // root + scene = memnew(Node3D); // root //determine what's going on with the lights for (int i = 0; i < vs.root_nodes.size(); i++) { @@ -1530,7 +1530,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones String path = scene->get_path_to(nm.node); if (nm.bone >= 0) { - Skeleton *sk = static_cast(nm.node); + Skeleton3D *sk = static_cast(nm.node); String name = sk->get_bone_name(nm.bone); path = path + ":" + name; } @@ -1621,7 +1621,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (nm.bone >= 0) { //make bone transform relative to rest (in case of skeleton) - Skeleton *sk = Object::cast_to(nm.node); + Skeleton3D *sk = Object::cast_to(nm.node); if (sk) { xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform; @@ -1662,7 +1662,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones NodeMap &nm = node_map[E->key()]; String path = scene->get_path_to(nm.node); ERR_CONTINUE(nm.bone < 0); - Skeleton *sk = static_cast(nm.node); + Skeleton3D *sk = static_cast(nm.node); String name = sk->get_bone_name(nm.bone); path = path + ":" + name; diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 398fc9ff49..208dc8fc26 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -37,9 +37,9 @@ #include "core/os/file_access.h" #include "core/os/os.h" #include "modules/regex/regex.h" -#include "scene/3d/bone_attachment.h" -#include "scene/3d/camera.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/bone_attachment_3d.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/surface_tool.h" @@ -2108,7 +2108,7 @@ Error EditorSceneImporterGLTF::_create_skeletons(GLTFState &state) { GLTFSkeleton &gltf_skeleton = state.skeletons.write[skel_i]; - Skeleton *skeleton = memnew(Skeleton); + Skeleton3D *skeleton = memnew(Skeleton3D); gltf_skeleton.godot_skeleton = skeleton; // Make a unique name, no gltf node represents this skeleton @@ -2485,12 +2485,12 @@ void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) { } } -BoneAttachment *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index) { +BoneAttachment3D *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; const GLTFNode *bone_node = state.nodes[gltf_node->parent]; - BoneAttachment *bone_attachment = memnew(BoneAttachment); + BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D); print_verbose("glTF: Creating bone attachment for: " + gltf_node->name); ERR_FAIL_COND_V(!bone_node->joint, nullptr); @@ -2500,12 +2500,12 @@ BoneAttachment *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &st return bone_attachment; } -MeshInstance *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +MeshInstance3D *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->mesh, state.meshes.size(), nullptr); - MeshInstance *mi = memnew(MeshInstance); + MeshInstance3D *mi = memnew(MeshInstance3D); print_verbose("glTF: Creating mesh for: " + gltf_node->name); GLTFMesh &mesh = state.meshes.write[gltf_node->mesh]; @@ -2522,12 +2522,12 @@ MeshInstance *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, return mi; } -Camera *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +Camera3D *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->camera, state.cameras.size(), nullptr); - Camera *camera = memnew(Camera); + Camera3D *camera = memnew(Camera3D); print_verbose("glTF: Creating camera for: " + gltf_node->name); const GLTFCamera &c = state.cameras[gltf_node->camera]; @@ -2540,26 +2540,26 @@ Camera *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_ return camera; } -Spatial *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +Node3D *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; - Spatial *spatial = memnew(Spatial); + Node3D *spatial = memnew(Node3D); print_verbose("glTF: Creating spatial for: " + gltf_node->name); return spatial; } -void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) { +void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; - Spatial *current_node = nullptr; + Node3D *current_node = nullptr; // Is our parent a skeleton - Skeleton *active_skeleton = Object::cast_to(scene_parent); + Skeleton3D *active_skeleton = Object::cast_to(scene_parent); if (gltf_node->skeleton >= 0) { - Skeleton *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton; + Skeleton3D *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton; if (active_skeleton != skeleton) { ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons"); @@ -2577,7 +2577,7 @@ void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) { - BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); + BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); @@ -2776,7 +2776,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye const GLTFNode *node = state.nodes[E->key()]; if (node->skeleton >= 0) { - const Skeleton *sk = Object::cast_to(state.scene_nodes.find(node_index)->get()); + const Skeleton3D *sk = Object::cast_to(state.scene_nodes.find(node_index)->get()); ERR_FAIL_COND(sk == nullptr); const String path = ap->get_parent()->get_path_to(sk); @@ -2853,7 +2853,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye xform.basis.set_quat_scale(rot, scale); xform.origin = pos; - const Skeleton *skeleton = state.skeletons[node->skeleton].godot_skeleton; + const Skeleton3D *skeleton = state.skeletons[node->skeleton].godot_skeleton; const int bone_idx = skeleton->find_bone(node->name); xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform; @@ -2922,7 +2922,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye ap->add_animation(name, animation); } -void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial *scene_root) { +void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Node3D *scene_root) { for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) { const GLTFNode *node = state.nodes[node_i]; @@ -2930,12 +2930,12 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial const GLTFSkinIndex skin_i = node->skin; Map::Element *mi_element = state.scene_nodes.find(node_i); - MeshInstance *mi = Object::cast_to(mi_element->get()); + MeshInstance3D *mi = Object::cast_to(mi_element->get()); ERR_FAIL_COND(mi == nullptr); const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton; const GLTFSkeleton &gltf_skeleton = state.skeletons[skel_i]; - Skeleton *skeleton = gltf_skeleton.godot_skeleton; + Skeleton3D *skeleton = gltf_skeleton.godot_skeleton; ERR_FAIL_COND(skeleton == nullptr); mi->get_parent()->remove_child(mi); @@ -2949,9 +2949,9 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial } } -Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) { +Node3D *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) { - Spatial *root = memnew(Spatial); + Node3D *root = memnew(Node3D); // scene_name is already unique root->set_name(state.scene_name); @@ -3084,7 +3084,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla _assign_scene_names(state); /* STEP 17 MAKE SCENE! */ - Spatial *scene = _generate_scene(state, p_bake_fps); + Node3D *scene = _generate_scene(state, p_bake_fps); return scene; } diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h index 9f354fde2d..79395cca93 100644 --- a/editor/import/editor_scene_importer_gltf.h +++ b/editor/import/editor_scene_importer_gltf.h @@ -32,12 +32,12 @@ #define EDITOR_SCENE_IMPORTER_GLTF_H #include "editor/import/resource_importer_scene.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" class AnimationPlayer; -class BoneAttachment; -class MeshInstance; +class BoneAttachment3D; +class MeshInstance3D; class EditorSceneImporterGLTF : public EditorSceneImporter { @@ -192,7 +192,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector roots; // The created Skeleton for the scene - Skeleton *godot_skeleton; + Skeleton3D *godot_skeleton; // Set of unique bone names for the skeleton Set unique_names; @@ -395,15 +395,15 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Error _parse_animations(GLTFState &state); - BoneAttachment *_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index); - MeshInstance *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - Camera *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - Spatial *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + BoneAttachment3D *_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index); + MeshInstance3D *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + Camera3D *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + Node3D *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - void _generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index); - Spatial *_generate_scene(GLTFState &state, const int p_bake_fps); + void _generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index); + Node3D *_generate_scene(GLTFState &state, const int p_bake_fps); - void _process_mesh_instances(GLTFState &state, Spatial *scene_root); + void _process_mesh_instances(GLTFState &state, Node3D *scene_root); void _assign_scene_names(GLTFState &state); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index fb1782cb65..4be6f2ed80 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -32,8 +32,8 @@ #include "core/io/resource_saver.h" #include "core/os/file_access.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/surface_tool.h" @@ -431,11 +431,11 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in return NULL; } - Spatial *scene = memnew(Spatial); + Node3D *scene = memnew(Node3D); for (List>::Element *E = meshes.front(); E; E = E->next()) { - MeshInstance *mi = memnew(MeshInstance); + MeshInstance3D *mi = memnew(MeshInstance3D); mi->set_mesh(E->get()); mi->set_name(E->get()->get_name()); scene->add_child(mi); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 94a6fee6b7..16b5c00969 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -32,19 +32,19 @@ #include "core/io/resource_saver.h" #include "editor/editor_node.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation.h" -#include "scene/3d/physics_body.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/physics_body_3d.h" #include "scene/3d/vehicle_body.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" -#include "scene/resources/box_shape.h" +#include "scene/resources/box_shape_3d.h" #include "scene/resources/packed_scene.h" #include "scene/resources/ray_shape.h" #include "scene/resources/resource_format_text.h" -#include "scene/resources/sphere_shape.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/sphere_shape_3d.h" +#include "scene/resources/world_margin_shape_3d.h" uint32_t EditorSceneImporter::get_import_flags() const { @@ -276,15 +276,15 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _gen_shape_list(const Ref &mesh, List> &r_shape_list, bool p_convex) { +static void _gen_shape_list(const Ref &mesh, List> &r_shape_list, bool p_convex) { if (!p_convex) { - Ref shape = mesh->create_trimesh_shape(); + Ref shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); } else { - Vector> cd = mesh->convex_decompose(); + Vector> cd = mesh->convex_decompose(); if (cd.size()) { for (int i = 0; i < cd.size(); i++) { r_shape_list.push_back(cd[i]); @@ -293,7 +293,7 @@ static void _gen_shape_list(const Ref &mesh, List> &r_shape_lis } } -Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode) { +Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { @@ -314,9 +314,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map return NULL; } - if (Object::cast_to(p_node)) { + if (Object::cast_to(p_node)) { - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); Ref m = mi->get_mesh(); @@ -344,7 +344,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (p_light_bake_mode != LIGHT_BAKE_DISABLED) { - mi->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); + mi->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); } } @@ -377,12 +377,12 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (isroot) return p_node; - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); if (mi) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { - List> shapes; + List> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -404,7 +404,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_transform(mi->get_transform()); col->set_name(fixed_name); p_node->replace_by(col); @@ -412,9 +412,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map p_node = col; int idx = 0; - for (List>::Element *E = shapes.front(); E; E = E->next()) { + for (List>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -427,55 +427,55 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); - StaticBody *sb = memnew(StaticBody); + StaticBody3D *sb = memnew(StaticBody3D); sb->set_name(_fixstr(name, "colonly")); - Object::cast_to(sb)->set_transform(Object::cast_to(p_node)->get_transform()); + Object::cast_to(sb)->set_transform(Object::cast_to(p_node)->get_transform()); p_node->replace_by(sb); memdelete(p_node); p_node = NULL; - CollisionShape *colshape = memnew(CollisionShape); + CollisionShape3D *colshape = memnew(CollisionShape3D); if (empty_draw_type == "CUBE") { - BoxShape *boxShape = memnew(BoxShape); + BoxShape3D *boxShape = memnew(BoxShape3D); boxShape->set_extents(Vector3(1, 1, 1)); colshape->set_shape(boxShape); - colshape->set_name("BoxShape"); + colshape->set_name("BoxShape3D"); } else if (empty_draw_type == "SINGLE_ARROW") { - RayShape *rayShape = memnew(RayShape); + RayShape3D *rayShape = memnew(RayShape3D); rayShape->set_length(1); colshape->set_shape(rayShape); - colshape->set_name("RayShape"); - Object::cast_to(sb)->rotate_x(Math_PI / 2); + colshape->set_name("RayShape3D"); + Object::cast_to(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { - WorldMarginShape *world_margin_shape = memnew(WorldMarginShape); + WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); colshape->set_shape(world_margin_shape); colshape->set_name("WorldMarginShape"); } else { - SphereShape *sphereShape = memnew(SphereShape); + SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); colshape->set_shape(sphereShape); - colshape->set_name("SphereShape"); + colshape->set_name("SphereShape3D"); } sb->add_child(colshape); colshape->set_owner(sb->get_owner()); } - } else if (_teststr(name, "rigid") && Object::cast_to(p_node)) { + } else if (_teststr(name, "rigid") && Object::cast_to(p_node)) { if (isroot) return p_node; - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { - List> shapes; + List> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else { _gen_shape_list(mesh, shapes, true); } - RigidBody *rigid_body = memnew(RigidBody); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(_fixstr(name, "rigid")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); @@ -486,9 +486,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map mi->set_owner(rigid_body->get_owner()); int idx = 0; - for (List>::Element *E = shapes.front(); E; E = E->next()) { + for (List>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); rigid_body->add_child(cshape); @@ -498,14 +498,14 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } } - } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to(p_node)) { + } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to(p_node)) { - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { - List> shapes; + List> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -530,15 +530,15 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_name("static_collision"); mi->add_child(col); col->set_owner(mi->get_owner()); int idx = 0; - for (List>::Element *E = shapes.front(); E; E = E->next()) { + for (List>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -550,22 +550,22 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } } - } else if (_teststr(name, "navmesh") && Object::cast_to(p_node)) { + } else if (_teststr(name, "navmesh") && Object::cast_to(p_node)) { if (isroot) return p_node; - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); Ref mesh = mi->get_mesh(); ERR_FAIL_COND_V(mesh.is_null(), NULL); - NavigationRegion *nmi = memnew(NavigationRegion); + NavigationRegion3D *nmi = memnew(NavigationRegion3D); nmi->set_name(_fixstr(name, "navmesh")); Ref nmesh = memnew(NavigationMesh); nmesh->create_from_mesh(mesh); nmi->set_navigation_mesh(nmesh); - Object::cast_to(nmi)->set_transform(mi->get_transform()); + Object::cast_to(nmi)->set_transform(mi->get_transform()); p_node->replace_by(nmi); memdelete(p_node); p_node = nmi; @@ -575,7 +575,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map return p_node; Node *owner = p_node->get_owner(); - Spatial *s = Object::cast_to(p_node); + Node3D *s = Object::cast_to(p_node); VehicleBody *bv = memnew(VehicleBody); String n = _fixstr(p_node->get_name(), "vehicle"); bv->set_name(n); @@ -595,7 +595,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map return p_node; Node *owner = p_node->get_owner(); - Spatial *s = Object::cast_to(p_node); + Node3D *s = Object::cast_to(p_node); VehicleWheel *bv = memnew(VehicleWheel); String n = _fixstr(p_node->get_name(), "wheel"); bv->set_name(n); @@ -609,16 +609,16 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map p_node = bv; - } else if (Object::cast_to(p_node)) { + } else if (Object::cast_to(p_node)) { //last attempt, maybe collision inside the mesh data - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); Ref mesh = mi->get_mesh(); if (!mesh.is_null()) { - List> shapes; + List> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(mesh->get_name(), "col")) { @@ -632,15 +632,15 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map } if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_name("static_collision"); p_node->add_child(col); col->set_owner(p_node->get_owner()); int idx = 0; - for (List>::Element *E = shapes.front(); E; E = E->next()) { + for (List>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -934,14 +934,14 @@ void ResourceImporterScene::_find_meshes(Node *p_node, Map, Trans List pi; p_node->get_property_list(&pi); - MeshInstance *mi = Object::cast_to(p_node); + MeshInstance3D *mi = Object::cast_to(p_node); if (mi) { Ref mesh = mi->get_mesh(); if (mesh.is_valid() && !meshes.has(mesh)) { - Spatial *s = mi; + Node3D *s = mi; Transform transform; while (s) { transform = transform * s->get_transform(); @@ -1141,7 +1141,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String void ResourceImporterScene::get_import_options(List *r_options, int p_preset) const { - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Spatial")); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); List script_extentions; @@ -1333,7 +1333,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p root_type = ScriptServer::get_global_class_base(root_type); } - if (root_type != "Spatial") { + if (root_type != "Node3D") { Node *base_node = Object::cast_to(ClassDB::instance(root_type)); if (base_node) { @@ -1348,9 +1348,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_script(Variant(root_script)); } - if (Object::cast_to(scene)) { + if (Object::cast_to(scene)) { float root_scale = p_options["nodes/root_scale"]; - Object::cast_to(scene)->scale(Vector3(root_scale, root_scale, root_scale)); + Object::cast_to(scene)->scale(Vector3(root_scale, root_scale, root_scale)); } if (p_options["nodes/root_name"] != "Scene Root") @@ -1368,7 +1368,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"]; int light_bake_mode = p_options["meshes/light_baking"]; - Map, List>> collision_map; + Map, List>> collision_map; scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode)); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 6d1043eb28..bb01725854 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -34,7 +34,7 @@ #include "core/io/resource_importer.h" #include "scene/resources/animation.h" #include "scene/resources/mesh.h" -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" class Material; @@ -147,7 +147,7 @@ public: void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map, Ref> &p_animations, Map, Ref> &p_materials, Map, Ref> &p_meshes); - Node *_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode); + Node *_fix_node(Node *p_node, Node *p_root, Map, List>> &collision_map, LightBakeMode p_light_bake_mode); void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all); void _filter_anim_tracks(Ref anim, Set &keep); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 916ebd27ab..223e7a841f 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -310,7 +310,7 @@ void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_valu } void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) { - Spatial *s = Object::cast_to(sp); + Node3D *s = Object::cast_to(sp); if (!s) return; AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(s, p_sub, p_key); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 03b48f1c15..4491c002e3 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -619,7 +619,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref &ano String concat = path.get_concatenated_subnames(); - Skeleton *skeleton = Object::cast_to(node); + Skeleton3D *skeleton = Object::cast_to(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton const String &bone = concat; @@ -643,7 +643,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref &ano ti->set_text(0, F->get()); ti->set_selectable(0, false); ti->set_editable(0, false); - ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons")); } else { ti = parenthood[accum]; } @@ -654,7 +654,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref &ano ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_checked(0, anode->is_path_filtered(path)); - ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons")); ti->set_metadata(0, path); } else { diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 4b75f09cf5..b75c56dd47 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1385,9 +1385,9 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { // Hide superfluous elements that would make the overlay unnecessary cluttered. Dictionary canvas_edit_state; Dictionary spatial_edit_state; - if (SpatialEditor::get_singleton()->is_visible()) { + if (Node3DEditor::get_singleton()->is_visible()) { // 3D - spatial_edit_state = SpatialEditor::get_singleton()->get_state(); + spatial_edit_state = Node3DEditor::get_singleton()->get_state(); Dictionary new_state = spatial_edit_state.duplicate(); new_state["show_grid"] = false; new_state["show_origin"] = false; @@ -1404,7 +1404,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { } new_state["viewports"] = vp; // TODO: Save/restore only affected entries. - SpatialEditor::get_singleton()->set_state(new_state); + Node3DEditor::get_singleton()->set_state(new_state); } else { // CanvasItemEditor // 2D canvas_edit_state = CanvasItemEditor::get_singleton()->get_state(); @@ -1465,7 +1465,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { onion.captures_valid.write[cidx] = valid; if (valid) { player->seek(pos, true); - get_tree()->flush_transform_notifications(); // Needed for transforms of Spatials. + get_tree()->flush_transform_notifications(); // Needed for transforms of Node3Ds. values_backup.update_skeletons(); // Needed for Skeletons (2D & 3D). VS::get_singleton()->viewport_set_active(onion.captures[cidx], true); @@ -1489,9 +1489,9 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { player->restore_animated_values(values_backup); // Restore state of main editors. - if (SpatialEditor::get_singleton()->is_visible()) { + if (Node3DEditor::get_singleton()->is_visible()) { // 3D - SpatialEditor::get_singleton()->set_state(spatial_edit_state); + Node3DEditor::get_singleton()->set_state(spatial_edit_state); } else { // CanvasItemEditor // 2D CanvasItemEditor::get_singleton()->set_state(canvas_edit_state); diff --git a/editor/plugins/camera_editor_plugin.cpp b/editor/plugins/camera_editor_plugin.cpp index 8726c8c552..2b6dd379e2 100644 --- a/editor/plugins/camera_editor_plugin.cpp +++ b/editor/plugins/camera_editor_plugin.cpp @@ -36,7 +36,7 @@ void CameraEditor::_node_removed(Node *p_node) { if (p_node == node) { node = NULL; - SpatialEditor::get_singleton()->set_custom_camera(NULL); + Node3DEditor::get_singleton()->set_custom_camera(NULL); hide(); } } @@ -44,7 +44,7 @@ void CameraEditor::_node_removed(Node *p_node) { void CameraEditor::_pressed() { Node *sn = (node && preview->is_pressed()) ? node : NULL; - SpatialEditor::get_singleton()->set_custom_camera(sn); + Node3DEditor::get_singleton()->set_custom_camera(sn); } void CameraEditor::_bind_methods() { @@ -56,13 +56,13 @@ void CameraEditor::edit(Node *p_camera) { if (!node) { preview->set_pressed(false); - SpatialEditor::get_singleton()->set_custom_camera(NULL); + Node3DEditor::get_singleton()->set_custom_camera(NULL); } else { if (preview->is_pressed()) - SpatialEditor::get_singleton()->set_custom_camera(p_camera); + Node3DEditor::get_singleton()->set_custom_camera(p_camera); else - SpatialEditor::get_singleton()->set_custom_camera(NULL); + Node3DEditor::get_singleton()->set_custom_camera(NULL); } } @@ -84,21 +84,21 @@ CameraEditor::CameraEditor() { void CameraEditorPlugin::edit(Object *p_object) { - SpatialEditor::get_singleton()->set_can_preview(Object::cast_to(p_object)); + Node3DEditor::get_singleton()->set_can_preview(Object::cast_to(p_object)); //camera_editor->edit(Object::cast_to(p_object)); } bool CameraEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Camera"); + return p_object->is_class("Camera3D"); } void CameraEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - //SpatialEditor::get_singleton()->set_can_preview(Object::cast_to(p_object)); + //Node3DEditor::get_singleton()->set_can_preview(Object::cast_to(p_object)); } else { - SpatialEditor::get_singleton()->set_can_preview(NULL); + Node3DEditor::get_singleton()->set_can_preview(NULL); } } diff --git a/editor/plugins/camera_editor_plugin.h b/editor/plugins/camera_editor_plugin.h index 9758a1ffbd..3e59d49371 100644 --- a/editor/plugins/camera_editor_plugin.h +++ b/editor/plugins/camera_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" class CameraEditor : public Control { @@ -62,7 +62,7 @@ class CameraEditorPlugin : public EditorPlugin { EditorNode *editor; public: - virtual String get_name() const { return "Camera"; } + virtual String get_name() const { return "Camera3D"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); virtual bool handles(Object *p_object) const; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 4cc0bd4780..dbd1f68f00 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -44,7 +44,7 @@ #include "scene/2d/particles_2d.h" #include "scene/2d/polygon_2d.h" #include "scene/2d/skeleton_2d.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/2d/touch_screen_button.h" #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" @@ -5888,7 +5888,7 @@ void CanvasItemEditorViewport::_create_preview(const Vector &files) cons Ref scene = Ref(Object::cast_to(*res)); if (texture != NULL || scene != NULL) { if (texture != NULL) { - Sprite *sprite = memnew(Sprite); + Sprite2D *sprite = memnew(Sprite2D); sprite->set_texture(texture); sprite->set_modulate(Color(1, 1, 1, 0.7f)); preview_node->add_child(sprite); @@ -6094,7 +6094,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { else if (default_type == "NinePatchRect") child = memnew(NinePatchRect); else - child = memnew(Sprite); // default + child = memnew(Sprite2D); // default _create_nodes(target_node, child, path, drop_pos); } diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 93295e6ab5..98bd655a03 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -35,7 +35,7 @@ #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "editor/editor_settings.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" #include "spatial_editor_plugin.h" void Polygon3DEditor::_notification(int p_what) { @@ -109,7 +109,7 @@ void Polygon3DEditor::_wip_close() { undo_redo->commit_action(); } -bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Ref &p_event) { +bool Polygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event) { if (!node) return false; @@ -346,10 +346,10 @@ bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Refis_snap_enabled()) { + if (!snap_ignore && Node3DEditor::get_singleton()->is_snap_enabled()) { cpoint = cpoint.snapped(Vector2( - SpatialEditor::get_singleton()->get_translate_snap(), - SpatialEditor::get_singleton()->get_translate_snap())); + Node3DEditor::get_singleton()->get_translate_snap(), + Node3DEditor::get_singleton()->get_translate_snap())); } edited_point_pos = cpoint; @@ -493,7 +493,7 @@ void Polygon3DEditor::edit(Node *p_collision_polygon) { if (p_collision_polygon) { - node = Object::cast_to(p_collision_polygon); + node = Object::cast_to(p_collision_polygon); //Enable the pencil tool if the polygon is empty if (Vector(node->call("get_polygon")).size() == 0) { _menu_option(MODE_CREATE); @@ -540,7 +540,7 @@ Polygon3DEditor::Polygon3DEditor(EditorNode *p_editor) { mode = MODE_EDIT; wip_active = false; - imgeom = memnew(ImmediateGeometry); + imgeom = memnew(ImmediateGeometry3D); imgeom->set_transform(Transform(Basis(), Vector3(0, 0, 0.00001))); line_material = Ref(memnew(StandardMaterial3D)); @@ -560,7 +560,7 @@ Polygon3DEditor::Polygon3DEditor(EditorNode *p_editor) { handle_material->set_point_size(handle->get_width()); handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle); - pointsm = memnew(MeshInstance); + pointsm = memnew(MeshInstance3D); imgeom->add_child(pointsm); m.instance(); pointsm->set_mesh(m); @@ -581,7 +581,7 @@ void Polygon3DEditorPlugin::edit(Object *p_object) { bool Polygon3DEditorPlugin::handles(Object *p_object) const { - return Object::cast_to(p_object) && bool(p_object->call("_is_editable_3d_polygon")); + return Object::cast_to(p_object) && bool(p_object->call("_is_editable_3d_polygon")); } void Polygon3DEditorPlugin::make_visible(bool p_visible) { @@ -599,7 +599,7 @@ Polygon3DEditorPlugin::Polygon3DEditorPlugin(EditorNode *p_node) { editor = p_node; collision_polygon_editor = memnew(Polygon3DEditor(p_node)); - SpatialEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); + Node3DEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); collision_polygon_editor->hide(); } diff --git a/editor/plugins/collision_polygon_editor_plugin.h b/editor/plugins/collision_polygon_editor_plugin.h index 3b6c25ac17..169b07b673 100644 --- a/editor/plugins/collision_polygon_editor_plugin.h +++ b/editor/plugins/collision_polygon_editor_plugin.h @@ -33,9 +33,9 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/collision_polygon.h" -#include "scene/3d/immediate_geometry.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/collision_polygon_3d.h" +#include "scene/3d/immediate_geometry_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/tool_button.h" class CanvasItemEditor; @@ -62,9 +62,9 @@ class Polygon3DEditor : public HBoxContainer { EditorNode *editor; Panel *panel; - Spatial *node; - ImmediateGeometry *imgeom; - MeshInstance *pointsm; + Node3D *node; + ImmediateGeometry3D *imgeom; + MeshInstance3D *pointsm; Ref m; MenuButton *options; @@ -90,7 +90,7 @@ protected: static void _bind_methods(); public: - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event); + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event); void edit(Node *p_collision_polygon); Polygon3DEditor(EditorNode *p_editor); ~Polygon3DEditor(); @@ -104,7 +104,7 @@ class Polygon3DEditorPlugin : public EditorPlugin { EditorNode *editor; public: - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event) { return collision_polygon_editor->forward_spatial_gui_input(p_camera, p_event); } + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event) { return collision_polygon_editor->forward_spatial_gui_input(p_camera, p_event); } virtual String get_name() const { return "Polygon3DEditor"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/cpu_particles_editor_plugin.cpp b/editor/plugins/cpu_particles_editor_plugin.cpp index 1388b9ca10..4674903256 100644 --- a/editor/plugins/cpu_particles_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_editor_plugin.cpp @@ -65,7 +65,7 @@ void CPUParticlesEditor::_menu_option(int p_option) { } } -void CPUParticlesEditor::edit(CPUParticles *p_particles) { +void CPUParticlesEditor::edit(CPUParticles3D *p_particles) { base_node = p_particles; node = p_particles; @@ -82,10 +82,10 @@ void CPUParticlesEditor::_generate_emission_points() { } if (normals.size() == 0) { - node->set_emission_shape(CPUParticles::EMISSION_SHAPE_POINTS); + node->set_emission_shape(CPUParticles3D::EMISSION_SHAPE_POINTS); node->set_emission_points(points); } else { - node->set_emission_shape(CPUParticles::EMISSION_SHAPE_DIRECTED_POINTS); + node->set_emission_shape(CPUParticles3D::EMISSION_SHAPE_DIRECTED_POINTS); node->set_emission_points(points); node->set_emission_normals(normals); } @@ -97,7 +97,7 @@ void CPUParticlesEditor::_bind_methods() { CPUParticlesEditor::CPUParticlesEditor() { particles_editor_hb = memnew(HBoxContainer); - SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); + Node3DEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); options = memnew(MenuButton); options->set_switch_on_hover(true); particles_editor_hb->add_child(options); @@ -112,12 +112,12 @@ CPUParticlesEditor::CPUParticlesEditor() { void CPUParticlesEditorPlugin::edit(Object *p_object) { - particles_editor->edit(Object::cast_to(p_object)); + particles_editor->edit(Object::cast_to(p_object)); } bool CPUParticlesEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("CPUParticles"); + return p_object->is_class("CPUParticles3D"); } void CPUParticlesEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/cpu_particles_editor_plugin.h b/editor/plugins/cpu_particles_editor_plugin.h index 4cf143fc0c..ed47ed1436 100644 --- a/editor/plugins/cpu_particles_editor_plugin.h +++ b/editor/plugins/cpu_particles_editor_plugin.h @@ -32,7 +32,7 @@ #define CPU_PARTICLES_EDITOR_PLUGIN_H #include "editor/plugins/particles_editor_plugin.h" -#include "scene/3d/cpu_particles.h" +#include "scene/3d/cpu_particles_3d.h" class CPUParticlesEditor : public ParticlesEditorBase { @@ -46,7 +46,7 @@ class CPUParticlesEditor : public ParticlesEditorBase { }; - CPUParticles *node; + CPUParticles3D *node; void _menu_option(int); @@ -60,7 +60,7 @@ protected: static void _bind_methods(); public: - void edit(CPUParticles *p_particles); + void edit(CPUParticles3D *p_particles); CPUParticlesEditor(); }; diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 74588d4439..9fe9675c69 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -123,25 +123,25 @@ MaterialEditor::MaterialEditor() { viewport->set_transparent_background(true); viewport->set_msaa(Viewport::MSAA_4X); - camera = memnew(Camera); + camera = memnew(Camera3D); camera->set_transform(Transform(Basis(), Vector3(0, 0, 3))); camera->set_perspective(45, 0.1, 10); camera->make_current(); viewport->add_child(camera); - light1 = memnew(DirectionalLight); + light1 = memnew(DirectionalLight3D); light1->set_transform(Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); viewport->add_child(light1); - light2 = memnew(DirectionalLight); + light2 = memnew(DirectionalLight3D); light2->set_transform(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); light2->set_color(Color(0.7, 0.7, 0.7)); viewport->add_child(light2); - sphere_instance = memnew(MeshInstance); + sphere_instance = memnew(MeshInstance3D); viewport->add_child(sphere_instance); - box_instance = memnew(MeshInstance); + box_instance = memnew(MeshInstance3D); viewport->add_child(box_instance); Transform box_xform; diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 895c3f80bd..0938e79ca2 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -36,9 +36,9 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/resources/material.h" class ViewportContainer; @@ -49,11 +49,11 @@ class MaterialEditor : public Control { ViewportContainer *vc; SubViewport *viewport; - MeshInstance *sphere_instance; - MeshInstance *box_instance; - DirectionalLight *light1; - DirectionalLight *light2; - Camera *camera; + MeshInstance3D *sphere_instance; + MeshInstance3D *box_instance; + DirectionalLight3D *light1; + DirectionalLight3D *light2; + Camera3D *camera; Ref sphere_mesh; Ref box_mesh; diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 352997d6fa..d7dd777cd3 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -123,23 +123,23 @@ MeshEditor::MeshEditor() { viewport->set_disable_input(true); viewport->set_msaa(Viewport::MSAA_2X); set_stretch(true); - camera = memnew(Camera); + camera = memnew(Camera3D); camera->set_transform(Transform(Basis(), Vector3(0, 0, 1.1))); camera->set_perspective(45, 0.1, 10); viewport->add_child(camera); - light1 = memnew(DirectionalLight); + light1 = memnew(DirectionalLight3D); light1->set_transform(Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); viewport->add_child(light1); - light2 = memnew(DirectionalLight); + light2 = memnew(DirectionalLight3D); light2->set_transform(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); light2->set_color(Color(0.7, 0.7, 0.7)); viewport->add_child(light2); - rotation = memnew(Spatial); + rotation = memnew(Node3D); viewport->add_child(rotation); - mesh_instance = memnew(MeshInstance); + mesh_instance = memnew(MeshInstance3D); rotation->add_child(mesh_instance); set_custom_minimum_size(Size2(1, 150) * EDSCALE); diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h index 6d39d49de1..59810517d9 100644 --- a/editor/plugins/mesh_editor_plugin.h +++ b/editor/plugins/mesh_editor_plugin.h @@ -33,9 +33,9 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/viewport_container.h" #include "scene/resources/material.h" @@ -47,11 +47,11 @@ class MeshEditor : public ViewportContainer { float rot_y; SubViewport *viewport; - MeshInstance *mesh_instance; - Spatial *rotation; - DirectionalLight *light1; - DirectionalLight *light2; - Camera *camera; + MeshInstance3D *mesh_instance; + Node3D *rotation; + DirectionalLight3D *light1; + DirectionalLight3D *light2; + Camera3D *camera; Ref mesh; diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 3fdda36177..dce69e53ca 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "mesh_instance_editor_plugin.h" #include "editor/editor_scale.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/navigation_region.h" -#include "scene/3d/physics_body.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/navigation_region_3d.h" +#include "scene/3d/physics_body_3d.h" #include "scene/gui/box_container.h" #include "spatial_editor_plugin.h" @@ -45,7 +45,7 @@ void MeshInstanceEditor::_node_removed(Node *p_node) { } } -void MeshInstanceEditor::edit(MeshInstance *p_mesh) { +void MeshInstanceEditor::edit(MeshInstance3D *p_mesh) { node = p_mesh; } @@ -68,16 +68,16 @@ void MeshInstanceEditor::_menu_option(int p_option) { List selection = editor_selection->get_selected_node_list(); if (selection.empty()) { - Ref shape = mesh->create_trimesh_shape(); + Ref shape = mesh->create_trimesh_shape(); if (shape.is_null()) { err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape.")); err_dialog->popup_centered(); return; } - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); - StaticBody *body = memnew(StaticBody); + StaticBody3D *body = memnew(StaticBody3D); body->add_child(cshape); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); @@ -96,7 +96,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - MeshInstance *instance = Object::cast_to(E->get()); + MeshInstance3D *instance = Object::cast_to(E->get()); if (!instance) continue; @@ -104,13 +104,13 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (m.is_null()) continue; - Ref shape = m->create_trimesh_shape(); + Ref shape = m->create_trimesh_shape(); if (shape.is_null()) continue; - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); - StaticBody *body = memnew(StaticBody); + StaticBody3D *body = memnew(StaticBody3D); body->add_child(cshape); Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner(); @@ -134,11 +134,11 @@ void MeshInstanceEditor::_menu_option(int p_option) { return; } - Ref shape = mesh->create_trimesh_shape(); + Ref shape = mesh->create_trimesh_shape(); if (shape.is_null()) return; - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); Node *owner = node->get_owner(); @@ -162,7 +162,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { return; } - Ref shape = mesh->create_convex_shape(); + Ref shape = mesh->create_convex_shape(); if (shape.is_null()) { err_dialog->set_text(TTR("Couldn't create a single convex collision shape.")); @@ -173,7 +173,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { ur->create_action(TTR("Create Single Convex Shape")); - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); cshape->set_transform(node->get_transform()); @@ -196,7 +196,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { return; } - Vector> shapes = mesh->convex_decompose(); + Vector> shapes = mesh->convex_decompose(); if (!shapes.size()) { err_dialog->set_text(TTR("Couldn't create any collision shapes.")); @@ -209,7 +209,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { for (int i = 0; i < shapes.size(); i++) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shapes[i]); cshape->set_transform(node->get_transform()); @@ -233,7 +233,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { return; nmesh->create_from_mesh(mesh); - NavigationRegion *nmi = memnew(NavigationRegion); + NavigationRegion3D *nmi = memnew(NavigationRegion3D); nmi->set_navigation_mesh(nmesh); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); @@ -415,7 +415,7 @@ void MeshInstanceEditor::_create_outline_mesh() { return; } - MeshInstance *mi = memnew(MeshInstance); + MeshInstance3D *mi = memnew(MeshInstance3D); mi->set_mesh(mesho); Node *owner = node->get_owner(); if (get_tree()->get_edited_scene_root() == node) { @@ -441,10 +441,10 @@ MeshInstanceEditor::MeshInstanceEditor() { options = memnew(MenuButton); options->set_switch_on_hover(true); - SpatialEditor::get_singleton()->add_control_to_menu_panel(options); + Node3DEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Mesh")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshInstance", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshInstance3D", "EditorIcons")); options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); @@ -459,7 +459,7 @@ MeshInstanceEditor::MeshInstanceEditor() { options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a static outline mesh. The outline mesh will have its normals flipped automatically.\nThis can be used instead of the SpatialMaterial Grow property when using that property isn't possible.")); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a static outline mesh. The outline mesh will have its normals flipped automatically.\nThis can be used instead of the StandardMaterial Grow property when using that property isn't possible.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1); options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2); @@ -499,12 +499,12 @@ MeshInstanceEditor::MeshInstanceEditor() { void MeshInstanceEditorPlugin::edit(Object *p_object) { - mesh_editor->edit(Object::cast_to(p_object)); + mesh_editor->edit(Object::cast_to(p_object)); } bool MeshInstanceEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("MeshInstance"); + return p_object->is_class("MeshInstance3D"); } void MeshInstanceEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h index 5ca9aa3fec..68354388ba 100644 --- a/editor/plugins/mesh_instance_editor_plugin.h +++ b/editor/plugins/mesh_instance_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/spin_box.h" class MeshInstanceEditor : public Control { @@ -53,7 +53,7 @@ class MeshInstanceEditor : public Control { MENU_OPTION_DEBUG_UV2, }; - MeshInstance *node; + MeshInstance3D *node; MenuButton *options; @@ -79,7 +79,7 @@ protected: static void _bind_methods(); public: - void edit(MeshInstance *p_mesh); + void edit(MeshInstance3D *p_mesh); MeshInstanceEditor(); }; @@ -91,7 +91,7 @@ class MeshInstanceEditorPlugin : public EditorPlugin { EditorNode *editor; public: - virtual String get_name() const { return "MeshInstance"; } + virtual String get_name() const { return "MeshInstance3D"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); virtual bool handles(Object *p_object) const; diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 32099c1364..88a6254c5c 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -33,9 +33,9 @@ #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "main/main.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation_region.h" -#include "scene/3d/physics_body.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/navigation_region_3d.h" +#include "scene/3d/physics_body_3d.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" #include "spatial_editor_plugin.h" @@ -71,16 +71,16 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, if (!p_merge) p_library->clear(); - Map mesh_instances; + Map mesh_instances; for (int i = 0; i < p_scene->get_child_count(); i++) { Node *child = p_scene->get_child(i); - if (!Object::cast_to(child)) { + if (!Object::cast_to(child)) { if (child->get_child_count() > 0) { child = child->get_child(0); - if (!Object::cast_to(child)) { + if (!Object::cast_to(child)) { continue; } @@ -88,7 +88,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, continue; } - MeshInstance *mi = Object::cast_to(child); + MeshInstance3D *mi = Object::cast_to(child); Ref mesh = mi->get_mesh(); if (mesh.is_null()) continue; @@ -118,10 +118,10 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, for (int j = 0; j < mi->get_child_count(); j++) { Node *child2 = mi->get_child(j); - if (!Object::cast_to(child2)) + if (!Object::cast_to(child2)) continue; - StaticBody *sb = Object::cast_to(child2); + StaticBody3D *sb = Object::cast_to(child2); List shapes; sb->get_shape_owners(&shapes); @@ -135,7 +135,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) { - Ref collision = sb->shape_owner_get_shape(E->get(), k); + Ref collision = sb->shape_owner_get_shape(E->get(), k); if (!collision.is_valid()) continue; MeshLibrary::ShapeData shape_data; @@ -152,9 +152,9 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, Transform navmesh_transform; for (int j = 0; j < mi->get_child_count(); j++) { Node *child2 = mi->get_child(j); - if (!Object::cast_to(child2)) + if (!Object::cast_to(child2)) continue; - NavigationRegion *sb = Object::cast_to(child2); + NavigationRegion3D *sb = Object::cast_to(child2); navmesh = sb->get_navigation_mesh(); navmesh_transform = sb->get_transform(); if (!navmesh.is_null()) @@ -267,7 +267,7 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { file->connect("file_selected", callable_mp(this, &MeshLibraryEditor::_import_scene_cbk)); menu = memnew(MenuButton); - SpatialEditor::get_singleton()->add_control_to_menu_panel(menu); + Node3DEditor::get_singleton()->add_control_to_menu_panel(menu); menu->set_position(Point2(1, 1)); menu->set_text(TTR("Mesh Library")); menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshLibrary", "EditorIcons")); diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index dcae59bbe8..dd2781aea7 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "multimesh_editor_plugin.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/box_container.h" #include "spatial_editor_plugin.h" @@ -78,7 +78,7 @@ void MultiMeshEditor::_populate() { return; } - MeshInstance *ms_instance = Object::cast_to(ms_node); + MeshInstance3D *ms_instance = Object::cast_to(ms_node); if (!ms_instance) { @@ -113,7 +113,7 @@ void MultiMeshEditor::_populate() { return; } - GeometryInstance *ss_instance = Object::cast_to(ss_node); + GeometryInstance3D *ss_instance = Object::cast_to(ss_node); if (!ss_instance) { @@ -124,7 +124,7 @@ void MultiMeshEditor::_populate() { Transform geom_xform = node->get_global_transform().affine_inverse() * ss_instance->get_global_transform(); - Vector geometry = ss_instance->get_faces(VisualInstance::FACES_SOLID); + Vector geometry = ss_instance->get_faces(VisualInstance3D::FACES_SOLID); if (geometry.size() == 0) { @@ -261,7 +261,7 @@ void MultiMeshEditor::_menu_option(int p_option) { } } -void MultiMeshEditor::edit(MultiMeshInstance *p_multimesh) { +void MultiMeshEditor::edit(MultiMeshInstance3D *p_multimesh) { node = p_multimesh; } @@ -284,7 +284,7 @@ MultiMeshEditor::MultiMeshEditor() { options = memnew(MenuButton); options->set_switch_on_hover(true); - SpatialEditor::get_singleton()->add_control_to_menu_panel(options); + Node3DEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text("MultiMesh"); options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MultiMeshInstance", "EditorIcons")); @@ -379,12 +379,12 @@ MultiMeshEditor::MultiMeshEditor() { void MultiMeshEditorPlugin::edit(Object *p_object) { - multimesh_editor->edit(Object::cast_to(p_object)); + multimesh_editor->edit(Object::cast_to(p_object)); } bool MultiMeshEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("MultiMeshInstance"); + return p_object->is_class("MultiMeshInstance3D"); } void MultiMeshEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h index 2c7b98cfbc..15c9b91fee 100644 --- a/editor/plugins/multimesh_editor_plugin.h +++ b/editor/plugins/multimesh_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/multimesh_instance.h" +#include "scene/3d/multimesh_instance_3d.h" #include "scene/gui/spin_box.h" class MultiMeshEditor : public Control { @@ -44,11 +44,11 @@ class MultiMeshEditor : public Control { AcceptDialog *err_dialog; MenuButton *options; - MultiMeshInstance *_last_pp_node; + MultiMeshInstance3D *_last_pp_node; bool browsing_source; Panel *panel; - MultiMeshInstance *node; + MultiMeshInstance3D *node; LineEdit *surface_source; LineEdit *mesh_source; @@ -78,7 +78,7 @@ protected: static void _bind_methods(); public: - void edit(MultiMeshInstance *p_multimesh); + void edit(MultiMeshInstance3D *p_multimesh); MultiMeshEditor(); }; diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index 744424a3fa..b018ef383e 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -43,7 +43,7 @@ void Particles2DEditorPlugin::edit(Object *p_object) { bool Particles2DEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Particles2D"); + return p_object->is_class("GPUParticles2D"); } void Particles2DEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 63acf7cfb6..628eb4a7fe 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -32,7 +32,7 @@ #include "core/io/resource_loader.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/cpu_particles.h" +#include "scene/3d/cpu_particles_3d.h" #include "scene/resources/particles_material.h" bool ParticlesEditorBase::_generate(Vector &points, Vector &normals) { @@ -167,20 +167,20 @@ void ParticlesEditorBase::_node_selected(const NodePath &p_path) { if (!sel) return; - if (!sel->is_class("Spatial")) { + if (!sel->is_class("Node3D")) { - EditorNode::get_singleton()->show_warning(vformat(TTR("\"%s\" doesn't inherit from Spatial."), sel->get_name())); + EditorNode::get_singleton()->show_warning(vformat(TTR("\"%s\" doesn't inherit from Node3D."), sel->get_name())); return; } - VisualInstance *vi = Object::cast_to(sel); + VisualInstance3D *vi = Object::cast_to(sel); if (!vi) { EditorNode::get_singleton()->show_warning(vformat(TTR("\"%s\" doesn't contain geometry."), sel->get_name())); return; } - geometry = vi->get_faces(VisualInstance::FACES_SOLID); + geometry = vi->get_faces(VisualInstance3D::FACES_SOLID); if (geometry.size() == 0) { @@ -274,7 +274,7 @@ void ParticlesEditor::_menu_option(int p_option) { } break; case MENU_OPTION_CONVERT_TO_CPU_PARTICLES: { - CPUParticles *cpu_particles = memnew(CPUParticles); + CPUParticles3D *cpu_particles = memnew(CPUParticles3D); cpu_particles->convert_from_particles(node); cpu_particles->set_name(node->get_name()); cpu_particles->set_transform(node->get_transform()); @@ -340,7 +340,7 @@ void ParticlesEditor::_generate_aabb() { ur->commit_action(); } -void ParticlesEditor::edit(Particles *p_particles) { +void ParticlesEditor::edit(GPUParticles3D *p_particles) { base_node = p_particles; node = p_particles; @@ -426,7 +426,7 @@ ParticlesEditor::ParticlesEditor() { node = NULL; particles_editor_hb = memnew(HBoxContainer); - SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); + Node3DEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); options = memnew(MenuButton); options->set_switch_on_hover(true); particles_editor_hb->add_child(options); @@ -460,12 +460,12 @@ ParticlesEditor::ParticlesEditor() { void ParticlesEditorPlugin::edit(Object *p_object) { - particles_editor->edit(Object::cast_to(p_object)); + particles_editor->edit(Object::cast_to(p_object)); } bool ParticlesEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Particles"); + return p_object->is_class("GPUParticles3D"); } void ParticlesEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index fb5ce17560..773f305a2b 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/particles.h" +#include "scene/3d/gpu_particles_3d.h" #include "scene/gui/spin_box.h" class ParticlesEditorBase : public Control { @@ -41,7 +41,7 @@ class ParticlesEditorBase : public Control { GDCLASS(ParticlesEditorBase, Control); protected: - Spatial *base_node; + Node3D *base_node; Panel *panel; MenuButton *options; HBoxContainer *particles_editor_hb; @@ -70,7 +70,7 @@ class ParticlesEditor : public ParticlesEditorBase { ConfirmationDialog *generate_aabb; SpinBox *generate_seconds; - Particles *node; + GPUParticles3D *node; enum Menu { @@ -96,7 +96,7 @@ protected: static void _bind_methods(); public: - void edit(Particles *p_particles); + void edit(GPUParticles3D *p_particles); ParticlesEditor(); }; diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index b6842be76c..e54fd17a5b 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "scene/resources/curve.h" #include "spatial_editor_plugin.h" -String PathSpatialGizmo::get_handle_name(int p_idx) const { +String PathNode3DGizmo::get_handle_name(int p_idx) const { Ref c = path->get_curve(); if (c.is_null()) @@ -57,7 +57,7 @@ String PathSpatialGizmo::get_handle_name(int p_idx) const { return n; } -Variant PathSpatialGizmo::get_handle_value(int p_idx) { +Variant PathNode3DGizmo::get_handle_value(int p_idx) { Ref c = path->get_curve(); if (c.is_null()) @@ -84,7 +84,7 @@ Variant PathSpatialGizmo::get_handle_value(int p_idx) { return ofs; } -void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void PathNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) { Ref c = path->get_curve(); if (c.is_null()) @@ -104,8 +104,8 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p if (p.intersects_ray(ray_from, ray_dir, &inters)) { - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - float snap = SpatialEditor::get_singleton()->get_translate_snap(); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + float snap = Node3DEditor::get_singleton()->get_translate_snap(); inters.snap(Vector3(snap, snap, snap)); } @@ -137,8 +137,8 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p } Vector3 local = gi.xform(inters) - base; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - float snap = SpatialEditor::get_singleton()->get_translate_snap(); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + float snap = Node3DEditor::get_singleton()->get_translate_snap(); local.snap(Vector3(snap, snap, snap)); } @@ -154,13 +154,13 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p } } -void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void PathNode3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { Ref c = path->get_curve(); if (c.is_null()) return; - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx < c->get_point_count()) { @@ -217,7 +217,7 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p } } -void PathSpatialGizmo::redraw() { +void PathNode3DGizmo::redraw() { clear(); @@ -286,13 +286,13 @@ void PathSpatialGizmo::redraw() { } } -PathSpatialGizmo::PathSpatialGizmo(Path *p_path) { +PathNode3DGizmo::PathNode3DGizmo(Path3D *p_path) { path = p_path; set_spatial_node(p_path); } -bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref &p_event) { +bool PathEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event) { if (!path) return false; @@ -451,7 +451,7 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref(p_object); + path = Object::cast_to(p_object); if (path) { if (path->get_curve().is_valid()) { @@ -459,7 +459,7 @@ void PathEditorPlugin::edit(Object *p_object) { } } } else { - Path *pre = path; + Path3D *pre = path; path = NULL; if (pre) { pre->get_curve()->emit_signal("changed"); @@ -470,7 +470,7 @@ void PathEditorPlugin::edit(Object *p_object) { bool PathEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Path"); + return p_object->is_class("Path3D"); } void PathEditorPlugin::make_visible(bool p_visible) { @@ -493,7 +493,7 @@ void PathEditorPlugin::make_visible(bool p_visible) { sep->hide(); { - Path *pre = path; + Path3D *pre = path; path = NULL; if (pre && pre->get_curve().is_valid()) { pre->get_curve()->emit_signal("changed"); @@ -563,47 +563,47 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { mirror_handle_angle = true; mirror_handle_length = true; - Ref gizmo_plugin; + Ref gizmo_plugin; gizmo_plugin.instance(); - SpatialEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); + Node3DEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); sep = memnew(VSeparator); sep->hide(); - SpatialEditor::get_singleton()->add_control_to_menu_panel(sep); + Node3DEditor::get_singleton()->add_control_to_menu_panel(sep); curve_edit = memnew(ToolButton); curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); - SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit); + Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); curve_create = memnew(ToolButton); curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->hide(); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); - SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create); + Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_create); curve_del = memnew(ToolButton); curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->hide(); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); - SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del); + Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_del); curve_close = memnew(ToolButton); curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->hide(); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); - SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close); + Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_close); PopupMenu *menu; handle_menu = memnew(MenuButton); handle_menu->set_text(TTR("Options")); handle_menu->hide(); - SpatialEditor::get_singleton()->add_control_to_menu_panel(handle_menu); + Node3DEditor::get_singleton()->add_control_to_menu_panel(handle_menu); menu = handle_menu->get_popup(); menu->add_check_item(TTR("Mirror Handle Angles")); @@ -627,24 +627,24 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { PathEditorPlugin::~PathEditorPlugin() { } -Ref PathSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { - Ref ref; +Ref PathNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) { + Ref ref; - Path *path = Object::cast_to(p_spatial); - if (path) ref = Ref(memnew(PathSpatialGizmo(path))); + Path3D *path = Object::cast_to(p_spatial); + if (path) ref = Ref(memnew(PathNode3DGizmo(path))); return ref; } -String PathSpatialGizmoPlugin::get_name() const { +String PathNode3DGizmoPlugin::get_name() const { return "Path"; } -int PathSpatialGizmoPlugin::get_priority() const { +int PathNode3DGizmoPlugin::get_priority() const { return -1; } -PathSpatialGizmoPlugin::PathSpatialGizmoPlugin() { +PathNode3DGizmoPlugin::PathNode3DGizmoPlugin() { Color path_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/path", Color(0.5, 0.5, 1.0, 0.8)); create_material("path_material", path_color); diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 8ff83911f8..0a27e1068e 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -32,13 +32,13 @@ #define PATH_EDITOR_PLUGIN_H #include "editor/spatial_editor_gizmos.h" -#include "scene/3d/path.h" +#include "scene/3d/path_3d.h" -class PathSpatialGizmo : public EditorSpatialGizmo { +class PathNode3DGizmo : public EditorNode3DGizmo { - GDCLASS(PathSpatialGizmo, EditorSpatialGizmo); + GDCLASS(PathNode3DGizmo, EditorNode3DGizmo); - Path *path; + Path3D *path; mutable Vector3 original; mutable float orig_in_length; mutable float orig_out_length; @@ -46,24 +46,24 @@ class PathSpatialGizmo : public EditorSpatialGizmo { public: virtual String get_handle_name(int p_idx) const; virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); + virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); virtual void redraw(); - PathSpatialGizmo(Path *p_path = NULL); + PathNode3DGizmo(Path3D *p_path = NULL); }; -class PathSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class PathNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(PathSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(PathNode3DGizmoPlugin, EditorNode3DGizmoPlugin); protected: - Ref create_gizmo(Spatial *p_spatial); + Ref create_gizmo(Node3D *p_spatial); public: String get_name() const; int get_priority() const; - PathSpatialGizmoPlugin(); + PathNode3DGizmoPlugin(); }; class PathEditorPlugin : public EditorPlugin { @@ -79,7 +79,7 @@ class PathEditorPlugin : public EditorPlugin { EditorNode *editor; - Path *path; + Path3D *path; void _mode_changed(int p_idx); void _close_curve(); @@ -98,13 +98,13 @@ protected: static void _bind_methods(); public: - Path *get_edited_path() { return path; } + Path3D *get_edited_path() { return path; } static PathEditorPlugin *singleton; - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event); + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event); //virtual bool forward_gui_input(const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); } - //virtual Ref create_spatial_gizmo(Spatial *p_spatial); + //virtual Ref create_spatial_gizmo(Spatial *p_spatial); virtual String get_name() const { return "Path"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); diff --git a/editor/plugins/physical_bone_plugin.cpp b/editor/plugins/physical_bone_plugin.cpp index ec29310029..d827472353 100644 --- a/editor/plugins/physical_bone_plugin.cpp +++ b/editor/plugins/physical_bone_plugin.cpp @@ -30,7 +30,7 @@ #include "physical_bone_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/physics_body.h" +#include "scene/3d/physics_body_3d.h" void PhysicalBoneEditor::_bind_methods() { } @@ -53,7 +53,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : spatial_editor_hb = memnew(HBoxContainer); spatial_editor_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); spatial_editor_hb->set_alignment(BoxContainer::ALIGN_BEGIN); - SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); + Node3DEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); spatial_editor_hb->add_child(memnew(VSeparator)); @@ -61,7 +61,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : spatial_editor_hb->add_child(button_transform_joint); button_transform_joint->set_text(TTR("Move Joint")); - button_transform_joint->set_icon(SpatialEditor::get_singleton()->get_theme_icon("PhysicalBone", "EditorIcons")); + button_transform_joint->set_icon(Node3DEditor::get_singleton()->get_theme_icon("PhysicalBone", "EditorIcons")); button_transform_joint->set_toggle_mode(true); button_transform_joint->connect("toggled", callable_mp(this, &PhysicalBoneEditor::_on_toggle_button_transform_joint)); @@ -70,7 +70,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : PhysicalBoneEditor::~PhysicalBoneEditor() {} -void PhysicalBoneEditor::set_selected(PhysicalBone *p_pb) { +void PhysicalBoneEditor::set_selected(PhysicalBone3D *p_pb) { button_transform_joint->set_pressed(false); @@ -105,7 +105,7 @@ void PhysicalBonePlugin::make_visible(bool p_visible) { } void PhysicalBonePlugin::edit(Object *p_node) { - selected = static_cast(p_node); // Trust it + selected = static_cast(p_node); // Trust it ERR_FAIL_COND(!selected); physical_bone_editor.set_selected(selected); diff --git a/editor/plugins/physical_bone_plugin.h b/editor/plugins/physical_bone_plugin.h index 459a67db05..0d4aa7138d 100644 --- a/editor/plugins/physical_bone_plugin.h +++ b/editor/plugins/physical_bone_plugin.h @@ -40,7 +40,7 @@ class PhysicalBoneEditor : public Object { HBoxContainer *spatial_editor_hb; ToolButton *button_transform_joint; - PhysicalBone *selected; + PhysicalBone3D *selected; protected: static void _bind_methods(); @@ -53,7 +53,7 @@ public: PhysicalBoneEditor(EditorNode *p_editor); ~PhysicalBoneEditor(); - void set_selected(PhysicalBone *p_pb); + void set_selected(PhysicalBone3D *p_pb); void hide(); void show(); @@ -63,12 +63,12 @@ class PhysicalBonePlugin : public EditorPlugin { GDCLASS(PhysicalBonePlugin, EditorPlugin); EditorNode *editor; - PhysicalBone *selected; + PhysicalBone3D *selected; PhysicalBoneEditor physical_bone_editor; public: - virtual String get_name() const { return "PhysicalBone"; } - virtual bool handles(Object *p_object) const { return p_object->is_class("PhysicalBone"); } + virtual String get_name() const { return "PhysicalBone3D"; } + virtual bool handles(Object *p_object) const { return p_object->is_class("PhysicalBone3D"); } virtual void make_visible(bool p_visible); virtual void edit(Object *p_node); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index 0f803218ea..516c52a8a4 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -128,7 +128,7 @@ void EditorPropertyRootMotion::_node_assign() { String concat = path.get_concatenated_subnames(); - Skeleton *skeleton = Object::cast_to(node); + Skeleton3D *skeleton = Object::cast_to(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton const String &bone = concat; @@ -152,7 +152,7 @@ void EditorPropertyRootMotion::_node_assign() { ti->set_text(0, F->get()); ti->set_selectable(0, true); ti->set_editable(0, false); - ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons")); ti->set_metadata(0, accum); } else { ti = parenthood[accum]; @@ -161,7 +161,7 @@ void EditorPropertyRootMotion::_node_assign() { ti->set_selectable(0, true); ti->set_text(0, concat); - ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment3D", "EditorIcons")); ti->set_metadata(0, path); if (path == current) { ti->select(0); diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index ac9980b79f..941461bb64 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -30,11 +30,11 @@ #include "skeleton_editor_plugin.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/physics_body.h" -#include "scene/3d/physics_joint.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/sphere_shape.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/3d/physics_joint_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/sphere_shape_3d.h" #include "spatial_editor_plugin.h" void SkeletonEditor::_on_click_option(int p_option) { @@ -94,25 +94,25 @@ void SkeletonEditor::create_physical_skeleton() { /// Create joint between parent of parent if (-1 != parent_parent) { - bones_infos[parent].physical_bone->set_joint_type(PhysicalBone::JOINT_TYPE_PIN); + bones_infos[parent].physical_bone->set_joint_type(PhysicalBone3D::JOINT_TYPE_PIN); } } } } } -PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector &bones_infos) { +PhysicalBone3D *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector &bones_infos) { const Transform child_rest = skeleton->get_bone_rest(bone_child_id); const real_t half_height(child_rest.origin.length() * 0.5); const real_t radius(half_height * 0.2); - CapsuleShape *bone_shape_capsule = memnew(CapsuleShape); + CapsuleShape3D *bone_shape_capsule = memnew(CapsuleShape3D); bone_shape_capsule->set_height((half_height - radius) * 2); bone_shape_capsule->set_radius(radius); - CollisionShape *bone_shape = memnew(CollisionShape); + CollisionShape3D *bone_shape = memnew(CollisionShape3D); bone_shape->set_shape(bone_shape_capsule); Transform body_transform; @@ -122,7 +122,7 @@ PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_i Transform joint_transform; joint_transform.origin = Vector3(0, 0, half_height); - PhysicalBone *physical_bone = memnew(PhysicalBone); + PhysicalBone3D *physical_bone = memnew(PhysicalBone3D); physical_bone->add_child(bone_shape); physical_bone->set_name("Physical Bone " + skeleton->get_bone_name(bone_id)); physical_bone->set_body_offset(body_transform); @@ -130,7 +130,7 @@ PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_i return physical_bone; } -void SkeletonEditor::edit(Skeleton *p_node) { +void SkeletonEditor::edit(Skeleton3D *p_node) { skeleton = p_node; } @@ -155,10 +155,10 @@ void SkeletonEditor::_bind_methods() { SkeletonEditor::SkeletonEditor() { skeleton = NULL; options = memnew(MenuButton); - SpatialEditor::get_singleton()->add_control_to_menu_panel(options); + Node3DEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Skeleton")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton3D", "EditorIcons")); options->get_popup()->add_item(TTR("Create physical skeleton"), MENU_OPTION_CREATE_PHYSICAL_SKELETON); @@ -169,11 +169,11 @@ SkeletonEditor::SkeletonEditor() { SkeletonEditor::~SkeletonEditor() {} void SkeletonEditorPlugin::edit(Object *p_object) { - skeleton_editor->edit(Object::cast_to(p_object)); + skeleton_editor->edit(Object::cast_to(p_object)); } bool SkeletonEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Skeleton"); + return p_object->is_class("Skeleton3D"); } void SkeletonEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/skeleton_editor_plugin.h b/editor/plugins/skeleton_editor_plugin.h index 1dce6d12ed..91e244285d 100644 --- a/editor/plugins/skeleton_editor_plugin.h +++ b/editor/plugins/skeleton_editor_plugin.h @@ -33,10 +33,10 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/3d/skeleton.h" +#include "scene/3d/skeleton_3d.h" -class PhysicalBone; -class Joint; +class PhysicalBone3D; +class Joint3D; class SkeletonEditor : public Node { GDCLASS(SkeletonEditor, Node); @@ -46,13 +46,13 @@ class SkeletonEditor : public Node { }; struct BoneInfo { - PhysicalBone *physical_bone; + PhysicalBone3D *physical_bone; Transform relative_rest; // Relative to skeleton node BoneInfo() : physical_bone(NULL) {} }; - Skeleton *skeleton; + Skeleton3D *skeleton; MenuButton *options; @@ -66,10 +66,10 @@ protected: static void _bind_methods(); void create_physical_skeleton(); - PhysicalBone *create_physical_bone(int bone_id, int bone_child_id, const Vector &bones_infos); + PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector &bones_infos); public: - void edit(Skeleton *p_node); + void edit(Skeleton3D *p_node); SkeletonEditor(); ~SkeletonEditor(); diff --git a/editor/plugins/skeleton_ik_editor_plugin.cpp b/editor/plugins/skeleton_ik_editor_plugin.cpp index 8b120e9543..548cbe9470 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_editor_plugin.cpp @@ -57,7 +57,7 @@ void SkeletonIKEditorPlugin::edit(Object *p_object) { } } - SkeletonIK *s = Object::cast_to(p_object); + SkeletonIK3D *s = Object::cast_to(p_object); if (!s) return; @@ -66,7 +66,7 @@ void SkeletonIKEditorPlugin::edit(Object *p_object) { bool SkeletonIKEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("SkeletonIK"); + return p_object->is_class("SkeletonIK3D"); } void SkeletonIKEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/skeleton_ik_editor_plugin.h b/editor/plugins/skeleton_ik_editor_plugin.h index 814eb8ff5b..8895a548fe 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.h +++ b/editor/plugins/skeleton_ik_editor_plugin.h @@ -34,13 +34,13 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -class SkeletonIK; +class SkeletonIK3D; class SkeletonIKEditorPlugin : public EditorPlugin { GDCLASS(SkeletonIKEditorPlugin, EditorPlugin); - SkeletonIK *skeleton_ik; + SkeletonIK3D *skeleton_ik; Button *play_btn; EditorNode *editor; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index f0730f0144..318f3d6b09 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -43,11 +43,11 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/spatial_editor_gizmos.h" -#include "scene/3d/camera.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/physics_body.h" -#include "scene/3d/visual_instance.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/3d/visual_instance_3d.h" #include "scene/gui/viewport_container.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" @@ -81,12 +81,12 @@ void ViewportRotationControl::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { axis_menu_options.clear(); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_RIGHT); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_TOP); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_FRONT); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_LEFT); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_BOTTOM); - axis_menu_options.push_back(SpatialEditorViewport::VIEW_REAR); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_RIGHT); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_TOP); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_LEFT); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_BOTTOM); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_REAR); axis_colors.clear(); axis_colors.push_back(get_theme_color("axis_x_color", "Editor")); @@ -239,7 +239,7 @@ void ViewportRotationControl::_on_mouse_exited() { update(); } -void ViewportRotationControl::set_viewport(SpatialEditorViewport *p_viewport) { +void ViewportRotationControl::set_viewport(Node3DEditorViewport *p_viewport) { viewport = p_viewport; } @@ -247,9 +247,9 @@ void ViewportRotationControl::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &ViewportRotationControl::_gui_input); } -void SpatialEditorViewport::_update_camera(float p_interp_delta) { +void Node3DEditorViewport::_update_camera(float p_interp_delta) { - bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; + bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; Cursor old_camera_cursor = camera_cursor; camera_cursor = cursor; @@ -357,7 +357,7 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) { } } -Transform SpatialEditorViewport::to_camera_transform(const Cursor &p_cursor) const { +Transform Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const { Transform camera_transform; camera_transform.translate(p_cursor.pos); camera_transform.basis.rotate(Vector3(1, 0, 0), -p_cursor.x_rot); @@ -371,7 +371,7 @@ Transform SpatialEditorViewport::to_camera_transform(const Cursor &p_cursor) con return camera_transform; } -int SpatialEditorViewport::get_selected_count() const { +int Node3DEditorViewport::get_selected_count() const { Map &selection = editor_selection->get_selection(); @@ -379,11 +379,11 @@ int SpatialEditorViewport::get_selected_count() const { for (Map::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->key()); + Node3D *sp = Object::cast_to(E->key()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -393,68 +393,68 @@ int SpatialEditorViewport::get_selected_count() const { return count; } -float SpatialEditorViewport::get_znear() const { +float Node3DEditorViewport::get_znear() const { return CLAMP(spatial_editor->get_znear(), MIN_Z, MAX_Z); } -float SpatialEditorViewport::get_zfar() const { +float Node3DEditorViewport::get_zfar() const { return CLAMP(spatial_editor->get_zfar(), MIN_Z, MAX_Z); } -float SpatialEditorViewport::get_fov() const { +float Node3DEditorViewport::get_fov() const { return CLAMP(spatial_editor->get_fov(), MIN_FOV, MAX_FOV); } -Transform SpatialEditorViewport::_get_camera_transform() const { +Transform Node3DEditorViewport::_get_camera_transform() const { return camera->get_global_transform(); } -Vector3 SpatialEditorViewport::_get_camera_position() const { +Vector3 Node3DEditorViewport::_get_camera_position() const { return _get_camera_transform().origin; } -Point2 SpatialEditorViewport::_point_to_screen(const Vector3 &p_point) { +Point2 Node3DEditorViewport::_point_to_screen(const Vector3 &p_point) { return camera->unproject_position(p_point) * viewport_container->get_stretch_shrink(); } -Vector3 SpatialEditorViewport::_get_ray_pos(const Vector2 &p_pos) const { +Vector3 Node3DEditorViewport::_get_ray_pos(const Vector2 &p_pos) const { return camera->project_ray_origin(p_pos / viewport_container->get_stretch_shrink()); } -Vector3 SpatialEditorViewport::_get_camera_normal() const { +Vector3 Node3DEditorViewport::_get_camera_normal() const { return -_get_camera_transform().basis.get_axis(2); } -Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) const { +Vector3 Node3DEditorViewport::_get_ray(const Vector2 &p_pos) const { return camera->project_ray_normal(p_pos / viewport_container->get_stretch_shrink()); } -void SpatialEditorViewport::_clear_selected() { +void Node3DEditorViewport::_clear_selected() { editor_selection->clear(); } -void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) { +void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) { if (clicked.is_null()) return; Node *node = Object::cast_to(ObjectDB::get_instance(clicked)); - Spatial *selected = Object::cast_to(node); + Node3D *selected = Object::cast_to(node); if (!selected) return; if (!p_allow_locked) { // Replace the node by the group if grouped while (node && node != editor->get_edited_scene()->get_parent()) { - Spatial *selected_tmp = Object::cast_to(node); + Node3D *selected_tmp = Object::cast_to(node); if (selected_tmp && node->has_meta("_edit_group_")) { selected = selected_tmp; } @@ -467,7 +467,7 @@ void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p } } -void SpatialEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { +void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { if (!p_append) { editor_selection->clear(); @@ -487,7 +487,7 @@ void SpatialEditorViewport::_select(Node *p_node, bool p_append, bool p_single) } } -ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) { +ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) { if (r_gizmo_handle) *r_gizmo_handle = -1; @@ -497,7 +497,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, Vector2 shrinked_pos = p_pos / viewport_container->get_stretch_shrink(); Vector instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); - Set> found_gizmos; + Set> found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); ObjectID closest; @@ -507,12 +507,12 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, for (int i = 0; i < instances.size(); i++) { - Spatial *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); + Node3D *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); if (!spat) continue; - Ref seg = spat->get_gizmo(); + Ref seg = spat->get_gizmo(); if ((!seg.is_valid()) || found_gizmos.has(seg)) { continue; @@ -558,24 +558,24 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, return closest; } -void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select) { +void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select) { Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); Vector instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); - Set> found_gizmos; + Set> found_gizmos; r_includes_current = false; for (int i = 0; i < instances.size(); i++) { - Spatial *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); + Node3D *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); if (!spat) continue; - Ref seg = spat->get_gizmo(); + Ref seg = spat->get_gizmo(); if (!seg.is_valid()) continue; @@ -614,7 +614,7 @@ void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_incl results.sort(); } -Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { +Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { CameraMatrix cm; if (orthogonal) { @@ -633,7 +633,7 @@ Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { return camera_transform.xform(Vector3(((p_vector3.x / get_size().width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / get_size().height)) * 2.0 - 1.0) * screen_he.y, -(get_znear() + p_vector3.z))); } -void SpatialEditorViewport::_select_region() { +void Node3DEditorViewport::_select_region() { if (cursor.region_begin == cursor.region_end) return; //nothing really @@ -693,7 +693,7 @@ void SpatialEditorViewport::_select_region() { for (int i = 0; i < instances.size(); i++) { - Spatial *sp = Object::cast_to(ObjectDB::get_instance(instances[i])); + Node3D *sp = Object::cast_to(ObjectDB::get_instance(instances[i])); if (!sp || _is_node_locked(sp)) continue; @@ -703,10 +703,10 @@ void SpatialEditorViewport::_select_region() { } // Replace the node by the group if grouped - if (item->is_class("Spatial")) { - Spatial *sel = Object::cast_to(item); + if (item->is_class("Node3D")) { + Node3D *sel = Object::cast_to(item); while (item && item != editor->get_edited_scene()->get_parent()) { - Spatial *selected_tmp = Object::cast_to(item); + Node3D *selected_tmp = Object::cast_to(item); if (selected_tmp && item->has_meta("_edit_group_")) { sel = selected_tmp; } @@ -719,7 +719,7 @@ void SpatialEditorViewport::_select_region() { if (_is_node_locked(item)) continue; - Ref seg = sp->get_gizmo(); + Ref seg = sp->get_gizmo(); if (!seg.is_valid()) continue; @@ -735,7 +735,7 @@ void SpatialEditorViewport::_select_region() { } } -void SpatialEditorViewport::_update_name() { +void Node3DEditorViewport::_update_name() { String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); @@ -751,7 +751,7 @@ void SpatialEditorViewport::_update_name() { view_menu->set_size(Vector2(0, 0)); // resets the button size } -void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { +void Node3DEditorViewport::_compute_edit(const Point2 &p_point) { _edit.click_ray = _get_ray(Vector2(p_point.x, p_point.y)); _edit.click_ray_pos = _get_ray_pos(Vector2(p_point.x, p_point.y)); @@ -763,11 +763,11 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -801,7 +801,7 @@ static int _get_key_modifier(Ref e) { return 0; } -bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) { +bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) { if (!spatial_editor->is_gizmo_visible()) return false; @@ -817,7 +817,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig Transform gt = spatial_editor->get_gizmo_transform(); float gs = gizmo_scale; - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) { int col_axis = -1; float col_d = 1e20; @@ -886,7 +886,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } } - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { int col_axis = -1; float col_d = 1e20; @@ -925,7 +925,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig } } - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) { int col_axis = -1; float col_d = 1e20; @@ -1000,37 +1000,37 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig return false; } -void SpatialEditorViewport::_surface_mouse_enter() { +void Node3DEditorViewport::_surface_mouse_enter() { if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) surface->grab_focus(); } -void SpatialEditorViewport::_surface_mouse_exit() { +void Node3DEditorViewport::_surface_mouse_exit() { _remove_preview(); } -void SpatialEditorViewport::_surface_focus_enter() { +void Node3DEditorViewport::_surface_focus_enter() { view_menu->set_disable_shortcuts(false); } -void SpatialEditorViewport::_surface_focus_exit() { +void Node3DEditorViewport::_surface_focus_exit() { view_menu->set_disable_shortcuts(true); } -bool SpatialEditorViewport ::_is_node_locked(const Node *p_node) { +bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) { return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); } -void SpatialEditorViewport::_list_select(Ref b) { +void Node3DEditorViewport::_list_select(Ref b) { _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift()); Node *scene = editor->get_edited_scene(); for (int i = 0; i < selection_results.size(); i++) { - Spatial *item = selection_results[i].item; + Node3D *item = selection_results[i].item; if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) { //invalid result selection_results.remove(i); @@ -1046,7 +1046,7 @@ void SpatialEditorViewport::_list_select(Ref b) { selection_results.clear(); if (clicked.is_valid()) { - _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); + _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != Node3DEditor::TOOL_MODE_LIST_SELECT); clicked = ObjectID(); } @@ -1057,7 +1057,7 @@ void SpatialEditorViewport::_list_select(Ref b) { for (int i = 0; i < selection_results.size(); i++) { - Spatial *spat = selection_results[i].item; + Node3D *spat = selection_results[i].item; Ref icon = EditorNode::get_singleton()->get_object_icon(spat, "Node"); @@ -1071,7 +1071,7 @@ void SpatialEditorViewport::_list_select(Ref b) { Node *node = spat; while (node && node != ed_scene->get_parent()) { - Spatial *selected_tmp = Object::cast_to(node); + Node3D *selected_tmp = Object::cast_to(node); if (selected_tmp && node->has_meta("_edit_group_")) { locked = 2; } @@ -1096,7 +1096,7 @@ void SpatialEditorViewport::_list_select(Ref b) { } } -void SpatialEditorViewport::_sinput(const Ref &p_event) { +void Node3DEditorViewport::_sinput(const Ref &p_event) { if (previewing) return; //do NONE @@ -1149,7 +1149,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (b->is_pressed() && _edit.gizmo.is_valid()) { //restore _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, true); - _edit.gizmo = Ref(); + _edit.gizmo = Ref(); } if (_edit.mode == TRANSFORM_NONE && b->is_pressed()) { @@ -1172,11 +1172,11 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -1251,7 +1251,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { break; } - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_LIST_SELECT) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_LIST_SELECT) { _list_select(b); break; } @@ -1271,7 +1271,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (can_select_gizmos && spatial_editor->get_selected()) { - Ref seg = spatial_editor->get_selected()->get_gizmo(); + Ref seg = spatial_editor->get_selected()->get_gizmo(); if (seg.is_valid()) { int handle = -1; Vector3 point; @@ -1293,7 +1293,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { clicked = ObjectID(); clicked_includes_current = false; - if ((spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT && b->get_control()) || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) { + if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->get_control()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { /* HANDLE ROTATION */ if (get_selected_count() == 0) @@ -1304,7 +1304,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { break; } - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) { if (get_selected_count() == 0) break; //bye @@ -1314,7 +1314,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { break; } - if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) { + if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) { if (get_selected_count() == 0) break; //bye @@ -1347,10 +1347,10 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (clicked.is_valid() && gizmo_handle >= 0) { - Spatial *spa = Object::cast_to(ObjectDB::get_instance(clicked)); + Node3D *spa = Object::cast_to(ObjectDB::get_instance(clicked)); if (spa) { - Ref seg = spa->get_gizmo(); + Ref seg = spa->get_gizmo(); if (seg.is_valid()) { _edit.gizmo = seg; @@ -1367,7 +1367,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (_edit.gizmo.is_valid()) { _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, false); - _edit.gizmo = Ref(); + _edit.gizmo = Ref(); break; } if (clicked.is_valid()) { @@ -1394,11 +1394,11 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -1425,7 +1425,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (spatial_editor->get_selected()) { - Ref seg = spatial_editor->get_selected()->get_gizmo(); + Ref seg = spatial_editor->get_selected()->get_gizmo(); if (seg.is_valid()) { int selected_handle = -1; @@ -1593,12 +1593,12 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) { continue; } - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) { continue; } @@ -1718,12 +1718,12 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) { continue; } - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) { continue; } @@ -1816,11 +1816,11 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -2054,7 +2054,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; @@ -2083,7 +2083,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { accept_event(); } -void SpatialEditorViewport::_nav_pan(Ref p_event, const Vector2 &p_relative) { +void Node3DEditorViewport::_nav_pan(Ref p_event, const Vector2 &p_relative) { const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); @@ -2103,7 +2103,7 @@ void SpatialEditorViewport::_nav_pan(Ref p_event, const cursor.pos = camera_transform.origin; } -void SpatialEditorViewport::_nav_zoom(Ref p_event, const Vector2 &p_relative) { +void Node3DEditorViewport::_nav_zoom(Ref p_event, const Vector2 &p_relative) { const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); @@ -2126,7 +2126,7 @@ void SpatialEditorViewport::_nav_zoom(Ref p_event, cons } } -void SpatialEditorViewport::_nav_orbit(Ref p_event, const Vector2 &p_relative) { +void Node3DEditorViewport::_nav_orbit(Ref p_event, const Vector2 &p_relative) { if (lock_rotation) { _nav_pan(p_event, p_relative); @@ -2155,7 +2155,7 @@ void SpatialEditorViewport::_nav_orbit(Ref p_event, con _update_name(); } -void SpatialEditorViewport::_nav_look(Ref p_event, const Vector2 &p_relative) { +void Node3DEditorViewport::_nav_look(Ref p_event, const Vector2 &p_relative) { if (orthogonal) { _nav_pan(p_event, p_relative); @@ -2195,7 +2195,7 @@ void SpatialEditorViewport::_nav_look(Ref p_event, cons _update_name(); } -void SpatialEditorViewport::set_freelook_active(bool active_now) { +void Node3DEditorViewport::set_freelook_active(bool active_now) { if (!freelook_active && active_now) { // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential @@ -2227,7 +2227,7 @@ void SpatialEditorViewport::set_freelook_active(bool active_now) { freelook_active = active_now; } -void SpatialEditorViewport::scale_cursor_distance(real_t scale) { +void Node3DEditorViewport::scale_cursor_distance(real_t scale) { // Prevents zero distance which would short-circuit any scaling if (cursor.distance < ZOOM_MIN_DISTANCE) @@ -2242,7 +2242,7 @@ void SpatialEditorViewport::scale_cursor_distance(real_t scale) { surface->update(); } -void SpatialEditorViewport::scale_freelook_speed(real_t scale) { +void Node3DEditorViewport::scale_freelook_speed(real_t scale) { // Prevents zero distance which would short-circuit any scaling if (freelook_speed < FREELOOK_MIN_SPEED) @@ -2257,7 +2257,7 @@ void SpatialEditorViewport::scale_freelook_speed(real_t scale) { surface->update(); } -Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref &p_ev_mouse_motion) const { +Point2i Node3DEditorViewport::_get_warped_mouse_motion(const Ref &p_ev_mouse_motion) const { Point2i relative; if (bool(EDITOR_DEF("editors/3d/navigation/warped_mouse_panning", false))) { relative = InputFilter::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect()); @@ -2281,7 +2281,7 @@ static bool is_shortcut_pressed(const String &p_path) { return input.is_key_pressed(keycode); } -void SpatialEditorViewport::_update_freelook(real_t delta) { +void Node3DEditorViewport::_update_freelook(real_t delta) { if (!is_freelook_active()) { return; @@ -2326,22 +2326,22 @@ void SpatialEditorViewport::_update_freelook(real_t delta) { cursor.eye_pos += motion; } -void SpatialEditorViewport::set_message(String p_message, float p_time) { +void Node3DEditorViewport::set_message(String p_message, float p_time) { message = p_message; message_time = p_time; } -void SpatialEditorPlugin::edited_scene_changed() { - for (uint32_t i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { - SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(i); +void Node3DEditorPlugin::edited_scene_changed() { + for (uint32_t i = 0; i < Node3DEditor::VIEWPORTS_COUNT; i++) { + Node3DEditorViewport *viewport = Node3DEditor::get_singleton()->get_editor_viewport(i); if (viewport->is_visible()) { viewport->notification(Control::NOTIFICATION_VISIBILITY_CHANGED); } } } -void SpatialEditorViewport::_notification(int p_what) { +void Node3DEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -2387,14 +2387,14 @@ void SpatialEditorViewport::_notification(int p_what) { Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root(); if (previewing_cinema && scene_root != NULL) { - Camera *cam = scene_root->get_viewport()->get_camera(); + Camera3D *cam = scene_root->get_viewport()->get_camera(); if (cam != NULL && cam != previewing) { //then switch the viewport's camera to the scene's viewport camera if (previewing != NULL) { - previewing->disconnect("tree_exited", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + previewing->disconnect("tree_exited", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); } previewing = cam; - previewing->connect("tree_exited", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + previewing->connect("tree_exited", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), cam->get_camera()); surface->update(); } @@ -2409,11 +2409,11 @@ void SpatialEditorViewport::_notification(int p_what) { for (Map::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->key()); + Node3D *sp = Object::cast_to(E->key()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -2426,7 +2426,7 @@ void SpatialEditorViewport::_notification(int p_what) { se->last_xform_dirty = false; se->last_xform = t; - VisualInstance *vi = Object::cast_to(sp); + VisualInstance3D *vi = Object::cast_to(sp); se->aabb = vi ? vi->get_aabb() : _calculate_spatial_bounds(sp); @@ -2484,7 +2484,7 @@ void SpatialEditorViewport::_notification(int p_what) { bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); info_label->set_visible(show_info); - Camera *current_camera; + Camera3D *current_camera; if (previewing) { current_camera = previewing; @@ -2538,12 +2538,12 @@ void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - surface->connect("draw", callable_mp(this, &SpatialEditorViewport::_draw)); - surface->connect("gui_input", callable_mp(this, &SpatialEditorViewport::_sinput)); - surface->connect("mouse_entered", callable_mp(this, &SpatialEditorViewport::_surface_mouse_enter)); - surface->connect("mouse_exited", callable_mp(this, &SpatialEditorViewport::_surface_mouse_exit)); - surface->connect("focus_entered", callable_mp(this, &SpatialEditorViewport::_surface_focus_enter)); - surface->connect("focus_exited", callable_mp(this, &SpatialEditorViewport::_surface_focus_exit)); + surface->connect("draw", callable_mp(this, &Node3DEditorViewport::_draw)); + surface->connect("gui_input", callable_mp(this, &Node3DEditorViewport::_sinput)); + surface->connect("mouse_entered", callable_mp(this, &Node3DEditorViewport::_surface_mouse_enter)); + surface->connect("mouse_exited", callable_mp(this, &Node3DEditorViewport::_surface_mouse_exit)); + surface->connect("focus_entered", callable_mp(this, &Node3DEditorViewport::_surface_focus_enter)); + surface->connect("focus_exited", callable_mp(this, &Node3DEditorViewport::_surface_focus_exit)); _init_gizmo_instance(index); } @@ -2556,7 +2556,7 @@ void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_THEME_CHANGED) { view_menu->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); - preview_camera->set_icon(get_theme_icon("Camera", "EditorIcons")); + preview_camera->set_icon(get_theme_icon("Camera3D", "EditorIcons")); view_menu->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); view_menu->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); @@ -2598,7 +2598,7 @@ static void draw_indicator_bar(Control &surface, real_t fill, Ref ico surface.draw_texture(icon, icon_pos); } -void SpatialEditorViewport::_draw() { +void Node3DEditorViewport::_draw() { EditorPluginList *over_plugin_list = EditorNode::get_singleton()->get_editor_plugins_over(); if (!over_plugin_list->empty()) { @@ -2659,14 +2659,14 @@ void SpatialEditorViewport::_draw() { Rect2 draw_rect; switch (previewing->get_keep_aspect_mode()) { - case Camera::KEEP_WIDTH: { + case Camera3D::KEEP_WIDTH: { draw_rect.size = Size2(s.width, s.width / aspect); draw_rect.position.x = 0; draw_rect.position.y = (s.height - draw_rect.size.y) * 0.5; } break; - case Camera::KEEP_HEIGHT: { + case Camera3D::KEEP_HEIGHT: { draw_rect.size = Size2(s.height * aspect, s.height); draw_rect.position.y = 0; @@ -2723,7 +2723,7 @@ void SpatialEditorViewport::_draw() { } } -void SpatialEditorViewport::_menu_option(int p_option) { +void Node3DEditorViewport::_menu_option(int p_option) { switch (p_option) { @@ -2810,11 +2810,11 @@ void SpatialEditorViewport::_menu_option(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -2846,11 +2846,11 @@ void SpatialEditorViewport::_menu_option(int p_option) { undo_redo->create_action(TTR("Align Rotation with View")); for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -2870,7 +2870,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { camera->set_environment(RES()); } else { - camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment()); + camera->set_environment(Node3DEditor::get_singleton()->get_viewport_environment()); } view_menu->get_popup()->set_item_checked(idx, current); @@ -2934,7 +2934,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER); bool current = view_menu->get_popup()->is_item_checked(idx); current = !current; - camera->set_doppler_tracking(current ? Camera::DOPPLER_TRACKING_IDLE_STEP : Camera::DOPPLER_TRACKING_DISABLED); + camera->set_doppler_tracking(current ? Camera3D::DOPPLER_TRACKING_IDLE_STEP : Camera3D::DOPPLER_TRACKING_DISABLED); view_menu->get_popup()->set_item_checked(idx, current); } break; @@ -3061,23 +3061,23 @@ void SpatialEditorViewport::_menu_option(int p_option) { } } -void SpatialEditorViewport::_set_auto_orthogonal() { +void Node3DEditorViewport::_set_auto_orthogonal() { if (!orthogonal && view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL))) { _menu_option(VIEW_ORTHOGONAL); auto_orthogonal = true; } } -void SpatialEditorViewport::_preview_exited_scene() { +void Node3DEditorViewport::_preview_exited_scene() { - preview_camera->disconnect("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview)); + preview_camera->disconnect("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview)); preview_camera->set_pressed(false); _toggle_camera_preview(false); - preview_camera->connect("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview)); + preview_camera->connect("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview)); view_menu->show(); } -void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { +void Node3DEditorViewport::_init_gizmo_instance(int p_idx) { uint32_t layer = 1 << (GIZMO_BASE_LAYER + p_idx); @@ -3119,7 +3119,7 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { } } -void SpatialEditorViewport::_finish_gizmo_instances() { +void Node3DEditorViewport::_finish_gizmo_instances() { for (int i = 0; i < 3; i++) { VS::get_singleton()->free(move_gizmo_instance[i]); @@ -3129,14 +3129,14 @@ void SpatialEditorViewport::_finish_gizmo_instances() { VS::get_singleton()->free(scale_plane_gizmo_instance[i]); } } -void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { +void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) { ERR_FAIL_COND(p_activate && !preview); ERR_FAIL_COND(!p_activate && !previewing); if (!p_activate) { - previewing->disconnect("tree_exiting", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + previewing->disconnect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); previewing = NULL; VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore if (!preview) @@ -3147,18 +3147,18 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { } else { previewing = preview; - previewing->connect("tree_exiting", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace view_menu->set_disabled(true); surface->update(); } } -void SpatialEditorViewport::_toggle_cinema_preview(bool p_activate) { +void Node3DEditorViewport::_toggle_cinema_preview(bool p_activate) { previewing_cinema = p_activate; if (!previewing_cinema) { if (previewing != NULL) - previewing->disconnect("tree_exited", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + previewing->disconnect("tree_exited", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); previewing = NULL; VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore @@ -3173,7 +3173,7 @@ void SpatialEditorViewport::_toggle_cinema_preview(bool p_activate) { } } -void SpatialEditorViewport::_selection_result_pressed(int p_result) { +void Node3DEditorViewport::_selection_result_pressed(int p_result) { if (selection_results.size() <= p_result) return; @@ -3181,19 +3181,19 @@ void SpatialEditorViewport::_selection_result_pressed(int p_result) { clicked = selection_results[p_result].item->get_instance_id(); if (clicked.is_valid()) { - _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); + _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != Node3DEditor::TOOL_MODE_LIST_SELECT); clicked = ObjectID(); } } -void SpatialEditorViewport::_selection_menu_hide() { +void Node3DEditorViewport::_selection_menu_hide() { selection_results.clear(); selection_menu->clear(); selection_menu->set_size(Vector2(0, 0)); } -void SpatialEditorViewport::set_can_preview(Camera *p_preview) { +void Node3DEditorViewport::set_can_preview(Camera3D *p_preview) { preview = p_preview; @@ -3201,7 +3201,7 @@ void SpatialEditorViewport::set_can_preview(Camera *p_preview) { preview_camera->set_visible(p_preview); } -void SpatialEditorViewport::update_transform_gizmo_view() { +void Node3DEditorViewport::update_transform_gizmo_view() { if (!is_visible_in_tree()) return; @@ -3245,19 +3245,19 @@ void SpatialEditorViewport::update_transform_gizmo_view() { for (int i = 0; i < 3; i++) { VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE)); + VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); VisualServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE)); + VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE)); + VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE)); + VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); VisualServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE)); + VisualServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); } } -void SpatialEditorViewport::set_state(const Dictionary &p_state) { +void Node3DEditorViewport::set_state(const Dictionary &p_state) { if (p_state.has("position")) cursor.pos = p_state["position"]; @@ -3318,7 +3318,7 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { bool doppler = p_state["doppler"]; int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER); - camera->set_doppler_tracking(doppler ? Camera::DOPPLER_TRACKING_IDLE_STEP : Camera::DOPPLER_TRACKING_DISABLED); + camera->set_doppler_tracking(doppler ? Camera3D::DOPPLER_TRACKING_IDLE_STEP : Camera3D::DOPPLER_TRACKING_DISABLED); view_menu->get_popup()->set_item_checked(idx, doppler); } if (p_state.has("gizmos")) { @@ -3355,14 +3355,14 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, previewing_cinema); } - if (preview_camera->is_connected("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview))) { - preview_camera->disconnect("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview)); + if (preview_camera->is_connected("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview))) { + preview_camera->disconnect("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview)); } if (p_state.has("previewing")) { Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]); - if (Object::cast_to(pv)) { - previewing = Object::cast_to(pv); - previewing->connect("tree_exiting", callable_mp(this, &SpatialEditorViewport::_preview_exited_scene)); + if (Object::cast_to(pv)) { + previewing = Object::cast_to(pv); + previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace view_menu->set_disabled(true); surface->update(); @@ -3370,10 +3370,10 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) { preview_camera->show(); } } - preview_camera->connect("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview)); + preview_camera->connect("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview)); } -Dictionary SpatialEditorViewport::get_state() const { +Dictionary Node3DEditorViewport::get_state() const { Dictionary d; d["position"] = cursor.pos; @@ -3381,7 +3381,7 @@ Dictionary SpatialEditorViewport::get_state() const { d["y_rotation"] = cursor.y_rot; d["distance"] = cursor.distance; d["use_environment"] = camera->get_environment().is_valid(); - d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; + d["use_orthogonal"] = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; d["view_name"] = name; d["auto_orthogonal"] = auto_orthogonal; d["auto_orthogonal_enabled"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL)); @@ -3408,17 +3408,17 @@ Dictionary SpatialEditorViewport::get_state() const { return d; } -void SpatialEditorViewport::_bind_methods() { +void Node3DEditorViewport::_bind_methods() { - ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &SpatialEditorViewport::update_transform_gizmo_view); // Used by call_deferred. - ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpatialEditorViewport::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw); + ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &Node3DEditorViewport::update_transform_gizmo_view); // Used by call_deferred. + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Node3DEditorViewport::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &Node3DEditorViewport::drop_data_fw); ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport"))); ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport"))); } -void SpatialEditorViewport::reset() { +void Node3DEditorViewport::reset() { orthogonal = false; auto_orthogonal = false; @@ -3436,7 +3436,7 @@ void SpatialEditorViewport::reset() { _update_name(); } -void SpatialEditorViewport::focus_selection() { +void Node3DEditorViewport::focus_selection() { if (!get_selected_count()) return; @@ -3447,11 +3447,11 @@ void SpatialEditorViewport::focus_selection() { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -3466,20 +3466,20 @@ void SpatialEditorViewport::focus_selection() { cursor.pos = center; } -void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node, AABB *p_preview_bounds, AcceptDialog *p_accept) { +void Node3DEditorViewport::assign_pending_data_pointers(Node3D *p_preview_node, AABB *p_preview_bounds, AcceptDialog *p_accept) { preview_node = p_preview_node; preview_bounds = p_preview_bounds; accept = p_accept; } -Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const { +Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const { const float MAX_DISTANCE = 10; Vector3 world_ray = _get_ray(p_pos); Vector3 world_pos = _get_ray_pos(p_pos); Vector instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario()); - Set> found_gizmos; + Set> found_gizmos; float closest_dist = MAX_DISTANCE; @@ -3488,12 +3488,12 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const for (int i = 0; i < instances.size(); i++) { - MeshInstance *mesh_instance = Object::cast_to(ObjectDB::get_instance(instances[i])); + MeshInstance3D *mesh_instance = Object::cast_to(ObjectDB::get_instance(instances[i])); if (!mesh_instance) continue; - Ref seg = mesh_instance->get_gizmo(); + Ref seg = mesh_instance->get_gizmo(); if ((!seg.is_valid()) || found_gizmos.has(seg)) { continue; @@ -3529,20 +3529,20 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const return point + offset; } -AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, bool p_exclude_toplevel_transform) { +AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_toplevel_transform) { AABB bounds; - const MeshInstance *mesh_instance = Object::cast_to(p_parent); + const MeshInstance3D *mesh_instance = Object::cast_to(p_parent); if (mesh_instance) { bounds = mesh_instance->get_aabb(); } for (int i = 0; i < p_parent->get_child_count(); i++) { - Spatial *child = Object::cast_to(p_parent->get_child(i)); + Node3D *child = Object::cast_to(p_parent->get_child(i)); if (child) { AABB child_bounds = _calculate_spatial_bounds(child, false); - if (bounds.size == Vector3() && p_parent->get_class_name() == StringName("Spatial")) { + if (bounds.size == Vector3() && p_parent->get_class_name() == StringName("Node3D")) { bounds = child_bounds; } else { bounds.merge_with(child_bounds); @@ -3550,7 +3550,7 @@ AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, b } } - if (bounds.size == Vector3() && p_parent->get_class_name() != StringName("Spatial")) { + if (bounds.size == Vector3() && p_parent->get_class_name() != StringName("Node3D")) { bounds = AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4)); } @@ -3561,7 +3561,7 @@ AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, b return bounds; } -void SpatialEditorViewport::_create_preview(const Vector &files) const { +void Node3DEditorViewport::_create_preview(const Vector &files) const { for (int i = 0; i < files.size(); i++) { String path = files[i]; RES res = ResourceLoader::load(path); @@ -3570,7 +3570,7 @@ void SpatialEditorViewport::_create_preview(const Vector &files) const { Ref mesh = Ref(Object::cast_to(*res)); if (mesh != NULL || scene != NULL) { if (mesh != NULL) { - MeshInstance *mesh_instance = memnew(MeshInstance); + MeshInstance3D *mesh_instance = memnew(MeshInstance3D); mesh_instance->set_mesh(mesh); preview_node->add_child(mesh_instance); } else { @@ -3587,7 +3587,7 @@ void SpatialEditorViewport::_create_preview(const Vector &files) const { *preview_bounds = _calculate_spatial_bounds(preview_node); } -void SpatialEditorViewport::_remove_preview() { +void Node3DEditorViewport::_remove_preview() { if (preview_node->get_parent()) { for (int i = preview_node->get_child_count() - 1; i >= 0; i--) { Node *node = preview_node->get_child(i); @@ -3598,7 +3598,7 @@ void SpatialEditorViewport::_remove_preview() { } } -bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) { +bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) { if (p_desired_node->get_filename() == p_target_scene_path) { return true; } @@ -3613,7 +3613,7 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s return false; } -bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { +bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { RES res = ResourceLoader::load(path); ERR_FAIL_COND_V(res.is_null(), false); @@ -3624,7 +3624,7 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P if (mesh != NULL || scene != NULL) { if (mesh != NULL) { - MeshInstance *mesh_instance = memnew(MeshInstance); + MeshInstance3D *mesh_instance = memnew(MeshInstance3D); mesh_instance->set_mesh(mesh); mesh_instance->set_name(path.get_file().get_basename()); instanced_scene = mesh_instance; @@ -3663,7 +3663,7 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); Transform global_transform; - Spatial *parent_spatial = Object::cast_to(parent); + Node3D *parent_spatial = Object::cast_to(parent); if (parent_spatial) global_transform = parent_spatial->get_global_gizmo_transform(); @@ -3674,7 +3674,7 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P return true; } -void SpatialEditorViewport::_perform_drop_data() { +void Node3DEditorViewport::_perform_drop_data() { _remove_preview(); Vector error_files; @@ -3710,7 +3710,7 @@ void SpatialEditorViewport::_perform_drop_data() { } } -bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { +bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { bool can_instance = false; @@ -3767,7 +3767,7 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian return can_instance; } -void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { +void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { if (!can_drop_data_fw(p_point, p_data, p_from)) return; @@ -3807,7 +3807,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p _perform_drop_data(); } -SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) { +Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, EditorNode *p_editor, int p_index) { _edit.mode = TRANSFORM_NONE; _edit.plane = TRANSFORM_VIEW; @@ -3843,7 +3843,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed add_child(surface); surface->set_anchors_and_margins_preset(Control::PRESET_WIDE); surface->set_clip_contents(true); - camera = memnew(Camera); + camera = memnew(Camera3D); camera->set_disable_gizmo(true); camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER)); viewport->add_child(camera); @@ -3924,8 +3924,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_transform_with_view"), VIEW_ALIGN_TRANSFORM_WITH_VIEW); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_rotation_with_view"), VIEW_ALIGN_ROTATION_WITH_VIEW); - view_menu->get_popup()->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option)); - display_submenu->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option)); + view_menu->get_popup()->connect("id_pressed", callable_mp(this, &Node3DEditorViewport::_menu_option)); + display_submenu->connect("id_pressed", callable_mp(this, &Node3DEditorViewport::_menu_option)); view_menu->set_disable_shortcuts(true); #ifndef _MSC_VER #warning this needs to be fixed @@ -3963,7 +3963,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed vbox->add_child(preview_camera); preview_camera->set_h_size_flags(0); preview_camera->hide(); - preview_camera->connect("toggled", callable_mp(this, &SpatialEditorViewport::_toggle_camera_preview)); + preview_camera->connect("toggled", callable_mp(this, &Node3DEditorViewport::_toggle_camera_preview)); previewing = NULL; gizmo_scale = 1.0; @@ -4038,8 +4038,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed selection_menu = memnew(PopupMenu); add_child(selection_menu); selection_menu->set_min_size(Size2(100, 0) * EDSCALE); - selection_menu->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_selection_result_pressed)); - selection_menu->connect("popup_hide", callable_mp(this, &SpatialEditorViewport::_selection_menu_hide)); + selection_menu->connect("id_pressed", callable_mp(this, &Node3DEditorViewport::_selection_result_pressed)); + selection_menu->connect("popup_hide", callable_mp(this, &Node3DEditorViewport::_selection_menu_hide)); if (p_index == 0) { view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER), true); @@ -4049,12 +4049,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed name = ""; _update_name(); - EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &SpatialEditorViewport::update_transform_gizmo_view)); + EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view)); } ////////////////////////////////////////////////////////////// -void SpatialEditorViewportContainer::_gui_input(const Ref &p_event) { +void Node3DEditorViewportContainer::_gui_input(const Ref &p_event) { Ref mb = p_event; @@ -4147,7 +4147,7 @@ void SpatialEditorViewportContainer::_gui_input(const Ref &p_event) } } -void SpatialEditorViewportContainer::_notification(int p_what) { +void Node3DEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_MOUSE_ENTER || p_what == NOTIFICATION_MOUSE_EXIT) { @@ -4243,10 +4243,10 @@ void SpatialEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_SORT_CHILDREN) { - SpatialEditorViewport *viewports[4]; + Node3DEditorViewport *viewports[4]; int vc = 0; for (int i = 0; i < get_child_count(); i++) { - viewports[vc] = Object::cast_to(get_child(i)); + viewports[vc] = Object::cast_to(get_child(i)); if (viewports[vc]) { vc++; } @@ -4362,23 +4362,23 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } } -void SpatialEditorViewportContainer::set_view(View p_view) { +void Node3DEditorViewportContainer::set_view(View p_view) { view = p_view; queue_sort(); } -SpatialEditorViewportContainer::View SpatialEditorViewportContainer::get_view() { +Node3DEditorViewportContainer::View Node3DEditorViewportContainer::get_view() { return view; } -void SpatialEditorViewportContainer::_bind_methods() { +void Node3DEditorViewportContainer::_bind_methods() { - ClassDB::bind_method("_gui_input", &SpatialEditorViewportContainer::_gui_input); + ClassDB::bind_method("_gui_input", &Node3DEditorViewportContainer::_gui_input); } -SpatialEditorViewportContainer::SpatialEditorViewportContainer() { +Node3DEditorViewportContainer::Node3DEditorViewportContainer() { set_clip_contents(true); view = VIEW_USE_1_VIEWPORT; @@ -4393,15 +4393,15 @@ SpatialEditorViewportContainer::SpatialEditorViewportContainer() { /////////////////////////////////////////////////////////////////// -SpatialEditor *SpatialEditor::singleton = NULL; +Node3DEditor *Node3DEditor::singleton = NULL; -SpatialEditorSelectedItem::~SpatialEditorSelectedItem() { +Node3DEditorSelectedItem::~Node3DEditorSelectedItem() { if (sbox_instance.is_valid()) VisualServer::get_singleton()->free(sbox_instance); } -void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { +void Node3DEditor::select_gizmo_highlight_axis(int p_axis) { for (int i = 0; i < 3; i++) { @@ -4413,7 +4413,7 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { } } -void SpatialEditor::update_transform_gizmo() { +void Node3DEditor::update_transform_gizmo() { List &selection = editor_selection->get_selected_node_list(); AABB center; @@ -4424,11 +4424,11 @@ void SpatialEditor::update_transform_gizmo() { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -4459,7 +4459,7 @@ void SpatialEditor::update_transform_gizmo() { void _update_all_gizmos(Node *p_node) { for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - Spatial *spatial_node = Object::cast_to(p_node->get_child(i)); + Node3D *spatial_node = Object::cast_to(p_node->get_child(i)); if (spatial_node) { spatial_node->update_gizmo(); } @@ -4468,20 +4468,20 @@ void _update_all_gizmos(Node *p_node) { } } -void SpatialEditor::update_all_gizmos(Node *p_node) { +void Node3DEditor::update_all_gizmos(Node *p_node) { if (!p_node) { p_node = SceneTree::get_singleton()->get_root(); } _update_all_gizmos(p_node); } -Object *SpatialEditor::_get_editor_data(Object *p_what) { +Object *Node3DEditor::_get_editor_data(Object *p_what) { - Spatial *sp = Object::cast_to(p_what); + Node3D *sp = Object::cast_to(p_what); if (!sp) return NULL; - SpatialEditorSelectedItem *si = memnew(SpatialEditorSelectedItem); + Node3DEditorSelectedItem *si = memnew(Node3DEditorSelectedItem); si->sp = sp; si->sbox_instance = VisualServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario()); @@ -4490,7 +4490,7 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) { return si; } -void SpatialEditor::_generate_selection_box() { +void Node3DEditor::_generate_selection_box() { AABB aabb(Vector3(), Vector3(1, 1, 1)); aabb.grow_by(aabb.get_longest_axis_size() / 20.0); @@ -4524,7 +4524,7 @@ void SpatialEditor::_generate_selection_box() { selection_box = st->commit(); } -Dictionary SpatialEditor::get_state() const { +Dictionary Node3DEditor::get_state() const { Dictionary d; @@ -4575,7 +4575,7 @@ Dictionary SpatialEditor::get_state() const { return d; } -void SpatialEditor::set_state(const Dictionary &p_state) { +void Node3DEditor::set_state(const Dictionary &p_state) { Dictionary d = p_state; @@ -4660,7 +4660,7 @@ void SpatialEditor::set_state(const Dictionary &p_state) { for (int j = 0; j < gizmo_plugins_by_name.size(); ++j) { if (!gizmo_plugins_by_name[j]->can_be_hidden()) continue; - int state = EditorSpatialGizmoPlugin::VISIBLE; + int state = EditorNode3DGizmoPlugin::VISIBLE; for (int i = 0; i < keys.size(); i++) { if (gizmo_plugins_by_name.write[j]->get_name() == keys[i]) { state = gizmos_status[keys[i]]; @@ -4674,12 +4674,12 @@ void SpatialEditor::set_state(const Dictionary &p_state) { } } -void SpatialEditor::edit(Spatial *p_spatial) { +void Node3DEditor::edit(Node3D *p_spatial) { if (p_spatial != selected) { if (selected) { - Ref seg = selected->get_gizmo(); + Ref seg = selected->get_gizmo(); if (seg.is_valid()) { seg->set_selected(false); selected->update_gizmo(); @@ -4691,7 +4691,7 @@ void SpatialEditor::edit(Spatial *p_spatial) { if (selected) { - Ref seg = selected->get_gizmo(); + Ref seg = selected->get_gizmo(); if (seg.is_valid()) { seg->set_selected(true); selected->update_gizmo(); @@ -4700,21 +4700,21 @@ void SpatialEditor::edit(Spatial *p_spatial) { } } -void SpatialEditor::_snap_changed() { +void Node3DEditor::_snap_changed() { snap_translate_value = snap_translate->get_text().to_double(); snap_rotate_value = snap_rotate->get_text().to_double(); snap_scale_value = snap_scale->get_text().to_double(); } -void SpatialEditor::_snap_update() { +void Node3DEditor::_snap_update() { snap_translate->set_text(String::num(snap_translate_value)); snap_rotate->set_text(String::num(snap_rotate_value)); snap_scale->set_text(String::num(snap_scale_value)); } -void SpatialEditor::_xform_dialog_action() { +void Node3DEditor::_xform_dialog_action() { Transform t; //translation @@ -4738,11 +4738,11 @@ void SpatialEditor::_xform_dialog_action() { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (!sp) continue; - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); if (!se) continue; @@ -4763,7 +4763,7 @@ void SpatialEditor::_xform_dialog_action() { undo_redo->commit_action(); } -void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) { +void Node3DEditor::_menu_item_toggled(bool pressed, int p_option) { switch (p_option) { case MENU_TOOL_LOCAL_COORDS: { @@ -4792,7 +4792,7 @@ void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) { } } -void SpatialEditor::_menu_gizmo_toggled(int p_option) { +void Node3DEditor::_menu_gizmo_toggled(int p_option) { const int idx = gizmos_menu->get_item_index(p_option); gizmos_menu->toggle_item_multistate(idx); @@ -4800,13 +4800,13 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) { // Change icon const int state = gizmos_menu->get_item_state(idx); switch (state) { - case EditorSpatialGizmoPlugin::VISIBLE: + case EditorNode3DGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_visible")); break; - case EditorSpatialGizmoPlugin::ON_TOP: + case EditorNode3DGizmoPlugin::ON_TOP: gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_xray")); break; - case EditorSpatialGizmoPlugin::HIDDEN: + case EditorNode3DGizmoPlugin::HIDDEN: gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_hidden")); break; } @@ -4816,7 +4816,7 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) { update_all_gizmos(); } -void SpatialEditor::_update_camera_override_button(bool p_game_running) { +void Node3DEditor::_update_camera_override_button(bool p_game_running) { Button *const button = tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]; if (p_game_running) { @@ -4829,8 +4829,8 @@ void SpatialEditor::_update_camera_override_button(bool p_game_running) { } } -void SpatialEditor::_update_camera_override_viewport(Object *p_viewport) { - SpatialEditorViewport *current_viewport = Object::cast_to(p_viewport); +void Node3DEditor::_update_camera_override_viewport(Object *p_viewport) { + Node3DEditorViewport *current_viewport = Object::cast_to(p_viewport); if (!current_viewport) return; @@ -4845,7 +4845,7 @@ void SpatialEditor::_update_camera_override_viewport(Object *p_viewport) { } } -void SpatialEditor::_menu_item_pressed(int p_option) { +void Node3DEditor::_menu_item_pressed(int p_option) { switch (p_option) { @@ -4879,7 +4879,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_1_VIEWPORT: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_1_VIEWPORT); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_1_VIEWPORT); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), true); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -4891,7 +4891,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_2_VIEWPORTS: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_2_VIEWPORTS); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_2_VIEWPORTS); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true); @@ -4903,7 +4903,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_2_VIEWPORTS_ALT: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_2_VIEWPORTS_ALT); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_2_VIEWPORTS_ALT); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -4915,7 +4915,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_3_VIEWPORTS: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_3_VIEWPORTS); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_3_VIEWPORTS); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -4927,7 +4927,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_3_VIEWPORTS_ALT: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_3_VIEWPORTS_ALT); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_3_VIEWPORTS_ALT); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -4939,7 +4939,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_USE_4_VIEWPORTS: { - viewport_base->set_view(SpatialEditorViewportContainer::VIEW_USE_4_VIEWPORTS); + viewport_base->set_view(Node3DEditorViewportContainer::VIEW_USE_4_VIEWPORTS); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false); @@ -4991,7 +4991,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *spatial = Object::cast_to(E->get()); + Node3D *spatial = Object::cast_to(E->get()); if (!spatial || !spatial->is_visible_in_tree()) continue; @@ -5015,7 +5015,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *spatial = Object::cast_to(E->get()); + Node3D *spatial = Object::cast_to(E->get()); if (!spatial || !spatial->is_visible_in_tree()) continue; @@ -5039,7 +5039,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *spatial = Object::cast_to(E->get()); + Node3D *spatial = Object::cast_to(E->get()); if (!spatial || !spatial->is_visible_in_tree()) continue; @@ -5062,7 +5062,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *spatial = Object::cast_to(E->get()); + Node3D *spatial = Object::cast_to(E->get()); if (!spatial || !spatial->is_visible_in_tree()) continue; @@ -5082,7 +5082,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } } -void SpatialEditor::_init_indicators() { +void Node3DEditor::_init_indicators() { { origin_enabled = true; @@ -5139,7 +5139,7 @@ void SpatialEditor::_init_indicators() { VisualServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid()); origin_instance = VisualServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); + VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF); } @@ -5419,7 +5419,7 @@ void SpatialEditor::_init_indicators() { _generate_selection_box(); } -void SpatialEditor::_update_gizmos_menu() { +void Node3DEditor::_update_gizmos_menu() { gizmos_menu->clear(); @@ -5430,39 +5430,39 @@ void SpatialEditor::_update_gizmos_menu() { gizmos_menu->add_multistate_item(TTR(plugin_name), 3, plugin_state, i); const int idx = gizmos_menu->get_item_index(i); switch (plugin_state) { - case EditorSpatialGizmoPlugin::VISIBLE: + case EditorNode3DGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible")); break; - case EditorSpatialGizmoPlugin::ON_TOP: + case EditorNode3DGizmoPlugin::ON_TOP: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray")); break; - case EditorSpatialGizmoPlugin::HIDDEN: + case EditorNode3DGizmoPlugin::HIDDEN: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden")); break; } } } -void SpatialEditor::_update_gizmos_menu_theme() { +void Node3DEditor::_update_gizmos_menu_theme() { for (int i = 0; i < gizmo_plugins_by_name.size(); ++i) { if (!gizmo_plugins_by_name[i]->can_be_hidden()) continue; const int plugin_state = gizmo_plugins_by_name[i]->get_state(); const int idx = gizmos_menu->get_item_index(i); switch (plugin_state) { - case EditorSpatialGizmoPlugin::VISIBLE: + case EditorNode3DGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible")); break; - case EditorSpatialGizmoPlugin::ON_TOP: + case EditorNode3DGizmoPlugin::ON_TOP: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray")); break; - case EditorSpatialGizmoPlugin::HIDDEN: + case EditorNode3DGizmoPlugin::HIDDEN: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden")); break; } } } -void SpatialEditor::_init_grid() { +void Node3DEditor::_init_grid() { Vector grid_colors[3]; Vector grid_points[3]; @@ -5517,11 +5517,11 @@ void SpatialEditor::_init_grid() { VisualServer::get_singleton()->instance_set_visible(grid_instance[i], grid_visible[i]); VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); + VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); } } -void SpatialEditor::_finish_indicators() { +void Node3DEditor::_finish_indicators() { VisualServer::get_singleton()->free(origin_instance); VisualServer::get_singleton()->free(origin); @@ -5529,14 +5529,14 @@ void SpatialEditor::_finish_indicators() { _finish_grid(); } -void SpatialEditor::_finish_grid() { +void Node3DEditor::_finish_grid() { for (int i = 0; i < 3; i++) { VisualServer::get_singleton()->free(grid_instance[i]); VisualServer::get_singleton()->free(grid[i]); } } -bool SpatialEditor::is_any_freelook_active() const { +bool Node3DEditor::is_any_freelook_active() const { for (unsigned int i = 0; i < VIEWPORTS_COUNT; ++i) { if (viewports[i]->is_freelook_active()) return true; @@ -5544,7 +5544,7 @@ bool SpatialEditor::is_any_freelook_active() const { return false; } -void SpatialEditor::_refresh_menu_icons() { +void Node3DEditor::_refresh_menu_icons() { bool all_locked = true; bool all_grouped = true; @@ -5556,13 +5556,13 @@ void SpatialEditor::_refresh_menu_icons() { all_grouped = false; } else { for (List::Element *E = selection.front(); E; E = E->next()) { - if (Object::cast_to(E->get()) && !Object::cast_to(E->get())->has_meta("_edit_lock_")) { + if (Object::cast_to(E->get()) && !Object::cast_to(E->get())->has_meta("_edit_lock_")) { all_locked = false; break; } } for (List::Element *E = selection.front(); E; E = E->next()) { - if (Object::cast_to(E->get()) && !Object::cast_to(E->get())->has_meta("_edit_group_")) { + if (Object::cast_to(E->get()) && !Object::cast_to(E->get())->has_meta("_edit_group_")) { all_grouped = false; break; } @@ -5599,35 +5599,35 @@ Set _get_child_nodes(Node *parent_node) { Set _get_physics_bodies_rid(Node *node) { Set rids = Set(); - PhysicsBody *pb = Node::cast_to(node); + PhysicsBody3D *pb = Node::cast_to(node); if (pb) { rids.insert(pb->get_rid()); } - Set child_nodes = _get_child_nodes(node); - for (Set::Element *I = child_nodes.front(); I; I = I->next()) { + Set child_nodes = _get_child_nodes(node); + for (Set::Element *I = child_nodes.front(); I; I = I->next()) { rids.insert(I->get()->get_rid()); } return rids; } -void SpatialEditor::snap_selected_nodes_to_floor() { +void Node3DEditor::snap_selected_nodes_to_floor() { List &selection = editor_selection->get_selected_node_list(); Dictionary snap_data; for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); + Node3D *sp = Object::cast_to(E->get()); if (sp) { Vector3 from = Vector3(); Vector3 position_offset = Vector3(); // Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin - Set vi = _get_child_nodes(sp); - Set cs = _get_child_nodes(sp); + Set vi = _get_child_nodes(sp); + Set cs = _get_child_nodes(sp); if (cs.size()) { AABB aabb = sp->get_global_transform().xform(cs.front()->get()->get_shape()->get_debug_mesh()->get_aabb()); - for (Set::Element *I = cs.front(); I; I = I->next()) { + for (Set::Element *I = cs.front(); I; I = I->next()) { aabb.merge_with(sp->get_global_transform().xform(I->get()->get_shape()->get_debug_mesh()->get_aabb())); } Vector3 size = aabb.size * Vector3(0.5, 0.0, 0.5); @@ -5635,7 +5635,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() { position_offset.y = from.y - sp->get_global_transform().origin.y; } else if (vi.size()) { AABB aabb = vi.front()->get()->get_transformed_aabb(); - for (Set::Element *I = vi.front(); I; I = I->next()) { + for (Set::Element *I = vi.front(); I; I = I->next()) { aabb.merge_with(I->get()->get_transformed_aabb()); } Vector3 size = aabb.size * Vector3(0.5, 0.0, 0.5); @@ -5674,7 +5674,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() { // We need to check this before snapping to register the undo/redo action only if needed. for (int i = 0; i < keys.size(); i++) { Node *node = keys[i]; - Spatial *sp = Object::cast_to(node); + Node3D *sp = Object::cast_to(node); Dictionary d = snap_data[node]; Vector3 from = d["from"]; Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); @@ -5691,7 +5691,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() { // Perform snapping if at least one node can be snapped for (int i = 0; i < keys.size(); i++) { Node *node = keys[i]; - Spatial *sp = Object::cast_to(node); + Node3D *sp = Object::cast_to(node); Dictionary d = snap_data[node]; Vector3 from = d["from"]; Vector3 to = from - Vector3(0.0, max_snap_height, 0.0); @@ -5716,30 +5716,30 @@ void SpatialEditor::snap_selected_nodes_to_floor() { } } -void SpatialEditor::_unhandled_key_input(Ref p_event) { +void Node3DEditor::_unhandled_key_input(Ref p_event) { if (!is_visible_in_tree()) return; snap_key_enabled = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); } -void SpatialEditor::_notification(int p_what) { +void Node3DEditor::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { - tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); + tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); + tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); + tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); + tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon("Camera", "EditorIcons")); + tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); + tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); + tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon("Camera3D", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons")); @@ -5752,12 +5752,12 @@ void SpatialEditor::_notification(int p_what) { _refresh_menu_icons(); - get_tree()->connect("node_removed", callable_mp(this, &SpatialEditor::_node_removed)); - EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &SpatialEditor::_refresh_menu_icons)); - editor_selection->connect("selection_changed", callable_mp(this, &SpatialEditor::_refresh_menu_icons)); + get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed)); + EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); + editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons)); - editor->connect("stop_pressed", callable_mp(this, &SpatialEditor::_update_camera_override_button), make_binds(false)); - editor->connect("play_pressed", callable_mp(this, &SpatialEditor::_update_camera_override_button), make_binds(true)); + editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false)); + editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true)); } else if (p_what == NOTIFICATION_ENTER_TREE) { _register_all_gizmos(); @@ -5769,18 +5769,18 @@ void SpatialEditor::_notification(int p_what) { _finish_indicators(); } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); - - tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); + tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); + tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); + tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); + tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + + tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); + tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons")); @@ -5802,41 +5802,41 @@ void SpatialEditor::_notification(int p_what) { } } -void SpatialEditor::add_control_to_menu_panel(Control *p_control) { +void Node3DEditor::add_control_to_menu_panel(Control *p_control) { hbc_menu->add_child(p_control); } -void SpatialEditor::remove_control_from_menu_panel(Control *p_control) { +void Node3DEditor::remove_control_from_menu_panel(Control *p_control) { hbc_menu->remove_child(p_control); } -void SpatialEditor::set_can_preview(Camera *p_preview) { +void Node3DEditor::set_can_preview(Camera3D *p_preview) { for (int i = 0; i < 4; i++) { viewports[i]->set_can_preview(p_preview); } } -VSplitContainer *SpatialEditor::get_shader_split() { +VSplitContainer *Node3DEditor::get_shader_split() { return shader_split; } -HSplitContainer *SpatialEditor::get_palette_split() { +HSplitContainer *Node3DEditor::get_palette_split() { return palette_split; } -void SpatialEditor::_request_gizmo(Object *p_obj) { +void Node3DEditor::_request_gizmo(Object *p_obj) { - Spatial *sp = Object::cast_to(p_obj); + Node3D *sp = Object::cast_to(p_obj); if (!sp) return; if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_a_parent_of(sp)))) { - Ref seg; + Ref seg; for (int i = 0; i < gizmo_plugins_by_priority.size(); ++i) { seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp); @@ -5855,9 +5855,9 @@ void SpatialEditor::_request_gizmo(Object *p_obj) { } } -void SpatialEditor::_toggle_maximize_view(Object *p_viewport) { +void Node3DEditor::_toggle_maximize_view(Object *p_viewport) { if (!p_viewport) return; - SpatialEditorViewport *current_viewport = Object::cast_to(p_viewport); + Node3DEditorViewport *current_viewport = Object::cast_to(p_viewport); if (!current_viewport) return; int index = -1; @@ -5900,49 +5900,49 @@ void SpatialEditor::_toggle_maximize_view(Object *p_viewport) { } } -void SpatialEditor::_node_removed(Node *p_node) { +void Node3DEditor::_node_removed(Node *p_node) { if (p_node == selected) selected = NULL; } -void SpatialEditor::_register_all_gizmos() { - add_gizmo_plugin(Ref(memnew(CameraSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(LightSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(AudioStreamPlayer3DSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(MeshInstanceSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(SoftBodySpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(Sprite3DSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(SkeletonSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(Position3DSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(RayCastSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(SpringArmSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(VehicleWheelSpatialGizmoPlugin))); +void Node3DEditor::_register_all_gizmos() { + add_gizmo_plugin(Ref(memnew(CameraNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(LightNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(AudioStreamPlayer3DNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(MeshInstanceNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(SoftBodyNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(Sprite3DNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(SkeletonNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(Position3DNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(RayCastNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(SpringArmNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(VehicleWheelNode3DGizmoPlugin))); add_gizmo_plugin(Ref(memnew(VisibilityNotifierGizmoPlugin))); add_gizmo_plugin(Ref(memnew(ParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CPUParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(ReflectionProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(GIProbeGizmoPlugin))); // add_gizmo_plugin(Ref(memnew(BakedIndirectLightGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(CollisionShapeSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(CollisionPolygonSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(NavigationMeshSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(JointSpatialGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(PhysicalBoneSpatialGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(CollisionShapeNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(CollisionPolygonNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(NavigationMeshNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(JointNode3DGizmoPlugin))); + add_gizmo_plugin(Ref(memnew(PhysicalBoneNode3DGizmoPlugin))); } -void SpatialEditor::_bind_methods() { +void Node3DEditor::_bind_methods() { - ClassDB::bind_method("_unhandled_key_input", &SpatialEditor::_unhandled_key_input); - ClassDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data); - ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo); + ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input); + ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data); + ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); } -void SpatialEditor::clear() { +void Node3DEditor::clear() { settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov", 70.0)); settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near", 0.05)); @@ -5963,14 +5963,14 @@ void SpatialEditor::clear() { for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { - viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER), i == 0); + viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(Node3DEditorViewport::VIEW_AUDIO_LISTENER), i == 0); viewports[i]->viewport->set_as_audio_listener(i == 0); } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true); } -SpatialEditor::SpatialEditor(EditorNode *p_editor) { +Node3DEditor::Node3DEditor(EditorNode *p_editor) { gizmo.visible = true; gizmo.scale = 1.0; @@ -6004,7 +6004,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->set_flat(true); tool_button[TOOL_MODE_SELECT]->set_pressed(true); button_binds.write[0] = MENU_TOOL_SELECT; - tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), KEY_Q)); tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection")); @@ -6015,7 +6015,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); button_binds.write[0] = MENU_TOOL_MOVE; - tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), KEY_W)); tool_button[TOOL_MODE_ROTATE] = memnew(ToolButton); @@ -6023,7 +6023,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); button_binds.write[0] = MENU_TOOL_ROTATE; - tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), KEY_E)); tool_button[TOOL_MODE_SCALE] = memnew(ToolButton); @@ -6031,7 +6031,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); button_binds.write[0] = MENU_TOOL_SCALE; - tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), KEY_R)); hbc_menu->add_child(memnew(VSeparator)); @@ -6041,31 +6041,31 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); button_binds.write[0] = MENU_TOOL_LIST_SELECT; - tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); button_binds.write[0] = MENU_LOCK_SELECTED; - tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); button_binds.write[0] = MENU_UNLOCK_SELECTED; - tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); tool_button[TOOL_GROUP_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); button_binds.write[0] = MENU_GROUP_SELECTED; - tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); tool_button[TOOL_UNGROUP_SELECTED] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); button_binds.write[0] = MENU_UNGROUP_SELECTED; - tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); hbc_menu->add_child(memnew(VSeparator)); @@ -6075,7 +6075,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); button_binds.write[0] = MENU_TOOL_LOCAL_COORDS; - tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &SpatialEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), KEY_T)); tool_option_button[TOOL_OPT_USE_SNAP] = memnew(ToolButton); @@ -6083,7 +6083,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); button_binds.write[0] = MENU_TOOL_USE_SNAP; - tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &SpatialEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), KEY_Y)); hbc_menu->add_child(memnew(VSeparator)); @@ -6094,13 +6094,13 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true); button_binds.write[0] = MENU_TOOL_OVERRIDE_CAMERA; - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &SpatialEditor::_menu_item_toggled), button_binds); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); _update_camera_override_button(false); hbc_menu->add_child(memnew(VSeparator)); // Drag and drop support; - preview_node = memnew(Spatial); + preview_node = memnew(Node3D); preview_bounds = AABB(); ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7); @@ -6131,7 +6131,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap...")), MENU_TRANSFORM_CONFIGURE_SNAP); - p->connect("id_pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed)); + p->connect("id_pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed)); view_menu = memnew(MenuButton); view_menu->set_text(TTR("View")); @@ -6163,13 +6163,13 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->set_item_checked(p->get_item_index(MENU_VIEW_ORIGIN), true); p->set_item_checked(p->get_item_index(MENU_VIEW_GRID), true); - p->connect("id_pressed", callable_mp(this, &SpatialEditor::_menu_item_pressed)); + p->connect("id_pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed)); gizmos_menu = memnew(PopupMenu); p->add_child(gizmos_menu); gizmos_menu->set_name("GizmosMenu"); gizmos_menu->set_hide_on_checkable_item_selection(false); - gizmos_menu->connect("id_pressed", callable_mp(this, &SpatialEditor::_menu_gizmo_toggled)); + gizmos_menu->connect("id_pressed", callable_mp(this, &Node3DEditor::_menu_gizmo_toggled)); /* REST OF MENU */ @@ -6180,14 +6180,14 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { shader_split = memnew(VSplitContainer); shader_split->set_h_size_flags(SIZE_EXPAND_FILL); palette_split->add_child(shader_split); - viewport_base = memnew(SpatialEditorViewportContainer); + viewport_base = memnew(Node3DEditorViewportContainer); shader_split->add_child(viewport_base); viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { - viewports[i] = memnew(SpatialEditorViewport(this, editor, i)); - viewports[i]->connect("toggle_maximize_view", callable_mp(this, &SpatialEditor::_toggle_maximize_view)); - viewports[i]->connect("clicked", callable_mp(this, &SpatialEditor::_update_camera_override_viewport)); + viewports[i] = memnew(Node3DEditorViewport(this, editor, i)); + viewports[i]->connect("toggle_maximize_view", callable_mp(this, &Node3DEditor::_toggle_maximize_view)); + viewports[i]->connect("clicked", callable_mp(this, &Node3DEditor::_update_camera_override_viewport)); viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept); viewport_base->add_child(viewports[i]); } @@ -6201,8 +6201,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { snap_dialog = memnew(ConfirmationDialog); snap_dialog->set_title(TTR("Snap Settings")); add_child(snap_dialog); - snap_dialog->connect("confirmed", callable_mp(this, &SpatialEditor::_snap_changed)); - snap_dialog->get_cancel()->connect("pressed", callable_mp(this, &SpatialEditor::_snap_update)); + snap_dialog->connect("confirmed", callable_mp(this, &Node3DEditor::_snap_changed)); + snap_dialog->get_cancel()->connect("pressed", callable_mp(this, &Node3DEditor::_snap_update)); VBoxContainer *snap_dialog_vbc = memnew(VBoxContainer); snap_dialog->add_child(snap_dialog_vbc); @@ -6249,7 +6249,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar); for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) { - settings_dialog->connect("confirmed", callable_mp(viewports[i], &SpatialEditorViewport::_update_camera), varray(0.0)); + settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_update_camera), varray(0.0)); } /* XFORM DIALOG */ @@ -6311,7 +6311,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { xform_type->add_item(TTR("Post")); xform_vbc->add_child(xform_type); - xform_dialog->connect("confirmed", callable_mp(this, &SpatialEditor::_xform_dialog_action)); + xform_dialog->connect("confirmed", callable_mp(this, &Node3DEditor::_xform_dialog_action)); scenario_debug = VisualServer::SCENARIO_DEBUG_DISABLED; @@ -6329,11 +6329,11 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { over_gizmo_handle = -1; } -SpatialEditor::~SpatialEditor() { +Node3DEditor::~Node3DEditor() { memdelete(preview_node); } -void SpatialEditorPlugin::make_visible(bool p_visible) { +void Node3DEditorPlugin::make_visible(bool p_visible) { if (p_visible) { @@ -6346,31 +6346,31 @@ void SpatialEditorPlugin::make_visible(bool p_visible) { spatial_editor->set_process(false); } } -void SpatialEditorPlugin::edit(Object *p_object) { +void Node3DEditorPlugin::edit(Object *p_object) { - spatial_editor->edit(Object::cast_to(p_object)); + spatial_editor->edit(Object::cast_to(p_object)); } -bool SpatialEditorPlugin::handles(Object *p_object) const { +bool Node3DEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Spatial"); + return p_object->is_class("Node3D"); } -Dictionary SpatialEditorPlugin::get_state() const { +Dictionary Node3DEditorPlugin::get_state() const { return spatial_editor->get_state(); } -void SpatialEditorPlugin::set_state(const Dictionary &p_state) { +void Node3DEditorPlugin::set_state(const Dictionary &p_state) { spatial_editor->set_state(p_state); } -void SpatialEditor::snap_cursor_to_plane(const Plane &p_plane) { +void Node3DEditor::snap_cursor_to_plane(const Plane &p_plane) { //cursor.pos=p_plane.project(cursor.pos); } -Vector3 SpatialEditor::snap_point(Vector3 p_target, Vector3 p_start) const { +Vector3 Node3DEditor::snap_point(Vector3 p_target, Vector3 p_start) const { if (is_snap_enabled()) { p_target.x = Math::snap_scalar(0.0, get_translate_snap(), p_target.x); p_target.y = Math::snap_scalar(0.0, get_translate_snap(), p_target.y); @@ -6379,7 +6379,7 @@ Vector3 SpatialEditor::snap_point(Vector3 p_target, Vector3 p_start) const { return p_target; } -float SpatialEditor::get_translate_snap() const { +float Node3DEditor::get_translate_snap() const { float snap_value; if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_translate->get_text().to_double() / 10.0; @@ -6390,7 +6390,7 @@ float SpatialEditor::get_translate_snap() const { return snap_value; } -float SpatialEditor::get_rotate_snap() const { +float Node3DEditor::get_rotate_snap() const { float snap_value; if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_rotate->get_text().to_double() / 3.0; @@ -6401,7 +6401,7 @@ float SpatialEditor::get_rotate_snap() const { return snap_value; } -float SpatialEditor::get_scale_snap() const { +float Node3DEditor::get_scale_snap() const { float snap_value; if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_scale->get_text().to_double() / 2.0; @@ -6412,19 +6412,19 @@ float SpatialEditor::get_scale_snap() const { return snap_value; } -void SpatialEditorPlugin::_bind_methods() { +void Node3DEditorPlugin::_bind_methods() { - ClassDB::bind_method("snap_cursor_to_plane", &SpatialEditorPlugin::snap_cursor_to_plane); + ClassDB::bind_method("snap_cursor_to_plane", &Node3DEditorPlugin::snap_cursor_to_plane); } -void SpatialEditorPlugin::snap_cursor_to_plane(const Plane &p_plane) { +void Node3DEditorPlugin::snap_cursor_to_plane(const Plane &p_plane) { spatial_editor->snap_cursor_to_plane(p_plane); } struct _GizmoPluginPriorityComparator { - bool operator()(const Ref &p_a, const Ref &p_b) const { + bool operator()(const Ref &p_a, const Ref &p_b) const { if (p_a->get_priority() == p_b->get_priority()) { return p_a->get_name() < p_b->get_name(); } @@ -6434,12 +6434,12 @@ struct _GizmoPluginPriorityComparator { struct _GizmoPluginNameComparator { - bool operator()(const Ref &p_a, const Ref &p_b) const { + bool operator()(const Ref &p_a, const Ref &p_b) const { return p_a->get_name() < p_b->get_name(); } }; -void SpatialEditor::add_gizmo_plugin(Ref p_plugin) { +void Node3DEditor::add_gizmo_plugin(Ref p_plugin) { ERR_FAIL_NULL(p_plugin.ptr()); gizmo_plugins_by_priority.push_back(p_plugin); @@ -6449,19 +6449,19 @@ void SpatialEditor::add_gizmo_plugin(Ref p_plugin) { gizmo_plugins_by_name.sort_custom<_GizmoPluginNameComparator>(); _update_gizmos_menu(); - SpatialEditor::get_singleton()->update_all_gizmos(); + Node3DEditor::get_singleton()->update_all_gizmos(); } -void SpatialEditor::remove_gizmo_plugin(Ref p_plugin) { +void Node3DEditor::remove_gizmo_plugin(Ref p_plugin) { gizmo_plugins_by_priority.erase(p_plugin); gizmo_plugins_by_name.erase(p_plugin); _update_gizmos_menu(); } -SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { +Node3DEditorPlugin::Node3DEditorPlugin(EditorNode *p_node) { editor = p_node; - spatial_editor = memnew(SpatialEditor(p_node)); + spatial_editor = memnew(Node3DEditor(p_node)); spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor->get_viewport()->add_child(spatial_editor); @@ -6469,10 +6469,10 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { spatial_editor->connect_compat("transform_key_request", editor->get_inspector_dock(), "_transform_keyed"); } -SpatialEditorPlugin::~SpatialEditorPlugin() { +Node3DEditorPlugin::~Node3DEditorPlugin() { } -void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { +void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); @@ -6514,7 +6514,7 @@ void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color materials[p_name] = mats; } -void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top, const Color &p_albedo) { +void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top, const Color &p_albedo) { Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); @@ -6555,12 +6555,12 @@ void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const materials[p_name] = icons; } -void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard) { +void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard) { Ref handle_material = Ref(memnew(StandardMaterial3D)); handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); - Ref handle_t = SpatialEditor::get_singleton()->get_theme_icon("Editor3DHandle", "EditorIcons"); + Ref handle_t = Node3DEditor::get_singleton()->get_theme_icon("Editor3DHandle", "EditorIcons"); handle_material->set_point_size(handle_t->get_width()); handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t); handle_material->set_albedo(Color(1, 1, 1)); @@ -6577,12 +6577,12 @@ void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool materials[p_name].push_back(handle_material); } -void EditorSpatialGizmoPlugin::add_material(const String &p_name, Ref p_material) { +void EditorNode3DGizmoPlugin::add_material(const String &p_name, Ref p_material) { materials[p_name] = Vector>(); materials[p_name].push_back(p_material); } -Ref EditorSpatialGizmoPlugin::get_material(const String &p_name, const Ref &p_gizmo) { +Ref EditorNode3DGizmoPlugin::get_material(const String &p_name, const Ref &p_gizmo) { ERR_FAIL_COND_V(!materials.has(p_name), Ref()); ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref()); @@ -6601,27 +6601,27 @@ Ref EditorSpatialGizmoPlugin::get_material(const String &p_n return mat; } -String EditorSpatialGizmoPlugin::get_name() const { +String EditorNode3DGizmoPlugin::get_name() const { if (get_script_instance() && get_script_instance()->has_method("get_name")) { return get_script_instance()->call("get_name"); } return TTR("Nameless gizmo"); } -int EditorSpatialGizmoPlugin::get_priority() const { +int EditorNode3DGizmoPlugin::get_priority() const { if (get_script_instance() && get_script_instance()->has_method("get_priority")) { return get_script_instance()->call("get_priority"); } return 0; } -Ref EditorSpatialGizmoPlugin::get_gizmo(Spatial *p_spatial) { +Ref EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) { if (get_script_instance() && get_script_instance()->has_method("get_gizmo")) { return get_script_instance()->call("get_gizmo", p_spatial); } - Ref ref = create_gizmo(p_spatial); + Ref ref = create_gizmo(p_spatial); if (ref.is_null()) return ref; @@ -6633,18 +6633,18 @@ Ref EditorSpatialGizmoPlugin::get_gizmo(Spatial *p_spatial) return ref; } -void EditorSpatialGizmoPlugin::_bind_methods() { -#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorSpatialGizmo") +void EditorNode3DGizmoPlugin::_bind_methods() { +#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo") - BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); - BIND_VMETHOD(MethodInfo(GIZMO_REF, "create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); + BIND_VMETHOD(MethodInfo(GIZMO_REF, "create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); - ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorSpatialGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorSpatialGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1))); - ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard"), &EditorSpatialGizmoPlugin::create_handle_material, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorSpatialGizmoPlugin::add_material); + ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1))); + ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material); - ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorSpatialGizmoPlugin::get_material); //, DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material); //, DEFVAL(Ref())); BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name")); BIND_VMETHOD(MethodInfo(Variant::STRING, "get_priority")); @@ -6658,7 +6658,7 @@ void EditorSpatialGizmoPlugin::_bind_methods() { hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; BIND_VMETHOD(hvget); - BIND_VMETHOD(MethodInfo("set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + BIND_VMETHOD(MethodInfo("set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); MethodInfo cm = MethodInfo("commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); cm.default_arguments.push_back(false); BIND_VMETHOD(cm); @@ -6668,103 +6668,103 @@ void EditorSpatialGizmoPlugin::_bind_methods() { #undef GIZMO_REF } -bool EditorSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { if (get_script_instance() && get_script_instance()->has_method("has_gizmo")) { return get_script_instance()->call("has_gizmo", p_spatial); } return false; } -Ref EditorSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { +Ref EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) { if (get_script_instance() && get_script_instance()->has_method("create_gizmo")) { return get_script_instance()->call("create_gizmo", p_spatial); } - Ref ref; + Ref ref; if (has_gizmo(p_spatial)) ref.instance(); return ref; } -bool EditorSpatialGizmoPlugin::can_be_hidden() const { +bool EditorNode3DGizmoPlugin::can_be_hidden() const { if (get_script_instance() && get_script_instance()->has_method("can_be_hidden")) { return get_script_instance()->call("can_be_hidden"); } return true; } -bool EditorSpatialGizmoPlugin::is_selectable_when_hidden() const { +bool EditorNode3DGizmoPlugin::is_selectable_when_hidden() const { if (get_script_instance() && get_script_instance()->has_method("is_selectable_when_hidden")) { return get_script_instance()->call("is_selectable_when_hidden"); } return false; } -void EditorSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (get_script_instance() && get_script_instance()->has_method("redraw")) { - Ref ref(p_gizmo); + Ref ref(p_gizmo); get_script_instance()->call("redraw", ref); } } -String EditorSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) { return get_script_instance()->call("get_handle_name", p_gizmo, p_idx); } return ""; } -Variant EditorSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant EditorNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) { return get_script_instance()->call("get_handle_value", p_gizmo, p_idx); } return Variant(); } -void EditorSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void EditorNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { if (get_script_instance() && get_script_instance()->has_method("set_handle")) { get_script_instance()->call("set_handle", p_gizmo, p_idx, p_camera, p_point); } } -void EditorSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void EditorNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { if (get_script_instance() && get_script_instance()->has_method("commit_handle")) { get_script_instance()->call("commit_handle", p_gizmo, p_idx, p_restore, p_cancel); } } -bool EditorSpatialGizmoPlugin::is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const { if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) { return get_script_instance()->call("is_handle_highlighted", p_gizmo, p_idx); } return false; } -void EditorSpatialGizmoPlugin::set_state(int p_state) { +void EditorNode3DGizmoPlugin::set_state(int p_state) { current_state = p_state; for (int i = 0; i < current_gizmos.size(); ++i) { current_gizmos[i]->set_hidden(current_state == HIDDEN); } } -int EditorSpatialGizmoPlugin::get_state() const { +int EditorNode3DGizmoPlugin::get_state() const { return current_state; } -void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) { +void EditorNode3DGizmoPlugin::unregister_gizmo(EditorNode3DGizmo *p_gizmo) { current_gizmos.erase(p_gizmo); } -EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() { +EditorNode3DGizmoPlugin::EditorNode3DGizmoPlugin() { current_state = VISIBLE; } -EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() { +EditorNode3DGizmoPlugin::~EditorNode3DGizmoPlugin() { for (int i = 0; i < current_gizmos.size(); ++i) { current_gizmos[i]->set_plugin(NULL); current_gizmos[i]->get_spatial_node()->set_gizmo(NULL); } - if (SpatialEditor::get_singleton()) { - SpatialEditor::get_singleton()->update_all_gizmos(); + if (Node3DEditor::get_singleton()) { + Node3DEditor::get_singleton()->update_all_gizmos(); } } diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 9dad66b647..819178408b 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -34,20 +34,20 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "editor/editor_scale.h" -#include "scene/3d/immediate_geometry.h" -#include "scene/3d/light.h" -#include "scene/3d/visual_instance.h" +#include "scene/3d/immediate_geometry_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/visual_instance_3d.h" #include "scene/gui/panel_container.h" -class Camera; -class SpatialEditor; -class EditorSpatialGizmoPlugin; -class SpatialEditorViewport; +class Camera3D; +class Node3DEditor; +class EditorNode3DGizmoPlugin; +class Node3DEditorViewport; class ViewportContainer; -class EditorSpatialGizmo : public SpatialGizmo { +class EditorNode3DGizmo : public Node3DGizmo { - GDCLASS(EditorSpatialGizmo, SpatialGizmo); + GDCLASS(EditorNode3DGizmo, Node3DGizmo); bool selected; bool instanced; @@ -75,7 +75,7 @@ public: extra_margin = false; } - void create_instance(Spatial *p_base, bool p_hidden = false); + void create_instance(Node3D *p_base, bool p_hidden = false); }; Vector collision_segments; @@ -93,12 +93,12 @@ public: bool valid; bool hidden; - Spatial *base; + Node3D *base; Vector instances; - Spatial *spatial_node; - EditorSpatialGizmoPlugin *gizmo_plugin; + Node3D *spatial_node; + EditorNode3DGizmoPlugin *gizmo_plugin; - void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to(p_node)); } + void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to(p_node)); } protected: static void _bind_methods(); @@ -115,15 +115,15 @@ public: virtual bool is_handle_highlighted(int p_idx) const; virtual String get_handle_name(int p_idx) const; virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); + virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); - void set_spatial_node(Spatial *p_node); - Spatial *get_spatial_node() const { return spatial_node; } - Ref get_plugin() const { return gizmo_plugin; } + void set_spatial_node(Node3D *p_node); + Node3D *get_spatial_node() const { return spatial_node; } + Ref get_plugin() const { return gizmo_plugin; } Vector3 get_handle_pos(int p_idx) const; - bool intersect_frustum(const Camera *p_camera, const Vector &p_frustum); - bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); + bool intersect_frustum(const Camera3D *p_camera, const Vector &p_frustum); + bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = NULL, bool p_sec_first = false); virtual void clear(); virtual void create(); @@ -134,10 +134,10 @@ public: virtual bool is_editable() const; void set_hidden(bool p_hidden); - void set_plugin(EditorSpatialGizmoPlugin *p_plugin); + void set_plugin(EditorNode3DGizmoPlugin *p_plugin); - EditorSpatialGizmo(); - ~EditorSpatialGizmo(); + EditorNode3DGizmo(); + ~EditorNode3DGizmo(); }; class ViewportRotationControl : public Control { @@ -155,7 +155,7 @@ class ViewportRotationControl : public Control { } }; - SpatialEditorViewport *viewport = nullptr; + Node3DEditorViewport *viewport = nullptr; Vector axis_colors; Vector axis_menu_options; bool orbiting = false; @@ -174,13 +174,13 @@ protected: void _on_mouse_exited(); public: - void set_viewport(SpatialEditorViewport *p_viewport); + void set_viewport(Node3DEditorViewport *p_viewport); }; -class SpatialEditorViewport : public Control { +class Node3DEditorViewport : public Control { - GDCLASS(SpatialEditorViewport, Control); - friend class SpatialEditor; + GDCLASS(Node3DEditorViewport, Control); + friend class Node3DEditor; friend class ViewportRotationControl; enum { @@ -242,7 +242,7 @@ private: String name; void _menu_option(int p_option); void _set_auto_orthogonal(); - Spatial *preview_node; + Node3D *preview_node; AABB *preview_bounds; Vector selected_files; AcceptDialog *accept; @@ -263,7 +263,7 @@ private: Control *surface; SubViewport *viewport; - Camera *camera; + Camera3D *camera; bool transforming; bool orthogonal; bool auto_orthogonal; @@ -284,7 +284,7 @@ private: struct _RayResult { - Spatial *item; + Node3D *item; float depth; int handle; _FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; } @@ -366,7 +366,7 @@ private: int edited_gizmo; Point2 mouse_pos; bool snap; - Ref gizmo; + Ref gizmo; int gizmo_handle; Variant gizmo_initial_value; Vector3 gizmo_initial_pos; @@ -418,10 +418,10 @@ private: void _sinput(const Ref &p_event); void _update_freelook(real_t delta); - SpatialEditor *spatial_editor; + Node3DEditor *spatial_editor; - Camera *previewing; - Camera *preview; + Camera3D *previewing; + Camera3D *preview; bool previewing_cinema; bool _is_node_locked(const Node *p_node); @@ -436,7 +436,7 @@ private: Point2i _get_warped_mouse_motion(const Ref &p_ev_mouse_motion) const; Vector3 _get_instance_position(const Point2 &p_pos) const; - static AABB _calculate_spatial_bounds(const Spatial *p_parent, bool p_exclude_toplevel_transform = true); + static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_toplevel_transform = true); void _create_preview(const Vector &files) const; void _remove_preview(); bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node); @@ -454,7 +454,7 @@ public: void update_surface() { surface->update(); } void update_transform_gizmo_view(); - void set_can_preview(Camera *p_preview); + void set_can_preview(Camera3D *p_preview); void set_state(const Dictionary &p_state); Dictionary get_state() const; void reset(); @@ -463,19 +463,19 @@ public: void focus_selection(); void assign_pending_data_pointers( - Spatial *p_preview_node, + Node3D *p_preview_node, AABB *p_preview_bounds, AcceptDialog *p_accept); SubViewport *get_viewport_node() { return viewport; } - Camera *get_camera() { return camera; } // return the default camera object. + Camera3D *get_camera() { return camera; } // return the default camera object. - SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index); + Node3DEditorViewport(Node3DEditor *p_spatial_editor, EditorNode *p_editor, int p_index); }; -class SpatialEditorSelectedItem : public Object { +class Node3DEditorSelectedItem : public Object { - GDCLASS(SpatialEditorSelectedItem, Object); + GDCLASS(Node3DEditorSelectedItem, Object); public: AABB aabb; @@ -483,19 +483,19 @@ public: Transform original_local; Transform last_xform; // last transform bool last_xform_dirty; - Spatial *sp; + Node3D *sp; RID sbox_instance; - SpatialEditorSelectedItem() { + Node3DEditorSelectedItem() { sp = NULL; last_xform_dirty = true; } - ~SpatialEditorSelectedItem(); + ~Node3DEditorSelectedItem(); }; -class SpatialEditorViewportContainer : public Container { +class Node3DEditorViewportContainer : public Container { - GDCLASS(SpatialEditorViewportContainer, Container); + GDCLASS(Node3DEditorViewportContainer, Container); public: enum View { @@ -531,12 +531,12 @@ public: void set_view(View p_view); View get_view(); - SpatialEditorViewportContainer(); + Node3DEditorViewportContainer(); }; -class SpatialEditor : public VBoxContainer { +class Node3DEditor : public VBoxContainer { - GDCLASS(SpatialEditor, VBoxContainer); + GDCLASS(Node3DEditor, VBoxContainer); public: static const unsigned int VIEWPORTS_COUNT = 4; @@ -568,8 +568,8 @@ private: EditorNode *editor; EditorSelection *editor_selection; - SpatialEditorViewportContainer *viewport_base; - SpatialEditorViewport *viewports[VIEWPORTS_COUNT]; + Node3DEditorViewportContainer *viewport_base; + Node3DEditorViewport *viewports[VIEWPORTS_COUNT]; VSplitContainer *shader_split; HSplitContainer *palette_split; @@ -609,7 +609,7 @@ private: Ref cursor_material; // Scene drag and drop support - Spatial *preview_node; + Node3D *preview_node; AABB preview_bounds; struct Gizmo { @@ -709,19 +709,19 @@ private: Ref viewport_environment; - Spatial *selected; + Node3D *selected; void _request_gizmo(Object *p_obj); - static SpatialEditor *singleton; + static Node3DEditor *singleton; void _node_removed(Node *p_node); - Vector> gizmo_plugins_by_priority; - Vector> gizmo_plugins_by_name; + Vector> gizmo_plugins_by_priority; + Vector> gizmo_plugins_by_name; void _register_all_gizmos(); - SpatialEditor(); + Node3DEditor(); bool is_any_freelook_active() const; @@ -735,7 +735,7 @@ protected: static void _bind_methods(); public: - static SpatialEditor *get_singleton() { return singleton; } + static Node3DEditor *get_singleton() { return singleton; } void snap_cursor_to_plane(const Plane &p_plane); Vector3 snap_point(Vector3 p_target, Vector3 p_start = Vector3(0, 0, 0)) const; @@ -748,7 +748,7 @@ public: bool is_gizmo_visible() const { return gizmo.visible; } ToolMode get_tool_mode() const { return tool_mode; } - bool are_local_coords_enabled() const { return tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); } + bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); } bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; } float get_translate_snap() const; float get_rotate_snap() const; @@ -780,33 +780,33 @@ public: VSplitContainer *get_shader_split(); HSplitContainer *get_palette_split(); - Spatial *get_selected() { return selected; } + Node3D *get_selected() { return selected; } int get_over_gizmo_handle() const { return over_gizmo_handle; } void set_over_gizmo_handle(int idx) { over_gizmo_handle = idx; } - void set_can_preview(Camera *p_preview); + void set_can_preview(Camera3D *p_preview); - SpatialEditorViewport *get_editor_viewport(int p_idx) { + Node3DEditorViewport *get_editor_viewport(int p_idx) { ERR_FAIL_INDEX_V(p_idx, static_cast(VIEWPORTS_COUNT), NULL); return viewports[p_idx]; } - void add_gizmo_plugin(Ref p_plugin); - void remove_gizmo_plugin(Ref p_plugin); + void add_gizmo_plugin(Ref p_plugin); + void remove_gizmo_plugin(Ref p_plugin); - void edit(Spatial *p_spatial); + void edit(Node3D *p_spatial); void clear(); - SpatialEditor(EditorNode *p_editor); - ~SpatialEditor(); + Node3DEditor(EditorNode *p_editor); + ~Node3DEditor(); }; -class SpatialEditorPlugin : public EditorPlugin { +class Node3DEditorPlugin : public EditorPlugin { - GDCLASS(SpatialEditorPlugin, EditorPlugin); + GDCLASS(Node3DEditorPlugin, EditorPlugin); - SpatialEditor *spatial_editor; + Node3DEditor *spatial_editor; EditorNode *editor; protected: @@ -815,7 +815,7 @@ protected: public: void snap_cursor_to_plane(const Plane &p_plane); - SpatialEditor *get_spatial_editor() { return spatial_editor; } + Node3DEditor *get_spatial_editor() { return spatial_editor; } virtual String get_name() const { return "3D"; } bool has_main_screen() const { return true; } virtual void make_visible(bool p_visible); @@ -828,13 +828,13 @@ public: virtual void edited_scene_changed(); - SpatialEditorPlugin(EditorNode *p_node); - ~SpatialEditorPlugin(); + Node3DEditorPlugin(EditorNode *p_node); + ~Node3DEditorPlugin(); }; -class EditorSpatialGizmoPlugin : public Resource { +class EditorNode3DGizmoPlugin : public Resource { - GDCLASS(EditorSpatialGizmoPlugin, Resource); + GDCLASS(EditorNode3DGizmoPlugin, Resource); public: static const int VISIBLE = 0; @@ -843,13 +843,13 @@ public: private: int current_state; - List current_gizmos; + List current_gizmos; HashMap>> materials; protected: static void _bind_methods(); - virtual bool has_gizmo(Spatial *p_spatial); - virtual Ref create_gizmo(Spatial *p_spatial); + virtual bool has_gizmo(Node3D *p_spatial); + virtual Ref create_gizmo(Node3D *p_spatial); public: void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); @@ -857,27 +857,27 @@ public: void create_handle_material(const String &p_name, bool p_billboard = false); void add_material(const String &p_name, Ref p_material); - Ref get_material(const String &p_name, const Ref &p_gizmo = Ref()); + Ref get_material(const String &p_name, const Ref &p_gizmo = Ref()); virtual String get_name() const; virtual int get_priority() const; virtual bool can_be_hidden() const; virtual bool is_selectable_when_hidden() const; - virtual void redraw(EditorSpatialGizmo *p_gizmo); - virtual String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - virtual Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - virtual void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - virtual bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx) const; + virtual void redraw(EditorNode3DGizmo *p_gizmo); + virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + virtual Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + virtual void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + virtual void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const; - Ref get_gizmo(Spatial *p_spatial); + Ref get_gizmo(Node3D *p_spatial); void set_state(int p_state); int get_state() const; - void unregister_gizmo(EditorSpatialGizmo *p_gizmo); + void unregister_gizmo(EditorNode3DGizmo *p_gizmo); - EditorSpatialGizmoPlugin(); - virtual ~EditorSpatialGizmoPlugin(); + EditorNode3DGizmoPlugin(); + virtual ~EditorNode3DGizmoPlugin(); }; #endif diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 251957eaa5..3eb76946a6 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -47,7 +47,7 @@ void SpriteEditor::_node_removed(Node *p_node) { } } -void SpriteEditor::edit(Sprite *p_sprite) { +void SpriteEditor::edit(Sprite2D *p_sprite) { node = p_sprite; } @@ -578,12 +578,12 @@ SpriteEditor::SpriteEditor() { void SpriteEditorPlugin::edit(Object *p_object) { - sprite_editor->edit(Object::cast_to(p_object)); + sprite_editor->edit(Object::cast_to(p_object)); } bool SpriteEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Sprite"); + return p_object->is_class("Sprite2D"); } void SpriteEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h index 998851b6ad..b55446469c 100644 --- a/editor/plugins/sprite_editor_plugin.h +++ b/editor/plugins/sprite_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/gui/spin_box.h" class SpriteEditor : public Control { @@ -49,7 +49,7 @@ class SpriteEditor : public Control { Menu selected_menu_item; - Sprite *node; + Sprite2D *node; MenuButton *options; @@ -92,7 +92,7 @@ protected: static void _bind_methods(); public: - void edit(Sprite *p_sprite); + void edit(Sprite2D *p_sprite); SpriteEditor(); }; diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 776b80d73b..76e60bb014 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -485,7 +485,7 @@ static void _find_anim_sprites(Node *p_node, List *r_nodes, Ref(p_node); + AnimatedSprite2D *as = Object::cast_to(p_node); if (as && as->get_sprite_frames() == p_sfames) { r_nodes->push_back(p_node); } @@ -1068,11 +1068,17 @@ void SpriteFramesEditorPlugin::edit(Object *p_object) { frames_editor->set_undo_redo(&get_undo_redo()); SpriteFrames *s; - AnimatedSprite *animated_sprite = Object::cast_to(p_object); + AnimatedSprite2D *animated_sprite = Object::cast_to(p_object); if (animated_sprite) { s = *animated_sprite->get_sprite_frames(); } else { - s = Object::cast_to(p_object); + AnimatedSprite3D *animated_sprite_3d = Object::cast_to(p_object); + if (animated_sprite_3d) { + s = *animated_sprite_3d->get_sprite_frames(); + } else { + + s = Object::cast_to(p_object); + } } frames_editor->edit(s); @@ -1080,9 +1086,12 @@ void SpriteFramesEditorPlugin::edit(Object *p_object) { bool SpriteFramesEditorPlugin::handles(Object *p_object) const { - AnimatedSprite *animated_sprite = Object::cast_to(p_object); + AnimatedSprite2D *animated_sprite = Object::cast_to(p_object); + AnimatedSprite3D *animated_sprite_3d = Object::cast_to(p_object); if (animated_sprite && *animated_sprite->get_sprite_frames()) { return true; + } else if (animated_sprite_3d && *animated_sprite_3d->get_sprite_frames()) { + return true; } else { return p_object->is_class("SpriteFrames"); } diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 1fa93b5c47..89d9bc6fd3 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -33,7 +33,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/2d/animated_sprite.h" +#include "scene/2d/animated_sprite_2d.h" #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" #include "scene/gui/split_container.h" diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 2186c7d5c3..029159180c 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -800,7 +800,7 @@ Sprite3D *TextureRegionEditor::get_sprite_3d() { return node_sprite_3d; } -Sprite *TextureRegionEditor::get_sprite() { +Sprite2D *TextureRegionEditor::get_sprite() { return node_sprite; } @@ -816,7 +816,7 @@ void TextureRegionEditor::edit(Object *p_obj) { if (atlas_tex.is_valid()) atlas_tex->remove_change_receptor(this); if (p_obj) { - node_sprite = Object::cast_to(p_obj); + node_sprite = Object::cast_to(p_obj); node_sprite_3d = Object::cast_to(p_obj); node_ninepatch = Object::cast_to(p_obj); if (Object::cast_to(p_obj)) @@ -1037,7 +1037,7 @@ void TextureRegionEditorPlugin::edit(Object *p_object) { } bool TextureRegionEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Sprite") || p_object->is_class("Sprite3D") || p_object->is_class("NinePatchRect") || p_object->is_class("StyleBoxTexture") || p_object->is_class("AtlasTexture"); + return p_object->is_class("Sprite2D") || p_object->is_class("Sprite3D") || p_object->is_class("NinePatchRect") || p_object->is_class("StyleBoxTexture") || p_object->is_class("AtlasTexture"); } void TextureRegionEditorPlugin::_editor_visiblity_changed() { diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index edc55071b7..c6cd648842 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -34,7 +34,7 @@ #include "canvas_item_editor_plugin.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/3d/sprite_3d.h" #include "scene/gui/nine_patch_rect.h" #include "scene/resources/style_box.h" @@ -84,7 +84,7 @@ class TextureRegionEditor : public VBoxContainer { Vector2 snap_step; Vector2 snap_separation; - Sprite *node_sprite; + Sprite2D *node_sprite; Sprite3D *node_sprite_3d; NinePatchRect *node_ninepatch; Ref obj_styleBox; @@ -136,7 +136,7 @@ public: bool is_atlas_texture(); bool is_ninepatch(); Sprite3D *get_sprite_3d(); - Sprite *get_sprite(); + Sprite2D *get_sprite(); void edit(Object *p_obj); TextureRegionEditor(EditorNode *p_editor); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 5d13b834cf..f5ffcc1a28 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -35,7 +35,7 @@ #include "editor/editor_scale.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "scene/2d/physics_body_2d.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" void TileSetEditor::edit(const Ref &p_tileset) { @@ -53,7 +53,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref p_library) { Node *child = p_node->get_child(i); - if (!Object::cast_to(child)) { + if (!Object::cast_to(child)) { if (child->get_child_count() > 0) { _import_node(child, p_library); } @@ -61,7 +61,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref p_library) { continue; } - Sprite *mi = Object::cast_to(child); + Sprite2D *mi = Object::cast_to(child); Ref texture = mi->get_texture(); Ref normal_map = mi->get_normal_map(); Ref material = mi->get_material(); @@ -601,7 +601,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { workspace->set_draw_behind_parent(true); workspace_overlay->add_child(workspace); - preview = memnew(Sprite); + preview = memnew(Sprite2D); workspace->add_child(preview); preview->set_centered(false); preview->set_draw_behind_parent(true); diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 0d106ed454..53f8e8c4d6 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -32,7 +32,7 @@ #define TILE_SET_EDITOR_PLUGIN_H #include "editor/editor_node.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" #include "scene/resources/tile_set.h" @@ -136,7 +136,7 @@ class TileSetEditor : public HSplitContainer { Ref edited_navigation_shape; int current_item_index; - Sprite *preview; + Sprite2D *preview; ScrollContainer *scroll; Label *empty_message; Control *workspace_container; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 613ba53fed..186a569183 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -367,8 +367,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node2D")) preferred = "Node2D"; - else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Spatial")) - preferred = "Spatial"; + else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node3D")) + preferred = "Node3D"; } create_dialog->set_preferred_search_result_type(preferred); create_dialog->popup_create(true); @@ -984,7 +984,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } else { switch (p_tool) { case TOOL_CREATE_2D_SCENE: new_node = memnew(Node2D); break; - case TOOL_CREATE_3D_SCENE: new_node = memnew(Spatial); break; + case TOOL_CREATE_3D_SCENE: new_node = memnew(Node3D); break; case TOOL_CREATE_USER_INTERFACE: { Control *node = memnew(Control); node->set_anchors_and_margins_preset(PRESET_WIDE); //more useful for resizable UIs. @@ -1053,7 +1053,7 @@ void SceneTreeDock::_notification(int p_what) { scene_tree->connect("node_changed", callable_mp((CanvasItem *)canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), &CanvasItem::update)); } - SpatialEditorPlugin *spatial_editor_plugin = Object::cast_to(editor_data->get_editor("3D")); + Node3DEditorPlugin *spatial_editor_plugin = Object::cast_to(editor_data->get_editor("3D")); spatial_editor_plugin->get_spatial_editor()->connect_compat("item_lock_status_changed", scene_tree, "_update_tree"); spatial_editor_plugin->get_spatial_editor()->connect_compat("item_group_status_changed", scene_tree, "_update_tree"); @@ -1102,7 +1102,7 @@ void SceneTreeDock::_notification(int p_what) { button_3d = memnew(Button); beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); - button_3d->set_icon(get_theme_icon("Spatial", "EditorIcons")); + button_3d->set_icon(get_theme_icon("Node3D", "EditorIcons")); button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false)); Button *button_ui = memnew(Button); @@ -1614,8 +1614,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V if (p_keep_global_xform) { if (Object::cast_to(node)) editor_data->get_undo_redo().add_do_method(node, "set_global_transform", Object::cast_to(node)->get_global_transform()); - if (Object::cast_to(node)) - editor_data->get_undo_redo().add_do_method(node, "set_global_transform", Object::cast_to(node)->get_global_transform()); + if (Object::cast_to(node)) + editor_data->get_undo_redo().add_do_method(node, "set_global_transform", Object::cast_to(node)->get_global_transform()); if (Object::cast_to(node)) editor_data->get_undo_redo().add_do_method(node, "set_global_position", Object::cast_to(node)->get_global_position()); } @@ -1655,8 +1655,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V if (p_keep_global_xform) { if (Object::cast_to(node)) editor_data->get_undo_redo().add_undo_method(node, "set_transform", Object::cast_to(node)->get_transform()); - if (Object::cast_to(node)) - editor_data->get_undo_redo().add_undo_method(node, "set_transform", Object::cast_to(node)->get_transform()); + if (Object::cast_to(node)) + editor_data->get_undo_redo().add_undo_method(node, "set_transform", Object::cast_to(node)->get_transform()); if (Object::cast_to(node)) editor_data->get_undo_redo().add_undo_method(node, "set_position", Object::cast_to(node)->get_position()); } @@ -1777,7 +1777,7 @@ void SceneTreeDock::_toggle_editable_children(Node *p_node) { if (editable) p_node->set_scene_instance_load_placeholder(false); - SpatialEditor::get_singleton()->update_all_gizmos(p_node); + Node3DEditor::get_singleton()->update_all_gizmos(p_node); scene_tree->update_tree(); } @@ -2568,7 +2568,7 @@ void SceneTreeDock::_focus_node() { CanvasItemEditorPlugin *editor = Object::cast_to(editor_data->get_editor("2D")); editor->get_canvas_item_editor()->focus_selection(); } else { - SpatialEditorPlugin *editor = Object::cast_to(editor_data->get_editor("3D")); + Node3DEditorPlugin *editor = Object::cast_to(editor_data->get_editor("3D")); editor->get_spatial_editor()->get_editor_viewport(0)->focus_selection(); } } diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index a290e57a4e..831b7b6775 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -92,7 +92,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } else if (p_id == BUTTON_LOCK) { undo_redo->create_action(TTR("Unlock Node")); - if (n->is_class("CanvasItem") || n->is_class("Spatial")) { + if (n->is_class("CanvasItem") || n->is_class("Node3D")) { undo_redo->add_do_method(n, "remove_meta", "_edit_lock_"); undo_redo->add_undo_method(n, "set_meta", "_edit_lock_", true); @@ -112,7 +112,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } else if (p_id == BUTTON_GROUP) { undo_redo->create_action(TTR("Button Group")); - if (n->is_class("CanvasItem") || n->is_class("Spatial")) { + if (n->is_class("CanvasItem") || n->is_class("Node3D")) { undo_redo->add_do_method(n, "remove_meta", "_edit_group_"); undo_redo->add_undo_method(n, "set_meta", "_edit_group_", true); @@ -354,7 +354,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); _update_visibility_color(p_node, item); - } else if (p_node->is_class("Spatial")) { + } else if (p_node->is_class("Node3D")) { bool is_locked = p_node->has_meta("_edit_lock_"); if (is_locked) @@ -457,7 +457,7 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) { if (p_node->is_class("CanvasItem")) { visible = p_node->call("is_visible"); CanvasItemEditor::get_singleton()->get_viewport_control()->update(); - } else if (p_node->is_class("Spatial")) { + } else if (p_node->is_class("Node3D")) { visible = p_node->call("is_visible"); } @@ -470,7 +470,7 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) { } void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) { - if (p_node->is_class("CanvasItem") || p_node->is_class("Spatial")) { + if (p_node->is_class("CanvasItem") || p_node->is_class("Node3D")) { Color color(1, 1, 1, 1); bool visible_on_screen = p_node->call("is_visible_in_tree"); if (!visible_on_screen) { @@ -498,7 +498,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) { if (p_node->is_connected("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed))) p_node->disconnect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed)); - if (p_node->is_class("Spatial") || p_node->is_class("CanvasItem")) { + if (p_node->is_class("Node3D") || p_node->is_class("CanvasItem")) { if (p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) p_node->disconnect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed)); } diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index a3030e7380..a7d014be33 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -34,39 +34,39 @@ #include "core/math/quick_hull.h" #include "scene/3d/audio_stream_player_3d.h" #include "scene/3d/baked_lightmap.h" -#include "scene/3d/collision_polygon.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/cpu_particles.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/gi_probe.h" -#include "scene/3d/light.h" -#include "scene/3d/listener.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation_region.h" -#include "scene/3d/particles.h" -#include "scene/3d/physics_joint.h" +#include "scene/3d/gpu_particles_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/listener_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/navigation_region_3d.h" +#include "scene/3d/physics_joint_3d.h" #include "scene/3d/position_3d.h" -#include "scene/3d/ray_cast.h" +#include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" -#include "scene/3d/soft_body.h" -#include "scene/3d/spring_arm.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.h" -#include "scene/3d/visibility_notifier.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" -#include "scene/resources/cylinder_shape.h" +#include "scene/3d/visibility_notifier_3d.h" +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/height_map_shape.h" #include "scene/resources/primitive_meshes.h" #include "scene/resources/ray_shape.h" -#include "scene/resources/sphere_shape.h" +#include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/world_margin_shape_3d.h" #define HANDLE_HALF_SIZE 9.5 -bool EditorSpatialGizmo::is_editable() const { +bool EditorNode3DGizmo::is_editable() const { ERR_FAIL_COND_V(!spatial_node, false); Node *edited_root = spatial_node->get_tree()->get_edited_scene_root(); @@ -81,7 +81,7 @@ bool EditorSpatialGizmo::is_editable() const { return false; } -void EditorSpatialGizmo::clear() { +void EditorNode3DGizmo::clear() { for (int i = 0; i < instances.size(); i++) { @@ -97,7 +97,7 @@ void EditorSpatialGizmo::clear() { secondary_handles.clear(); } -void EditorSpatialGizmo::redraw() { +void EditorNode3DGizmo::redraw() { if (get_script_instance() && get_script_instance()->has_method("redraw")) { get_script_instance()->call("redraw"); @@ -108,7 +108,7 @@ void EditorSpatialGizmo::redraw() { gizmo_plugin->redraw(this); } -String EditorSpatialGizmo::get_handle_name(int p_idx) const { +String EditorNode3DGizmo::get_handle_name(int p_idx) const { if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) { return get_script_instance()->call("get_handle_name", p_idx); @@ -118,7 +118,7 @@ String EditorSpatialGizmo::get_handle_name(int p_idx) const { return gizmo_plugin->get_handle_name(this, p_idx); } -bool EditorSpatialGizmo::is_handle_highlighted(int p_idx) const { +bool EditorNode3DGizmo::is_handle_highlighted(int p_idx) const { if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) { return get_script_instance()->call("is_handle_highlighted", p_idx); @@ -128,7 +128,7 @@ bool EditorSpatialGizmo::is_handle_highlighted(int p_idx) const { return gizmo_plugin->is_handle_highlighted(this, p_idx); } -Variant EditorSpatialGizmo::get_handle_value(int p_idx) { +Variant EditorNode3DGizmo::get_handle_value(int p_idx) { if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) { return get_script_instance()->call("get_handle_value", p_idx); @@ -138,7 +138,7 @@ Variant EditorSpatialGizmo::get_handle_value(int p_idx) { return gizmo_plugin->get_handle_value(this, p_idx); } -void EditorSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void EditorNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) { if (get_script_instance() && get_script_instance()->has_method("set_handle")) { get_script_instance()->call("set_handle", p_idx, p_camera, p_point); @@ -149,7 +149,7 @@ void EditorSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p gizmo_plugin->set_handle(this, p_idx, p_camera, p_point); } -void EditorSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void EditorNode3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { if (get_script_instance() && get_script_instance()->has_method("commit_handle")) { get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel); @@ -160,13 +160,13 @@ void EditorSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool gizmo_plugin->commit_handle(this, p_idx, p_restore, p_cancel); } -void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { +void EditorNode3DGizmo::set_spatial_node(Node3D *p_node) { ERR_FAIL_NULL(p_node); spatial_node = p_node; } -void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidden) { +void EditorNode3DGizmo::Instance::create_instance(Node3D *p_base, bool p_hidden) { instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); @@ -176,11 +176,11 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde if (extra_margin) VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF); - int layer = p_hidden ? 0 : 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER; + int layer = p_hidden ? 0 : 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER; VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 } -void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const Ref &p_skin_reference, const Ref &p_material) { +void EditorNode3DGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const Ref &p_skin_reference, const Ref &p_material) { ERR_FAIL_COND(!spatial_node); Instance ins; @@ -200,7 +200,7 @@ void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, bool p_billboard instances.push_back(ins); } -void EditorSpatialGizmo::add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard, const Color &p_modulate) { +void EditorNode3DGizmo::add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard, const Color &p_modulate) { if (p_lines.empty()) { return; } @@ -252,7 +252,7 @@ void EditorSpatialGizmo::add_lines(const Vector &p_lines, const Ref &p_material, float p_scale, const Color &p_modulate) { +void EditorNode3DGizmo::add_unscaled_billboard(const Ref &p_material, float p_scale, const Color &p_modulate) { ERR_FAIL_COND(!spatial_node); Instance ins; @@ -318,11 +318,11 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref &p_material, instances.push_back(ins); } -void EditorSpatialGizmo::add_collision_triangles(const Ref &p_tmesh) { +void EditorNode3DGizmo::add_collision_triangles(const Ref &p_tmesh) { collision_mesh = p_tmesh; } -void EditorSpatialGizmo::add_collision_segments(const Vector &p_lines) { +void EditorNode3DGizmo::add_collision_segments(const Vector &p_lines) { int from = collision_segments.size(); collision_segments.resize(from + p_lines.size()); @@ -332,7 +332,7 @@ void EditorSpatialGizmo::add_collision_segments(const Vector &p_lines) } } -void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref &p_material, bool p_billboard, bool p_secondary) { +void EditorNode3DGizmo::add_handles(const Vector &p_handles, const Ref &p_material, bool p_billboard, bool p_secondary) { billboard_handle = p_billboard; @@ -358,7 +358,7 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref if (is_handle_highlighted(i)) col = Color(0, 0, 1, 0.9); - if (SpatialEditor::get_singleton()->get_over_gizmo_handle() != i) + if (Node3DEditor::get_singleton()->get_over_gizmo_handle() != i) col.a = 0.8; w[i] = col; @@ -403,7 +403,7 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref } } -void EditorSpatialGizmo::add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position) { +void EditorNode3DGizmo::add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position) { ERR_FAIL_COND(!spatial_node); CubeMesh cubem; @@ -425,7 +425,7 @@ void EditorSpatialGizmo::add_solid_box(Ref &p_material, Vector3 p_size add_mesh(m); } -bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector &p_frustum) { +bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector &p_frustum) { ERR_FAIL_COND_V(!spatial_node, false); ERR_FAIL_COND_V(!valid, false); @@ -497,7 +497,7 @@ bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector< return false; } -bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) { +bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) { ERR_FAIL_COND_V(!spatial_node, false); ERR_FAIL_COND_V(!valid, false); @@ -574,7 +574,7 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, float scale = t.origin.distance_to(p_camera->get_camera_transform().origin); - if (p_camera->get_projection() == Camera::PROJECTION_ORTHOGONAL) { + if (p_camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL) { float aspect = p_camera->get_viewport()->get_visible_rect().size.aspect(); float size = p_camera->get_size(); scale = size / aspect; @@ -689,7 +689,7 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, return false; } -void EditorSpatialGizmo::create() { +void EditorNode3DGizmo::create() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(valid); @@ -703,7 +703,7 @@ void EditorSpatialGizmo::create() { transform(); } -void EditorSpatialGizmo::transform() { +void EditorNode3DGizmo::transform() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(!valid); @@ -712,7 +712,7 @@ void EditorSpatialGizmo::transform() { } } -void EditorSpatialGizmo::free() { +void EditorNode3DGizmo::free() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(!valid); @@ -729,31 +729,31 @@ void EditorSpatialGizmo::free() { valid = false; } -void EditorSpatialGizmo::set_hidden(bool p_hidden) { +void EditorNode3DGizmo::set_hidden(bool p_hidden) { hidden = p_hidden; - int layer = hidden ? 0 : 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER; + int layer = hidden ? 0 : 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER; for (int i = 0; i < instances.size(); ++i) { VS::get_singleton()->instance_set_layer_mask(instances[i].instance, layer); } } -void EditorSpatialGizmo::set_plugin(EditorSpatialGizmoPlugin *p_plugin) { +void EditorNode3DGizmo::set_plugin(EditorNode3DGizmoPlugin *p_plugin) { gizmo_plugin = p_plugin; } -void EditorSpatialGizmo::_bind_methods() { +void EditorNode3DGizmo::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard", "modulate"), &EditorSpatialGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1))); - ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorSpatialGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref()), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorSpatialGizmo::add_collision_segments); - ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorSpatialGizmo::add_collision_triangles); - ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale", "modulate"), &EditorSpatialGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1))); - ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorSpatialGizmo::_set_spatial_node); - ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorSpatialGizmo::get_spatial_node); - ClassDB::bind_method(D_METHOD("get_plugin"), &EditorSpatialGizmo::get_plugin); - ClassDB::bind_method(D_METHOD("clear"), &EditorSpatialGizmo::clear); - ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorSpatialGizmo::set_hidden); + ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard", "modulate"), &EditorNode3DGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorNode3DGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref()), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorNode3DGizmo::add_collision_segments); + ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorNode3DGizmo::add_collision_triangles); + ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale", "modulate"), &EditorNode3DGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorNode3DGizmo::add_handles, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorNode3DGizmo::_set_spatial_node); + ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorNode3DGizmo::get_spatial_node); + ClassDB::bind_method(D_METHOD("get_plugin"), &EditorNode3DGizmo::get_plugin); + ClassDB::bind_method(D_METHOD("clear"), &EditorNode3DGizmo::clear); + ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorNode3DGizmo::set_hidden); BIND_VMETHOD(MethodInfo("redraw")); BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "index"))); @@ -763,13 +763,13 @@ void EditorSpatialGizmo::_bind_methods() { hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; BIND_VMETHOD(hvget); - BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); MethodInfo cm = MethodInfo("commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); cm.default_arguments.push_back(false); BIND_VMETHOD(cm); } -EditorSpatialGizmo::EditorSpatialGizmo() { +EditorNode3DGizmo::EditorNode3DGizmo() { valid = false; billboard_handle = false; hidden = false; @@ -781,13 +781,13 @@ EditorSpatialGizmo::EditorSpatialGizmo() { selectable_icon_size = -1.0f; } -EditorSpatialGizmo::~EditorSpatialGizmo() { +EditorNode3DGizmo::~EditorNode3DGizmo() { if (gizmo_plugin != NULL) gizmo_plugin->unregister_gizmo(this); clear(); } -Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const { +Vector3 EditorNode3DGizmo::get_handle_pos(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, handles.size(), Vector3()); @@ -796,34 +796,34 @@ Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const { //// light gizmo -LightSpatialGizmoPlugin::LightSpatialGizmoPlugin() { +LightNode3DGizmoPlugin::LightNode3DGizmoPlugin() { // Enable vertex colors for the materials below as the gizmo color depends on the light color. create_material("lines_primary", Color(1, 1, 1), false, false, true); create_material("lines_secondary", Color(1, 1, 1, 0.35), false, false, true); create_material("lines_billboard", Color(1, 1, 1), true, false, true); - create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoDirectionalLight", "EditorIcons")); - create_icon_material("light_omni_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoLight", "EditorIcons")); - create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoSpotLight", "EditorIcons")); + create_icon_material("light_directional_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoDirectionalLight", "EditorIcons")); + create_icon_material("light_omni_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoLight", "EditorIcons")); + create_icon_material("light_spot_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoSpotLight", "EditorIcons")); create_handle_material("handles"); create_handle_material("handles_billboard", true); } -bool LightSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool LightNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String LightSpatialGizmoPlugin::get_name() const { +String LightNode3DGizmoPlugin::get_name() const { return "Lights"; } -int LightSpatialGizmoPlugin::get_priority() const { +int LightNode3DGizmoPlugin::get_priority() const { return -1; } -String LightSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String LightNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { if (p_idx == 0) return "Radius"; @@ -831,13 +831,13 @@ String LightSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizm return "Aperture"; } -Variant LightSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant LightNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - Light *light = Object::cast_to(p_gizmo->get_spatial_node()); + Light3D *light = Object::cast_to(p_gizmo->get_spatial_node()); if (p_idx == 0) - return light->get_param(Light::PARAM_RANGE); + return light->get_param(Light3D::PARAM_RANGE); if (p_idx == 1) - return light->get_param(Light::PARAM_SPOT_ANGLE); + return light->get_param(Light3D::PARAM_SPOT_ANGLE); return Variant(); } @@ -871,9 +871,9 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec return a * 180.0 / Math_PI; } -void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void LightNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - Light *light = Object::cast_to(p_gizmo->get_spatial_node()); + Light3D *light = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = light->get_global_transform(); Transform gi = gt.affine_inverse(); @@ -883,20 +883,20 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; if (p_idx == 0) { - if (Object::cast_to(light)) { + if (Object::cast_to(light)) { Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb); float d = -ra.z; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d <= 0) // Equal is here for negative zero. d = 0; - light->set_param(Light::PARAM_RANGE, d); - } else if (Object::cast_to(light)) { + light->set_param(Light3D::PARAM_RANGE, d); + } else if (Object::cast_to(light)) { Plane cp = Plane(gt.origin, p_camera->get_transform().basis.get_axis(2)); @@ -904,48 +904,48 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, if (cp.intersects_ray(ray_from, ray_dir, &inters)) { float r = inters.distance_to(gt.origin); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - r = Math::stepify(r, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + r = Math::stepify(r, Node3DEditor::get_singleton()->get_translate_snap()); } - light->set_param(Light::PARAM_RANGE, r); + light->set_param(Light3D::PARAM_RANGE, r); } } } else if (p_idx == 1) { - float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], light->get_param(Light::PARAM_RANGE), gt); - light->set_param(Light::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99)); + float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], light->get_param(Light3D::PARAM_RANGE), gt); + light->set_param(Light3D::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99)); } } -void LightSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void LightNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - Light *light = Object::cast_to(p_gizmo->get_spatial_node()); + Light3D *light = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { - light->set_param(p_idx == 0 ? Light::PARAM_RANGE : Light::PARAM_SPOT_ANGLE, p_restore); + light->set_param(p_idx == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore); } else if (p_idx == 0) { - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); - ur->add_do_method(light, "set_param", Light::PARAM_RANGE, light->get_param(Light::PARAM_RANGE)); - ur->add_undo_method(light, "set_param", Light::PARAM_RANGE, p_restore); + ur->add_do_method(light, "set_param", Light3D::PARAM_RANGE, light->get_param(Light3D::PARAM_RANGE)); + ur->add_undo_method(light, "set_param", Light3D::PARAM_RANGE, p_restore); ur->commit_action(); } else if (p_idx == 1) { - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); - ur->add_do_method(light, "set_param", Light::PARAM_SPOT_ANGLE, light->get_param(Light::PARAM_SPOT_ANGLE)); - ur->add_undo_method(light, "set_param", Light::PARAM_SPOT_ANGLE, p_restore); + ur->add_do_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, light->get_param(Light3D::PARAM_SPOT_ANGLE)); + ur->add_undo_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, p_restore); ur->commit_action(); } } -void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void LightNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - Light *light = Object::cast_to(p_gizmo->get_spatial_node()); + Light3D *light = Object::cast_to(p_gizmo->get_spatial_node()); Color color = light->get_color(); // Make the gizmo color as bright as possible for better visibility @@ -953,7 +953,7 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->clear(); - if (Object::cast_to(light)) { + if (Object::cast_to(light)) { Ref material = get_material("lines_primary", p_gizmo); Ref icon = get_material("light_directional_icon", p_gizmo); @@ -991,15 +991,15 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_unscaled_billboard(icon, 0.05, color); } - if (Object::cast_to(light)) { + if (Object::cast_to(light)) { // Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation const Ref lines_material = get_material("lines_secondary", p_gizmo); const Ref lines_billboard_material = get_material("lines_billboard", p_gizmo); const Ref icon = get_material("light_omni_icon", p_gizmo); - OmniLight *on = Object::cast_to(light); - const float r = on->get_param(Light::PARAM_RANGE); + OmniLight3D *on = Object::cast_to(light); + const float r = on->get_param(Light3D::PARAM_RANGE); Vector points; Vector points_billboard; @@ -1033,7 +1033,7 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, get_material("handles_billboard"), true); } - if (Object::cast_to(light)) { + if (Object::cast_to(light)) { const Ref material_primary = get_material("lines_primary", p_gizmo); const Ref material_secondary = get_material("lines_secondary", p_gizmo); @@ -1041,11 +1041,11 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Vector points_primary; Vector points_secondary; - SpotLight *sl = Object::cast_to(light); + SpotLight3D *sl = Object::cast_to(light); - float r = sl->get_param(Light::PARAM_RANGE); - float w = r * Math::sin(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE))); - float d = r * Math::cos(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE))); + float r = sl->get_param(Light3D::PARAM_RANGE); + float w = r * Math::sin(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); + float d = r * Math::cos(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); for (int i = 0; i < 120; i++) { @@ -1086,39 +1086,39 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ////// //// player gizmo -AudioStreamPlayer3DSpatialGizmoPlugin::AudioStreamPlayer3DSpatialGizmoPlugin() { +AudioStreamPlayer3DNode3DGizmoPlugin::AudioStreamPlayer3DNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1)); - create_icon_material("stream_player_3d_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoSpatialSamplePlayer", "EditorIcons")); + create_icon_material("stream_player_3d_icon", Node3DEditor::get_singleton()->get_theme_icon("Gizmo3DSamplePlayer", "EditorIcons")); create_material("stream_player_3d_material_primary", gizmo_color); create_material("stream_player_3d_material_secondary", gizmo_color * Color(1, 1, 1, 0.35)); create_handle_material("handles"); } -bool AudioStreamPlayer3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool AudioStreamPlayer3DNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } -String AudioStreamPlayer3DSpatialGizmoPlugin::get_name() const { +String AudioStreamPlayer3DNode3DGizmoPlugin::get_name() const { return "AudioStreamPlayer3D"; } -int AudioStreamPlayer3DSpatialGizmoPlugin::get_priority() const { +int AudioStreamPlayer3DNode3DGizmoPlugin::get_priority() const { return -1; } -String AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String AudioStreamPlayer3DNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { return "Emission Radius"; } -Variant AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant AudioStreamPlayer3DNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); return player->get_emission_angle(); } -void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void AudioStreamPlayer3DNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); @@ -1157,7 +1157,7 @@ void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_giz } } -void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void AudioStreamPlayer3DNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); @@ -1167,7 +1167,7 @@ void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_ } else { - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change AudioStreamPlayer3D Emission Angle")); ur->add_do_method(player, "set_emission_angle", player->get_emission_angle()); ur->add_undo_method(player, "set_emission_angle", p_restore); @@ -1175,7 +1175,7 @@ void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_ } } -void AudioStreamPlayer3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void AudioStreamPlayer3DNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { const AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); @@ -1233,7 +1233,7 @@ void AudioStreamPlayer3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) ////// -CameraSpatialGizmoPlugin::CameraSpatialGizmoPlugin() { +CameraNode3DGizmoPlugin::CameraNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/camera", Color(0.8, 0.4, 0.8)); @@ -1241,34 +1241,34 @@ CameraSpatialGizmoPlugin::CameraSpatialGizmoPlugin() { create_handle_material("handles"); } -bool CameraSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool CameraNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String CameraSpatialGizmoPlugin::get_name() const { - return "Camera"; +String CameraNode3DGizmoPlugin::get_name() const { + return "Camera3D"; } -int CameraSpatialGizmoPlugin::get_priority() const { +int CameraNode3DGizmoPlugin::get_priority() const { return -1; } -String CameraSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String CameraNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { - Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); + Camera3D *camera = Object::cast_to(p_gizmo->get_spatial_node()); - if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { + if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) { return "FOV"; } else { return "Size"; } } -Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant CameraNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); + Camera3D *camera = Object::cast_to(p_gizmo->get_spatial_node()); - if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { + if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) { return camera->get_fov(); } else { @@ -1276,9 +1276,9 @@ Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, } } -void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void CameraNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); + Camera3D *camera = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = camera->get_global_transform(); Transform gi = gt.affine_inverse(); @@ -1288,7 +1288,7 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; - if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { + if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) { Transform gt2 = camera->get_global_transform(); float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt2); camera->set("fov", CLAMP(a * 2.0, 1, 179)); @@ -1297,8 +1297,8 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb); float d = ra.x * 2.0; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } d = CLAMP(d, 0.1, 16384); @@ -1307,17 +1307,17 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx } } -void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CameraNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); + Camera3D *camera = Object::cast_to(p_gizmo->get_spatial_node()); - if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { + if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) { if (p_cancel) { camera->set("fov", p_restore); } else { - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Camera FOV")); ur->add_do_property(camera, "fov", camera->get_fov()); ur->add_undo_property(camera, "fov", p_restore); @@ -1330,7 +1330,7 @@ void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_ camera->set("size", p_restore); } else { - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Camera Size")); ur->add_do_property(camera, "size", camera->get_size()); ur->add_undo_property(camera, "size", p_restore); @@ -1339,9 +1339,9 @@ void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_ } } -void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void CameraNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); + Camera3D *camera = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -1374,7 +1374,7 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { switch (camera->get_projection()) { - case Camera::PROJECTION_PERSPECTIVE: { + case Camera3D::PROJECTION_PERSPECTIVE: { // The real FOV is halved for accurate representation float fov = camera->get_fov() / 2.0; @@ -1396,7 +1396,7 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ADD_TRIANGLE(tup, side + up, nside + up); } break; - case Camera::PROJECTION_ORTHOGONAL: { + case Camera3D::PROJECTION_ORTHOGONAL: { float size = camera->get_size(); @@ -1418,7 +1418,7 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ADD_TRIANGLE(tup, right + up + back, -right + up + back); } break; - case Camera::PROJECTION_FRUSTUM: { + case Camera3D::PROJECTION_FRUSTUM: { float hsize = camera->get_size() / 2.0; Vector3 side = Vector3(hsize, 0, -camera->get_znear()).normalized(); @@ -1447,7 +1447,7 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ClippedCamera *clipcam = Object::cast_to(camera); if (clipcam) { - Spatial *parent = Object::cast_to(camera->get_parent()); + Node3D *parent = Object::cast_to(camera->get_parent()); if (!parent) { return; } @@ -1489,28 +1489,28 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ////// -MeshInstanceSpatialGizmoPlugin::MeshInstanceSpatialGizmoPlugin() { +MeshInstanceNode3DGizmoPlugin::MeshInstanceNode3DGizmoPlugin() { } -bool MeshInstanceSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL && Object::cast_to(p_spatial) == NULL; +bool MeshInstanceNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL && Object::cast_to(p_spatial) == NULL; } -String MeshInstanceSpatialGizmoPlugin::get_name() const { - return "MeshInstance"; +String MeshInstanceNode3DGizmoPlugin::get_name() const { + return "MeshInstance3D"; } -int MeshInstanceSpatialGizmoPlugin::get_priority() const { +int MeshInstanceNode3DGizmoPlugin::get_priority() const { return -1; } -bool MeshInstanceSpatialGizmoPlugin::can_be_hidden() const { +bool MeshInstanceNode3DGizmoPlugin::can_be_hidden() const { return false; } -void MeshInstanceSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void MeshInstanceNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - MeshInstance *mesh = Object::cast_to(p_gizmo->get_spatial_node()); + MeshInstance3D *mesh = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -1526,26 +1526,26 @@ void MeshInstanceSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } ///// -Sprite3DSpatialGizmoPlugin::Sprite3DSpatialGizmoPlugin() { +Sprite3DNode3DGizmoPlugin::Sprite3DNode3DGizmoPlugin() { } -bool Sprite3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool Sprite3DNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } -String Sprite3DSpatialGizmoPlugin::get_name() const { +String Sprite3DNode3DGizmoPlugin::get_name() const { return "Sprite3D"; } -int Sprite3DSpatialGizmoPlugin::get_priority() const { +int Sprite3DNode3DGizmoPlugin::get_priority() const { return -1; } -bool Sprite3DSpatialGizmoPlugin::can_be_hidden() const { +bool Sprite3DNode3DGizmoPlugin::can_be_hidden() const { return false; } -void Sprite3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void Sprite3DNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Sprite3D *sprite = Object::cast_to(p_gizmo->get_spatial_node()); @@ -1559,7 +1559,7 @@ void Sprite3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { /// -Position3DSpatialGizmoPlugin::Position3DSpatialGizmoPlugin() { +Position3DNode3DGizmoPlugin::Position3DNode3DGizmoPlugin() { pos3d_mesh = Ref(memnew(ArrayMesh)); cursor_points = Vector(); @@ -1592,19 +1592,19 @@ Position3DSpatialGizmoPlugin::Position3DSpatialGizmoPlugin() { pos3d_mesh->surface_set_material(0, mat); } -bool Position3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool Position3DNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } -String Position3DSpatialGizmoPlugin::get_name() const { +String Position3DNode3DGizmoPlugin::get_name() const { return "Position3D"; } -int Position3DSpatialGizmoPlugin::get_priority() const { +int Position3DNode3DGizmoPlugin::get_priority() const { return -1; } -void Position3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void Position3DNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); p_gizmo->add_mesh(pos3d_mesh); @@ -1613,27 +1613,27 @@ void Position3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ///// -SkeletonSpatialGizmoPlugin::SkeletonSpatialGizmoPlugin() { +SkeletonNode3DGizmoPlugin::SkeletonNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4)); create_material("skeleton_material", gizmo_color); } -bool SkeletonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool SkeletonNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String SkeletonSpatialGizmoPlugin::get_name() const { - return "Skeleton"; +String SkeletonNode3DGizmoPlugin::get_name() const { + return "Skeleton3D"; } -int SkeletonSpatialGizmoPlugin::get_priority() const { +int SkeletonNode3DGizmoPlugin::get_priority() const { return -1; } -void SkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void SkeletonNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - Skeleton *skel = Object::cast_to(p_gizmo->get_spatial_node()); + Skeleton3D *skel = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -1822,54 +1822,54 @@ void SkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// -PhysicalBoneSpatialGizmoPlugin::PhysicalBoneSpatialGizmoPlugin() { +PhysicalBoneNode3DGizmoPlugin::PhysicalBoneNode3DGizmoPlugin() { create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1))); } -bool PhysicalBoneSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool PhysicalBoneNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String PhysicalBoneSpatialGizmoPlugin::get_name() const { +String PhysicalBoneNode3DGizmoPlugin::get_name() const { return "PhysicalBones"; } -int PhysicalBoneSpatialGizmoPlugin::get_priority() const { +int PhysicalBoneNode3DGizmoPlugin::get_priority() const { return -1; } -void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void PhysicalBoneNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); - PhysicalBone *physical_bone = Object::cast_to(p_gizmo->get_spatial_node()); + PhysicalBone3D *physical_bone = Object::cast_to(p_gizmo->get_spatial_node()); if (!physical_bone) return; - Skeleton *sk(physical_bone->find_skeleton_parent()); + Skeleton3D *sk(physical_bone->find_skeleton_parent()); if (!sk) return; - PhysicalBone *pb(sk->get_physical_bone(physical_bone->get_bone_id())); + PhysicalBone3D *pb(sk->get_physical_bone(physical_bone->get_bone_id())); if (!pb) return; - PhysicalBone *pbp(sk->get_physical_bone_parent(physical_bone->get_bone_id())); + PhysicalBone3D *pbp(sk->get_physical_bone_parent(physical_bone->get_bone_id())); if (!pbp) return; Vector points; switch (physical_bone->get_joint_type()) { - case PhysicalBone::JOINT_TYPE_PIN: { + case PhysicalBone3D::JOINT_TYPE_PIN: { - JointSpatialGizmoPlugin::CreatePinJointGizmo(physical_bone->get_joint_offset(), points); + JointNode3DGizmoPlugin::CreatePinJointGizmo(physical_bone->get_joint_offset(), points); } break; - case PhysicalBone::JOINT_TYPE_CONE: { + case PhysicalBone3D::JOINT_TYPE_CONE: { - const PhysicalBone::ConeJointData *cjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateConeTwistJointGizmo( + const PhysicalBone3D::ConeJointData *cjd(static_cast(physical_bone->get_joint_data())); + JointNode3DGizmoPlugin::CreateConeTwistJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb->get_global_transform(), @@ -1879,10 +1879,10 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { &points, &points); } break; - case PhysicalBone::JOINT_TYPE_HINGE: { + case PhysicalBone3D::JOINT_TYPE_HINGE: { - const PhysicalBone::HingeJointData *hjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateHingeJointGizmo( + const PhysicalBone3D::HingeJointData *hjd(static_cast(physical_bone->get_joint_data())); + JointNode3DGizmoPlugin::CreateHingeJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb->get_global_transform(), @@ -1894,10 +1894,10 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { &points, &points); } break; - case PhysicalBone::JOINT_TYPE_SLIDER: { + case PhysicalBone3D::JOINT_TYPE_SLIDER: { - const PhysicalBone::SliderJointData *sjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateSliderJointGizmo( + const PhysicalBone3D::SliderJointData *sjd(static_cast(physical_bone->get_joint_data())); + JointNode3DGizmoPlugin::CreateSliderJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb->get_global_transform(), @@ -1910,10 +1910,10 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { &points, &points); } break; - case PhysicalBone::JOINT_TYPE_6DOF: { + case PhysicalBone3D::JOINT_TYPE_6DOF: { - const PhysicalBone::SixDOFJointData *sdofjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( + const PhysicalBone3D::SixDOFJointData *sdofjd(static_cast(physical_bone->get_joint_data())); + JointNode3DGizmoPlugin::CreateGeneric6DOFJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), @@ -1957,7 +1957,7 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ///// -RayCastSpatialGizmoPlugin::RayCastSpatialGizmoPlugin() { +RayCastNode3DGizmoPlugin::RayCastNode3DGizmoPlugin() { const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); @@ -1966,21 +1966,21 @@ RayCastSpatialGizmoPlugin::RayCastSpatialGizmoPlugin() { create_material("shape_material_disabled", gizmo_color_disabled); } -bool RayCastSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool RayCastNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String RayCastSpatialGizmoPlugin::get_name() const { +String RayCastNode3DGizmoPlugin::get_name() const { return "RayCast"; } -int RayCastSpatialGizmoPlugin::get_priority() const { +int RayCastNode3DGizmoPlugin::get_priority() const { return -1; } -void RayCastSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void RayCastNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - RayCast *raycast = Object::cast_to(p_gizmo->get_spatial_node()); + RayCast3D *raycast = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -1998,9 +1998,9 @@ void RayCastSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ///// -void SpringArmSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void SpringArmNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - SpringArm *spring_arm = Object::cast_to(p_gizmo->get_spatial_node()); + SpringArm3D *spring_arm = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2015,44 +2015,44 @@ void SpringArmSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(lines); } -SpringArmSpatialGizmoPlugin::SpringArmSpatialGizmoPlugin() { +SpringArmNode3DGizmoPlugin::SpringArmNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); } -bool SpringArmSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool SpringArmNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String SpringArmSpatialGizmoPlugin::get_name() const { +String SpringArmNode3DGizmoPlugin::get_name() const { return "SpringArm"; } -int SpringArmSpatialGizmoPlugin::get_priority() const { +int SpringArmNode3DGizmoPlugin::get_priority() const { return -1; } ///// -VehicleWheelSpatialGizmoPlugin::VehicleWheelSpatialGizmoPlugin() { +VehicleWheelNode3DGizmoPlugin::VehicleWheelNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); } -bool VehicleWheelSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool VehicleWheelNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } -String VehicleWheelSpatialGizmoPlugin::get_name() const { +String VehicleWheelNode3DGizmoPlugin::get_name() const { return "VehicleWheel"; } -int VehicleWheelSpatialGizmoPlugin::get_priority() const { +int VehicleWheelNode3DGizmoPlugin::get_priority() const { return -1; } -void VehicleWheelSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void VehicleWheelNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { VehicleWheel *car_wheel = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2108,30 +2108,30 @@ void VehicleWheelSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { /////////// -SoftBodySpatialGizmoPlugin::SoftBodySpatialGizmoPlugin() { +SoftBodyNode3DGizmoPlugin::SoftBodyNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); create_handle_material("handles"); } -bool SoftBodySpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool SoftBodyNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String SoftBodySpatialGizmoPlugin::get_name() const { +String SoftBodyNode3DGizmoPlugin::get_name() const { return "SoftBody"; } -int SoftBodySpatialGizmoPlugin::get_priority() const { +int SoftBodyNode3DGizmoPlugin::get_priority() const { return -1; } -bool SoftBodySpatialGizmoPlugin::is_selectable_when_hidden() const { +bool SoftBodyNode3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void SoftBodySpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); +void SoftBodyNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + SoftBody3D *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2161,22 +2161,22 @@ void SoftBodySpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_triangles(tm); } -String SoftBodySpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String SoftBodyNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { return "SoftBody pin point"; } -Variant SoftBodySpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { - SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); +Variant SoftBodyNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { + SoftBody3D *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); return Variant(soft_body->is_point_pinned(p_idx)); } -void SoftBodySpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); +void SoftBodyNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + SoftBody3D *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); soft_body->pin_point_toggle(p_idx); } -bool SoftBodySpatialGizmoPlugin::is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const { - SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); +bool SoftBodyNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const { + SoftBody3D *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); return soft_body->is_point_pinned(idx); } @@ -2190,8 +2190,8 @@ VisibilityNotifierGizmoPlugin::VisibilityNotifierGizmoPlugin() { create_handle_material("handles"); } -bool VisibilityNotifierGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool VisibilityNotifierGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } String VisibilityNotifierGizmoPlugin::get_name() const { @@ -2202,7 +2202,7 @@ int VisibilityNotifierGizmoPlugin::get_priority() const { return -1; } -String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Size X"; @@ -2216,14 +2216,14 @@ String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo * return ""; } -Variant VisibilityNotifierGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant VisibilityNotifierGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); + VisibilityNotifier3D *notifier = Object::cast_to(p_gizmo->get_spatial_node()); return notifier->get_aabb(); } -void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void VisibilityNotifierGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); + VisibilityNotifier3D *notifier = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = notifier->get_global_transform(); @@ -2249,8 +2249,8 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; @@ -2261,8 +2261,8 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx] - ofs[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -2274,25 +2274,25 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int } } -void VisibilityNotifierGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void VisibilityNotifierGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); + VisibilityNotifier3D *notifier = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { notifier->set_aabb(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Notifier AABB")); ur->add_do_method(notifier, "set_aabb", notifier->get_aabb()); ur->add_undo_method(notifier, "set_aabb", p_restore); ur->commit_action(); } -void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void VisibilityNotifierGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); + VisibilityNotifier3D *notifier = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2343,11 +2343,11 @@ void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// CPUParticlesGizmoPlugin::CPUParticlesGizmoPlugin() { - create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoCPUParticles", "EditorIcons")); + create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoCPUParticles", "EditorIcons")); } -bool CPUParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool CPUParticlesGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } String CPUParticlesGizmoPlugin::get_name() const { @@ -2362,7 +2362,7 @@ bool CPUParticlesGizmoPlugin::is_selectable_when_hidden() const { return true; } -void CPUParticlesGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void CPUParticlesGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref icon = get_material("particles_icon", p_gizmo); p_gizmo->add_unscaled_billboard(icon, 0.05); } @@ -2374,12 +2374,12 @@ ParticlesGizmoPlugin::ParticlesGizmoPlugin() { create_material("particles_material", gizmo_color); gizmo_color.a = 0.1; create_material("particles_solid_material", gizmo_color); - create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoParticles", "EditorIcons")); + create_icon_material("particles_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoParticles", "EditorIcons")); create_handle_material("handles"); } -bool ParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool ParticlesGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } String ParticlesGizmoPlugin::get_name() const { @@ -2394,7 +2394,7 @@ bool ParticlesGizmoPlugin::is_selectable_when_hidden() const { return true; } -String ParticlesGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String ParticlesGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Size X"; @@ -2407,14 +2407,14 @@ String ParticlesGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, return ""; } -Variant ParticlesGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant ParticlesGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - Particles *particles = Object::cast_to(p_gizmo->get_spatial_node()); + GPUParticles3D *particles = Object::cast_to(p_gizmo->get_spatial_node()); return particles->get_visibility_aabb(); } -void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void ParticlesGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - Particles *particles = Object::cast_to(p_gizmo->get_spatial_node()); + GPUParticles3D *particles = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = particles->get_global_transform(); Transform gi = gt.affine_inverse(); @@ -2439,8 +2439,8 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; @@ -2451,8 +2451,8 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx] - ofs[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -2464,25 +2464,25 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca } } -void ParticlesGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void ParticlesGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - Particles *particles = Object::cast_to(p_gizmo->get_spatial_node()); + GPUParticles3D *particles = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { particles->set_visibility_aabb(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Particles AABB")); ur->add_do_method(particles, "set_visibility_aabb", particles->get_visibility_aabb()); ur->add_undo_method(particles, "set_visibility_aabb", p_restore); ur->commit_action(); } -void ParticlesGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void ParticlesGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - Particles *particles = Object::cast_to(p_gizmo->get_spatial_node()); + GPUParticles3D *particles = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2543,11 +2543,11 @@ ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { gizmo_color.a = 0.1; create_material("reflection_probe_solid_material", gizmo_color); - create_icon_material("reflection_probe_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoReflectionProbe", "EditorIcons")); + create_icon_material("reflection_probe_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoReflectionProbe", "EditorIcons")); create_handle_material("handles"); } -bool ReflectionProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool ReflectionProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } @@ -2559,7 +2559,7 @@ int ReflectionProbeGizmoPlugin::get_priority() const { return -1; } -String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Extents X"; @@ -2572,12 +2572,12 @@ String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_g return ""; } -Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); return AABB(probe->get_extents(), probe->get_origin_offset()); } -void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = probe->get_global_transform(); @@ -2598,8 +2598,8 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -2626,8 +2626,8 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb); // Adjust the actual position to account for the gizmo handle position float d = ra[p_idx] + 0.25; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } origin[p_idx] = d; @@ -2635,7 +2635,7 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i } } -void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void ReflectionProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2647,7 +2647,7 @@ void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Probe Extents")); ur->add_do_method(probe, "set_extents", probe->get_extents()); ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); @@ -2656,7 +2656,7 @@ void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } -void ReflectionProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2731,11 +2731,11 @@ GIProbeGizmoPlugin::GIProbeGizmoPlugin() { gizmo_color.a = 0.05; create_material("gi_probe_solid_material", gizmo_color); - create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons")); + create_icon_material("gi_probe_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons")); create_handle_material("handles"); } -bool GIProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { +bool GIProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != NULL; } @@ -2747,7 +2747,7 @@ int GIProbeGizmoPlugin::get_priority() const { return -1; } -String GIProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String GIProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Extents X"; @@ -2757,12 +2757,12 @@ String GIProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, in return ""; } -Variant GIProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant GIProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); return probe->get_extents(); } -void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void GIProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2782,8 +2782,8 @@ void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Came Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -2793,7 +2793,7 @@ void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Came probe->set_extents(extents); } -void GIProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void GIProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2804,14 +2804,14 @@ void GIProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, c return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Probe Extents")); ur->add_do_method(probe, "set_extents", probe->get_extents()); ur->add_undo_method(probe, "set_extents", restore); ur->commit_action(); } -void GIProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void GIProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2911,11 +2911,11 @@ BakedIndirectLightGizmoPlugin::BakedIndirectLightGizmoPlugin() { gizmo_color.a = 0.1; create_material("baked_indirect_light_internal_material", gizmo_color); - create_icon_material("baked_indirect_light_icon", SpatialEditor::get_singleton()->get_icon("GizmoBakedLightmap", "EditorIcons")); + create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_icon("GizmoBakedLightmap", "EditorIcons")); create_handle_material("handles"); } -String BakedIndirectLightGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String BakedIndirectLightGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { switch (p_idx) { case 0: return "Extents X"; @@ -2925,12 +2925,12 @@ String BakedIndirectLightGizmoPlugin::get_handle_name(const EditorSpatialGizmo * return ""; } -Variant BakedIndirectLightGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant BakedIndirectLightGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); return baker->get_extents(); } -void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void BakedIndirectLightGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2950,8 +2950,8 @@ void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -2961,7 +2961,7 @@ void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int baker->set_extents(extents); } -void BakedIndirectLightGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void BakedIndirectLightGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); @@ -2972,7 +2972,7 @@ void BakedIndirectLightGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, i return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Probe Extents")); ur->add_do_method(baker, "set_extents", baker->get_extents()); ur->add_undo_method(baker, "set_extents", restore); @@ -2991,7 +2991,7 @@ int BakedIndirectLightGizmoPlugin::get_priority() const { return -1; } -void BakedIndirectLightGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void BakedIndirectLightGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { BakedLightmap *baker = Object::cast_to(p_gizmo->get_spatial_node()); @@ -3034,7 +3034,7 @@ void BakedIndirectLightGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { #endif //// -CollisionShapeSpatialGizmoPlugin::CollisionShapeSpatialGizmoPlugin() { +CollisionShapeNode3DGizmoPlugin::CollisionShapeNode3DGizmoPlugin() { const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); const float gizmo_value = gizmo_color.get_v(); @@ -3043,47 +3043,47 @@ CollisionShapeSpatialGizmoPlugin::CollisionShapeSpatialGizmoPlugin() { create_handle_material("handles"); } -bool CollisionShapeSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool CollisionShapeNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String CollisionShapeSpatialGizmoPlugin::get_name() const { - return "CollisionShape"; +String CollisionShapeNode3DGizmoPlugin::get_name() const { + return "CollisionShape3D"; } -int CollisionShapeSpatialGizmoPlugin::get_priority() const { +int CollisionShapeNode3DGizmoPlugin::get_priority() const { return -1; } -String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String CollisionShapeNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { - const CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + const CollisionShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - Ref s = cs->get_shape(); + Ref s = cs->get_shape(); if (s.is_null()) return ""; - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return "Radius"; } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return "Extents"; } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return p_idx == 0 ? "Radius" : "Height"; } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return p_idx == 0 ? "Radius" : "Height"; } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return "Length"; } @@ -3091,51 +3091,51 @@ String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizm return ""; } -Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant CollisionShapeNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CollisionShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - Ref s = cs->get_shape(); + Ref s = cs->get_shape(); if (s.is_null()) return Variant(); - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; return ss->get_radius(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref bs = s; + Ref bs = s; return bs->get_extents(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; return cs2->get_length(); } return Variant(); } -void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void CollisionShapeNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CollisionShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - Ref s = cs->get_shape(); + Ref s = cs->get_shape(); if (s.is_null()) return; @@ -3147,14 +3147,14 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb); float d = ra.x; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -3163,14 +3163,14 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i ss->set_radius(d); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref rs = s; + Ref rs = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb); float d = ra.z; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -3179,16 +3179,16 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i rs->set_length(d); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { Vector3 axis; axis[p_idx] = 1.0; - Ref bs = s; + Ref bs = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -3199,19 +3199,19 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i bs->set_extents(he); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { Vector3 axis; axis[p_idx == 0 ? 0 : 2] = 1.0; - Ref cs2 = s; + Ref cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); if (p_idx == 1) d -= cs2->get_radius(); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -3223,16 +3223,16 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i cs2->set_height(d * 2.0); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { Vector3 axis; axis[p_idx == 0 ? 0 : 1] = 1.0; - Ref cs2 = s; + Ref cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -3244,47 +3244,47 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i cs2->set_height(d * 2.0); } } -void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CollisionShapeNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CollisionShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - Ref s = cs->get_shape(); + Ref s = cs->get_shape(); if (s.is_null()) return; - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; if (p_cancel) { ss->set_radius(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Sphere Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); ur->add_undo_method(ss.ptr(), "set_radius", p_restore); ur->commit_action(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; if (p_cancel) { ss->set_extents(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Box Shape Extents")); ur->add_do_method(ss.ptr(), "set_extents", ss->get_extents()); ur->add_undo_method(ss.ptr(), "set_extents", p_restore); ur->commit_action(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; if (p_cancel) { if (p_idx == 0) ss->set_radius(p_restore); @@ -3293,7 +3293,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Capsule Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); @@ -3307,9 +3307,9 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo ur->commit_action(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; if (p_cancel) { if (p_idx == 0) ss->set_radius(p_restore); @@ -3318,7 +3318,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Cylinder Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); @@ -3336,28 +3336,28 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo ur->commit_action(); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ss = s; + Ref ss = s; if (p_cancel) { ss->set_length(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Ray Shape Length")); ur->add_do_method(ss.ptr(), "set_length", ss->get_length()); ur->add_undo_method(ss.ptr(), "set_length", p_restore); ur->commit_action(); } } -void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void CollisionShapeNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CollisionShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); - Ref s = cs->get_shape(); + Ref s = cs->get_shape(); if (s.is_null()) return; @@ -3365,9 +3365,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { get_material(!cs->is_disabled() ? "shape_material" : "shape_material_disabled", p_gizmo); Ref handles_material = get_material("handles"); - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref sp = s; + Ref sp = s; float r = sp->get_radius(); Vector points; @@ -3411,9 +3411,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref bs = s; + Ref bs = s; Vector lines; AABB aabb; aabb.position = -bs->get_extents(); @@ -3440,9 +3440,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; float radius = cs2->get_radius(); float height = cs2->get_height(); @@ -3515,9 +3515,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; float radius = cs2->get_radius(); float height = cs2->get_height(); @@ -3576,9 +3576,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref ps = s; + Ref ps = s; Plane p = ps->get_plane(); Vector points; @@ -3607,9 +3607,9 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(points); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Vector points = Object::cast_to(*s)->get_points(); + Vector points = Object::cast_to(*s)->get_points(); if (points.size() > 3) { @@ -3630,17 +3630,17 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref cs2 = s; + Ref cs2 = s; Ref mesh = cs2->get_debug_mesh(); p_gizmo->add_mesh(mesh, false, Ref(), material); p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines()); } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { - Ref rs = s; + Ref rs = s; Vector points; points.push_back(Vector3()); @@ -3663,7 +3663,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { ///// -CollisionPolygonSpatialGizmoPlugin::CollisionPolygonSpatialGizmoPlugin() { +CollisionPolygonNode3DGizmoPlugin::CollisionPolygonNode3DGizmoPlugin() { const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); const float gizmo_value = gizmo_color.get_v(); @@ -3671,21 +3671,21 @@ CollisionPolygonSpatialGizmoPlugin::CollisionPolygonSpatialGizmoPlugin() { create_material("shape_material_disabled", gizmo_color_disabled); } -bool CollisionPolygonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool CollisionPolygonNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String CollisionPolygonSpatialGizmoPlugin::get_name() const { - return "CollisionPolygon"; +String CollisionPolygonNode3DGizmoPlugin::get_name() const { + return "CollisionPolygon3D"; } -int CollisionPolygonSpatialGizmoPlugin::get_priority() const { +int CollisionPolygonNode3DGizmoPlugin::get_priority() const { return -1; } -void CollisionPolygonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void CollisionPolygonNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - CollisionPolygon *polygon = Object::cast_to(p_gizmo->get_spatial_node()); + CollisionPolygon3D *polygon = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -3713,28 +3713,28 @@ void CollisionPolygonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// -NavigationMeshSpatialGizmoPlugin::NavigationMeshSpatialGizmoPlugin() { +NavigationMeshNode3DGizmoPlugin::NavigationMeshNode3DGizmoPlugin() { create_material("navigation_edge_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1))); create_material("navigation_edge_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7))); create_material("navigation_solid_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4))); create_material("navigation_solid_material_disabled", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid_disabled", Color(0.7, 0.7, 0.7, 0.4))); } -bool NavigationMeshSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool NavigationMeshNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String NavigationMeshSpatialGizmoPlugin::get_name() const { +String NavigationMeshNode3DGizmoPlugin::get_name() const { return "NavigationRegion"; } -int NavigationMeshSpatialGizmoPlugin::get_priority() const { +int NavigationMeshNode3DGizmoPlugin::get_priority() const { return -1; } -void NavigationMeshSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void NavigationMeshNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - NavigationRegion *navmesh = Object::cast_to(p_gizmo->get_spatial_node()); + NavigationRegion3D *navmesh = Object::cast_to(p_gizmo->get_spatial_node()); Ref edge_material = get_material("navigation_edge_material", p_gizmo); Ref edge_material_disabled = get_material("navigation_edge_material_disabled", p_gizmo); @@ -4078,37 +4078,37 @@ void JointGizmosDrawer::draw_cone(const Transform &p_offset, const Basis &p_base //// -JointSpatialGizmoPlugin::JointSpatialGizmoPlugin() { +JointNode3DGizmoPlugin::JointNode3DGizmoPlugin() { create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1))); create_material("joint_body_a_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1))); create_material("joint_body_b_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1))); } -bool JointSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != NULL; +bool JointNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) != NULL; } -String JointSpatialGizmoPlugin::get_name() const { +String JointNode3DGizmoPlugin::get_name() const { return "Joints"; } -int JointSpatialGizmoPlugin::get_priority() const { +int JointNode3DGizmoPlugin::get_priority() const { return -1; } -void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - Joint *joint = Object::cast_to(p_gizmo->get_spatial_node()); +void JointNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + Joint3D *joint = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); - Spatial *node_body_a = NULL; + Node3D *node_body_a = NULL; if (!joint->get_node_a().is_empty()) { - node_body_a = Object::cast_to(joint->get_node(joint->get_node_a())); + node_body_a = Object::cast_to(joint->get_node(joint->get_node_a())); } - Spatial *node_body_b = NULL; + Node3D *node_body_b = NULL; if (!joint->get_node_b().is_empty()) { - node_body_b = Object::cast_to(joint->get_node(joint->get_node_b())); + node_body_b = Object::cast_to(joint->get_node(joint->get_node_b())); } if (!node_body_a && !node_body_b) { @@ -4123,13 +4123,13 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Vector body_a_points; Vector body_b_points; - if (Object::cast_to(joint)) { + if (Object::cast_to(joint)) { CreatePinJointGizmo(Transform(), points); p_gizmo->add_collision_segments(points); p_gizmo->add_lines(points, common_material); } - HingeJoint *hinge = Object::cast_to(joint); + HingeJoint3D *hinge = Object::cast_to(joint); if (hinge) { CreateHingeJointGizmo( @@ -4137,9 +4137,9 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { hinge->get_global_transform(), node_body_a ? node_body_a->get_global_transform() : Transform(), node_body_b ? node_body_b->get_global_transform() : Transform(), - hinge->get_param(HingeJoint::PARAM_LIMIT_LOWER), - hinge->get_param(HingeJoint::PARAM_LIMIT_UPPER), - hinge->get_flag(HingeJoint::FLAG_USE_LIMIT), + hinge->get_param(HingeJoint3D::PARAM_LIMIT_LOWER), + hinge->get_param(HingeJoint3D::PARAM_LIMIT_UPPER), + hinge->get_flag(HingeJoint3D::FLAG_USE_LIMIT), points, node_body_a ? &body_a_points : NULL, node_body_b ? &body_b_points : NULL); @@ -4153,7 +4153,7 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_lines(body_b_points, body_b_material); } - SliderJoint *slider = Object::cast_to(joint); + SliderJoint3D *slider = Object::cast_to(joint); if (slider) { CreateSliderJointGizmo( @@ -4161,10 +4161,10 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { slider->get_global_transform(), node_body_a ? node_body_a->get_global_transform() : Transform(), node_body_b ? node_body_b->get_global_transform() : Transform(), - slider->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER), - slider->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER), - slider->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER), - slider->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER), + slider->get_param(SliderJoint3D::PARAM_ANGULAR_LIMIT_LOWER), + slider->get_param(SliderJoint3D::PARAM_ANGULAR_LIMIT_UPPER), + slider->get_param(SliderJoint3D::PARAM_LINEAR_LIMIT_LOWER), + slider->get_param(SliderJoint3D::PARAM_LINEAR_LIMIT_UPPER), points, node_body_a ? &body_a_points : NULL, node_body_b ? &body_b_points : NULL); @@ -4178,7 +4178,7 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_lines(body_b_points, body_b_material); } - ConeTwistJoint *cone = Object::cast_to(joint); + ConeTwistJoint3D *cone = Object::cast_to(joint); if (cone) { CreateConeTwistJointGizmo( @@ -4186,8 +4186,8 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { cone->get_global_transform(), node_body_a ? node_body_a->get_global_transform() : Transform(), node_body_b ? node_body_b->get_global_transform() : Transform(), - cone->get_param(ConeTwistJoint::PARAM_SWING_SPAN), - cone->get_param(ConeTwistJoint::PARAM_TWIST_SPAN), + cone->get_param(ConeTwistJoint3D::PARAM_SWING_SPAN), + cone->get_param(ConeTwistJoint3D::PARAM_TWIST_SPAN), node_body_a ? &body_a_points : NULL, node_body_b ? &body_b_points : NULL); @@ -4198,7 +4198,7 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_lines(body_b_points, body_b_material); } - Generic6DOFJoint *gen = Object::cast_to(joint); + Generic6DOFJoint3D *gen = Object::cast_to(joint); if (gen) { CreateGeneric6DOFJointGizmo( @@ -4207,26 +4207,26 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { node_body_a ? node_body_a->get_global_transform() : Transform(), node_body_b ? node_body_b->get_global_transform() : Transform(), - gen->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - gen->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - gen->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - gen->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - gen->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - gen->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), - - gen->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - gen->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - gen->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - gen->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - gen->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - gen->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), - - gen->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT), - gen->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT), - gen->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT), - gen->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT), - gen->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT), - gen->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT), + gen->get_param_x(Generic6DOFJoint3D::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_x(Generic6DOFJoint3D::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_x(Generic6DOFJoint3D::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_x(Generic6DOFJoint3D::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_x(Generic6DOFJoint3D::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_x(Generic6DOFJoint3D::FLAG_ENABLE_LINEAR_LIMIT), + + gen->get_param_y(Generic6DOFJoint3D::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_y(Generic6DOFJoint3D::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_y(Generic6DOFJoint3D::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_y(Generic6DOFJoint3D::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_y(Generic6DOFJoint3D::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_y(Generic6DOFJoint3D::FLAG_ENABLE_LINEAR_LIMIT), + + gen->get_param_z(Generic6DOFJoint3D::PARAM_ANGULAR_LOWER_LIMIT), + gen->get_param_z(Generic6DOFJoint3D::PARAM_ANGULAR_UPPER_LIMIT), + gen->get_param_z(Generic6DOFJoint3D::PARAM_LINEAR_LOWER_LIMIT), + gen->get_param_z(Generic6DOFJoint3D::PARAM_LINEAR_UPPER_LIMIT), + gen->get_flag_z(Generic6DOFJoint3D::FLAG_ENABLE_ANGULAR_LIMIT), + gen->get_flag_z(Generic6DOFJoint3D::FLAG_ENABLE_LINEAR_LIMIT), points, node_body_a ? &body_a_points : NULL, @@ -4242,7 +4242,7 @@ void JointSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } } -void JointSpatialGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vector &r_cursor_points) { +void JointNode3DGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vector &r_cursor_points) { float cs = 0.25; r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin); @@ -4253,7 +4253,7 @@ void JointSpatialGizmoPlugin::CreatePinJointGizmo(const Transform &p_offset, Vec r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin); } -void JointSpatialGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector &r_common_points, Vector *r_body_a_points, Vector *r_body_b_points) { +void JointNode3DGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector &r_common_points, Vector *r_body_a_points, Vector *r_body_b_points) { r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin); r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin); @@ -4285,7 +4285,7 @@ void JointSpatialGizmoPlugin::CreateHingeJointGizmo(const Transform &p_offset, c } } -void JointSpatialGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector &r_points, Vector *r_body_a_points, Vector *r_body_b_points) { +void JointNode3DGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector &r_points, Vector *r_body_a_points, Vector *r_body_b_points) { p_linear_limit_lower = -p_linear_limit_lower; p_linear_limit_upper = -p_linear_limit_upper; @@ -4345,7 +4345,7 @@ void JointSpatialGizmoPlugin::CreateSliderJointGizmo(const Transform &p_offset, true); } -void JointSpatialGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector *r_body_a_points, Vector *r_body_b_points) { +void JointNode3DGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector *r_body_a_points, Vector *r_body_b_points) { if (r_body_a_points) JointGizmosDrawer::draw_cone( @@ -4364,7 +4364,7 @@ void JointSpatialGizmoPlugin::CreateConeTwistJointGizmo(const Transform &p_offse *r_body_b_points); } -void JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( +void JointNode3DGizmoPlugin::CreateGeneric6DOFJointGizmo( const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index b786aa2b50..86926b38d2 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -32,328 +32,328 @@ #define SPATIAL_EDITOR_GIZMOS_H #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" -class Camera; +class Camera3D; -class LightSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class LightNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(LightSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(LightNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - void redraw(EditorSpatialGizmo *p_gizmo); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorNode3DGizmo *p_gizmo); - LightSpatialGizmoPlugin(); + LightNode3DGizmoPlugin(); }; -class AudioStreamPlayer3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class AudioStreamPlayer3DNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(AudioStreamPlayer3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(AudioStreamPlayer3DNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - void redraw(EditorSpatialGizmo *p_gizmo); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorNode3DGizmo *p_gizmo); - AudioStreamPlayer3DSpatialGizmoPlugin(); + AudioStreamPlayer3DNode3DGizmoPlugin(); }; -class CameraSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class CameraNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(CameraSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(CameraNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - void redraw(EditorSpatialGizmo *p_gizmo); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + void redraw(EditorNode3DGizmo *p_gizmo); - CameraSpatialGizmoPlugin(); + CameraNode3DGizmoPlugin(); }; -class MeshInstanceSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class MeshInstanceNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(MeshInstanceSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(MeshInstanceNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool can_be_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - MeshInstanceSpatialGizmoPlugin(); + MeshInstanceNode3DGizmoPlugin(); }; -class Sprite3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class Sprite3DNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(Sprite3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(Sprite3DNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool can_be_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - Sprite3DSpatialGizmoPlugin(); + Sprite3DNode3DGizmoPlugin(); }; -class Position3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class Position3DNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(Position3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(Position3DNode3DGizmoPlugin, EditorNode3DGizmoPlugin); Ref pos3d_mesh; Vector cursor_points; public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - Position3DSpatialGizmoPlugin(); + Position3DNode3DGizmoPlugin(); }; -class SkeletonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class SkeletonNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SkeletonSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(SkeletonNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - SkeletonSpatialGizmoPlugin(); + SkeletonNode3DGizmoPlugin(); }; -class PhysicalBoneSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class PhysicalBoneNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(PhysicalBoneSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(PhysicalBoneNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - PhysicalBoneSpatialGizmoPlugin(); + PhysicalBoneNode3DGizmoPlugin(); }; -class RayCastSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class RayCastNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(RayCastSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(RayCastNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - RayCastSpatialGizmoPlugin(); + RayCastNode3DGizmoPlugin(); }; -class SpringArmSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class SpringArmNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SpringArmSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(SpringArmNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - SpringArmSpatialGizmoPlugin(); + SpringArmNode3DGizmoPlugin(); }; -class VehicleWheelSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class VehicleWheelNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(VehicleWheelSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(VehicleWheelNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - VehicleWheelSpatialGizmoPlugin(); + VehicleWheelNode3DGizmoPlugin(); }; -class SoftBodySpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class SoftBodyNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SoftBodySpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(SoftBodyNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool is_selectable_when_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); - bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const; + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const; - SoftBodySpatialGizmoPlugin(); + SoftBodyNode3DGizmoPlugin(); }; -class VisibilityNotifierGizmoPlugin : public EditorSpatialGizmoPlugin { +class VisibilityNotifierGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(VisibilityNotifierGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(VisibilityNotifierGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); VisibilityNotifierGizmoPlugin(); }; -class CPUParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(CPUParticlesGizmoPlugin, EditorSpatialGizmoPlugin); +class CPUParticlesGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(CPUParticlesGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool is_selectable_when_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); CPUParticlesGizmoPlugin(); }; -class ParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { +class ParticlesGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(ParticlesGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(ParticlesGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool is_selectable_when_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); ParticlesGizmoPlugin(); }; -class ReflectionProbeGizmoPlugin : public EditorSpatialGizmoPlugin { +class ReflectionProbeGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(ReflectionProbeGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(ReflectionProbeGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); ReflectionProbeGizmoPlugin(); }; -class GIProbeGizmoPlugin : public EditorSpatialGizmoPlugin { +class GIProbeGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(GIProbeGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(GIProbeGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); GIProbeGizmoPlugin(); }; #if 0 -class BakedIndirectLightGizmoPlugin : public EditorSpatialGizmoPlugin { +class BakedIndirectLightGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(BakedIndirectLightGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(BakedIndirectLightGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Spatial *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); BakedIndirectLightGizmoPlugin(); }; #endif -class CollisionShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class CollisionShapeNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(CollisionShapeSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(CollisionShapeNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - CollisionShapeSpatialGizmoPlugin(); + CollisionShapeNode3DGizmoPlugin(); }; -class CollisionPolygonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(CollisionPolygonSpatialGizmoPlugin, EditorSpatialGizmoPlugin); +class CollisionPolygonNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(CollisionPolygonNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); - CollisionPolygonSpatialGizmoPlugin(); + void redraw(EditorNode3DGizmo *p_gizmo); + CollisionPolygonNode3DGizmoPlugin(); }; -class NavigationMeshSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class NavigationMeshNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(NavigationMeshSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(NavigationMeshNode3DGizmoPlugin, EditorNode3DGizmoPlugin); struct _EdgeKey { @@ -364,12 +364,12 @@ class NavigationMeshSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { }; public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - NavigationMeshSpatialGizmoPlugin(); + NavigationMeshNode3DGizmoPlugin(); }; class JointGizmosDrawer { @@ -387,15 +387,15 @@ public: static void draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector &r_points); }; -class JointSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class JointNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(JointSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(JointNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); static void CreatePinJointGizmo(const Transform &p_offset, Vector &r_cursor_points); static void CreateHingeJointGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector &r_common_points, Vector *r_body_a_points, Vector *r_body_b_points); @@ -428,7 +428,7 @@ public: Vector *r_body_a_points, Vector *r_body_b_points); - JointSpatialGizmoPlugin(); + JointNode3DGizmoPlugin(); }; #endif // SPATIAL_EDITOR_GIZMOS_H diff --git a/main/tests/test_gui.cpp b/main/tests/test_gui.cpp index 5ad1b2fe31..c5c8917a51 100644 --- a/main/tests/test_gui.cpp +++ b/main/tests/test_gui.cpp @@ -35,7 +35,7 @@ #include "core/io/image_loader.h" #include "core/os/os.h" #include "core/print_string.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/gui/button.h" #include "scene/gui/control.h" #include "scene/gui/label.h" @@ -53,7 +53,7 @@ #include "scene/gui/tree.h" #include "scene/main/scene_tree.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" #include "scene/main/window.h" namespace TestGUI { diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp index 682a7e33c8..1482fe99eb 100644 --- a/modules/assimp/editor_scene_importer_assimp.cpp +++ b/modules/assimp/editor_scene_importer_assimp.cpp @@ -32,9 +32,9 @@ #include "core/io/image_loader.h" #include "editor/import/resource_importer_scene.h" #include "import_utils.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/main/node.h" #include "scene/resources/material.h" #include "scene/resources/surface_tool.h" @@ -297,7 +297,7 @@ aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiStr return NULL; } -Spatial * +Node3D * EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights) { ERR_FAIL_COND_V(scene == NULL, NULL); @@ -343,7 +343,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, String node_name = AssimpUtils::get_assimp_string(element_assimp_node->mName); //print_verbose("node: " + node_name); - Spatial *spatial = NULL; + Node3D *spatial = NULL; Transform transform = AssimpUtils::assimp_matrix_transform(element_assimp_node->mTransformation); // retrieve this node bone @@ -356,7 +356,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } else if (state.armature_nodes.find(element_assimp_node)) { // create skeleton print_verbose("Making skeleton: " + node_name); - Skeleton *skeleton = memnew(Skeleton); + Skeleton3D *skeleton = memnew(Skeleton3D); spatial = skeleton; if (!state.armature_skeletons.has(element_assimp_node)) { state.armature_skeletons.insert(element_assimp_node, skeleton); @@ -364,7 +364,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } else if (bone != NULL) { continue; } else { - spatial = memnew(Spatial); + spatial = memnew(Node3D); } ERR_CONTINUE_MSG(spatial == NULL, "FBX Import - are we out of ram?"); @@ -381,11 +381,11 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, // flat node map parent lookup tool state.flat_node_map.insert(element_assimp_node, spatial); - Map::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node); + Map::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node); // note: this always fails on the root node :) keep that in mind this is by design if (parent_lookup) { - Spatial *parent_node = parent_lookup->value(); + Node3D *parent_node = parent_lookup->value(); ERR_FAIL_COND_V_MSG(parent_node == NULL, state.root, "Parent node invalid even though lookup successful, out of ram?"); @@ -435,7 +435,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, String bone_name = AssimpUtils::get_anim_string_from_assimp(bone->mName); ERR_CONTINUE_MSG(armature_for_bone == NULL, "Armature for bone invalid: " + bone_name); - Skeleton *skeleton = state.armature_skeletons[armature_for_bone]; + Skeleton3D *skeleton = state.armature_skeletons[armature_for_bone]; state.skeleton_bone_map[bone] = skeleton; @@ -464,11 +464,11 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, print_verbose("generating mesh phase from skeletal mesh"); - List cleanup_template_nodes; + List cleanup_template_nodes; - for (Map::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { + for (Map::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { const aiNode *assimp_node = key_value_pair->key(); - Spatial *mesh_template = key_value_pair->value(); + Node3D *mesh_template = key_value_pair->value(); ERR_CONTINUE(assimp_node == NULL); ERR_CONTINUE(mesh_template == NULL); @@ -488,7 +488,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, Transform node_transform = AssimpUtils::assimp_matrix_transform(assimp_node->mTransformation); if (assimp_node->mNumMeshes > 0) { - MeshInstance *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform); + MeshInstance3D *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform); if (mesh) { parent_node->remove_child(mesh_template); @@ -522,7 +522,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } } - for (List::Element *element = cleanup_template_nodes.front(); element; element = element->next()) { + for (List::Element *element = cleanup_template_nodes.front(); element; element = element->next()) { if (element->get()) { memdelete(element->get()); } @@ -559,7 +559,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, int anim_fps, Ref animation, float ticks_per_second, - Skeleton *skeleton, const NodePath &node_path, + Skeleton3D *skeleton, const NodePath &node_path, const String &node_name, aiBone *track_bone) { const aiNodeAnim *assimp_track = assimp_anim->mChannels[track_id]; //make transform track @@ -652,9 +652,9 @@ void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, cons // I really do not like this but need to figure out a better way of removing it later. Node *EditorSceneImporterAssimp::get_node_by_name(ImportState &state, String name) { - for (Map::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { + for (Map::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { const aiNode *assimp_node = key_value_pair->key(); - Spatial *node = key_value_pair->value(); + Node3D *node = key_value_pair->value(); String node_name = AssimpUtils::get_assimp_string(assimp_node->mName); if (name == node_name && node) { @@ -747,7 +747,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim continue; //do not bother } - Skeleton *skeleton = NULL; + Skeleton3D *skeleton = NULL; NodePath node_path; aiBone *bone = NULL; @@ -805,7 +805,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim Node *item = get_node_by_name(state, mesh_name); ERR_CONTINUE_MSG(!item, "failed to look up node by name"); - const MeshInstance *mesh_instance = Object::cast_to(item); + const MeshInstance3D *mesh_instance = Object::cast_to(item); ERR_CONTINUE(mesh_instance == NULL); String base_path = state.root->get_path_to(mesh_instance); @@ -842,7 +842,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim Ref EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &state, const Vector &p_surface_indices, const aiNode *assimp_node, Ref &skin, - Skeleton *&skeleton_assigned) { + Skeleton3D *&skeleton_assigned) { Ref mesh; mesh.instance(); @@ -1299,7 +1299,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat /** * Create a new mesh for the node supplied */ -MeshInstance * +MeshInstance3D * EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform) { /* MESH NODE */ Ref mesh; @@ -1325,7 +1325,7 @@ EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_ mesh_key += itos(surface_indices[i]); } - Skeleton *skeleton = NULL; + Skeleton3D *skeleton = NULL; aiNode *armature = NULL; if (!state.mesh_cache.has(mesh_key)) { @@ -1333,7 +1333,7 @@ EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_ state.mesh_cache[mesh_key] = mesh; } - MeshInstance *mesh_node = memnew(MeshInstance); + MeshInstance3D *mesh_node = memnew(MeshInstance3D); mesh = state.mesh_cache[mesh_key]; mesh_node->set_mesh(mesh); @@ -1407,20 +1407,20 @@ EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_ * Create a light for the scene * Automatically caches lights for lookup later */ -Spatial *EditorSceneImporterAssimp::create_light( +Node3D *EditorSceneImporterAssimp::create_light( ImportState &state, const String &node_name, Transform &look_at_transform) { - Light *light = NULL; + Light3D *light = NULL; aiLight *assimp_light = state.assimp_scene->mLights[state.light_cache[node_name]]; ERR_FAIL_COND_V(!assimp_light, NULL); if (assimp_light->mType == aiLightSource_DIRECTIONAL) { - light = memnew(DirectionalLight); + light = memnew(DirectionalLight3D); } else if (assimp_light->mType == aiLightSource_POINT) { - light = memnew(OmniLight); + light = memnew(OmniLight3D); } else if (assimp_light->mType == aiLightSource_SPOT) { - light = memnew(SpotLight); + light = memnew(SpotLight3D); } ERR_FAIL_COND_V(light == NULL, NULL); @@ -1453,14 +1453,14 @@ Spatial *EditorSceneImporterAssimp::create_light( /** * Create camera for the scene */ -Spatial *EditorSceneImporterAssimp::create_camera( +Node3D *EditorSceneImporterAssimp::create_camera( ImportState &state, const String &node_name, Transform &look_at_transform) { aiCamera *camera = state.assimp_scene->mCameras[state.camera_cache[node_name]]; ERR_FAIL_COND_V(!camera, NULL); - Camera *camera_node = memnew(Camera); + Camera3D *camera_node = memnew(Camera3D); ERR_FAIL_COND_V(!camera_node, NULL); float near = camera->mClipPlaneNear; if (Math::is_equal_approx(near, 0.0f)) { diff --git a/modules/assimp/editor_scene_importer_assimp.h b/modules/assimp/editor_scene_importer_assimp.h index 4cd50e7681..5059138b64 100644 --- a/modules/assimp/editor_scene_importer_assimp.h +++ b/modules/assimp/editor_scene_importer_assimp.h @@ -37,9 +37,9 @@ #include "core/vector.h" #include "editor/import/resource_importer_scene.h" #include "editor/project_settings_editor.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/surface_tool.h" @@ -90,29 +90,29 @@ private: Ref _generate_mesh_from_surface_indices(ImportState &state, const Vector &p_surface_indices, const aiNode *assimp_node, Ref &skin, - Skeleton *&skeleton_assigned); + Skeleton3D *&skeleton_assigned); // simple object creation functions - Spatial *create_light(ImportState &state, + Node3D *create_light(ImportState &state, const String &node_name, Transform &look_at_transform); - Spatial *create_camera( + Node3D *create_camera( ImportState &state, const String &node_name, Transform &look_at_transform); // non recursive - linear so must not use recursive arguments - MeshInstance *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform); + MeshInstance3D *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform); // recursive node generator void _generate_node(ImportState &state, const aiNode *assimp_node); void _insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, int anim_fps, Ref animation, float ticks_per_second, - Skeleton *skeleton, const NodePath &node_path, + Skeleton3D *skeleton, const NodePath &node_path, const String &node_name, aiBone *track_bone); void _import_animation(ImportState &state, int p_animation_index, int p_bake_fps); Node *get_node_by_name(ImportState &state, String name); aiBone *get_bone_from_stack(ImportState &state, aiString name); - Spatial *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights); + Node3D *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights); template T _interpolate_track(const Vector &p_times, const Vector &p_values, float p_time, AssetImportAnimation::Interpolation p_interp); diff --git a/modules/assimp/import_state.h b/modules/assimp/import_state.h index fbbbe23399..b16366b38c 100644 --- a/modules/assimp/import_state.h +++ b/modules/assimp/import_state.h @@ -36,9 +36,9 @@ #include "core/vector.h" #include "editor/import/resource_importer_scene.h" #include "editor/project_settings_editor.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/surface_tool.h" @@ -57,7 +57,7 @@ namespace AssimpImporter { struct ImportState { String path; - Spatial *root; + Node3D *root; const aiScene *assimp_scene; uint32_t max_bone_weights; @@ -74,15 +74,15 @@ struct ImportState { // Generation 3 - determinisitic iteration // to lower potential recursion errors List nodes; - Map flat_node_map; + Map flat_node_map; AnimationPlayer *animation_player; // Generation 3 - deterministic armatures // list of armature nodes - flat and simple to parse // assimp node, node in godot List armature_nodes; - Map armature_skeletons; - Map skeleton_bone_map; + Map armature_skeletons; + Map skeleton_bone_map; // Generation 3 - deterministic bone handling // bones from the stack are popped when found // this means we can detect @@ -103,8 +103,8 @@ struct RecursiveState { RecursiveState() {} // do not construct :) RecursiveState( Transform &_node_transform, - Skeleton *_skeleton, - Spatial *_new_node, + Skeleton3D *_skeleton, + Node3D *_new_node, String &_node_name, aiNode *_assimp_node, Node *_parent_node, @@ -118,8 +118,8 @@ struct RecursiveState { bone(_bone) {} Transform node_transform; - Skeleton *skeleton = NULL; - Spatial *new_node = NULL; + Skeleton3D *skeleton = NULL; + Node3D *new_node = NULL; String node_name; aiNode *assimp_node = NULL; Node *parent_node = NULL; diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index f21206dd0d..fb36a0d3e1 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -32,7 +32,7 @@ #include "bullet_types_converter.h" #include "bullet_utilities.h" -#include "scene/3d/soft_body.h" +#include "scene/3d/soft_body_3d.h" #include "space_bullet.h" SoftBodyBullet::SoftBodyBullet() : diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index 1b63bccb06..4b27eea019 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -32,7 +32,7 @@ /////////// -CSGShapeSpatialGizmoPlugin::CSGShapeSpatialGizmoPlugin() { +CSGShapeNode3DGizmoPlugin::CSGShapeNode3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15)); create_material("shape_union_material", gizmo_color); @@ -49,46 +49,46 @@ CSGShapeSpatialGizmoPlugin::CSGShapeSpatialGizmoPlugin() { create_handle_material("handles"); } -String CSGShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String CSGShapeNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { - CSGShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CSGShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { return "Radius"; } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { static const char *hname[3] = { "Width", "Height", "Depth" }; return hname[p_idx]; } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { return p_idx == 0 ? "Radius" : "Height"; } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { return p_idx == 0 ? "InnerRadius" : "OuterRadius"; } return ""; } -Variant CSGShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant CSGShapeNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { - CSGShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CSGShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGSphere *s = Object::cast_to(cs); + CSGSphere3D *s = Object::cast_to(cs); return s->get_radius(); } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGBox *s = Object::cast_to(cs); + CSGBox3D *s = Object::cast_to(cs); switch (p_idx) { case 0: return s->get_width(); case 1: return s->get_height(); @@ -96,23 +96,23 @@ Variant CSGShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo } } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGCylinder *s = Object::cast_to(cs); + CSGCylinder3D *s = Object::cast_to(cs); return p_idx == 0 ? s->get_radius() : s->get_height(); } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGTorus *s = Object::cast_to(cs); + CSGTorus3D *s = Object::cast_to(cs); return p_idx == 0 ? s->get_inner_radius() : s->get_outer_radius(); } return Variant(); } -void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void CSGShapeNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { - CSGShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CSGShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = cs->get_global_transform(); //gt.orthonormalize(); @@ -123,15 +123,15 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGSphere *s = Object::cast_to(cs); + CSGSphere3D *s = Object::cast_to(cs); Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb); float d = ra.x; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -140,17 +140,17 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i s->set_radius(d); } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGBox *s = Object::cast_to(cs); + CSGBox3D *s = Object::cast_to(cs); Vector3 axis; axis[p_idx] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -163,17 +163,17 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i } } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGCylinder *s = Object::cast_to(cs); + CSGCylinder3D *s = Object::cast_to(cs); Vector3 axis; axis[p_idx == 0 ? 0 : 1] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -185,17 +185,17 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i s->set_height(d * 2.0); } - if (Object::cast_to(cs)) { + if (Object::cast_to(cs)) { - CSGTorus *s = Object::cast_to(cs); + CSGTorus3D *s = Object::cast_to(cs); Vector3 axis; axis[0] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } if (d < 0.001) @@ -207,26 +207,26 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i s->set_outer_radius(d); } } -void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CSGShapeNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - CSGShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CSGShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); - if (Object::cast_to(cs)) { - CSGSphere *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGSphere3D *s = Object::cast_to(cs); if (p_cancel) { s->set_radius(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Sphere Shape Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); ur->add_undo_method(s, "set_radius", p_restore); ur->commit_action(); } - if (Object::cast_to(cs)) { - CSGBox *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGBox3D *s = Object::cast_to(cs); if (p_cancel) { switch (p_idx) { case 0: s->set_width(p_restore); break; @@ -236,7 +236,7 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Box Shape Extents")); static const char *method[3] = { "set_width", "set_height", "set_depth" }; float current = 0; @@ -251,8 +251,8 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } - if (Object::cast_to(cs)) { - CSGCylinder *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGCylinder3D *s = Object::cast_to(cs); if (p_cancel) { if (p_idx == 0) s->set_radius(p_restore); @@ -261,7 +261,7 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Cylinder Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); @@ -275,8 +275,8 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } - if (Object::cast_to(cs)) { - CSGTorus *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGTorus3D *s = Object::cast_to(cs); if (p_cancel) { if (p_idx == 0) s->set_inner_radius(p_restore); @@ -285,7 +285,7 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Torus Inner Radius")); ur->add_do_method(s, "set_inner_radius", s->get_inner_radius()); @@ -299,37 +299,37 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } } -bool CSGShapeSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial); +bool CSGShapeNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial) || Object::cast_to(p_spatial); } -String CSGShapeSpatialGizmoPlugin::get_name() const { +String CSGShapeNode3DGizmoPlugin::get_name() const { return "CSGShapes"; } -int CSGShapeSpatialGizmoPlugin::get_priority() const { +int CSGShapeNode3DGizmoPlugin::get_priority() const { return -1; } -bool CSGShapeSpatialGizmoPlugin::is_selectable_when_hidden() const { +bool CSGShapeNode3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { +void CSGShapeNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - CSGShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); + CSGShape3D *cs = Object::cast_to(p_gizmo->get_spatial_node()); p_gizmo->clear(); Ref material; switch (cs->get_operation()) { - case CSGShape::OPERATION_UNION: + case CSGShape3D::OPERATION_UNION: material = get_material("shape_union_material", p_gizmo); break; - case CSGShape::OPERATION_INTERSECTION: + case CSGShape3D::OPERATION_INTERSECTION: material = get_material("shape_intersection_material", p_gizmo); break; - case CSGShape::OPERATION_SUBTRACTION: + case CSGShape3D::OPERATION_SUBTRACTION: material = get_material("shape_subtraction_material", p_gizmo); break; } @@ -366,13 +366,13 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Ref solid_material; switch (cs->get_operation()) { - case CSGShape::OPERATION_UNION: + case CSGShape3D::OPERATION_UNION: solid_material = get_material("shape_union_solid_material", p_gizmo); break; - case CSGShape::OPERATION_INTERSECTION: + case CSGShape3D::OPERATION_INTERSECTION: solid_material = get_material("shape_intersection_solid_material", p_gizmo); break; - case CSGShape::OPERATION_SUBTRACTION: + case CSGShape3D::OPERATION_SUBTRACTION: solid_material = get_material("shape_subtraction_solid_material", p_gizmo); break; } @@ -380,8 +380,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_mesh(mesh, false, Ref(), solid_material); } - if (Object::cast_to(cs)) { - CSGSphere *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGSphere3D *s = Object::cast_to(cs); float r = s->get_radius(); Vector handles; @@ -389,8 +389,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(cs)) { - CSGBox *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGBox3D *s = Object::cast_to(cs); Vector handles; handles.push_back(Vector3(s->get_width() * 0.5, 0, 0)); @@ -399,8 +399,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(cs)) { - CSGCylinder *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGCylinder3D *s = Object::cast_to(cs); Vector handles; handles.push_back(Vector3(s->get_radius(), 0, 0)); @@ -408,8 +408,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to(cs)) { - CSGTorus *s = Object::cast_to(cs); + if (Object::cast_to(cs)) { + CSGTorus3D *s = Object::cast_to(cs); Vector handles; handles.push_back(Vector3(s->get_inner_radius(), 0, 0)); @@ -419,6 +419,6 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } EditorPluginCSG::EditorPluginCSG(EditorNode *p_editor) { - Ref gizmo_plugin = Ref(memnew(CSGShapeSpatialGizmoPlugin)); - SpatialEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); + Ref gizmo_plugin = Ref(memnew(CSGShapeNode3DGizmoPlugin)); + Node3DEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); } diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h index 966b654802..cca27a4629 100644 --- a/modules/csg/csg_gizmos.h +++ b/modules/csg/csg_gizmos.h @@ -35,23 +35,23 @@ #include "editor/editor_plugin.h" #include "editor/spatial_editor_gizmos.h" -class CSGShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { +class CSGShapeNode3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(CSGShapeSpatialGizmoPlugin, EditorSpatialGizmoPlugin); + GDCLASS(CSGShapeNode3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool is_selectable_when_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); - CSGShapeSpatialGizmoPlugin(); + CSGShapeNode3DGizmoPlugin(); }; class EditorPluginCSG : public EditorPlugin { diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 746c66bdf1..d052eba41c 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -29,9 +29,9 @@ /*************************************************************************/ #include "csg_shape.h" -#include "scene/3d/path.h" +#include "scene/3d/path_3d.h" -void CSGShape::set_use_collision(bool p_enable) { +void CSGShape3D::set_use_collision(bool p_enable) { if (use_collision == p_enable) return; @@ -59,23 +59,23 @@ void CSGShape::set_use_collision(bool p_enable) { _change_notify(); } -bool CSGShape::is_using_collision() const { +bool CSGShape3D::is_using_collision() const { return use_collision; } -void CSGShape::set_collision_layer(uint32_t p_layer) { +void CSGShape3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; if (root_collision_instance.is_valid()) { PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); } } -uint32_t CSGShape::get_collision_layer() const { +uint32_t CSGShape3D::get_collision_layer() const { return collision_layer; } -void CSGShape::set_collision_mask(uint32_t p_mask) { +void CSGShape3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; if (root_collision_instance.is_valid()) { @@ -83,12 +83,12 @@ void CSGShape::set_collision_mask(uint32_t p_mask) { } } -uint32_t CSGShape::get_collision_mask() const { +uint32_t CSGShape3D::get_collision_mask() const { return collision_mask; } -void CSGShape::set_collision_mask_bit(int p_bit, bool p_value) { +void CSGShape3D::set_collision_mask_bit(int p_bit, bool p_value) { uint32_t mask = get_collision_mask(); if (p_value) @@ -98,12 +98,12 @@ void CSGShape::set_collision_mask_bit(int p_bit, bool p_value) { set_collision_mask(mask); } -bool CSGShape::get_collision_mask_bit(int p_bit) const { +bool CSGShape3D::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } -void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) { +void CSGShape3D::set_collision_layer_bit(int p_bit, bool p_value) { uint32_t mask = get_collision_layer(); if (p_value) @@ -113,25 +113,25 @@ void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) { set_collision_layer(mask); } -bool CSGShape::get_collision_layer_bit(int p_bit) const { +bool CSGShape3D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } -bool CSGShape::is_root_shape() const { +bool CSGShape3D::is_root_shape() const { return !parent; } -void CSGShape::set_snap(float p_snap) { +void CSGShape3D::set_snap(float p_snap) { snap = p_snap; } -float CSGShape::get_snap() const { +float CSGShape3D::get_snap() const { return snap; } -void CSGShape::_make_dirty() { +void CSGShape3D::_make_dirty() { if (!is_inside_tree()) return; @@ -150,7 +150,7 @@ void CSGShape::_make_dirty() { } } -CSGBrush *CSGShape::_get_brush() { +CSGBrush *CSGShape3D::_get_brush() { if (dirty) { if (brush) { @@ -162,7 +162,7 @@ CSGBrush *CSGShape::_get_brush() { for (int i = 0; i < get_child_count(); i++) { - CSGShape *child = Object::cast_to(get_child(i)); + CSGShape3D *child = Object::cast_to(get_child(i)); if (!child) continue; if (!child->is_visible_in_tree()) @@ -185,9 +185,9 @@ CSGBrush *CSGShape::_get_brush() { CSGBrushOperation bop; switch (child->get_operation()) { - case CSGShape::OPERATION_UNION: bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); break; - case CSGShape::OPERATION_INTERSECTION: bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); break; - case CSGShape::OPERATION_SUBTRACTION: bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); break; + case CSGShape3D::OPERATION_UNION: bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); break; + case CSGShape3D::OPERATION_INTERSECTION: bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); break; + case CSGShape3D::OPERATION_SUBTRACTION: bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); break; } memdelete(n); memdelete(nn2); @@ -218,18 +218,18 @@ CSGBrush *CSGShape::_get_brush() { return brush; } -int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { +int CSGShape3D::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); return surface.vertices.size() / 3; } -int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { +int CSGShape3D::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { // always 3 return 3; } -void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector3 v = surface.verticesw[iFace * 3 + iVert]; @@ -238,7 +238,7 @@ void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosO fvPosOut[2] = v.z; } -void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector3 n = surface.normalsw[iFace * 3 + iVert]; @@ -247,7 +247,7 @@ void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOu fvNormOut[2] = n.z; } -void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector2 t = surface.uvsw[iFace * 3 + iVert]; @@ -255,7 +255,7 @@ void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexc fvTexcOut[1] = t.y; } -void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, +void CSGShape3D::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); @@ -273,7 +273,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f surface.tansw[i++] = d < 0 ? -1 : 1; } -void CSGShape::_update_shape() { +void CSGShape3D::_update_shape() { if (parent) return; @@ -460,11 +460,11 @@ void CSGShape::_update_shape() { set_base(root_mesh->get_rid()); } -AABB CSGShape::get_aabb() const { +AABB CSGShape3D::get_aabb() const { return node_aabb; } -Vector CSGShape::get_brush_faces() { +Vector CSGShape3D::get_brush_faces() { ERR_FAIL_COND_V(!is_inside_tree(), Vector()); CSGBrush *b = _get_brush(); if (!b) { @@ -486,18 +486,18 @@ Vector CSGShape::get_brush_faces() { return faces; } -Vector CSGShape::get_faces(uint32_t p_usage_flags) const { +Vector CSGShape3D::get_faces(uint32_t p_usage_flags) const { return Vector(); } -void CSGShape::_notification(int p_what) { +void CSGShape3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { Node *parentn = get_parent(); if (parentn) { - parent = Object::cast_to(parentn); + parent = Object::cast_to(parentn); if (parent) { set_base(RID()); root_mesh.unref(); @@ -547,27 +547,27 @@ void CSGShape::_notification(int p_what) { } } -void CSGShape::set_operation(Operation p_operation) { +void CSGShape3D::set_operation(Operation p_operation) { operation = p_operation; _make_dirty(); update_gizmo(); } -CSGShape::Operation CSGShape::get_operation() const { +CSGShape3D::Operation CSGShape3D::get_operation() const { return operation; } -void CSGShape::set_calculate_tangents(bool p_calculate_tangents) { +void CSGShape3D::set_calculate_tangents(bool p_calculate_tangents) { calculate_tangents = p_calculate_tangents; _make_dirty(); } -bool CSGShape::is_calculating_tangents() const { +bool CSGShape3D::is_calculating_tangents() const { return calculate_tangents; } -void CSGShape::_validate_property(PropertyInfo &property) const { +void CSGShape3D::_validate_property(PropertyInfo &property) const { bool is_collision_prefixed = property.name.begins_with("collision_"); if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) { //hide collision if not root @@ -577,7 +577,7 @@ void CSGShape::_validate_property(PropertyInfo &property) const { } } -Array CSGShape::get_meshes() const { +Array CSGShape3D::get_meshes() const { if (root_mesh.is_valid()) { Array arr; @@ -589,36 +589,36 @@ Array CSGShape::get_meshes() const { return Array(); } -void CSGShape::_bind_methods() { +void CSGShape3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape::_update_shape); - ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape::is_root_shape); + ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape3D::_update_shape); + ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape3D::is_root_shape); - ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape::set_operation); - ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_operation); + ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape3D::set_operation); + ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape3D::get_operation); - ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); - ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape3D::set_snap); + ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape3D::get_snap); - ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape::set_use_collision); - ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape::is_using_collision); + ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape3D::set_use_collision); + ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape3D::is_using_collision); - ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape::get_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape3D::get_collision_layer); - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape3D::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape::get_collision_mask_bit); + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape3D::get_collision_mask_bit); - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape::get_collision_layer_bit); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape3D::get_collision_layer_bit); - ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents); - ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents); + ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape3D::set_calculate_tangents); + ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape3D::is_calculating_tangents); - ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape::get_meshes); + ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape3D::get_meshes); ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); @@ -634,7 +634,7 @@ void CSGShape::_bind_methods() { BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION); } -CSGShape::CSGShape() { +CSGShape3D::CSGShape3D() { operation = OPERATION_UNION; parent = NULL; brush = NULL; @@ -647,7 +647,7 @@ CSGShape::CSGShape() { set_notify_local_transform(true); } -CSGShape::~CSGShape() { +CSGShape3D::~CSGShape3D() { if (brush) { memdelete(brush); brush = NULL; @@ -655,17 +655,17 @@ CSGShape::~CSGShape() { } ////////////////////////////////// -CSGBrush *CSGCombiner::_build_brush() { +CSGBrush *CSGCombiner3D::_build_brush() { return NULL; //does not build anything } -CSGCombiner::CSGCombiner() { +CSGCombiner3D::CSGCombiner3D() { } ///////////////////// -CSGBrush *CSGPrimitive::_create_brush_from_arrays(const Vector &p_vertices, const Vector &p_uv, const Vector &p_smooth, const Vector> &p_materials) { +CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector &p_vertices, const Vector &p_uv, const Vector &p_smooth, const Vector> &p_materials) { CSGBrush *brush = memnew(CSGBrush); @@ -683,15 +683,15 @@ CSGBrush *CSGPrimitive::_create_brush_from_arrays(const Vector &p_verti return brush; } -void CSGPrimitive::_bind_methods() { +void CSGPrimitive3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive::set_invert_faces); - ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive::is_inverting_faces); + ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive3D::set_invert_faces); + ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive3D::is_inverting_faces); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_faces"), "set_invert_faces", "is_inverting_faces"); } -void CSGPrimitive::set_invert_faces(bool p_invert) { +void CSGPrimitive3D::set_invert_faces(bool p_invert) { if (invert_faces == p_invert) return; @@ -700,17 +700,17 @@ void CSGPrimitive::set_invert_faces(bool p_invert) { _make_dirty(); } -bool CSGPrimitive::is_inverting_faces() { +bool CSGPrimitive3D::is_inverting_faces() { return invert_faces; } -CSGPrimitive::CSGPrimitive() { +CSGPrimitive3D::CSGPrimitive3D() { invert_faces = false; } ///////////////////// -CSGBrush *CSGMesh::_build_brush() { +CSGBrush *CSGMesh3D::_build_brush() { if (!mesh.is_valid()) return NULL; @@ -862,58 +862,58 @@ CSGBrush *CSGMesh::_build_brush() { return _create_brush_from_arrays(vertices, uvs, smooth, materials); } -void CSGMesh::_mesh_changed() { +void CSGMesh3D::_mesh_changed() { _make_dirty(); update_gizmo(); } -void CSGMesh::set_material(const Ref &p_material) { +void CSGMesh3D::set_material(const Ref &p_material) { if (material == p_material) return; material = p_material; _make_dirty(); } -Ref CSGMesh::get_material() const { +Ref CSGMesh3D::get_material() const { return material; } -void CSGMesh::_bind_methods() { +void CSGMesh3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh"), &CSGMesh::get_mesh); + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh3D::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &CSGMesh3D::get_mesh); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGMesh::set_mesh(const Ref &p_mesh) { +void CSGMesh3D::set_mesh(const Ref &p_mesh) { if (mesh == p_mesh) return; if (mesh.is_valid()) { - mesh->disconnect("changed", callable_mp(this, &CSGMesh::_mesh_changed)); + mesh->disconnect("changed", callable_mp(this, &CSGMesh3D::_mesh_changed)); } mesh = p_mesh; if (mesh.is_valid()) { - mesh->connect("changed", callable_mp(this, &CSGMesh::_mesh_changed)); + mesh->connect("changed", callable_mp(this, &CSGMesh3D::_mesh_changed)); } _make_dirty(); } -Ref CSGMesh::get_mesh() { +Ref CSGMesh3D::get_mesh() { return mesh; } //////////////////////////////// -CSGBrush *CSGSphere::_build_brush() { +CSGBrush *CSGSphere3D::_build_brush() { // set our bounding box @@ -1032,20 +1032,20 @@ CSGBrush *CSGSphere::_build_brush() { return brush; } -void CSGSphere::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGSphere::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CSGSphere::get_radius); +void CSGSphere3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGSphere3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CSGSphere3D::get_radius); - ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &CSGSphere::set_radial_segments); - ClassDB::bind_method(D_METHOD("get_radial_segments"), &CSGSphere::get_radial_segments); - ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CSGSphere::set_rings); - ClassDB::bind_method(D_METHOD("get_rings"), &CSGSphere::get_rings); + ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &CSGSphere3D::set_radial_segments); + ClassDB::bind_method(D_METHOD("get_radial_segments"), &CSGSphere3D::get_radial_segments); + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CSGSphere3D::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &CSGSphere3D::get_rings); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGSphere::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGSphere::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGSphere3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGSphere3D::get_smooth_faces); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGSphere::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGSphere::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGSphere3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGSphere3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); @@ -1054,7 +1054,7 @@ void CSGSphere::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGSphere::set_radius(const float p_radius) { +void CSGSphere3D::set_radius(const float p_radius) { ERR_FAIL_COND(p_radius <= 0); radius = p_radius; _make_dirty(); @@ -1062,51 +1062,51 @@ void CSGSphere::set_radius(const float p_radius) { _change_notify("radius"); } -float CSGSphere::get_radius() const { +float CSGSphere3D::get_radius() const { return radius; } -void CSGSphere::set_radial_segments(const int p_radial_segments) { +void CSGSphere3D::set_radial_segments(const int p_radial_segments) { radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; _make_dirty(); update_gizmo(); } -int CSGSphere::get_radial_segments() const { +int CSGSphere3D::get_radial_segments() const { return radial_segments; } -void CSGSphere::set_rings(const int p_rings) { +void CSGSphere3D::set_rings(const int p_rings) { rings = p_rings > 1 ? p_rings : 1; _make_dirty(); update_gizmo(); } -int CSGSphere::get_rings() const { +int CSGSphere3D::get_rings() const { return rings; } -void CSGSphere::set_smooth_faces(const bool p_smooth_faces) { +void CSGSphere3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGSphere::get_smooth_faces() const { +bool CSGSphere3D::get_smooth_faces() const { return smooth_faces; } -void CSGSphere::set_material(const Ref &p_material) { +void CSGSphere3D::set_material(const Ref &p_material) { material = p_material; _make_dirty(); } -Ref CSGSphere::get_material() const { +Ref CSGSphere3D::get_material() const { return material; } -CSGSphere::CSGSphere() { +CSGSphere3D::CSGSphere3D() { // defaults radius = 1.0; radial_segments = 12; @@ -1116,7 +1116,7 @@ CSGSphere::CSGSphere() { /////////////// -CSGBrush *CSGBox::_build_brush() { +CSGBrush *CSGBox3D::_build_brush() { // set our bounding box @@ -1221,18 +1221,18 @@ CSGBrush *CSGBox::_build_brush() { return brush; } -void CSGBox::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &CSGBox::set_width); - ClassDB::bind_method(D_METHOD("get_width"), &CSGBox::get_width); +void CSGBox3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &CSGBox3D::set_width); + ClassDB::bind_method(D_METHOD("get_width"), &CSGBox3D::get_width); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGBox::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CSGBox::get_height); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGBox3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CSGBox3D::get_height); - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGBox::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CSGBox::get_depth); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGBox3D::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &CSGBox3D::get_depth); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGBox::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGBox3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); @@ -1240,52 +1240,52 @@ void CSGBox::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGBox::set_width(const float p_width) { +void CSGBox3D::set_width(const float p_width) { width = p_width; _make_dirty(); update_gizmo(); _change_notify("width"); } -float CSGBox::get_width() const { +float CSGBox3D::get_width() const { return width; } -void CSGBox::set_height(const float p_height) { +void CSGBox3D::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); _change_notify("height"); } -float CSGBox::get_height() const { +float CSGBox3D::get_height() const { return height; } -void CSGBox::set_depth(const float p_depth) { +void CSGBox3D::set_depth(const float p_depth) { depth = p_depth; _make_dirty(); update_gizmo(); _change_notify("depth"); } -float CSGBox::get_depth() const { +float CSGBox3D::get_depth() const { return depth; } -void CSGBox::set_material(const Ref &p_material) { +void CSGBox3D::set_material(const Ref &p_material) { material = p_material; _make_dirty(); update_gizmo(); } -Ref CSGBox::get_material() const { +Ref CSGBox3D::get_material() const { return material; } -CSGBox::CSGBox() { +CSGBox3D::CSGBox3D() { // defaults width = 2.0; height = 2.0; @@ -1294,7 +1294,7 @@ CSGBox::CSGBox() { /////////////// -CSGBrush *CSGCylinder::_build_brush() { +CSGBrush *CSGCylinder3D::_build_brush() { // set our bounding box @@ -1430,24 +1430,24 @@ CSGBrush *CSGCylinder::_build_brush() { return brush; } -void CSGCylinder::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGCylinder::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CSGCylinder::get_radius); +void CSGCylinder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGCylinder3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CSGCylinder3D::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGCylinder::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CSGCylinder::get_height); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGCylinder3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CSGCylinder3D::get_height); - ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGCylinder::set_sides); - ClassDB::bind_method(D_METHOD("get_sides"), &CSGCylinder::get_sides); + ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGCylinder3D::set_sides); + ClassDB::bind_method(D_METHOD("get_sides"), &CSGCylinder3D::get_sides); - ClassDB::bind_method(D_METHOD("set_cone", "cone"), &CSGCylinder::set_cone); - ClassDB::bind_method(D_METHOD("is_cone"), &CSGCylinder::is_cone); + ClassDB::bind_method(D_METHOD("set_cone", "cone"), &CSGCylinder3D::set_cone); + ClassDB::bind_method(D_METHOD("is_cone"), &CSGCylinder3D::is_cone); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGCylinder::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGCylinder::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGCylinder3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGCylinder3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder3D::get_smooth_faces); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); @@ -1457,70 +1457,70 @@ void CSGCylinder::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGCylinder::set_radius(const float p_radius) { +void CSGCylinder3D::set_radius(const float p_radius) { radius = p_radius; _make_dirty(); update_gizmo(); _change_notify("radius"); } -float CSGCylinder::get_radius() const { +float CSGCylinder3D::get_radius() const { return radius; } -void CSGCylinder::set_height(const float p_height) { +void CSGCylinder3D::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); _change_notify("height"); } -float CSGCylinder::get_height() const { +float CSGCylinder3D::get_height() const { return height; } -void CSGCylinder::set_sides(const int p_sides) { +void CSGCylinder3D::set_sides(const int p_sides) { ERR_FAIL_COND(p_sides < 3); sides = p_sides; _make_dirty(); update_gizmo(); } -int CSGCylinder::get_sides() const { +int CSGCylinder3D::get_sides() const { return sides; } -void CSGCylinder::set_cone(const bool p_cone) { +void CSGCylinder3D::set_cone(const bool p_cone) { cone = p_cone; _make_dirty(); update_gizmo(); } -bool CSGCylinder::is_cone() const { +bool CSGCylinder3D::is_cone() const { return cone; } -void CSGCylinder::set_smooth_faces(const bool p_smooth_faces) { +void CSGCylinder3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGCylinder::get_smooth_faces() const { +bool CSGCylinder3D::get_smooth_faces() const { return smooth_faces; } -void CSGCylinder::set_material(const Ref &p_material) { +void CSGCylinder3D::set_material(const Ref &p_material) { material = p_material; _make_dirty(); } -Ref CSGCylinder::get_material() const { +Ref CSGCylinder3D::get_material() const { return material; } -CSGCylinder::CSGCylinder() { +CSGCylinder3D::CSGCylinder3D() { // defaults radius = 1.0; height = 1.0; @@ -1531,7 +1531,7 @@ CSGCylinder::CSGCylinder() { /////////////// -CSGBrush *CSGTorus::_build_brush() { +CSGBrush *CSGTorus3D::_build_brush() { // set our bounding box @@ -1657,24 +1657,24 @@ CSGBrush *CSGTorus::_build_brush() { return brush; } -void CSGTorus::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &CSGTorus::set_inner_radius); - ClassDB::bind_method(D_METHOD("get_inner_radius"), &CSGTorus::get_inner_radius); +void CSGTorus3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &CSGTorus3D::set_inner_radius); + ClassDB::bind_method(D_METHOD("get_inner_radius"), &CSGTorus3D::get_inner_radius); - ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &CSGTorus::set_outer_radius); - ClassDB::bind_method(D_METHOD("get_outer_radius"), &CSGTorus::get_outer_radius); + ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &CSGTorus3D::set_outer_radius); + ClassDB::bind_method(D_METHOD("get_outer_radius"), &CSGTorus3D::get_outer_radius); - ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGTorus::set_sides); - ClassDB::bind_method(D_METHOD("get_sides"), &CSGTorus::get_sides); + ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGTorus3D::set_sides); + ClassDB::bind_method(D_METHOD("get_sides"), &CSGTorus3D::get_sides); - ClassDB::bind_method(D_METHOD("set_ring_sides", "sides"), &CSGTorus::set_ring_sides); - ClassDB::bind_method(D_METHOD("get_ring_sides"), &CSGTorus::get_ring_sides); + ClassDB::bind_method(D_METHOD("set_ring_sides", "sides"), &CSGTorus3D::set_ring_sides); + ClassDB::bind_method(D_METHOD("get_ring_sides"), &CSGTorus3D::get_ring_sides); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGTorus::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGTorus::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGTorus3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGTorus3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus3D::get_smooth_faces); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_inner_radius", "get_inner_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_outer_radius", "get_outer_radius"); @@ -1684,71 +1684,71 @@ void CSGTorus::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGTorus::set_inner_radius(const float p_inner_radius) { +void CSGTorus3D::set_inner_radius(const float p_inner_radius) { inner_radius = p_inner_radius; _make_dirty(); update_gizmo(); _change_notify("inner_radius"); } -float CSGTorus::get_inner_radius() const { +float CSGTorus3D::get_inner_radius() const { return inner_radius; } -void CSGTorus::set_outer_radius(const float p_outer_radius) { +void CSGTorus3D::set_outer_radius(const float p_outer_radius) { outer_radius = p_outer_radius; _make_dirty(); update_gizmo(); _change_notify("outer_radius"); } -float CSGTorus::get_outer_radius() const { +float CSGTorus3D::get_outer_radius() const { return outer_radius; } -void CSGTorus::set_sides(const int p_sides) { +void CSGTorus3D::set_sides(const int p_sides) { ERR_FAIL_COND(p_sides < 3); sides = p_sides; _make_dirty(); update_gizmo(); } -int CSGTorus::get_sides() const { +int CSGTorus3D::get_sides() const { return sides; } -void CSGTorus::set_ring_sides(const int p_ring_sides) { +void CSGTorus3D::set_ring_sides(const int p_ring_sides) { ERR_FAIL_COND(p_ring_sides < 3); ring_sides = p_ring_sides; _make_dirty(); update_gizmo(); } -int CSGTorus::get_ring_sides() const { +int CSGTorus3D::get_ring_sides() const { return ring_sides; } -void CSGTorus::set_smooth_faces(const bool p_smooth_faces) { +void CSGTorus3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGTorus::get_smooth_faces() const { +bool CSGTorus3D::get_smooth_faces() const { return smooth_faces; } -void CSGTorus::set_material(const Ref &p_material) { +void CSGTorus3D::set_material(const Ref &p_material) { material = p_material; _make_dirty(); } -Ref CSGTorus::get_material() const { +Ref CSGTorus3D::get_material() const { return material; } -CSGTorus::CSGTorus() { +CSGTorus3D::CSGTorus3D() { // defaults inner_radius = 2.0; outer_radius = 3.0; @@ -1759,7 +1759,7 @@ CSGTorus::CSGTorus() { /////////////// -CSGBrush *CSGPolygon::_build_brush() { +CSGBrush *CSGPolygon3D::_build_brush() { // set our bounding box @@ -1777,7 +1777,7 @@ CSGBrush *CSGPolygon::_build_brush() { if (triangles.size() < 3) return NULL; - Path *path = NULL; + Path3D *path = NULL; Ref curve; // get bounds for our polygon @@ -1804,21 +1804,21 @@ CSGBrush *CSGPolygon::_build_brush() { Node *n = get_node(path_node); if (!n) return NULL; - path = Object::cast_to(n); + path = Object::cast_to(n); if (!path) return NULL; if (path != path_cache) { if (path_cache) { - path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); + path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); path_cache = NULL; } path_cache = path; - path_cache->connect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->connect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); + path_cache->connect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->connect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); path_cache = NULL; } curve = path->get_curve(); @@ -2231,17 +2231,17 @@ CSGBrush *CSGPolygon::_build_brush() { return brush; } -void CSGPolygon::_notification(int p_what) { +void CSGPolygon3D::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_TREE) { if (path_cache) { - path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); + path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); path_cache = NULL; } } } -void CSGPolygon::_validate_property(PropertyInfo &property) const { +void CSGPolygon3D::_validate_property(PropertyInfo &property) const { if (property.name.begins_with("spin") && mode != MODE_SPIN) { property.usage = 0; } @@ -2252,60 +2252,60 @@ void CSGPolygon::_validate_property(PropertyInfo &property) const { property.usage = 0; } - CSGShape::_validate_property(property); + CSGShape3D::_validate_property(property); } -void CSGPolygon::_path_changed() { +void CSGPolygon3D::_path_changed() { _make_dirty(); update_gizmo(); } -void CSGPolygon::_path_exited() { +void CSGPolygon3D::_path_exited() { path_cache = NULL; } -void CSGPolygon::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CSGPolygon::set_polygon); - ClassDB::bind_method(D_METHOD("get_polygon"), &CSGPolygon::get_polygon); +void CSGPolygon3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CSGPolygon3D::set_polygon); + ClassDB::bind_method(D_METHOD("get_polygon"), &CSGPolygon3D::get_polygon); - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &CSGPolygon::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &CSGPolygon::get_mode); + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &CSGPolygon3D::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &CSGPolygon3D::get_mode); - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGPolygon::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CSGPolygon::get_depth); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGPolygon3D::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &CSGPolygon3D::get_depth); - ClassDB::bind_method(D_METHOD("set_spin_degrees", "degrees"), &CSGPolygon::set_spin_degrees); - ClassDB::bind_method(D_METHOD("get_spin_degrees"), &CSGPolygon::get_spin_degrees); + ClassDB::bind_method(D_METHOD("set_spin_degrees", "degrees"), &CSGPolygon3D::set_spin_degrees); + ClassDB::bind_method(D_METHOD("get_spin_degrees"), &CSGPolygon3D::get_spin_degrees); - ClassDB::bind_method(D_METHOD("set_spin_sides", "spin_sides"), &CSGPolygon::set_spin_sides); - ClassDB::bind_method(D_METHOD("get_spin_sides"), &CSGPolygon::get_spin_sides); + ClassDB::bind_method(D_METHOD("set_spin_sides", "spin_sides"), &CSGPolygon3D::set_spin_sides); + ClassDB::bind_method(D_METHOD("get_spin_sides"), &CSGPolygon3D::get_spin_sides); - ClassDB::bind_method(D_METHOD("set_path_node", "path"), &CSGPolygon::set_path_node); - ClassDB::bind_method(D_METHOD("get_path_node"), &CSGPolygon::get_path_node); + ClassDB::bind_method(D_METHOD("set_path_node", "path"), &CSGPolygon3D::set_path_node); + ClassDB::bind_method(D_METHOD("get_path_node"), &CSGPolygon3D::get_path_node); - ClassDB::bind_method(D_METHOD("set_path_interval", "distance"), &CSGPolygon::set_path_interval); - ClassDB::bind_method(D_METHOD("get_path_interval"), &CSGPolygon::get_path_interval); + ClassDB::bind_method(D_METHOD("set_path_interval", "distance"), &CSGPolygon3D::set_path_interval); + ClassDB::bind_method(D_METHOD("get_path_interval"), &CSGPolygon3D::get_path_interval); - ClassDB::bind_method(D_METHOD("set_path_rotation", "mode"), &CSGPolygon::set_path_rotation); - ClassDB::bind_method(D_METHOD("get_path_rotation"), &CSGPolygon::get_path_rotation); + ClassDB::bind_method(D_METHOD("set_path_rotation", "mode"), &CSGPolygon3D::set_path_rotation); + ClassDB::bind_method(D_METHOD("get_path_rotation"), &CSGPolygon3D::get_path_rotation); - ClassDB::bind_method(D_METHOD("set_path_local", "enable"), &CSGPolygon::set_path_local); - ClassDB::bind_method(D_METHOD("is_path_local"), &CSGPolygon::is_path_local); + ClassDB::bind_method(D_METHOD("set_path_local", "enable"), &CSGPolygon3D::set_path_local); + ClassDB::bind_method(D_METHOD("is_path_local"), &CSGPolygon3D::is_path_local); - ClassDB::bind_method(D_METHOD("set_path_continuous_u", "enable"), &CSGPolygon::set_path_continuous_u); - ClassDB::bind_method(D_METHOD("is_path_continuous_u"), &CSGPolygon::is_path_continuous_u); + ClassDB::bind_method(D_METHOD("set_path_continuous_u", "enable"), &CSGPolygon3D::set_path_continuous_u); + ClassDB::bind_method(D_METHOD("is_path_continuous_u"), &CSGPolygon3D::is_path_continuous_u); - ClassDB::bind_method(D_METHOD("set_path_joined", "enable"), &CSGPolygon::set_path_joined); - ClassDB::bind_method(D_METHOD("is_path_joined"), &CSGPolygon::is_path_joined); + ClassDB::bind_method(D_METHOD("set_path_joined", "enable"), &CSGPolygon3D::set_path_joined); + ClassDB::bind_method(D_METHOD("is_path_joined"), &CSGPolygon3D::is_path_joined); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGPolygon::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGPolygon::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGPolygon3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGPolygon3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGPolygon::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGPolygon::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGPolygon3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGPolygon3D::get_smooth_faces); - ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CSGPolygon::_is_editable_3d_polygon); - ClassDB::bind_method(D_METHOD("_has_editable_3d_polygon_no_depth"), &CSGPolygon::_has_editable_3d_polygon_no_depth); + ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CSGPolygon3D::_is_editable_3d_polygon); + ClassDB::bind_method(D_METHOD("_has_editable_3d_polygon_no_depth"), &CSGPolygon3D::_has_editable_3d_polygon_no_depth); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Depth,Spin,Path"), "set_mode", "get_mode"); @@ -2330,148 +2330,148 @@ void CSGPolygon::_bind_methods() { BIND_ENUM_CONSTANT(PATH_ROTATION_PATH_FOLLOW); } -void CSGPolygon::set_polygon(const Vector &p_polygon) { +void CSGPolygon3D::set_polygon(const Vector &p_polygon) { polygon = p_polygon; _make_dirty(); update_gizmo(); } -Vector CSGPolygon::get_polygon() const { +Vector CSGPolygon3D::get_polygon() const { return polygon; } -void CSGPolygon::set_mode(Mode p_mode) { +void CSGPolygon3D::set_mode(Mode p_mode) { mode = p_mode; _make_dirty(); update_gizmo(); _change_notify(); } -CSGPolygon::Mode CSGPolygon::get_mode() const { +CSGPolygon3D::Mode CSGPolygon3D::get_mode() const { return mode; } -void CSGPolygon::set_depth(const float p_depth) { +void CSGPolygon3D::set_depth(const float p_depth) { ERR_FAIL_COND(p_depth < 0.001); depth = p_depth; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_depth() const { +float CSGPolygon3D::get_depth() const { return depth; } -void CSGPolygon::set_path_continuous_u(bool p_enable) { +void CSGPolygon3D::set_path_continuous_u(bool p_enable) { path_continuous_u = p_enable; _make_dirty(); } -bool CSGPolygon::is_path_continuous_u() const { +bool CSGPolygon3D::is_path_continuous_u() const { return path_continuous_u; } -void CSGPolygon::set_spin_degrees(const float p_spin_degrees) { +void CSGPolygon3D::set_spin_degrees(const float p_spin_degrees) { ERR_FAIL_COND(p_spin_degrees < 0.01 || p_spin_degrees > 360); spin_degrees = p_spin_degrees; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_spin_degrees() const { +float CSGPolygon3D::get_spin_degrees() const { return spin_degrees; } -void CSGPolygon::set_spin_sides(const int p_spin_sides) { +void CSGPolygon3D::set_spin_sides(const int p_spin_sides) { ERR_FAIL_COND(p_spin_sides < 3); spin_sides = p_spin_sides; _make_dirty(); update_gizmo(); } -int CSGPolygon::get_spin_sides() const { +int CSGPolygon3D::get_spin_sides() const { return spin_sides; } -void CSGPolygon::set_path_node(const NodePath &p_path) { +void CSGPolygon3D::set_path_node(const NodePath &p_path) { path_node = p_path; _make_dirty(); update_gizmo(); } -NodePath CSGPolygon::get_path_node() const { +NodePath CSGPolygon3D::get_path_node() const { return path_node; } -void CSGPolygon::set_path_interval(float p_interval) { +void CSGPolygon3D::set_path_interval(float p_interval) { ERR_FAIL_COND_MSG(p_interval < 0.001, "Path interval cannot be smaller than 0.001."); path_interval = p_interval; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_path_interval() const { +float CSGPolygon3D::get_path_interval() const { return path_interval; } -void CSGPolygon::set_path_rotation(PathRotation p_rotation) { +void CSGPolygon3D::set_path_rotation(PathRotation p_rotation) { path_rotation = p_rotation; _make_dirty(); update_gizmo(); } -CSGPolygon::PathRotation CSGPolygon::get_path_rotation() const { +CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const { return path_rotation; } -void CSGPolygon::set_path_local(bool p_enable) { +void CSGPolygon3D::set_path_local(bool p_enable) { path_local = p_enable; _make_dirty(); update_gizmo(); } -bool CSGPolygon::is_path_local() const { +bool CSGPolygon3D::is_path_local() const { return path_local; } -void CSGPolygon::set_path_joined(bool p_enable) { +void CSGPolygon3D::set_path_joined(bool p_enable) { path_joined = p_enable; _make_dirty(); update_gizmo(); } -bool CSGPolygon::is_path_joined() const { +bool CSGPolygon3D::is_path_joined() const { return path_joined; } -void CSGPolygon::set_smooth_faces(const bool p_smooth_faces) { +void CSGPolygon3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGPolygon::get_smooth_faces() const { +bool CSGPolygon3D::get_smooth_faces() const { return smooth_faces; } -void CSGPolygon::set_material(const Ref &p_material) { +void CSGPolygon3D::set_material(const Ref &p_material) { material = p_material; _make_dirty(); } -Ref CSGPolygon::get_material() const { +Ref CSGPolygon3D::get_material() const { return material; } -bool CSGPolygon::_is_editable_3d_polygon() const { +bool CSGPolygon3D::_is_editable_3d_polygon() const { return true; } -bool CSGPolygon::_has_editable_3d_polygon_no_depth() const { +bool CSGPolygon3D::_has_editable_3d_polygon_no_depth() const { return true; } -CSGPolygon::CSGPolygon() { +CSGPolygon3D::CSGPolygon3D() { // defaults mode = MODE_DEPTH; polygon.push_back(Vector2(0, 0)); diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index fdbf979fe7..abab1ded20 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -34,12 +34,12 @@ #define CSGJS_HEADER_ONLY #include "csg.h" -#include "scene/3d/visual_instance.h" -#include "scene/resources/concave_polygon_shape.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" #include "thirdparty/misc/mikktspace.h" -class CSGShape : public GeometryInstance { - GDCLASS(CSGShape, GeometryInstance); +class CSGShape3D : public GeometryInstance3D { + GDCLASS(CSGShape3D, GeometryInstance3D); public: enum Operation { @@ -51,7 +51,7 @@ public: private: Operation operation; - CSGShape *parent; + CSGShape3D *parent; CSGBrush *brush; @@ -63,7 +63,7 @@ private: bool use_collision; uint32_t collision_layer; uint32_t collision_mask; - Ref root_collision_shape; + Ref root_collision_shape; RID root_collision_instance; bool calculate_tangents; @@ -111,7 +111,7 @@ protected: static void _bind_methods(); - friend class CSGCombiner; + friend class CSGCombiner3D; CSGBrush *_get_brush(); virtual void _validate_property(PropertyInfo &property) const; @@ -149,24 +149,24 @@ public: bool is_calculating_tangents() const; bool is_root_shape() const; - CSGShape(); - ~CSGShape(); + CSGShape3D(); + ~CSGShape3D(); }; -VARIANT_ENUM_CAST(CSGShape::Operation) +VARIANT_ENUM_CAST(CSGShape3D::Operation) -class CSGCombiner : public CSGShape { - GDCLASS(CSGCombiner, CSGShape); +class CSGCombiner3D : public CSGShape3D { + GDCLASS(CSGCombiner3D, CSGShape3D); private: virtual CSGBrush *_build_brush(); public: - CSGCombiner(); + CSGCombiner3D(); }; -class CSGPrimitive : public CSGShape { - GDCLASS(CSGPrimitive, CSGShape); +class CSGPrimitive3D : public CSGShape3D { + GDCLASS(CSGPrimitive3D, CSGShape3D); private: bool invert_faces; @@ -179,11 +179,11 @@ public: void set_invert_faces(bool p_invert); bool is_inverting_faces(); - CSGPrimitive(); + CSGPrimitive3D(); }; -class CSGMesh : public CSGPrimitive { - GDCLASS(CSGMesh, CSGPrimitive); +class CSGMesh3D : public CSGPrimitive3D { + GDCLASS(CSGMesh3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -203,9 +203,9 @@ public: Ref get_material() const; }; -class CSGSphere : public CSGPrimitive { +class CSGSphere3D : public CSGPrimitive3D { - GDCLASS(CSGSphere, CSGPrimitive); + GDCLASS(CSGSphere3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref material; @@ -233,12 +233,12 @@ public: void set_smooth_faces(bool p_smooth_faces); bool get_smooth_faces() const; - CSGSphere(); + CSGSphere3D(); }; -class CSGBox : public CSGPrimitive { +class CSGBox3D : public CSGPrimitive3D { - GDCLASS(CSGBox, CSGPrimitive); + GDCLASS(CSGBox3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref material; @@ -262,12 +262,12 @@ public: void set_material(const Ref &p_material); Ref get_material() const; - CSGBox(); + CSGBox3D(); }; -class CSGCylinder : public CSGPrimitive { +class CSGCylinder3D : public CSGPrimitive3D { - GDCLASS(CSGCylinder, CSGPrimitive); + GDCLASS(CSGCylinder3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref material; @@ -299,12 +299,12 @@ public: void set_material(const Ref &p_material); Ref get_material() const; - CSGCylinder(); + CSGCylinder3D(); }; -class CSGTorus : public CSGPrimitive { +class CSGTorus3D : public CSGPrimitive3D { - GDCLASS(CSGTorus, CSGPrimitive); + GDCLASS(CSGTorus3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref material; @@ -336,12 +336,12 @@ public: void set_material(const Ref &p_material); Ref get_material() const; - CSGTorus(); + CSGTorus3D(); }; -class CSGPolygon : public CSGPrimitive { +class CSGPolygon3D : public CSGPrimitive3D { - GDCLASS(CSGPolygon, CSGPrimitive); + GDCLASS(CSGPolygon3D, CSGPrimitive3D); public: enum Mode { @@ -431,10 +431,10 @@ public: void set_material(const Ref &p_material); Ref get_material() const; - CSGPolygon(); + CSGPolygon3D(); }; -VARIANT_ENUM_CAST(CSGPolygon::Mode) -VARIANT_ENUM_CAST(CSGPolygon::PathRotation) +VARIANT_ENUM_CAST(CSGPolygon3D::Mode) +VARIANT_ENUM_CAST(CSGPolygon3D::PathRotation) #endif // CSG_SHAPE_H diff --git a/modules/csg/icons/CSGBox.svg b/modules/csg/icons/CSGBox.svg deleted file mode 100644 index 67e34df444..0000000000 --- a/modules/csg/icons/CSGBox.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGBox3D.svg b/modules/csg/icons/CSGBox3D.svg new file mode 100644 index 0000000000..67e34df444 --- /dev/null +++ b/modules/csg/icons/CSGBox3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGCapsule.svg b/modules/csg/icons/CSGCapsule.svg deleted file mode 100644 index 92a7b5a870..0000000000 --- a/modules/csg/icons/CSGCapsule.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGCapsule3D.svg b/modules/csg/icons/CSGCapsule3D.svg new file mode 100644 index 0000000000..92a7b5a870 --- /dev/null +++ b/modules/csg/icons/CSGCapsule3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGCombiner.svg b/modules/csg/icons/CSGCombiner.svg deleted file mode 100644 index cce2902e24..0000000000 --- a/modules/csg/icons/CSGCombiner.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/modules/csg/icons/CSGCombiner3D.svg b/modules/csg/icons/CSGCombiner3D.svg new file mode 100644 index 0000000000..cce2902e24 --- /dev/null +++ b/modules/csg/icons/CSGCombiner3D.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/csg/icons/CSGCylinder.svg b/modules/csg/icons/CSGCylinder.svg deleted file mode 100644 index 645a74c79b..0000000000 --- a/modules/csg/icons/CSGCylinder.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGCylinder3D.svg b/modules/csg/icons/CSGCylinder3D.svg new file mode 100644 index 0000000000..645a74c79b --- /dev/null +++ b/modules/csg/icons/CSGCylinder3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGMesh.svg b/modules/csg/icons/CSGMesh.svg deleted file mode 100644 index 6e940a4aa5..0000000000 --- a/modules/csg/icons/CSGMesh.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGMesh3D.svg b/modules/csg/icons/CSGMesh3D.svg new file mode 100644 index 0000000000..6e940a4aa5 --- /dev/null +++ b/modules/csg/icons/CSGMesh3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGPolygon.svg b/modules/csg/icons/CSGPolygon.svg deleted file mode 100644 index 71b03cb8e6..0000000000 --- a/modules/csg/icons/CSGPolygon.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGPolygon3D.svg b/modules/csg/icons/CSGPolygon3D.svg new file mode 100644 index 0000000000..71b03cb8e6 --- /dev/null +++ b/modules/csg/icons/CSGPolygon3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGSphere.svg b/modules/csg/icons/CSGSphere.svg deleted file mode 100644 index f81b566993..0000000000 --- a/modules/csg/icons/CSGSphere.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGSphere3D.svg b/modules/csg/icons/CSGSphere3D.svg new file mode 100644 index 0000000000..f81b566993 --- /dev/null +++ b/modules/csg/icons/CSGSphere3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/icons/CSGTorus.svg b/modules/csg/icons/CSGTorus.svg deleted file mode 100644 index 3d30aa47b2..0000000000 --- a/modules/csg/icons/CSGTorus.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/modules/csg/icons/CSGTorus3D.svg b/modules/csg/icons/CSGTorus3D.svg new file mode 100644 index 0000000000..3d30aa47b2 --- /dev/null +++ b/modules/csg/icons/CSGTorus3D.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index 677a20df38..1a12a6706d 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -37,15 +37,24 @@ void register_csg_types() { #ifndef _3D_DISABLED - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + + ClassDB::add_compatibility_class("CSGShape", "CSGShape3D"); + ClassDB::add_compatibility_class("CSGMesh", "CSGMesh3D"); + ClassDB::add_compatibility_class("CSGSphere", "CSGSphere3D"); + ClassDB::add_compatibility_class("CSGBox", "CSGBox3D"); + ClassDB::add_compatibility_class("CSGCylinder", "CSGCylinder3D"); + ClassDB::add_compatibility_class("CSGTorus", "CSGTorus3D"); + ClassDB::add_compatibility_class("CSGPolygon", "CSGPolygon3D"); + ClassDB::add_compatibility_class("CSGCombiner", "CSGCombiner3D"); #ifdef TOOLS_ENABLED EditorPlugins::add_by_type(); diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h index d99254d1ad..f35ee4bea0 100644 --- a/modules/gdnavigation/nav_region.h +++ b/modules/gdnavigation/nav_region.h @@ -34,7 +34,7 @@ #include "nav_rid.h" #include "nav_utils.h" -#include "scene/3d/navigation.h" +#include "scene/3d/navigation_3d.h" #include /** diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp index 05feb97131..6238acfdc5 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "core/io/marshalls.h" #include "core/io/resource_saver.h" #include "navigation_mesh_generator.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/box_container.h" void NavigationMeshEditor::_node_removed(Node *p_node) { @@ -84,7 +84,7 @@ void NavigationMeshEditor::_clear_pressed() { } } -void NavigationMeshEditor::edit(NavigationRegion *p_nav_region) { +void NavigationMeshEditor::edit(NavigationRegion3D *p_nav_region) { if (p_nav_region == NULL || node == p_nav_region) { return; @@ -125,12 +125,12 @@ NavigationMeshEditor::~NavigationMeshEditor() { void NavigationMeshEditorPlugin::edit(Object *p_object) { - navigation_mesh_editor->edit(Object::cast_to(p_object)); + navigation_mesh_editor->edit(Object::cast_to(p_object)); } bool NavigationMeshEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("NavigationRegion"); + return p_object->is_class("NavigationRegion3D"); } void NavigationMeshEditorPlugin::make_visible(bool p_visible) { diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.h b/modules/gdnavigation/navigation_mesh_editor_plugin.h index 847ad4f63d..434981c9e0 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.h +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.h @@ -36,7 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -class NavigationRegion; +class NavigationRegion3D; class NavigationMeshEditor : public Control { friend class NavigationMeshEditorPlugin; @@ -50,7 +50,7 @@ class NavigationMeshEditor : public Control { ToolButton *button_reset; Label *bake_info; - NavigationRegion *node; + NavigationRegion3D *node; void _bake_pressed(); void _clear_pressed(); @@ -61,7 +61,7 @@ protected: void _notification(int p_option); public: - void edit(NavigationRegion *p_nav_region); + void edit(NavigationRegion3D *p_nav_region); NavigationMeshEditor(); ~NavigationMeshEditor(); }; diff --git a/modules/gdnavigation/navigation_mesh_generator.cpp b/modules/gdnavigation/navigation_mesh_generator.cpp index e7038b38a2..ec19c7b8a3 100644 --- a/modules/gdnavigation/navigation_mesh_generator.cpp +++ b/modules/gdnavigation/navigation_mesh_generator.cpp @@ -34,18 +34,18 @@ #include "core/math/quick_hull.h" #include "core/os/thread.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/physics_body.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" -#include "scene/resources/cylinder_shape.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/primitive_meshes.h" -#include "scene/resources/shape.h" -#include "scene/resources/sphere_shape.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/shape_3d.h" +#include "scene/resources/sphere_shape_3d.h" +#include "scene/resources/world_margin_shape_3d.h" #include "modules/modules_enabled.gen.h" #ifdef TOOLS_ENABLED @@ -140,9 +140,9 @@ void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, cons void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector &p_verticies, Vector &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children) { - if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { + if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { - MeshInstance *mesh_instance = Object::cast_to(p_node); + MeshInstance3D *mesh_instance = Object::cast_to(p_node); Ref mesh = mesh_instance->get_mesh(); if (mesh.is_valid()) { _add_mesh(mesh, p_accumulated_transform * mesh_instance->get_transform(), p_verticies, p_indices); @@ -150,9 +150,9 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #ifdef MODULE_CSG_ENABLED - if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { + if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { - CSGShape *csg_shape = Object::cast_to(p_node); + CSGShape3D *csg_shape = Object::cast_to(p_node); Array meshes = csg_shape->get_meshes(); if (!meshes.empty()) { Ref mesh = meshes[1]; @@ -163,22 +163,22 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #endif - if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) { - StaticBody *static_body = Object::cast_to(p_node); + if (Object::cast_to(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) { + StaticBody3D *static_body = Object::cast_to(p_node); if (static_body->get_collision_layer() & p_collision_mask) { for (int i = 0; i < p_node->get_child_count(); ++i) { Node *child = p_node->get_child(i); - if (Object::cast_to(child)) { - CollisionShape *col_shape = Object::cast_to(child); + if (Object::cast_to(child)) { + CollisionShape3D *col_shape = Object::cast_to(child); Transform transform = p_accumulated_transform * static_body->get_transform() * col_shape->get_transform(); Ref mesh; - Ref s = col_shape->get_shape(); + Ref s = col_shape->get_shape(); - BoxShape *box = Object::cast_to(*s); + BoxShape3D *box = Object::cast_to(*s); if (box) { Ref cube_mesh; cube_mesh.instance(); @@ -186,7 +186,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = cube_mesh; } - CapsuleShape *capsule = Object::cast_to(*s); + CapsuleShape3D *capsule = Object::cast_to(*s); if (capsule) { Ref capsule_mesh; capsule_mesh.instance(); @@ -195,7 +195,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = capsule_mesh; } - CylinderShape *cylinder = Object::cast_to(*s); + CylinderShape3D *cylinder = Object::cast_to(*s); if (cylinder) { Ref cylinder_mesh; cylinder_mesh.instance(); @@ -205,7 +205,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = cylinder_mesh; } - SphereShape *sphere = Object::cast_to(*s); + SphereShape3D *sphere = Object::cast_to(*s); if (sphere) { Ref sphere_mesh; sphere_mesh.instance(); @@ -214,12 +214,12 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = sphere_mesh; } - ConcavePolygonShape *concave_polygon = Object::cast_to(*s); + ConcavePolygonShape3D *concave_polygon = Object::cast_to(*s); if (concave_polygon) { _add_faces(concave_polygon->get_faces(), transform, p_verticies, p_indices); } - ConvexPolygonShape *convex_polygon = Object::cast_to(*s); + ConvexPolygonShape3D *convex_polygon = Object::cast_to(*s); if (convex_polygon) { Vector varr = Variant(convex_polygon->get_points()); Geometry::MeshData md; @@ -265,8 +265,8 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #endif - if (Object::cast_to(p_node)) { - Spatial *spatial = Object::cast_to(p_node); + if (Object::cast_to(p_node)) { + Node3D *spatial = Object::cast_to(p_node); p_accumulated_transform = p_accumulated_transform * spatial->get_transform(); } @@ -505,7 +505,7 @@ void NavigationMeshGenerator::bake(Ref p_nav_mesh, Node *p_node) p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes); } - Transform navmesh_xform = Object::cast_to(p_node)->get_transform().affine_inverse(); + Transform navmesh_xform = Object::cast_to(p_node)->get_transform().affine_inverse(); for (const List::Element *E = parse_nodes.front(); E; E = E->next()) { int geometry_type = p_nav_mesh->get_parsed_geometry_type(); uint32_t collision_mask = p_nav_mesh->get_collision_mask(); diff --git a/modules/gdnavigation/navigation_mesh_generator.h b/modules/gdnavigation/navigation_mesh_generator.h index d1f2e4b56f..c5f7b2ab81 100644 --- a/modules/gdnavigation/navigation_mesh_generator.h +++ b/modules/gdnavigation/navigation_mesh_generator.h @@ -33,7 +33,7 @@ #ifndef _3D_DISABLED -#include "scene/3d/navigation_region.h" +#include "scene/3d/navigation_region_3d.h" #include diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 7273a014f0..61f18fbfee 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -32,7 +32,7 @@ #include "core/io/marshalls.h" #include "core/message_queue.h" -#include "scene/3d/light.h" +#include "scene/3d/light_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" @@ -667,14 +667,14 @@ void GridMap::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { - Spatial *c = this; + Node3D *c = this; while (c) { - navigation = Object::cast_to(c); + navigation = Object::cast_to(c); if (navigation) { break; } - c = Object::cast_to(c->get_parent()); + c = Object::cast_to(c->get_parent()); } last_transform = get_global_transform(); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index cc1c8c2923..43f4c09715 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -31,17 +31,17 @@ #ifndef GRID_MAP_H #define GRID_MAP_H -#include "scene/3d/navigation.h" -#include "scene/3d/spatial.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/node_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/multimesh.h" //heh heh, godotsphir!! this shares no code and the design is completely different with previous projects i've done.. //should scale better with hardware that supports instancing -class GridMap : public Spatial { +class GridMap : public Node3D { - GDCLASS(GridMap, Spatial); + GDCLASS(GridMap, Node3D); enum { MAP_DIRTY_TRANSFORMS = 1, @@ -147,7 +147,7 @@ class GridMap : public Spatial { int octant_size; bool center_x, center_y, center_z; float cell_scale; - Navigation *navigation; + Navigation3D *navigation; bool clip; bool clip_above; diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 1917a69388..0f377e2dec 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -33,7 +33,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/camera.h" +#include "scene/3d/camera_3d.h" #include "core/math/geometry.h" #include "core/os/keyboard.h" @@ -362,7 +362,7 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_FILL), !selection.active); } -bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) { +bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click) { if (!spatial_editor) return false; @@ -375,7 +375,7 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) return false; - Camera *camera = p_camera; + Camera3D *camera = p_camera; Vector3 from = camera->project_ray_origin(p_point); Vector3 normal = camera->project_ray_normal(p_point); Transform local_xform = node->get_global_transform().affine_inverse(); @@ -639,7 +639,7 @@ void GridMapEditor::_do_paste() { _clear_clipboard_data(); } -bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref &p_event) { +bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref &p_event) { if (!node) { return false; } @@ -660,8 +660,8 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Refis_pressed()) { - SpatialEditorViewport::NavigationScheme nav_scheme = (SpatialEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); - if ((nav_scheme == SpatialEditorViewport::NAVIGATION_MAYA || nav_scheme == SpatialEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { + Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); + if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { input_action = INPUT_NONE; } else if (mb->get_button_index() == BUTTON_LEFT) { @@ -964,7 +964,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { _update_selection_transform(); _update_paste_indicator(); - spatial_editor = Object::cast_to(editor->get_editor_plugin_screen()); + spatial_editor = Object::cast_to(editor->get_editor_plugin_screen()); if (!node) { set_process(false); @@ -1140,7 +1140,7 @@ void GridMapEditor::_notification(int p_what) { p.d = edit_floor[edit_axis] * node->get_cell_size()[edit_axis]; p = node->get_transform().xform(p); // plane to snap - SpatialEditorPlugin *sep = Object::cast_to(editor->get_editor_plugin_screen()); + Node3DEditorPlugin *sep = Object::cast_to(editor->get_editor_plugin_screen()); if (sep) sep->snap_cursor_to_plane(p); } @@ -1217,7 +1217,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { spatial_editor_hb = memnew(HBoxContainer); spatial_editor_hb->set_h_size_flags(SIZE_EXPAND_FILL); spatial_editor_hb->set_alignment(BoxContainer::ALIGN_END); - SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); + Node3DEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); spin_box_label = memnew(Label); spin_box_label->set_text(TTR("Floor:")); @@ -1519,10 +1519,10 @@ void GridMapEditorPlugin::_notification(int p_what) { switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) { case 0: { // Left. - SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0); + Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0); } break; case 1: { // Right. - SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1); + Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1); } break; } } diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index d6459cee0a..fd880e8b7b 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -36,7 +36,7 @@ #include "editor/pane_drag.h" #include "grid_map.h" -class SpatialEditorPlugin; +class Node3DEditorPlugin; class GridMapEditor : public VBoxContainer { GDCLASS(GridMapEditor, VBoxContainer); @@ -188,7 +188,7 @@ class GridMapEditor : public VBoxContainer { }; - SpatialEditorPlugin *spatial_editor; + Node3DEditorPlugin *spatial_editor; struct AreaDisplay { @@ -232,7 +232,7 @@ class GridMapEditor : public VBoxContainer { void _delete_selection(); void _fill_selection(); - bool do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click); + bool do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click); friend class GridMapEditorPlugin; @@ -242,7 +242,7 @@ protected: static void _bind_methods(); public: - bool forward_spatial_input_event(Camera *p_camera, const Ref &p_event); + bool forward_spatial_input_event(Camera3D *p_camera, const Ref &p_event); void edit(GridMap *p_gridmap); GridMapEditor() {} @@ -261,7 +261,7 @@ protected: void _notification(int p_what); public: - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref &p_event) { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref &p_event) { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } virtual String get_name() const { return "GridMap"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index be0b846702..e493098211 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -122,7 +122,7 @@ void CachedData::clear_godot_api_cache() { class_GodotResource = NULL; class_Node = NULL; class_Control = NULL; - class_Spatial = NULL; + class_Node3D = NULL; class_WeakRef = NULL; class_Callable = NULL; class_SignalInfo = NULL; @@ -251,7 +251,7 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(GodotResource, GODOT_API_CLASS(Resource)); CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node)); CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); - CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); + CACHE_CLASS_AND_CHECK(Node3D, GODOT_API_CLASS(Node3Dshou)); CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); CACHE_CLASS_AND_CHECK(Callable, GODOT_API_CLASS(Callable)); CACHE_CLASS_AND_CHECK(SignalInfo, GODOT_API_CLASS(SignalInfo)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index b2dacee67c..21c8ed4efe 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -92,7 +92,7 @@ struct CachedData { GDMonoClass *class_GodotResource; GDMonoClass *class_Node; GDMonoClass *class_Control; - GDMonoClass *class_Spatial; + GDMonoClass *class_Node3D; GDMonoClass *class_WeakRef; GDMonoClass *class_Callable; GDMonoClass *class_SignalInfo; diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp deleted file mode 100644 index f3f7ba9ddd..0000000000 --- a/scene/2d/animated_sprite.cpp +++ /dev/null @@ -1,772 +0,0 @@ -/*************************************************************************/ -/* animated_sprite.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "animated_sprite.h" - -#include "core/os/os.h" -#include "scene/scene_string_names.h" - -#define NORMAL_SUFFIX "_normal" -#define SPECULAR_SUFFIX "_specular" - -#ifdef TOOLS_ENABLED -Dictionary AnimatedSprite::_edit_get_state() const { - Dictionary state = Node2D::_edit_get_state(); - state["offset"] = offset; - return state; -} - -void AnimatedSprite::_edit_set_state(const Dictionary &p_state) { - Node2D::_edit_set_state(p_state); - set_offset(p_state["offset"]); -} - -void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { - set_offset(get_offset() - p_pivot); - set_position(get_transform().xform(p_pivot)); -} - -Point2 AnimatedSprite::_edit_get_pivot() const { - return Vector2(); -} - -bool AnimatedSprite::_edit_use_pivot() const { - return true; -} - -Rect2 AnimatedSprite::_edit_get_rect() const { - return _get_rect(); -} - -bool AnimatedSprite::_edit_use_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return false; - } - Ref t; - if (animation) - t = frames->get_frame(animation, frame); - return t.is_valid(); -} -#endif - -Rect2 AnimatedSprite::get_anchorable_rect() const { - return _get_rect(); -} - -Rect2 AnimatedSprite::_get_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return Rect2(); - } - - Ref t; - if (animation) - t = frames->get_frame(animation, frame); - if (t.is_null()) - return Rect2(); - Size2 s = t->get_size(); - - Point2 ofs = offset; - if (centered) - ofs -= Size2(s) / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); - - return Rect2(ofs, s); -} - -void SpriteFrames::add_frame(const StringName &p_anim, const Ref &p_frame, int p_at_pos) { - - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) - E->get().frames.insert(p_at_pos, p_frame); - else - E->get().frames.push_back(p_frame); - - emit_changed(); -} - -int SpriteFrames::get_frame_count(const StringName &p_anim) const { - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - - return E->get().frames.size(); -} - -void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { - - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - E->get().frames.remove(p_idx); - emit_changed(); -} -void SpriteFrames::clear(const StringName &p_anim) { - - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - E->get().frames.clear(); - emit_changed(); -} - -void SpriteFrames::clear_all() { - - animations.clear(); - add_animation("default"); -} - -void SpriteFrames::add_animation(const StringName &p_anim) { - - ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'."); - - animations[p_anim] = Anim(); - animations[p_anim].normal_name = String(p_anim) + NORMAL_SUFFIX; - animations[p_anim].specular_name = String(p_anim) + SPECULAR_SUFFIX; -} - -bool SpriteFrames::has_animation(const StringName &p_anim) const { - - return animations.has(p_anim); -} -void SpriteFrames::remove_animation(const StringName &p_anim) { - - animations.erase(p_anim); -} - -void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) { - - ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'."); - ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists."); - - Anim anim = animations[p_prev]; - animations.erase(p_prev); - animations[p_next] = anim; - animations[p_next].normal_name = String(p_next) + NORMAL_SUFFIX; - animations[p_next].specular_name = String(p_next) + SPECULAR_SUFFIX; -} - -Vector SpriteFrames::_get_animation_list() const { - - Vector ret; - List al; - get_animation_list(&al); - for (List::Element *E = al.front(); E; E = E->next()) { - - ret.push_back(E->get()); - } - - return ret; -} - -void SpriteFrames::get_animation_list(List *r_animations) const { - - for (const Map::Element *E = animations.front(); E; E = E->next()) { - r_animations->push_back(E->key()); - } -} - -Vector SpriteFrames::get_animation_names() const { - - Vector names; - for (const Map::Element *E = animations.front(); E; E = E->next()) { - names.push_back(E->key()); - } - names.sort(); - return names; -} - -void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) { - - ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ")."); - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().speed = p_fps; -} -float SpriteFrames::get_animation_speed(const StringName &p_anim) const { - - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().speed; -} - -void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) { - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().loop = p_loop; -} -bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().loop; -} - -void SpriteFrames::_set_frames(const Array &p_frames) { - - clear_all(); - Map::Element *E = animations.find(SceneStringNames::get_singleton()->_default); - ERR_FAIL_COND(!E); - - E->get().frames.resize(p_frames.size()); - for (int i = 0; i < E->get().frames.size(); i++) - E->get().frames.write[i] = p_frames[i]; -} -Array SpriteFrames::_get_frames() const { - - return Array(); -} - -Array SpriteFrames::_get_animations() const { - - Array anims; - for (Map::Element *E = animations.front(); E; E = E->next()) { - Dictionary d; - d["name"] = E->key(); - d["speed"] = E->get().speed; - d["loop"] = E->get().loop; - Array frames; - for (int i = 0; i < E->get().frames.size(); i++) { - frames.push_back(E->get().frames[i]); - } - d["frames"] = frames; - anims.push_back(d); - } - - return anims; -} -void SpriteFrames::_set_animations(const Array &p_animations) { - - animations.clear(); - for (int i = 0; i < p_animations.size(); i++) { - - Dictionary d = p_animations[i]; - - ERR_CONTINUE(!d.has("name")); - ERR_CONTINUE(!d.has("speed")); - ERR_CONTINUE(!d.has("loop")); - ERR_CONTINUE(!d.has("frames")); - - Anim anim; - anim.speed = d["speed"]; - anim.loop = d["loop"]; - Array frames = d["frames"]; - for (int j = 0; j < frames.size(); j++) { - - RES res = frames[j]; - anim.frames.push_back(res); - } - - animations[d["name"]] = anim; - } -} - -void SpriteFrames::_bind_methods() { - - ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation); - ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation); - ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation); - ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation); - - ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names); - - ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed); - ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed); - - ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop); - ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop); - - ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count); - ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame); - ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame); - ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame); - ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear); - ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all); - - ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames); - ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility - - ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); - ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility -} - -SpriteFrames::SpriteFrames() { - - add_animation(SceneStringNames::get_singleton()->_default); -} - -void AnimatedSprite::_validate_property(PropertyInfo &property) const { - - if (!frames.is_valid()) - return; - if (property.name == "animation") { - - property.hint = PROPERTY_HINT_ENUM; - List names; - frames->get_animation_list(&names); - names.sort_custom(); - - bool current_found = false; - - for (List::Element *E = names.front(); E; E = E->next()) { - if (E->prev()) { - property.hint_string += ","; - } - - property.hint_string += String(E->get()); - if (animation == E->get()) { - current_found = true; - } - } - - if (!current_found) { - if (property.hint_string == String()) { - property.hint_string = String(animation); - } else { - property.hint_string = String(animation) + "," + property.hint_string; - } - } - } - - if (property.name == "frame") { - property.hint = PROPERTY_HINT_RANGE; - if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) { - property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; - } - property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; - } -} - -void AnimatedSprite::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_INTERNAL_PROCESS: { - - if (frames.is_null()) - return; - if (!frames->has_animation(animation)) - return; - if (frame < 0) - return; - - float speed = frames->get_animation_speed(animation) * speed_scale; - if (speed == 0) - return; //do nothing - - float remaining = get_process_delta_time(); - - while (remaining) { - - if (timeout <= 0) { - - timeout = _get_frame_duration(); - - int fc = frames->get_frame_count(animation); - if ((!backwards && frame >= fc - 1) || (backwards && frame <= 0)) { - if (frames->get_animation_loop(animation)) { - if (backwards) - frame = fc - 1; - else - frame = 0; - - emit_signal(SceneStringNames::get_singleton()->animation_finished); - } else { - if (backwards) - frame = 0; - else - frame = fc - 1; - - if (!is_over) { - is_over = true; - emit_signal(SceneStringNames::get_singleton()->animation_finished); - } - } - } else { - if (backwards) - frame--; - else - frame++; - } - - update(); - _change_notify("frame"); - emit_signal(SceneStringNames::get_singleton()->frame_changed); - } - - float to_process = MIN(timeout, remaining); - remaining -= to_process; - timeout -= to_process; - } - } break; - - case NOTIFICATION_DRAW: { - - if (frames.is_null()) - return; - if (frame < 0) - return; - if (!frames->has_animation(animation)) - return; - - Ref texture = frames->get_frame(animation, frame); - if (texture.is_null()) - return; - - Ref normal = frames->get_normal_frame(animation, frame); - Ref specular = frames->get_specular_frame(animation, frame); - - RID ci = get_canvas_item(); - - Size2i s; - s = texture->get_size(); - Point2 ofs = offset; - if (centered) - ofs -= s / 2; - - if (Engine::get_singleton()->get_use_pixel_snap()) { - ofs = ofs.floor(); - } - Rect2 dst_rect(ofs, s); - - if (hflip) - dst_rect.size.x = -dst_rect.size.x; - if (vflip) - dst_rect.size.y = -dst_rect.size.y; - - texture->draw_rect_region(ci, dst_rect, Rect2(Vector2(), texture->get_size()), Color(1, 1, 1), false, normal, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess)); - - } break; - } -} - -void AnimatedSprite::set_sprite_frames(const Ref &p_frames) { - - if (frames.is_valid()) - frames->disconnect("changed", callable_mp(this, &AnimatedSprite::_res_changed)); - frames = p_frames; - if (frames.is_valid()) - frames->connect("changed", callable_mp(this, &AnimatedSprite::_res_changed)); - - if (!frames.is_valid()) { - frame = 0; - } else { - set_frame(frame); - } - - _change_notify(); - _reset_timeout(); - update(); - update_configuration_warning(); -} - -Ref AnimatedSprite::get_sprite_frames() const { - - return frames; -} - -void AnimatedSprite::set_frame(int p_frame) { - - if (!frames.is_valid()) { - return; - } - - if (frames->has_animation(animation)) { - int limit = frames->get_frame_count(animation); - if (p_frame >= limit) - p_frame = limit - 1; - } - - if (p_frame < 0) - p_frame = 0; - - if (frame == p_frame) - return; - - frame = p_frame; - _reset_timeout(); - update(); - _change_notify("frame"); - emit_signal(SceneStringNames::get_singleton()->frame_changed); -} -int AnimatedSprite::get_frame() const { - - return frame; -} - -void AnimatedSprite::set_speed_scale(float p_speed_scale) { - - float elapsed = _get_frame_duration() - timeout; - - speed_scale = MAX(p_speed_scale, 0.0f); - - // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed - _reset_timeout(); - timeout -= elapsed; -} - -float AnimatedSprite::get_speed_scale() const { - - return speed_scale; -} - -void AnimatedSprite::set_centered(bool p_center) { - - centered = p_center; - update(); - item_rect_changed(); -} - -bool AnimatedSprite::is_centered() const { - - return centered; -} - -void AnimatedSprite::set_offset(const Point2 &p_offset) { - - offset = p_offset; - update(); - item_rect_changed(); - _change_notify("offset"); -} -Point2 AnimatedSprite::get_offset() const { - - return offset; -} - -void AnimatedSprite::set_flip_h(bool p_flip) { - - hflip = p_flip; - update(); -} -bool AnimatedSprite::is_flipped_h() const { - - return hflip; -} - -void AnimatedSprite::set_flip_v(bool p_flip) { - - vflip = p_flip; - update(); -} -bool AnimatedSprite::is_flipped_v() const { - - return vflip; -} - -void AnimatedSprite::_res_changed() { - - set_frame(frame); - _change_notify("frame"); - _change_notify("animation"); - update(); -} - -void AnimatedSprite::_set_playing(bool p_playing) { - - if (playing == p_playing) - return; - playing = p_playing; - _reset_timeout(); - set_process_internal(playing); -} - -bool AnimatedSprite::_is_playing() const { - - return playing; -} - -void AnimatedSprite::play(const StringName &p_animation, const bool p_backwards) { - - backwards = p_backwards; - - if (p_animation) { - set_animation(p_animation); - if (backwards && get_frame() == 0) - set_frame(frames->get_frame_count(p_animation) - 1); - } - - _set_playing(true); -} - -void AnimatedSprite::stop() { - - _set_playing(false); -} - -bool AnimatedSprite::is_playing() const { - - return playing; -} - -float AnimatedSprite::_get_frame_duration() { - if (frames.is_valid() && frames->has_animation(animation)) { - float speed = frames->get_animation_speed(animation) * speed_scale; - if (speed > 0) { - return 1.0 / speed; - } - } - return 0.0; -} - -void AnimatedSprite::_reset_timeout() { - - if (!playing) - return; - - timeout = _get_frame_duration(); - is_over = false; -} - -void AnimatedSprite::set_animation(const StringName &p_animation) { - - ERR_FAIL_COND_MSG(frames == NULL, vformat("There is no animation with name '%s'.", p_animation)); - ERR_FAIL_COND_MSG(frames->get_animation_names().find(p_animation) == -1, vformat("There is no animation with name '%s'.", p_animation)); - - if (animation == p_animation) - return; - - animation = p_animation; - _reset_timeout(); - set_frame(0); - _change_notify(); - update(); -} -StringName AnimatedSprite::get_animation() const { - - return animation; -} - -String AnimatedSprite::get_configuration_warning() const { - - if (frames.is_null()) { - return TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite to display frames."); - } - - return String(); -} - -void AnimatedSprite::set_specular_color(const Color &p_color) { - specular_color = p_color; - update(); -} - -Color AnimatedSprite::get_specular_color() const { - return specular_color; -} - -void AnimatedSprite::set_shininess(float p_shininess) { - shininess = CLAMP(p_shininess, 0.0, 1.0); - update(); -} - -float AnimatedSprite::get_shininess() const { - return shininess; -} - -void AnimatedSprite::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames"), &AnimatedSprite::set_sprite_frames); - ClassDB::bind_method(D_METHOD("get_sprite_frames"), &AnimatedSprite::get_sprite_frames); - - ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite::set_animation); - ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite::get_animation); - - ClassDB::bind_method(D_METHOD("_set_playing", "playing"), &AnimatedSprite::_set_playing); - ClassDB::bind_method(D_METHOD("_is_playing"), &AnimatedSprite::_is_playing); - - ClassDB::bind_method(D_METHOD("play", "anim", "backwards"), &AnimatedSprite::play, DEFVAL(StringName()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("stop"), &AnimatedSprite::stop); - ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite::is_playing); - - ClassDB::bind_method(D_METHOD("set_centered", "centered"), &AnimatedSprite::set_centered); - ClassDB::bind_method(D_METHOD("is_centered"), &AnimatedSprite::is_centered); - - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &AnimatedSprite::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &AnimatedSprite::get_offset); - - ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &AnimatedSprite::set_flip_h); - ClassDB::bind_method(D_METHOD("is_flipped_h"), &AnimatedSprite::is_flipped_h); - - ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &AnimatedSprite::set_flip_v); - ClassDB::bind_method(D_METHOD("is_flipped_v"), &AnimatedSprite::is_flipped_v); - - ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite::set_frame); - ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite::get_frame); - - ClassDB::bind_method(D_METHOD("set_speed_scale", "speed_scale"), &AnimatedSprite::set_speed_scale); - ClassDB::bind_method(D_METHOD("get_speed_scale"), &AnimatedSprite::get_speed_scale); - - ClassDB::bind_method(D_METHOD("set_specular_color", "color"), &AnimatedSprite::set_specular_color); - ClassDB::bind_method(D_METHOD("get_specular_color"), &AnimatedSprite::get_specular_color); - - ClassDB::bind_method(D_METHOD("set_shininess", "shininess"), &AnimatedSprite::set_shininess); - ClassDB::bind_method(D_METHOD("get_shininess"), &AnimatedSprite::get_shininess); - - ADD_SIGNAL(MethodInfo("frame_changed")); - ADD_SIGNAL(MethodInfo("animation_finished")); - - ADD_GROUP("Animation", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale"), "set_speed_scale", "get_speed_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); - ADD_GROUP("Lighting", ""); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_shininess", "get_shininess"); - ADD_GROUP("Offset", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); -} - -AnimatedSprite::AnimatedSprite() { - - centered = true; - hflip = false; - vflip = false; - - frame = 0; - speed_scale = 1.0f; - playing = false; - backwards = false; - animation = "default"; - timeout = 0; - is_over = false; - specular_color = Color(1, 1, 1, 1); - shininess = 1.0; -} diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h deleted file mode 100644 index e5d015b07c..0000000000 --- a/scene/2d/animated_sprite.h +++ /dev/null @@ -1,231 +0,0 @@ -/*************************************************************************/ -/* animated_sprite.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef ANIMATED_SPRITE_H -#define ANIMATED_SPRITE_H - -#include "scene/2d/node_2d.h" -#include "scene/resources/texture.h" - -class SpriteFrames : public Resource { - - GDCLASS(SpriteFrames, Resource); - - struct Anim { - - float speed; - bool loop; - Vector> frames; - - Anim() { - loop = true; - speed = 5; - } - - StringName normal_name; - StringName specular_name; - }; - - Color specular_color; - float shininess; - - Map animations; - - Array _get_frames() const; - void _set_frames(const Array &p_frames); - - Array _get_animations() const; - void _set_animations(const Array &p_animations); - - Vector _get_animation_list() const; - -protected: - static void _bind_methods(); - -public: - void add_animation(const StringName &p_anim); - bool has_animation(const StringName &p_anim) const; - void remove_animation(const StringName &p_anim); - void rename_animation(const StringName &p_prev, const StringName &p_next); - - void get_animation_list(List *r_animations) const; - Vector get_animation_names() const; - - void set_animation_speed(const StringName &p_anim, float p_fps); - float get_animation_speed(const StringName &p_anim) const; - - void set_animation_loop(const StringName &p_anim, bool p_loop); - bool get_animation_loop(const StringName &p_anim) const; - - void add_frame(const StringName &p_anim, const Ref &p_frame, int p_at_pos = -1); - int get_frame_count(const StringName &p_anim) const; - _FORCE_INLINE_ Ref get_frame(const StringName &p_anim, int p_idx) const { - - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, Ref(), "Animation '" + String(p_anim) + "' doesn't exist."); - ERR_FAIL_COND_V(p_idx < 0, Ref()); - if (p_idx >= E->get().frames.size()) - return Ref(); - - return E->get().frames[p_idx]; - } - - _FORCE_INLINE_ Ref get_normal_frame(const StringName &p_anim, int p_idx) const { - - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, Ref(), "Animation '" + String(p_anim) + "' doesn't exist."); - ERR_FAIL_COND_V(p_idx < 0, Ref()); - - const Map::Element *EN = animations.find(E->get().normal_name); - - if (!EN || p_idx >= EN->get().frames.size()) - return Ref(); - - return EN->get().frames[p_idx]; - } - - _FORCE_INLINE_ Ref get_specular_frame(const StringName &p_anim, int p_idx) const { - - const Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V(!E, Ref()); - ERR_FAIL_COND_V(p_idx < 0, Ref()); - - const Map::Element *EN = animations.find(E->get().specular_name); - - if (!EN || p_idx >= EN->get().frames.size()) - return Ref(); - - return EN->get().frames[p_idx]; - } - - void set_frame(const StringName &p_anim, int p_idx, const Ref &p_frame) { - Map::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - ERR_FAIL_COND(p_idx < 0); - if (p_idx >= E->get().frames.size()) - return; - E->get().frames.write[p_idx] = p_frame; - } - void remove_frame(const StringName &p_anim, int p_idx); - void clear(const StringName &p_anim); - void clear_all(); - - SpriteFrames(); -}; - -class AnimatedSprite : public Node2D { - - GDCLASS(AnimatedSprite, Node2D); - - Ref frames; - bool playing; - bool backwards; - StringName animation; - int frame; - float speed_scale; - - bool centered; - Point2 offset; - - bool is_over; - float timeout; - - bool hflip; - bool vflip; - - void _res_changed(); - - float _get_frame_duration(); - void _reset_timeout(); - void _set_playing(bool p_playing); - bool _is_playing() const; - Rect2 _get_rect() const; - - Color specular_color; - float shininess; - -protected: - static void _bind_methods(); - void _notification(int p_what); - virtual void _validate_property(PropertyInfo &property) const; - -public: -#ifdef TOOLS_ENABLED - virtual Dictionary _edit_get_state() const; - virtual void _edit_set_state(const Dictionary &p_state); - - virtual void _edit_set_pivot(const Point2 &p_pivot); - virtual Point2 _edit_get_pivot() const; - virtual bool _edit_use_pivot() const; - virtual Rect2 _edit_get_rect() const; - virtual bool _edit_use_rect() const; -#endif - - virtual Rect2 get_anchorable_rect() const; - - void set_sprite_frames(const Ref &p_frames); - Ref get_sprite_frames() const; - - void play(const StringName &p_animation = StringName(), const bool p_backwards = false); - void stop(); - bool is_playing() const; - - void set_animation(const StringName &p_animation); - StringName get_animation() const; - - void set_frame(int p_frame); - int get_frame() const; - - void set_speed_scale(float p_speed_scale); - float get_speed_scale() const; - - void set_centered(bool p_center); - bool is_centered() const; - - void set_offset(const Point2 &p_offset); - Point2 get_offset() const; - - void set_flip_h(bool p_flip); - bool is_flipped_h() const; - - void set_flip_v(bool p_flip); - bool is_flipped_v() const; - - void set_specular_color(const Color &p_color); - Color get_specular_color() const; - - void set_shininess(float p_shininess); - float get_shininess() const; - - virtual String get_configuration_warning() const; - AnimatedSprite(); -}; - -#endif // ANIMATED_SPRITE_H diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp new file mode 100644 index 0000000000..4cedfc0c20 --- /dev/null +++ b/scene/2d/animated_sprite_2d.cpp @@ -0,0 +1,772 @@ +/*************************************************************************/ +/* animated_sprite_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "animated_sprite_2d.h" + +#include "core/os/os.h" +#include "scene/scene_string_names.h" + +#define NORMAL_SUFFIX "_normal" +#define SPECULAR_SUFFIX "_specular" + +#ifdef TOOLS_ENABLED +Dictionary AnimatedSprite2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void AnimatedSprite2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void AnimatedSprite2D::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} + +Point2 AnimatedSprite2D::_edit_get_pivot() const { + return Vector2(); +} + +bool AnimatedSprite2D::_edit_use_pivot() const { + return true; +} + +Rect2 AnimatedSprite2D::_edit_get_rect() const { + return _get_rect(); +} + +bool AnimatedSprite2D::_edit_use_rect() const { + if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + return false; + } + Ref t; + if (animation) + t = frames->get_frame(animation, frame); + return t.is_valid(); +} +#endif + +Rect2 AnimatedSprite2D::get_anchorable_rect() const { + return _get_rect(); +} + +Rect2 AnimatedSprite2D::_get_rect() const { + if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + return Rect2(); + } + + Ref t; + if (animation) + t = frames->get_frame(animation, frame); + if (t.is_null()) + return Rect2(); + Size2 s = t->get_size(); + + Point2 ofs = offset; + if (centered) + ofs -= Size2(s) / 2; + + if (s == Size2(0, 0)) + s = Size2(1, 1); + + return Rect2(ofs, s); +} + +void SpriteFrames::add_frame(const StringName &p_anim, const Ref &p_frame, int p_at_pos) { + + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) + E->get().frames.insert(p_at_pos, p_frame); + else + E->get().frames.push_back(p_frame); + + emit_changed(); +} + +int SpriteFrames::get_frame_count(const StringName &p_anim) const { + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); + + return E->get().frames.size(); +} + +void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { + + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + E->get().frames.remove(p_idx); + emit_changed(); +} +void SpriteFrames::clear(const StringName &p_anim) { + + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + E->get().frames.clear(); + emit_changed(); +} + +void SpriteFrames::clear_all() { + + animations.clear(); + add_animation("default"); +} + +void SpriteFrames::add_animation(const StringName &p_anim) { + + ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'."); + + animations[p_anim] = Anim(); + animations[p_anim].normal_name = String(p_anim) + NORMAL_SUFFIX; + animations[p_anim].specular_name = String(p_anim) + SPECULAR_SUFFIX; +} + +bool SpriteFrames::has_animation(const StringName &p_anim) const { + + return animations.has(p_anim); +} +void SpriteFrames::remove_animation(const StringName &p_anim) { + + animations.erase(p_anim); +} + +void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) { + + ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'."); + ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists."); + + Anim anim = animations[p_prev]; + animations.erase(p_prev); + animations[p_next] = anim; + animations[p_next].normal_name = String(p_next) + NORMAL_SUFFIX; + animations[p_next].specular_name = String(p_next) + SPECULAR_SUFFIX; +} + +Vector SpriteFrames::_get_animation_list() const { + + Vector ret; + List al; + get_animation_list(&al); + for (List::Element *E = al.front(); E; E = E->next()) { + + ret.push_back(E->get()); + } + + return ret; +} + +void SpriteFrames::get_animation_list(List *r_animations) const { + + for (const Map::Element *E = animations.front(); E; E = E->next()) { + r_animations->push_back(E->key()); + } +} + +Vector SpriteFrames::get_animation_names() const { + + Vector names; + for (const Map::Element *E = animations.front(); E; E = E->next()) { + names.push_back(E->key()); + } + names.sort(); + return names; +} + +void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) { + + ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ")."); + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + E->get().speed = p_fps; +} +float SpriteFrames::get_animation_speed(const StringName &p_anim) const { + + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); + return E->get().speed; +} + +void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) { + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + E->get().loop = p_loop; +} +bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist."); + return E->get().loop; +} + +void SpriteFrames::_set_frames(const Array &p_frames) { + + clear_all(); + Map::Element *E = animations.find(SceneStringNames::get_singleton()->_default); + ERR_FAIL_COND(!E); + + E->get().frames.resize(p_frames.size()); + for (int i = 0; i < E->get().frames.size(); i++) + E->get().frames.write[i] = p_frames[i]; +} +Array SpriteFrames::_get_frames() const { + + return Array(); +} + +Array SpriteFrames::_get_animations() const { + + Array anims; + for (Map::Element *E = animations.front(); E; E = E->next()) { + Dictionary d; + d["name"] = E->key(); + d["speed"] = E->get().speed; + d["loop"] = E->get().loop; + Array frames; + for (int i = 0; i < E->get().frames.size(); i++) { + frames.push_back(E->get().frames[i]); + } + d["frames"] = frames; + anims.push_back(d); + } + + return anims; +} +void SpriteFrames::_set_animations(const Array &p_animations) { + + animations.clear(); + for (int i = 0; i < p_animations.size(); i++) { + + Dictionary d = p_animations[i]; + + ERR_CONTINUE(!d.has("name")); + ERR_CONTINUE(!d.has("speed")); + ERR_CONTINUE(!d.has("loop")); + ERR_CONTINUE(!d.has("frames")); + + Anim anim; + anim.speed = d["speed"]; + anim.loop = d["loop"]; + Array frames = d["frames"]; + for (int j = 0; j < frames.size(); j++) { + + RES res = frames[j]; + anim.frames.push_back(res); + } + + animations[d["name"]] = anim; + } +} + +void SpriteFrames::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation); + ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation); + ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation); + ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation); + + ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names); + + ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed); + ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed); + + ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop); + ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop); + + ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count); + ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame); + ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame); + ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame); + ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear); + ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all); + + ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames); + ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility + + ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); + ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility +} + +SpriteFrames::SpriteFrames() { + + add_animation(SceneStringNames::get_singleton()->_default); +} + +void AnimatedSprite2D::_validate_property(PropertyInfo &property) const { + + if (!frames.is_valid()) + return; + if (property.name == "animation") { + + property.hint = PROPERTY_HINT_ENUM; + List names; + frames->get_animation_list(&names); + names.sort_custom(); + + bool current_found = false; + + for (List::Element *E = names.front(); E; E = E->next()) { + if (E->prev()) { + property.hint_string += ","; + } + + property.hint_string += String(E->get()); + if (animation == E->get()) { + current_found = true; + } + } + + if (!current_found) { + if (property.hint_string == String()) { + property.hint_string = String(animation); + } else { + property.hint_string = String(animation) + "," + property.hint_string; + } + } + } + + if (property.name == "frame") { + property.hint = PROPERTY_HINT_RANGE; + if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) { + property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; + } + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; + } +} + +void AnimatedSprite2D::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_INTERNAL_PROCESS: { + + if (frames.is_null()) + return; + if (!frames->has_animation(animation)) + return; + if (frame < 0) + return; + + float speed = frames->get_animation_speed(animation) * speed_scale; + if (speed == 0) + return; //do nothing + + float remaining = get_process_delta_time(); + + while (remaining) { + + if (timeout <= 0) { + + timeout = _get_frame_duration(); + + int fc = frames->get_frame_count(animation); + if ((!backwards && frame >= fc - 1) || (backwards && frame <= 0)) { + if (frames->get_animation_loop(animation)) { + if (backwards) + frame = fc - 1; + else + frame = 0; + + emit_signal(SceneStringNames::get_singleton()->animation_finished); + } else { + if (backwards) + frame = 0; + else + frame = fc - 1; + + if (!is_over) { + is_over = true; + emit_signal(SceneStringNames::get_singleton()->animation_finished); + } + } + } else { + if (backwards) + frame--; + else + frame++; + } + + update(); + _change_notify("frame"); + emit_signal(SceneStringNames::get_singleton()->frame_changed); + } + + float to_process = MIN(timeout, remaining); + remaining -= to_process; + timeout -= to_process; + } + } break; + + case NOTIFICATION_DRAW: { + + if (frames.is_null()) + return; + if (frame < 0) + return; + if (!frames->has_animation(animation)) + return; + + Ref texture = frames->get_frame(animation, frame); + if (texture.is_null()) + return; + + Ref normal = frames->get_normal_frame(animation, frame); + Ref specular = frames->get_specular_frame(animation, frame); + + RID ci = get_canvas_item(); + + Size2i s; + s = texture->get_size(); + Point2 ofs = offset; + if (centered) + ofs -= s / 2; + + if (Engine::get_singleton()->get_use_pixel_snap()) { + ofs = ofs.floor(); + } + Rect2 dst_rect(ofs, s); + + if (hflip) + dst_rect.size.x = -dst_rect.size.x; + if (vflip) + dst_rect.size.y = -dst_rect.size.y; + + texture->draw_rect_region(ci, dst_rect, Rect2(Vector2(), texture->get_size()), Color(1, 1, 1), false, normal, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess)); + + } break; + } +} + +void AnimatedSprite2D::set_sprite_frames(const Ref &p_frames) { + + if (frames.is_valid()) + frames->disconnect("changed", callable_mp(this, &AnimatedSprite2D::_res_changed)); + frames = p_frames; + if (frames.is_valid()) + frames->connect("changed", callable_mp(this, &AnimatedSprite2D::_res_changed)); + + if (!frames.is_valid()) { + frame = 0; + } else { + set_frame(frame); + } + + _change_notify(); + _reset_timeout(); + update(); + update_configuration_warning(); +} + +Ref AnimatedSprite2D::get_sprite_frames() const { + + return frames; +} + +void AnimatedSprite2D::set_frame(int p_frame) { + + if (!frames.is_valid()) { + return; + } + + if (frames->has_animation(animation)) { + int limit = frames->get_frame_count(animation); + if (p_frame >= limit) + p_frame = limit - 1; + } + + if (p_frame < 0) + p_frame = 0; + + if (frame == p_frame) + return; + + frame = p_frame; + _reset_timeout(); + update(); + _change_notify("frame"); + emit_signal(SceneStringNames::get_singleton()->frame_changed); +} +int AnimatedSprite2D::get_frame() const { + + return frame; +} + +void AnimatedSprite2D::set_speed_scale(float p_speed_scale) { + + float elapsed = _get_frame_duration() - timeout; + + speed_scale = MAX(p_speed_scale, 0.0f); + + // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed + _reset_timeout(); + timeout -= elapsed; +} + +float AnimatedSprite2D::get_speed_scale() const { + + return speed_scale; +} + +void AnimatedSprite2D::set_centered(bool p_center) { + + centered = p_center; + update(); + item_rect_changed(); +} + +bool AnimatedSprite2D::is_centered() const { + + return centered; +} + +void AnimatedSprite2D::set_offset(const Point2 &p_offset) { + + offset = p_offset; + update(); + item_rect_changed(); + _change_notify("offset"); +} +Point2 AnimatedSprite2D::get_offset() const { + + return offset; +} + +void AnimatedSprite2D::set_flip_h(bool p_flip) { + + hflip = p_flip; + update(); +} +bool AnimatedSprite2D::is_flipped_h() const { + + return hflip; +} + +void AnimatedSprite2D::set_flip_v(bool p_flip) { + + vflip = p_flip; + update(); +} +bool AnimatedSprite2D::is_flipped_v() const { + + return vflip; +} + +void AnimatedSprite2D::_res_changed() { + + set_frame(frame); + _change_notify("frame"); + _change_notify("animation"); + update(); +} + +void AnimatedSprite2D::_set_playing(bool p_playing) { + + if (playing == p_playing) + return; + playing = p_playing; + _reset_timeout(); + set_process_internal(playing); +} + +bool AnimatedSprite2D::_is_playing() const { + + return playing; +} + +void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) { + + backwards = p_backwards; + + if (p_animation) { + set_animation(p_animation); + if (backwards && get_frame() == 0) + set_frame(frames->get_frame_count(p_animation) - 1); + } + + _set_playing(true); +} + +void AnimatedSprite2D::stop() { + + _set_playing(false); +} + +bool AnimatedSprite2D::is_playing() const { + + return playing; +} + +float AnimatedSprite2D::_get_frame_duration() { + if (frames.is_valid() && frames->has_animation(animation)) { + float speed = frames->get_animation_speed(animation) * speed_scale; + if (speed > 0) { + return 1.0 / speed; + } + } + return 0.0; +} + +void AnimatedSprite2D::_reset_timeout() { + + if (!playing) + return; + + timeout = _get_frame_duration(); + is_over = false; +} + +void AnimatedSprite2D::set_animation(const StringName &p_animation) { + + ERR_FAIL_COND_MSG(frames == NULL, vformat("There is no animation with name '%s'.", p_animation)); + ERR_FAIL_COND_MSG(frames->get_animation_names().find(p_animation) == -1, vformat("There is no animation with name '%s'.", p_animation)); + + if (animation == p_animation) + return; + + animation = p_animation; + _reset_timeout(); + set_frame(0); + _change_notify(); + update(); +} +StringName AnimatedSprite2D::get_animation() const { + + return animation; +} + +String AnimatedSprite2D::get_configuration_warning() const { + + if (frames.is_null()) { + return TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite to display frames."); + } + + return String(); +} + +void AnimatedSprite2D::set_specular_color(const Color &p_color) { + specular_color = p_color; + update(); +} + +Color AnimatedSprite2D::get_specular_color() const { + return specular_color; +} + +void AnimatedSprite2D::set_shininess(float p_shininess) { + shininess = CLAMP(p_shininess, 0.0, 1.0); + update(); +} + +float AnimatedSprite2D::get_shininess() const { + return shininess; +} + +void AnimatedSprite2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_sprite_frames", "sprite_frames"), &AnimatedSprite2D::set_sprite_frames); + ClassDB::bind_method(D_METHOD("get_sprite_frames"), &AnimatedSprite2D::get_sprite_frames); + + ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite2D::set_animation); + ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite2D::get_animation); + + ClassDB::bind_method(D_METHOD("_set_playing", "playing"), &AnimatedSprite2D::_set_playing); + ClassDB::bind_method(D_METHOD("_is_playing"), &AnimatedSprite2D::_is_playing); + + ClassDB::bind_method(D_METHOD("play", "anim", "backwards"), &AnimatedSprite2D::play, DEFVAL(StringName()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("stop"), &AnimatedSprite2D::stop); + ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite2D::is_playing); + + ClassDB::bind_method(D_METHOD("set_centered", "centered"), &AnimatedSprite2D::set_centered); + ClassDB::bind_method(D_METHOD("is_centered"), &AnimatedSprite2D::is_centered); + + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &AnimatedSprite2D::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &AnimatedSprite2D::get_offset); + + ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &AnimatedSprite2D::set_flip_h); + ClassDB::bind_method(D_METHOD("is_flipped_h"), &AnimatedSprite2D::is_flipped_h); + + ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &AnimatedSprite2D::set_flip_v); + ClassDB::bind_method(D_METHOD("is_flipped_v"), &AnimatedSprite2D::is_flipped_v); + + ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite2D::set_frame); + ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite2D::get_frame); + + ClassDB::bind_method(D_METHOD("set_speed_scale", "speed_scale"), &AnimatedSprite2D::set_speed_scale); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &AnimatedSprite2D::get_speed_scale); + + ClassDB::bind_method(D_METHOD("set_specular_color", "color"), &AnimatedSprite2D::set_specular_color); + ClassDB::bind_method(D_METHOD("get_specular_color"), &AnimatedSprite2D::get_specular_color); + + ClassDB::bind_method(D_METHOD("set_shininess", "shininess"), &AnimatedSprite2D::set_shininess); + ClassDB::bind_method(D_METHOD("get_shininess"), &AnimatedSprite2D::get_shininess); + + ADD_SIGNAL(MethodInfo("frame_changed")); + ADD_SIGNAL(MethodInfo("animation_finished")); + + ADD_GROUP("Animation", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); + ADD_GROUP("Lighting", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_shininess", "get_shininess"); + ADD_GROUP("Offset", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); +} + +AnimatedSprite2D::AnimatedSprite2D() { + + centered = true; + hflip = false; + vflip = false; + + frame = 0; + speed_scale = 1.0f; + playing = false; + backwards = false; + animation = "default"; + timeout = 0; + is_over = false; + specular_color = Color(1, 1, 1, 1); + shininess = 1.0; +} diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h new file mode 100644 index 0000000000..726ecefd32 --- /dev/null +++ b/scene/2d/animated_sprite_2d.h @@ -0,0 +1,231 @@ +/*************************************************************************/ +/* animated_sprite_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ANIMATED_SPRITE_2D_H +#define ANIMATED_SPRITE_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/resources/texture.h" + +class SpriteFrames : public Resource { + + GDCLASS(SpriteFrames, Resource); + + struct Anim { + + float speed; + bool loop; + Vector> frames; + + Anim() { + loop = true; + speed = 5; + } + + StringName normal_name; + StringName specular_name; + }; + + Color specular_color; + float shininess; + + Map animations; + + Array _get_frames() const; + void _set_frames(const Array &p_frames); + + Array _get_animations() const; + void _set_animations(const Array &p_animations); + + Vector _get_animation_list() const; + +protected: + static void _bind_methods(); + +public: + void add_animation(const StringName &p_anim); + bool has_animation(const StringName &p_anim) const; + void remove_animation(const StringName &p_anim); + void rename_animation(const StringName &p_prev, const StringName &p_next); + + void get_animation_list(List *r_animations) const; + Vector get_animation_names() const; + + void set_animation_speed(const StringName &p_anim, float p_fps); + float get_animation_speed(const StringName &p_anim) const; + + void set_animation_loop(const StringName &p_anim, bool p_loop); + bool get_animation_loop(const StringName &p_anim) const; + + void add_frame(const StringName &p_anim, const Ref &p_frame, int p_at_pos = -1); + int get_frame_count(const StringName &p_anim) const; + _FORCE_INLINE_ Ref get_frame(const StringName &p_anim, int p_idx) const { + + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, Ref(), "Animation '" + String(p_anim) + "' doesn't exist."); + ERR_FAIL_COND_V(p_idx < 0, Ref()); + if (p_idx >= E->get().frames.size()) + return Ref(); + + return E->get().frames[p_idx]; + } + + _FORCE_INLINE_ Ref get_normal_frame(const StringName &p_anim, int p_idx) const { + + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, Ref(), "Animation '" + String(p_anim) + "' doesn't exist."); + ERR_FAIL_COND_V(p_idx < 0, Ref()); + + const Map::Element *EN = animations.find(E->get().normal_name); + + if (!EN || p_idx >= EN->get().frames.size()) + return Ref(); + + return EN->get().frames[p_idx]; + } + + _FORCE_INLINE_ Ref get_specular_frame(const StringName &p_anim, int p_idx) const { + + const Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V(!E, Ref()); + ERR_FAIL_COND_V(p_idx < 0, Ref()); + + const Map::Element *EN = animations.find(E->get().specular_name); + + if (!EN || p_idx >= EN->get().frames.size()) + return Ref(); + + return EN->get().frames[p_idx]; + } + + void set_frame(const StringName &p_anim, int p_idx, const Ref &p_frame) { + Map::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + ERR_FAIL_COND(p_idx < 0); + if (p_idx >= E->get().frames.size()) + return; + E->get().frames.write[p_idx] = p_frame; + } + void remove_frame(const StringName &p_anim, int p_idx); + void clear(const StringName &p_anim); + void clear_all(); + + SpriteFrames(); +}; + +class AnimatedSprite2D : public Node2D { + + GDCLASS(AnimatedSprite2D, Node2D); + + Ref frames; + bool playing; + bool backwards; + StringName animation; + int frame; + float speed_scale; + + bool centered; + Point2 offset; + + bool is_over; + float timeout; + + bool hflip; + bool vflip; + + void _res_changed(); + + float _get_frame_duration(); + void _reset_timeout(); + void _set_playing(bool p_playing); + bool _is_playing() const; + Rect2 _get_rect() const; + + Color specular_color; + float shininess; + +protected: + static void _bind_methods(); + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; + +public: +#ifdef TOOLS_ENABLED + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; +#endif + + virtual Rect2 get_anchorable_rect() const; + + void set_sprite_frames(const Ref &p_frames); + Ref get_sprite_frames() const; + + void play(const StringName &p_animation = StringName(), const bool p_backwards = false); + void stop(); + bool is_playing() const; + + void set_animation(const StringName &p_animation); + StringName get_animation() const; + + void set_frame(int p_frame); + int get_frame() const; + + void set_speed_scale(float p_speed_scale); + float get_speed_scale() const; + + void set_centered(bool p_center); + bool is_centered() const; + + void set_offset(const Point2 &p_offset); + Point2 get_offset() const; + + void set_flip_h(bool p_flip); + bool is_flipped_h() const; + + void set_flip_v(bool p_flip); + bool is_flipped_v() const; + + void set_specular_color(const Color &p_color); + Color get_specular_color() const; + + void set_shininess(float p_shininess); + float get_shininess() const; + + virtual String get_configuration_warning() const; + AnimatedSprite2D(); +}; + +#endif // ANIMATED_SPRITE_H diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp deleted file mode 100644 index a6fb6f7435..0000000000 --- a/scene/2d/sprite.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/*************************************************************************/ -/* sprite.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "sprite.h" - -#include "core/core_string_names.h" -#include "core/os/os.h" -#include "scene/main/window.h" -#include "scene/scene_string_names.h" - -#ifdef TOOLS_ENABLED -Dictionary Sprite::_edit_get_state() const { - Dictionary state = Node2D::_edit_get_state(); - state["offset"] = offset; - return state; -} - -void Sprite::_edit_set_state(const Dictionary &p_state) { - Node2D::_edit_set_state(p_state); - set_offset(p_state["offset"]); -} - -void Sprite::_edit_set_pivot(const Point2 &p_pivot) { - set_offset(get_offset() - p_pivot); - set_position(get_transform().xform(p_pivot)); -} - -Point2 Sprite::_edit_get_pivot() const { - return Vector2(); -} - -bool Sprite::_edit_use_pivot() const { - return true; -} - -bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - return is_pixel_opaque(p_point); -} - -Rect2 Sprite::_edit_get_rect() const { - return get_rect(); -} - -bool Sprite::_edit_use_rect() const { - return texture.is_valid(); -} -#endif - -Rect2 Sprite::get_anchorable_rect() const { - return get_rect(); -} - -void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { - - Rect2 base_rect; - - if (region) { - r_filter_clip = region_filter_clip; - base_rect = region_rect; - } else { - r_filter_clip = false; - base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); - } - - Size2 frame_size = base_rect.size / Size2(hframes, vframes); - Point2 frame_offset = Point2(frame % hframes, frame / hframes); - frame_offset *= frame_size; - - r_src_rect.size = frame_size; - r_src_rect.position = base_rect.position + frame_offset; - - Point2 dest_offset = offset; - if (centered) - dest_offset -= frame_size / 2; - if (Engine::get_singleton()->get_use_pixel_snap()) { - dest_offset = dest_offset.floor(); - } - - r_dst_rect = Rect2(dest_offset, frame_size); - - if (hflip) - r_dst_rect.size.x = -r_dst_rect.size.x; - if (vflip) - r_dst_rect.size.y = -r_dst_rect.size.y; -} - -void Sprite::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_DRAW: { - - if (texture.is_null()) - return; - - RID ci = get_canvas_item(); - - /* - texture->draw(ci,Point2()); - break; - */ - - Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); - texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess), VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, filter_clip); - - } break; - } -} - -void Sprite::set_texture(const Ref &p_texture) { - - if (p_texture == texture) - return; - - if (texture.is_valid()) - texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite::_texture_changed)); - - texture = p_texture; - - if (texture.is_valid()) - texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite::_texture_changed)); - - update(); - emit_signal("texture_changed"); - item_rect_changed(); - _change_notify("texture"); -} - -void Sprite::set_normal_map(const Ref &p_texture) { - - normal_map = p_texture; - update(); -} - -Ref Sprite::get_normal_map() const { - - return normal_map; -} - -void Sprite::set_specular_map(const Ref &p_texture) { - - specular = p_texture; - update(); -} - -Ref Sprite::get_specular_map() const { - - return specular; -} - -void Sprite::set_specular_color(const Color &p_color) { - specular_color = p_color; - update(); -} - -Color Sprite::get_specular_color() const { - return specular_color; -} - -void Sprite::set_shininess(float p_shininess) { - shininess = CLAMP(p_shininess, 0.0, 1.0); - update(); -} - -float Sprite::get_shininess() const { - return shininess; -} - -Ref Sprite::get_texture() const { - - return texture; -} - -void Sprite::set_centered(bool p_center) { - - centered = p_center; - update(); - item_rect_changed(); -} - -bool Sprite::is_centered() const { - - return centered; -} - -void Sprite::set_offset(const Point2 &p_offset) { - - offset = p_offset; - update(); - item_rect_changed(); - _change_notify("offset"); -} -Point2 Sprite::get_offset() const { - - return offset; -} - -void Sprite::set_flip_h(bool p_flip) { - - hflip = p_flip; - update(); -} -bool Sprite::is_flipped_h() const { - - return hflip; -} - -void Sprite::set_flip_v(bool p_flip) { - - vflip = p_flip; - update(); -} -bool Sprite::is_flipped_v() const { - - return vflip; -} - -void Sprite::set_region(bool p_region) { - - if (p_region == region) - return; - - region = p_region; - update(); -} - -bool Sprite::is_region() const { - - return region; -} - -void Sprite::set_region_rect(const Rect2 &p_region_rect) { - - if (region_rect == p_region_rect) - return; - - region_rect = p_region_rect; - - if (region) - item_rect_changed(); - - _change_notify("region_rect"); -} - -Rect2 Sprite::get_region_rect() const { - - return region_rect; -} - -void Sprite::set_region_filter_clip(bool p_enable) { - region_filter_clip = p_enable; - update(); -} - -bool Sprite::is_region_filter_clip_enabled() const { - return region_filter_clip; -} - -void Sprite::set_frame(int p_frame) { - - ERR_FAIL_INDEX(p_frame, vframes * hframes); - - if (frame != p_frame) - item_rect_changed(); - - frame = p_frame; - - _change_notify("frame"); - _change_notify("frame_coords"); - emit_signal(SceneStringNames::get_singleton()->frame_changed); -} - -int Sprite::get_frame() const { - - return frame; -} - -void Sprite::set_frame_coords(const Vector2 &p_coord) { - ERR_FAIL_INDEX(int(p_coord.x), hframes); - ERR_FAIL_INDEX(int(p_coord.y), vframes); - - set_frame(int(p_coord.y) * hframes + int(p_coord.x)); -} - -Vector2 Sprite::get_frame_coords() const { - return Vector2(frame % hframes, frame / hframes); -} - -void Sprite::set_vframes(int p_amount) { - - ERR_FAIL_COND_MSG(p_amount < 1, "Amount of vframes cannot be smaller than 1."); - vframes = p_amount; - update(); - item_rect_changed(); - _change_notify(); -} -int Sprite::get_vframes() const { - - return vframes; -} - -void Sprite::set_hframes(int p_amount) { - - ERR_FAIL_COND_MSG(p_amount < 1, "Amount of hframes cannot be smaller than 1."); - hframes = p_amount; - update(); - item_rect_changed(); - _change_notify(); -} -int Sprite::get_hframes() const { - - return hframes; -} - -bool Sprite::is_pixel_opaque(const Point2 &p_point) const { - - if (texture.is_null()) - return false; - - if (texture->get_size().width == 0 || texture->get_size().height == 0) - return false; - - Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); - dst_rect.size = dst_rect.size.abs(); - - if (!dst_rect.has_point(p_point)) - return false; - - Vector2 q = (p_point - dst_rect.position) / dst_rect.size; - if (hflip) - q.x = 1.0f - q.x; - if (vflip) - q.y = 1.0f - q.y; - q = q * src_rect.size + src_rect.position; -#ifndef _MSC_VER -#warning this need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that) -#endif - bool is_repeat = false; - bool is_mirrored_repeat = false; - if (is_repeat) { - int mirror_x = 0; - int mirror_y = 0; - if (is_mirrored_repeat) { - mirror_x = (int)(q.x / texture->get_size().width); - mirror_y = (int)(q.y / texture->get_size().height); - } - q.x = Math::fmod(q.x, texture->get_size().width); - q.y = Math::fmod(q.y, texture->get_size().height); - if (mirror_x % 2 == 1) { - q.x = texture->get_size().width - q.x - 1; - } - if (mirror_y % 2 == 1) { - q.y = texture->get_size().height - q.y - 1; - } - } else { - q.x = MIN(q.x, texture->get_size().width - 1); - q.y = MIN(q.y, texture->get_size().height - 1); - } - - return texture->is_pixel_opaque((int)q.x, (int)q.y); -} - -Rect2 Sprite::get_rect() const { - - if (texture.is_null()) - return Rect2(0, 0, 1, 1); - - Size2i s; - - if (region) { - s = region_rect.size; - } else { - s = texture->get_size(); - } - - s = s / Point2(hframes, vframes); - - Point2 ofs = offset; - if (centered) - ofs -= Size2(s) / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); - - return Rect2(ofs, s); -} - -void Sprite::_validate_property(PropertyInfo &property) const { - - if (property.name == "frame") { - property.hint = PROPERTY_HINT_RANGE; - property.hint_string = "0," + itos(vframes * hframes - 1) + ",1"; - property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; - } - - if (property.name == "frame_coords") { - property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; - } -} - -void Sprite::_texture_changed() { - - // Changes to the texture need to trigger an update to make - // the editor redraw the sprite with the updated texture. - if (texture.is_valid()) { - update(); - } -} - -void Sprite::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite::set_texture); - ClassDB::bind_method(D_METHOD("get_texture"), &Sprite::get_texture); - - ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &Sprite::set_normal_map); - ClassDB::bind_method(D_METHOD("get_normal_map"), &Sprite::get_normal_map); - - ClassDB::bind_method(D_METHOD("set_specular_map", "specular_map"), &Sprite::set_specular_map); - ClassDB::bind_method(D_METHOD("get_specular_map"), &Sprite::get_specular_map); - - ClassDB::bind_method(D_METHOD("set_specular_color", "specular_color"), &Sprite::set_specular_color); - ClassDB::bind_method(D_METHOD("get_specular_color"), &Sprite::get_specular_color); - - ClassDB::bind_method(D_METHOD("set_shininess", "shininess"), &Sprite::set_shininess); - ClassDB::bind_method(D_METHOD("get_shininess"), &Sprite::get_shininess); - - ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Sprite::set_centered); - ClassDB::bind_method(D_METHOD("is_centered"), &Sprite::is_centered); - - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Sprite::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &Sprite::get_offset); - - ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &Sprite::set_flip_h); - ClassDB::bind_method(D_METHOD("is_flipped_h"), &Sprite::is_flipped_h); - - ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite::set_flip_v); - ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite::is_flipped_v); - - ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite::set_region); - ClassDB::bind_method(D_METHOD("is_region"), &Sprite::is_region); - - ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite::is_pixel_opaque); - - ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect); - ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect); - - ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite::set_region_filter_clip); - ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite::is_region_filter_clip_enabled); - - ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite::set_frame); - ClassDB::bind_method(D_METHOD("get_frame"), &Sprite::get_frame); - - ClassDB::bind_method(D_METHOD("set_frame_coords", "coords"), &Sprite::set_frame_coords); - ClassDB::bind_method(D_METHOD("get_frame_coords"), &Sprite::get_frame_coords); - - ClassDB::bind_method(D_METHOD("set_vframes", "vframes"), &Sprite::set_vframes); - ClassDB::bind_method(D_METHOD("get_vframes"), &Sprite::get_vframes); - - ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite::set_hframes); - ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite::get_hframes); - - ClassDB::bind_method(D_METHOD("get_rect"), &Sprite::get_rect); - - ADD_SIGNAL(MethodInfo("frame_changed")); - ADD_SIGNAL(MethodInfo("texture_changed")); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); - ADD_GROUP("Lighting", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_map", "get_normal_map"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "specular_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_specular_map", "get_specular_map"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_shininess", "get_shininess"); - ADD_GROUP("Offset", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); - ADD_GROUP("Animation", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); - - ADD_GROUP("Region", "region_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); - ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); -} - -Sprite::Sprite() { - - centered = true; - hflip = false; - vflip = false; - region = false; - region_filter_clip = false; - shininess = 1.0; - specular_color = Color(1, 1, 1, 1); - - frame = 0; - - vframes = 1; - hframes = 1; -} - -Sprite::~Sprite() { -} diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h deleted file mode 100644 index a96f023231..0000000000 --- a/scene/2d/sprite.h +++ /dev/null @@ -1,143 +0,0 @@ -/*************************************************************************/ -/* sprite.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPRITE_H -#define SPRITE_H - -#include "scene/2d/node_2d.h" -#include "scene/resources/texture.h" - -class Sprite : public Node2D { - - GDCLASS(Sprite, Node2D); - - Ref texture; - Ref normal_map; - Ref specular; - Color specular_color; - float shininess; - - bool centered; - Point2 offset; - - bool hflip; - bool vflip; - bool region; - Rect2 region_rect; - bool region_filter_clip; - - int frame; - - int vframes; - int hframes; - - void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const; - - void _texture_changed(); - -protected: - void _notification(int p_what); - - static void _bind_methods(); - - virtual void _validate_property(PropertyInfo &property) const; - -public: -#ifdef TOOLS_ENABLED - virtual Dictionary _edit_get_state() const; - virtual void _edit_set_state(const Dictionary &p_state); - - virtual void _edit_set_pivot(const Point2 &p_pivot); - virtual Point2 _edit_get_pivot() const; - virtual bool _edit_use_pivot() const; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - - virtual Rect2 _edit_get_rect() const; - virtual bool _edit_use_rect() const; -#endif - - bool is_pixel_opaque(const Point2 &p_point) const; - - void set_texture(const Ref &p_texture); - Ref get_texture() const; - - void set_normal_map(const Ref &p_texture); - Ref get_normal_map() const; - - void set_specular_map(const Ref &p_texture); - Ref get_specular_map() const; - - void set_specular_color(const Color &p_color); - Color get_specular_color() const; - - void set_shininess(float p_shininess); - float get_shininess() const; - - void set_centered(bool p_center); - bool is_centered() const; - - void set_offset(const Point2 &p_offset); - Point2 get_offset() const; - - void set_flip_h(bool p_flip); - bool is_flipped_h() const; - - void set_flip_v(bool p_flip); - bool is_flipped_v() const; - - void set_region(bool p_region); - bool is_region() const; - - void set_region_filter_clip(bool p_enable); - bool is_region_filter_clip_enabled() const; - - void set_region_rect(const Rect2 &p_region_rect); - Rect2 get_region_rect() const; - - void set_frame(int p_frame); - int get_frame() const; - - void set_frame_coords(const Vector2 &p_coord); - Vector2 get_frame_coords() const; - - void set_vframes(int p_amount); - int get_vframes() const; - - void set_hframes(int p_amount); - int get_hframes() const; - - Rect2 get_rect() const; - virtual Rect2 get_anchorable_rect() const; - - Sprite(); - ~Sprite(); -}; - -#endif // SPRITE_H diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp new file mode 100644 index 0000000000..d45fe9a2a5 --- /dev/null +++ b/scene/2d/sprite_2d.cpp @@ -0,0 +1,539 @@ +/*************************************************************************/ +/* sprite_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sprite_2d.h" + +#include "core/core_string_names.h" +#include "core/os/os.h" +#include "scene/main/window.h" +#include "scene/scene_string_names.h" + +#ifdef TOOLS_ENABLED +Dictionary Sprite2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void Sprite2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void Sprite2D::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} + +Point2 Sprite2D::_edit_get_pivot() const { + return Vector2(); +} + +bool Sprite2D::_edit_use_pivot() const { + return true; +} + +bool Sprite2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return is_pixel_opaque(p_point); +} + +Rect2 Sprite2D::_edit_get_rect() const { + return get_rect(); +} + +bool Sprite2D::_edit_use_rect() const { + return texture.is_valid(); +} +#endif + +Rect2 Sprite2D::get_anchorable_rect() const { + return get_rect(); +} + +void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { + + Rect2 base_rect; + + if (region) { + r_filter_clip = region_filter_clip; + base_rect = region_rect; + } else { + r_filter_clip = false; + base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); + } + + Size2 frame_size = base_rect.size / Size2(hframes, vframes); + Point2 frame_offset = Point2(frame % hframes, frame / hframes); + frame_offset *= frame_size; + + r_src_rect.size = frame_size; + r_src_rect.position = base_rect.position + frame_offset; + + Point2 dest_offset = offset; + if (centered) + dest_offset -= frame_size / 2; + if (Engine::get_singleton()->get_use_pixel_snap()) { + dest_offset = dest_offset.floor(); + } + + r_dst_rect = Rect2(dest_offset, frame_size); + + if (hflip) + r_dst_rect.size.x = -r_dst_rect.size.x; + if (vflip) + r_dst_rect.size.y = -r_dst_rect.size.y; +} + +void Sprite2D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_DRAW: { + + if (texture.is_null()) + return; + + RID ci = get_canvas_item(); + + /* + texture->draw(ci,Point2()); + break; + */ + + Rect2 src_rect, dst_rect; + bool filter_clip; + _get_rects(src_rect, dst_rect, filter_clip); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess), VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, filter_clip); + + } break; + } +} + +void Sprite2D::set_texture(const Ref &p_texture) { + + if (p_texture == texture) + return; + + if (texture.is_valid()) + texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite2D::_texture_changed)); + + texture = p_texture; + + if (texture.is_valid()) + texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite2D::_texture_changed)); + + update(); + emit_signal("texture_changed"); + item_rect_changed(); + _change_notify("texture"); +} + +void Sprite2D::set_normal_map(const Ref &p_texture) { + + normal_map = p_texture; + update(); +} + +Ref Sprite2D::get_normal_map() const { + + return normal_map; +} + +void Sprite2D::set_specular_map(const Ref &p_texture) { + + specular = p_texture; + update(); +} + +Ref Sprite2D::get_specular_map() const { + + return specular; +} + +void Sprite2D::set_specular_color(const Color &p_color) { + specular_color = p_color; + update(); +} + +Color Sprite2D::get_specular_color() const { + return specular_color; +} + +void Sprite2D::set_shininess(float p_shininess) { + shininess = CLAMP(p_shininess, 0.0, 1.0); + update(); +} + +float Sprite2D::get_shininess() const { + return shininess; +} + +Ref Sprite2D::get_texture() const { + + return texture; +} + +void Sprite2D::set_centered(bool p_center) { + + centered = p_center; + update(); + item_rect_changed(); +} + +bool Sprite2D::is_centered() const { + + return centered; +} + +void Sprite2D::set_offset(const Point2 &p_offset) { + + offset = p_offset; + update(); + item_rect_changed(); + _change_notify("offset"); +} +Point2 Sprite2D::get_offset() const { + + return offset; +} + +void Sprite2D::set_flip_h(bool p_flip) { + + hflip = p_flip; + update(); +} +bool Sprite2D::is_flipped_h() const { + + return hflip; +} + +void Sprite2D::set_flip_v(bool p_flip) { + + vflip = p_flip; + update(); +} +bool Sprite2D::is_flipped_v() const { + + return vflip; +} + +void Sprite2D::set_region(bool p_region) { + + if (p_region == region) + return; + + region = p_region; + update(); +} + +bool Sprite2D::is_region() const { + + return region; +} + +void Sprite2D::set_region_rect(const Rect2 &p_region_rect) { + + if (region_rect == p_region_rect) + return; + + region_rect = p_region_rect; + + if (region) + item_rect_changed(); + + _change_notify("region_rect"); +} + +Rect2 Sprite2D::get_region_rect() const { + + return region_rect; +} + +void Sprite2D::set_region_filter_clip(bool p_enable) { + region_filter_clip = p_enable; + update(); +} + +bool Sprite2D::is_region_filter_clip_enabled() const { + return region_filter_clip; +} + +void Sprite2D::set_frame(int p_frame) { + + ERR_FAIL_INDEX(p_frame, vframes * hframes); + + if (frame != p_frame) + item_rect_changed(); + + frame = p_frame; + + _change_notify("frame"); + _change_notify("frame_coords"); + emit_signal(SceneStringNames::get_singleton()->frame_changed); +} + +int Sprite2D::get_frame() const { + + return frame; +} + +void Sprite2D::set_frame_coords(const Vector2 &p_coord) { + ERR_FAIL_INDEX(int(p_coord.x), hframes); + ERR_FAIL_INDEX(int(p_coord.y), vframes); + + set_frame(int(p_coord.y) * hframes + int(p_coord.x)); +} + +Vector2 Sprite2D::get_frame_coords() const { + return Vector2(frame % hframes, frame / hframes); +} + +void Sprite2D::set_vframes(int p_amount) { + + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of vframes cannot be smaller than 1."); + vframes = p_amount; + update(); + item_rect_changed(); + _change_notify(); +} +int Sprite2D::get_vframes() const { + + return vframes; +} + +void Sprite2D::set_hframes(int p_amount) { + + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of hframes cannot be smaller than 1."); + hframes = p_amount; + update(); + item_rect_changed(); + _change_notify(); +} +int Sprite2D::get_hframes() const { + + return hframes; +} + +bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const { + + if (texture.is_null()) + return false; + + if (texture->get_size().width == 0 || texture->get_size().height == 0) + return false; + + Rect2 src_rect, dst_rect; + bool filter_clip; + _get_rects(src_rect, dst_rect, filter_clip); + dst_rect.size = dst_rect.size.abs(); + + if (!dst_rect.has_point(p_point)) + return false; + + Vector2 q = (p_point - dst_rect.position) / dst_rect.size; + if (hflip) + q.x = 1.0f - q.x; + if (vflip) + q.y = 1.0f - q.y; + q = q * src_rect.size + src_rect.position; +#ifndef _MSC_VER +#warning this need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that) +#endif + bool is_repeat = false; + bool is_mirrored_repeat = false; + if (is_repeat) { + int mirror_x = 0; + int mirror_y = 0; + if (is_mirrored_repeat) { + mirror_x = (int)(q.x / texture->get_size().width); + mirror_y = (int)(q.y / texture->get_size().height); + } + q.x = Math::fmod(q.x, texture->get_size().width); + q.y = Math::fmod(q.y, texture->get_size().height); + if (mirror_x % 2 == 1) { + q.x = texture->get_size().width - q.x - 1; + } + if (mirror_y % 2 == 1) { + q.y = texture->get_size().height - q.y - 1; + } + } else { + q.x = MIN(q.x, texture->get_size().width - 1); + q.y = MIN(q.y, texture->get_size().height - 1); + } + + return texture->is_pixel_opaque((int)q.x, (int)q.y); +} + +Rect2 Sprite2D::get_rect() const { + + if (texture.is_null()) + return Rect2(0, 0, 1, 1); + + Size2i s; + + if (region) { + s = region_rect.size; + } else { + s = texture->get_size(); + } + + s = s / Point2(hframes, vframes); + + Point2 ofs = offset; + if (centered) + ofs -= Size2(s) / 2; + + if (s == Size2(0, 0)) + s = Size2(1, 1); + + return Rect2(ofs, s); +} + +void Sprite2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "frame") { + property.hint = PROPERTY_HINT_RANGE; + property.hint_string = "0," + itos(vframes * hframes - 1) + ",1"; + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; + } + + if (property.name == "frame_coords") { + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; + } +} + +void Sprite2D::_texture_changed() { + + // Changes to the texture need to trigger an update to make + // the editor redraw the sprite with the updated texture. + if (texture.is_valid()) { + update(); + } +} + +void Sprite2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite2D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &Sprite2D::get_texture); + + ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &Sprite2D::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &Sprite2D::get_normal_map); + + ClassDB::bind_method(D_METHOD("set_specular_map", "specular_map"), &Sprite2D::set_specular_map); + ClassDB::bind_method(D_METHOD("get_specular_map"), &Sprite2D::get_specular_map); + + ClassDB::bind_method(D_METHOD("set_specular_color", "specular_color"), &Sprite2D::set_specular_color); + ClassDB::bind_method(D_METHOD("get_specular_color"), &Sprite2D::get_specular_color); + + ClassDB::bind_method(D_METHOD("set_shininess", "shininess"), &Sprite2D::set_shininess); + ClassDB::bind_method(D_METHOD("get_shininess"), &Sprite2D::get_shininess); + + ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Sprite2D::set_centered); + ClassDB::bind_method(D_METHOD("is_centered"), &Sprite2D::is_centered); + + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Sprite2D::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &Sprite2D::get_offset); + + ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &Sprite2D::set_flip_h); + ClassDB::bind_method(D_METHOD("is_flipped_h"), &Sprite2D::is_flipped_h); + + ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite2D::set_flip_v); + ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite2D::is_flipped_v); + + ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite2D::set_region); + ClassDB::bind_method(D_METHOD("is_region"), &Sprite2D::is_region); + + ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite2D::is_pixel_opaque); + + ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite2D::set_region_rect); + ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite2D::get_region_rect); + + ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite2D::set_region_filter_clip); + ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite2D::is_region_filter_clip_enabled); + + ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite2D::set_frame); + ClassDB::bind_method(D_METHOD("get_frame"), &Sprite2D::get_frame); + + ClassDB::bind_method(D_METHOD("set_frame_coords", "coords"), &Sprite2D::set_frame_coords); + ClassDB::bind_method(D_METHOD("get_frame_coords"), &Sprite2D::get_frame_coords); + + ClassDB::bind_method(D_METHOD("set_vframes", "vframes"), &Sprite2D::set_vframes); + ClassDB::bind_method(D_METHOD("get_vframes"), &Sprite2D::get_vframes); + + ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite2D::set_hframes); + ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite2D::get_hframes); + + ClassDB::bind_method(D_METHOD("get_rect"), &Sprite2D::get_rect); + + ADD_SIGNAL(MethodInfo("frame_changed")); + ADD_SIGNAL(MethodInfo("texture_changed")); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); + ADD_GROUP("Lighting", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_map", "get_normal_map"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "specular_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_specular_map", "get_specular_map"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_shininess", "get_shininess"); + ADD_GROUP("Offset", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v"); + ADD_GROUP("Animation", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); + + ADD_GROUP("Region", "region_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); + ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); +} + +Sprite2D::Sprite2D() { + + centered = true; + hflip = false; + vflip = false; + region = false; + region_filter_clip = false; + shininess = 1.0; + specular_color = Color(1, 1, 1, 1); + + frame = 0; + + vframes = 1; + hframes = 1; +} + +Sprite2D::~Sprite2D() { +} diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h new file mode 100644 index 0000000000..599a9e937e --- /dev/null +++ b/scene/2d/sprite_2d.h @@ -0,0 +1,143 @@ +/*************************************************************************/ +/* sprite_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPRITE_2D_H +#define SPRITE_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/resources/texture.h" + +class Sprite2D : public Node2D { + + GDCLASS(Sprite2D, Node2D); + + Ref texture; + Ref normal_map; + Ref specular; + Color specular_color; + float shininess; + + bool centered; + Point2 offset; + + bool hflip; + bool vflip; + bool region; + Rect2 region_rect; + bool region_filter_clip; + + int frame; + + int vframes; + int hframes; + + void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const; + + void _texture_changed(); + +protected: + void _notification(int p_what); + + static void _bind_methods(); + + virtual void _validate_property(PropertyInfo &property) const; + +public: +#ifdef TOOLS_ENABLED + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; +#endif + + bool is_pixel_opaque(const Point2 &p_point) const; + + void set_texture(const Ref &p_texture); + Ref get_texture() const; + + void set_normal_map(const Ref &p_texture); + Ref get_normal_map() const; + + void set_specular_map(const Ref &p_texture); + Ref get_specular_map() const; + + void set_specular_color(const Color &p_color); + Color get_specular_color() const; + + void set_shininess(float p_shininess); + float get_shininess() const; + + void set_centered(bool p_center); + bool is_centered() const; + + void set_offset(const Point2 &p_offset); + Point2 get_offset() const; + + void set_flip_h(bool p_flip); + bool is_flipped_h() const; + + void set_flip_v(bool p_flip); + bool is_flipped_v() const; + + void set_region(bool p_region); + bool is_region() const; + + void set_region_filter_clip(bool p_enable); + bool is_region_filter_clip_enabled() const; + + void set_region_rect(const Rect2 &p_region_rect); + Rect2 get_region_rect() const; + + void set_frame(int p_frame); + int get_frame() const; + + void set_frame_coords(const Vector2 &p_coord); + Vector2 get_frame_coords() const; + + void set_vframes(int p_amount); + int get_vframes() const; + + void set_hframes(int p_amount); + int get_hframes() const; + + Rect2 get_rect() const; + virtual Rect2 get_anchorable_rect() const; + + Sprite2D(); + ~Sprite2D(); +}; + +#endif // SPRITE_H diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 65dabb92b1..6c1d7c3749 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "particles_2d.h" -#include "scene/2d/animated_sprite.h" +#include "scene/2d/animated_sprite_2d.h" #include "scene/2d/physics_body_2d.h" #include "scene/animation/animation_player.h" #include "scene/main/window.h" @@ -205,7 +205,7 @@ void VisibilityEnabler2D::_find_nodes(Node *p_node) { } { - AnimatedSprite *as = Object::cast_to(p_node); + AnimatedSprite2D *as = Object::cast_to(p_node); if (as) { add = true; } @@ -292,7 +292,7 @@ void VisibilityEnabler2D::_change_node_state(Node *p_node, bool p_enabled) { } if (enabler[ENABLER_PAUSE_ANIMATED_SPRITES]) { - AnimatedSprite *as = Object::cast_to(p_node); + AnimatedSprite2D *as = Object::cast_to(p_node); if (as) { diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp deleted file mode 100644 index 321926d841..0000000000 --- a/scene/3d/area.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/*************************************************************************/ -/* area.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "area.h" - -#include "scene/scene_string_names.h" -#include "servers/audio_server.h" -#include "servers/physics_server.h" - -void Area::set_space_override_mode(SpaceOverride p_mode) { - - space_override = p_mode; - PhysicsServer::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer::AreaSpaceOverrideMode(p_mode)); -} -Area::SpaceOverride Area::get_space_override_mode() const { - - return space_override; -} - -void Area::set_gravity_is_point(bool p_enabled) { - - gravity_is_point = p_enabled; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); -} -bool Area::is_gravity_a_point() const { - - return gravity_is_point; -} - -void Area::set_gravity_distance_scale(real_t p_scale) { - - gravity_distance_scale = p_scale; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); -} - -real_t Area::get_gravity_distance_scale() const { - return gravity_distance_scale; -} - -void Area::set_gravity_vector(const Vector3 &p_vec) { - - gravity_vec = p_vec; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, p_vec); -} -Vector3 Area::get_gravity_vector() const { - - return gravity_vec; -} - -void Area::set_gravity(real_t p_gravity) { - - gravity = p_gravity; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY, p_gravity); -} -real_t Area::get_gravity() const { - - return gravity; -} -void Area::set_linear_damp(real_t p_linear_damp) { - - linear_damp = p_linear_damp; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_LINEAR_DAMP, p_linear_damp); -} -real_t Area::get_linear_damp() const { - - return linear_damp; -} - -void Area::set_angular_damp(real_t p_angular_damp) { - - angular_damp = p_angular_damp; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); -} - -real_t Area::get_angular_damp() const { - - return angular_damp; -} - -void Area::set_priority(real_t p_priority) { - - priority = p_priority; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_PRIORITY, p_priority); -} -real_t Area::get_priority() const { - - return priority; -} - -void Area::_body_enter_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - - Map::Element *E = body_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); - - E->get().in_tree = true; - emit_signal(SceneStringNames::get_singleton()->body_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); - } -} - -void Area::_body_exit_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - Map::Element *E = body_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; - emit_signal(SceneStringNames::get_singleton()->body_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); - } -} - -void Area::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { - - bool body_in = p_status == PhysicsServer::AREA_BODY_ADDED; - ObjectID objid = p_instance; - - Object *obj = ObjectDB::get_instance(objid); - Node *node = Object::cast_to(obj); - - Map::Element *E = body_map.find(objid); - - if (!body_in && !E) { - return; //likely removed from the tree - } - - locked = true; - - if (body_in) { - if (!E) { - - E = body_map.insert(objid, BodyState()); - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); - if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree), make_binds(objid)); - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_entered, node); - } - } - } - E->get().rc++; - if (node) - E->get().shapes.insert(ShapePair(p_body_shape, p_area_shape)); - - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape); - } - - } else { - - E->get().rc--; - - if (node) - E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape)); - - bool eraseit = false; - - if (E->get().rc == 0) { - - if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree)); - if (E->get().in_tree) - emit_signal(SceneStringNames::get_singleton()->body_exited, obj); - } - - eraseit = true; - } - if (node && E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); - } - - if (eraseit) - body_map.erase(E); - } - - locked = false; -} - -void Area::_clear_monitoring() { - - ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal."); - - { - Map bmcopy = body_map; - body_map.clear(); - //disconnect all monitored stuff - - for (Map::Element *E = bmcopy.front(); E; E = E->next()) { - - Object *obj = ObjectDB::get_instance(E->key()); - Node *node = Object::cast_to(obj); - - if (!node) //node may have been deleted in previous frame or at other legiminate point - continue; - //ERR_CONTINUE(!node); - - if (!E->get().in_tree) - continue; - - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); - } - - emit_signal(SceneStringNames::get_singleton()->body_exited, node); - - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_body_exit_tree)); - } - } - - { - - Map bmcopy = area_map; - area_map.clear(); - //disconnect all monitored stuff - - for (Map::Element *E = bmcopy.front(); E; E = E->next()) { - - Object *obj = ObjectDB::get_instance(E->key()); - Node *node = Object::cast_to(obj); - - if (!node) //node may have been deleted in previous frame or at other legiminate point - continue; - //ERR_CONTINUE(!node); - - if (!E->get().in_tree) - continue; - - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); - } - - emit_signal(SceneStringNames::get_singleton()->area_exited, obj); - - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree)); - } - } -} -void Area::_notification(int p_what) { - - if (p_what == NOTIFICATION_EXIT_TREE) { - _clear_monitoring(); - } -} - -void Area::set_monitoring(bool p_enable) { - - ERR_FAIL_COND_MSG(locked, "Function blocked during in/out signal. Use set_deferred(\"monitoring\", true/false)."); - - if (p_enable == monitoring) - return; - - monitoring = p_enable; - - if (monitoring) { - - PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); - PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); - } else { - PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); - PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); - _clear_monitoring(); - } -} - -void Area::_area_enter_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - - Map::Element *E = area_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); - - E->get().in_tree = true; - emit_signal(SceneStringNames::get_singleton()->area_entered, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); - } -} - -void Area::_area_exit_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - Map::Element *E = area_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; - emit_signal(SceneStringNames::get_singleton()->area_exited, node); - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); - } -} - -void Area::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { - - bool area_in = p_status == PhysicsServer::AREA_BODY_ADDED; - ObjectID objid = p_instance; - - Object *obj = ObjectDB::get_instance(objid); - Node *node = Object::cast_to(obj); - - Map::Element *E = area_map.find(objid); - - if (!area_in && !E) { - return; //likely removed from the tree - } - - locked = true; - - if (area_in) { - if (!E) { - - E = area_map.insert(objid, AreaState()); - E->get().rc = 0; - E->get().in_tree = node && node->is_inside_tree(); - if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree), make_binds(objid)); - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_entered, node); - } - } - } - E->get().rc++; - if (node) - E->get().shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); - - if (!node || E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape); - } - - } else { - - E->get().rc--; - - if (node) - E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); - - bool eraseit = false; - - if (E->get().rc == 0) { - - if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area::_area_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area::_area_exit_tree)); - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_exited, obj); - } - } - - eraseit = true; - } - if (!node || E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); - } - - if (eraseit) - area_map.erase(E); - } - - locked = false; -} - -bool Area::is_monitoring() const { - - return monitoring; -} - -Array Area::get_overlapping_bodies() const { - - ERR_FAIL_COND_V(!monitoring, Array()); - Array ret; - ret.resize(body_map.size()); - int idx = 0; - for (const Map::Element *E = body_map.front(); E; E = E->next()) { - Object *obj = ObjectDB::get_instance(E->key()); - if (!obj) { - ret.resize(ret.size() - 1); //ops - } else { - ret[idx++] = obj; - } - } - - return ret; -} - -void Area::set_monitorable(bool p_enable) { - - ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); - - if (p_enable == monitorable) - return; - - monitorable = p_enable; - - PhysicsServer::get_singleton()->area_set_monitorable(get_rid(), monitorable); -} - -bool Area::is_monitorable() const { - - return monitorable; -} - -Array Area::get_overlapping_areas() const { - - ERR_FAIL_COND_V(!monitoring, Array()); - Array ret; - ret.resize(area_map.size()); - int idx = 0; - for (const Map::Element *E = area_map.front(); E; E = E->next()) { - Object *obj = ObjectDB::get_instance(E->key()); - if (!obj) { - ret.resize(ret.size() - 1); //ops - } else { - ret[idx++] = obj; - } - } - - return ret; -} - -bool Area::overlaps_area(Node *p_area) const { - - ERR_FAIL_NULL_V(p_area, false); - const Map::Element *E = area_map.find(p_area->get_instance_id()); - if (!E) - return false; - return E->get().in_tree; -} - -bool Area::overlaps_body(Node *p_body) const { - - ERR_FAIL_NULL_V(p_body, false); - const Map::Element *E = body_map.find(p_body->get_instance_id()); - if (!E) - return false; - return E->get().in_tree; -} -void Area::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; - PhysicsServer::get_singleton()->area_set_collision_mask(get_rid(), p_mask); -} - -uint32_t Area::get_collision_mask() const { - - return collision_mask; -} -void Area::set_collision_layer(uint32_t p_layer) { - - collision_layer = p_layer; - PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); -} - -uint32_t Area::get_collision_layer() const { - - return collision_layer; -} - -void Area::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool Area::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -void Area::set_collision_layer_bit(int p_bit, bool p_value) { - - uint32_t layer = get_collision_layer(); - if (p_value) - layer |= 1 << p_bit; - else - layer &= ~(1 << p_bit); - set_collision_layer(layer); -} - -bool Area::get_collision_layer_bit(int p_bit) const { - - return get_collision_layer() & (1 << p_bit); -} - -void Area::set_audio_bus_override(bool p_override) { - - audio_bus_override = p_override; -} - -bool Area::is_overriding_audio_bus() const { - - return audio_bus_override; -} - -void Area::set_audio_bus(const StringName &p_audio_bus) { - - audio_bus = p_audio_bus; -} -StringName Area::get_audio_bus() const { - - for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { - if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { - return audio_bus; - } - } - return "Master"; -} - -void Area::set_use_reverb_bus(bool p_enable) { - - use_reverb_bus = p_enable; -} -bool Area::is_using_reverb_bus() const { - - return use_reverb_bus; -} - -void Area::set_reverb_bus(const StringName &p_audio_bus) { - - reverb_bus = p_audio_bus; -} -StringName Area::get_reverb_bus() const { - - for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { - if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) { - return reverb_bus; - } - } - return "Master"; -} - -void Area::set_reverb_amount(float p_amount) { - - reverb_amount = p_amount; -} -float Area::get_reverb_amount() const { - - return reverb_amount; -} - -void Area::set_reverb_uniformity(float p_uniformity) { - - reverb_uniformity = p_uniformity; -} -float Area::get_reverb_uniformity() const { - - return reverb_uniformity; -} - -void Area::_validate_property(PropertyInfo &property) const { - - if (property.name == "audio_bus_name" || property.name == "reverb_bus_name") { - - String options; - for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { - if (i > 0) - options += ","; - String name = AudioServer::get_singleton()->get_bus_name(i); - options += name; - } - - property.hint_string = options; - } -} - -void Area::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_space_override_mode", "enable"), &Area::set_space_override_mode); - ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area::get_space_override_mode); - - ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area::set_gravity_is_point); - ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area::is_gravity_a_point); - - ClassDB::bind_method(D_METHOD("set_gravity_distance_scale", "distance_scale"), &Area::set_gravity_distance_scale); - ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area::get_gravity_distance_scale); - - ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area::set_gravity_vector); - ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area::get_gravity_vector); - - ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area::set_gravity); - ClassDB::bind_method(D_METHOD("get_gravity"), &Area::get_gravity); - - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &Area::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &Area::get_angular_damp); - - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &Area::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &Area::get_linear_damp); - - ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area::set_priority); - ClassDB::bind_method(D_METHOD("get_priority"), &Area::get_priority); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &Area::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &Area::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Area::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &Area::get_collision_layer); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &Area::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &Area::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &Area::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &Area::get_collision_layer_bit); - - ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area::set_monitorable); - ClassDB::bind_method(D_METHOD("is_monitorable"), &Area::is_monitorable); - - ClassDB::bind_method(D_METHOD("set_monitoring", "enable"), &Area::set_monitoring); - ClassDB::bind_method(D_METHOD("is_monitoring"), &Area::is_monitoring); - - ClassDB::bind_method(D_METHOD("get_overlapping_bodies"), &Area::get_overlapping_bodies); - ClassDB::bind_method(D_METHOD("get_overlapping_areas"), &Area::get_overlapping_areas); - - ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area::overlaps_body); - ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area::overlaps_area); - - ClassDB::bind_method(D_METHOD("_body_inout"), &Area::_body_inout); - ClassDB::bind_method(D_METHOD("_area_inout"), &Area::_area_inout); - - ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area::set_audio_bus_override); - ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area::is_overriding_audio_bus); - - ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area::set_audio_bus); - ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area::get_audio_bus); - - ClassDB::bind_method(D_METHOD("set_use_reverb_bus", "enable"), &Area::set_use_reverb_bus); - ClassDB::bind_method(D_METHOD("is_using_reverb_bus"), &Area::is_using_reverb_bus); - - ClassDB::bind_method(D_METHOD("set_reverb_bus", "name"), &Area::set_reverb_bus); - ClassDB::bind_method(D_METHOD("get_reverb_bus"), &Area::get_reverb_bus); - - ClassDB::bind_method(D_METHOD("set_reverb_amount", "amount"), &Area::set_reverb_amount); - ClassDB::bind_method(D_METHOD("get_reverb_amount"), &Area::get_reverb_amount); - - ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area::set_reverb_uniformity); - ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area::get_reverb_uniformity); - - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - - ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); - ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); - ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"))); - ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area"))); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity"); - 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::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); - ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_GROUP("Audio Bus", "audio_bus_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); - ADD_GROUP("Reverb Bus", "reverb_bus_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity"); - - BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED); - BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE); - BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE); - BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE); - BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE); -} - -Area::Area() : - CollisionObject(PhysicsServer::get_singleton()->area_create(), true) { - - space_override = SPACE_OVERRIDE_DISABLED; - set_gravity(9.8); - locked = false; - set_gravity_vector(Vector3(0, -1, 0)); - gravity_is_point = false; - gravity_distance_scale = 0; - linear_damp = 0.1; - angular_damp = 0.1; - priority = 0; - monitoring = false; - monitorable = false; - collision_mask = 1; - collision_layer = 1; - set_monitoring(true); - set_monitorable(true); - - audio_bus_override = false; - audio_bus = "Master"; - - use_reverb_bus = false; - reverb_bus = "Master"; - reverb_amount = 0.0; - reverb_uniformity = 0.0; -} - -Area::~Area() { -} diff --git a/scene/3d/area.h b/scene/3d/area.h deleted file mode 100644 index 7fe61430fa..0000000000 --- a/scene/3d/area.h +++ /dev/null @@ -1,217 +0,0 @@ -/*************************************************************************/ -/* area.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef AREA_H -#define AREA_H - -#include "core/vset.h" -#include "scene/3d/collision_object.h" - -class Area : public CollisionObject { - - GDCLASS(Area, CollisionObject); - -public: - enum SpaceOverride { - SPACE_OVERRIDE_DISABLED, - SPACE_OVERRIDE_COMBINE, - SPACE_OVERRIDE_COMBINE_REPLACE, - SPACE_OVERRIDE_REPLACE, - SPACE_OVERRIDE_REPLACE_COMBINE - }; - -private: - SpaceOverride space_override; - Vector3 gravity_vec; - real_t gravity; - bool gravity_is_point; - real_t gravity_distance_scale; - real_t angular_damp; - real_t linear_damp; - uint32_t collision_mask; - uint32_t collision_layer; - int priority; - bool monitoring; - bool monitorable; - bool locked; - - void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape); - - void _body_enter_tree(ObjectID p_id); - void _body_exit_tree(ObjectID p_id); - - struct ShapePair { - - int body_shape; - int area_shape; - bool operator<(const ShapePair &p_sp) const { - if (body_shape == p_sp.body_shape) - return area_shape < p_sp.area_shape; - else - return body_shape < p_sp.body_shape; - } - - ShapePair() {} - ShapePair(int p_bs, int p_as) { - body_shape = p_bs; - area_shape = p_as; - } - }; - - struct BodyState { - - int rc; - bool in_tree; - VSet shapes; - }; - - Map body_map; - - void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); - - void _area_enter_tree(ObjectID p_id); - void _area_exit_tree(ObjectID p_id); - - struct AreaShapePair { - - int area_shape; - int self_shape; - bool operator<(const AreaShapePair &p_sp) const { - if (area_shape == p_sp.area_shape) - return self_shape < p_sp.self_shape; - else - return area_shape < p_sp.area_shape; - } - - AreaShapePair() {} - AreaShapePair(int p_bs, int p_as) { - area_shape = p_bs; - self_shape = p_as; - } - }; - - struct AreaState { - - int rc; - bool in_tree; - VSet shapes; - }; - - Map area_map; - void _clear_monitoring(); - - bool audio_bus_override; - StringName audio_bus; - - bool use_reverb_bus; - StringName reverb_bus; - float reverb_amount; - float reverb_uniformity; - - void _validate_property(PropertyInfo &property) const; - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_space_override_mode(SpaceOverride p_mode); - SpaceOverride get_space_override_mode() const; - - void set_gravity_is_point(bool p_enabled); - bool is_gravity_a_point() const; - - void set_gravity_distance_scale(real_t p_scale); - real_t get_gravity_distance_scale() const; - - void set_gravity_vector(const Vector3 &p_vec); - Vector3 get_gravity_vector() const; - - void set_gravity(real_t p_gravity); - real_t get_gravity() const; - - void set_angular_damp(real_t p_angular_damp); - real_t get_angular_damp() const; - - void set_linear_damp(real_t p_linear_damp); - real_t get_linear_damp() const; - - void set_priority(real_t p_priority); - real_t get_priority() const; - - void set_monitoring(bool p_enable); - bool is_monitoring() const; - - void set_monitorable(bool p_enable); - bool is_monitorable() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; - - Array get_overlapping_bodies() const; - Array get_overlapping_areas() const; //function for script - - bool overlaps_area(Node *p_area) const; - bool overlaps_body(Node *p_body) const; - - void set_audio_bus_override(bool p_override); - bool is_overriding_audio_bus() const; - - void set_audio_bus(const StringName &p_audio_bus); - StringName get_audio_bus() const; - - void set_use_reverb_bus(bool p_enable); - bool is_using_reverb_bus() const; - - void set_reverb_bus(const StringName &p_audio_bus); - StringName get_reverb_bus() const; - - void set_reverb_amount(float p_amount); - float get_reverb_amount() const; - - void set_reverb_uniformity(float p_uniformity); - float get_reverb_uniformity() const; - - Area(); - ~Area(); -}; - -VARIANT_ENUM_CAST(Area::SpaceOverride); - -#endif // AREA__H diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp new file mode 100644 index 0000000000..beeaf7125a --- /dev/null +++ b/scene/3d/area_3d.cpp @@ -0,0 +1,759 @@ +/*************************************************************************/ +/* area_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "area_3d.h" + +#include "scene/scene_string_names.h" +#include "servers/audio_server.h" +#include "servers/physics_server.h" + +void Area3D::set_space_override_mode(SpaceOverride p_mode) { + + space_override = p_mode; + PhysicsServer::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer::AreaSpaceOverrideMode(p_mode)); +} +Area3D::SpaceOverride Area3D::get_space_override_mode() const { + + return space_override; +} + +void Area3D::set_gravity_is_point(bool p_enabled) { + + gravity_is_point = p_enabled; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); +} +bool Area3D::is_gravity_a_point() const { + + return gravity_is_point; +} + +void Area3D::set_gravity_distance_scale(real_t p_scale) { + + gravity_distance_scale = p_scale; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); +} + +real_t Area3D::get_gravity_distance_scale() const { + return gravity_distance_scale; +} + +void Area3D::set_gravity_vector(const Vector3 &p_vec) { + + gravity_vec = p_vec; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, p_vec); +} +Vector3 Area3D::get_gravity_vector() const { + + return gravity_vec; +} + +void Area3D::set_gravity(real_t p_gravity) { + + gravity = p_gravity; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY, p_gravity); +} +real_t Area3D::get_gravity() const { + + return gravity; +} +void Area3D::set_linear_damp(real_t p_linear_damp) { + + linear_damp = p_linear_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_LINEAR_DAMP, p_linear_damp); +} +real_t Area3D::get_linear_damp() const { + + return linear_damp; +} + +void Area3D::set_angular_damp(real_t p_angular_damp) { + + angular_damp = p_angular_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); +} + +real_t Area3D::get_angular_damp() const { + + return angular_damp; +} + +void Area3D::set_priority(real_t p_priority) { + + priority = p_priority; + PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_PRIORITY, p_priority); +} +real_t Area3D::get_priority() const { + + return priority; +} + +void Area3D::_body_enter_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + + Map::Element *E = body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree = true; + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + } +} + +void Area3D::_body_exit_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + Map::Element *E = body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree = false; + emit_signal(SceneStringNames::get_singleton()->body_exited, node); + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + } +} + +void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { + + bool body_in = p_status == PhysicsServer::AREA_BODY_ADDED; + ObjectID objid = p_instance; + + Object *obj = ObjectDB::get_instance(objid); + Node *node = Object::cast_to(obj); + + Map::Element *E = body_map.find(objid); + + if (!body_in && !E) { + return; //likely removed from the tree + } + + locked = true; + + if (body_in) { + if (!E) { + + E = body_map.insert(objid, BodyState()); + E->get().rc = 0; + E->get().in_tree = node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree), make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + } + } + } + E->get().rc++; + if (node) + E->get().shapes.insert(ShapePair(p_body_shape, p_area_shape)); + + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape); + } + + } else { + + E->get().rc--; + + if (node) + E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape)); + + bool eraseit = false; + + if (E->get().rc == 0) { + + if (node) { + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); + if (E->get().in_tree) + emit_signal(SceneStringNames::get_singleton()->body_exited, obj); + } + + eraseit = true; + } + if (node && E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); + } + + if (eraseit) + body_map.erase(E); + } + + locked = false; +} + +void Area3D::_clear_monitoring() { + + ERR_FAIL_COND_MSG(locked, "This function can't be used during the in/out signal."); + + { + Map bmcopy = body_map; + body_map.clear(); + //disconnect all monitored stuff + + for (Map::Element *E = bmcopy.front(); E; E = E->next()) { + + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = Object::cast_to(obj); + + if (!node) //node may have been deleted in previous frame or at other legiminate point + continue; + //ERR_CONTINUE(!node); + + if (!E->get().in_tree) + continue; + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + } + + emit_signal(SceneStringNames::get_singleton()->body_exited, node); + + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); + } + } + + { + + Map bmcopy = area_map; + area_map.clear(); + //disconnect all monitored stuff + + for (Map::Element *E = bmcopy.front(); E; E = E->next()) { + + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = Object::cast_to(obj); + + if (!node) //node may have been deleted in previous frame or at other legiminate point + continue; + //ERR_CONTINUE(!node); + + if (!E->get().in_tree) + continue; + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + } + + emit_signal(SceneStringNames::get_singleton()->area_exited, obj); + + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); + } + } +} +void Area3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_EXIT_TREE) { + _clear_monitoring(); + } +} + +void Area3D::set_monitoring(bool p_enable) { + + ERR_FAIL_COND_MSG(locked, "Function blocked during in/out signal. Use set_deferred(\"monitoring\", true/false)."); + + if (p_enable == monitoring) + return; + + monitoring = p_enable; + + if (monitoring) { + + PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); + PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); + } else { + PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); + _clear_monitoring(); + } +} + +void Area3D::_area_enter_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + + Map::Element *E = area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree = true; + emit_signal(SceneStringNames::get_singleton()->area_entered, node); + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + } +} + +void Area3D::_area_exit_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + Map::Element *E = area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree = false; + emit_signal(SceneStringNames::get_singleton()->area_exited, node); + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + } +} + +void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { + + bool area_in = p_status == PhysicsServer::AREA_BODY_ADDED; + ObjectID objid = p_instance; + + Object *obj = ObjectDB::get_instance(objid); + Node *node = Object::cast_to(obj); + + Map::Element *E = area_map.find(objid); + + if (!area_in && !E) { + return; //likely removed from the tree + } + + locked = true; + + if (area_in) { + if (!E) { + + E = area_map.insert(objid, AreaState()); + E->get().rc = 0; + E->get().in_tree = node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree), make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_entered, node); + } + } + } + E->get().rc++; + if (node) + E->get().shapes.insert(AreaShapePair(p_area_shape, p_self_shape)); + + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape); + } + + } else { + + E->get().rc--; + + if (node) + E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); + + bool eraseit = false; + + if (E->get().rc == 0) { + + if (node) { + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_exited, obj); + } + } + + eraseit = true; + } + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); + } + + if (eraseit) + area_map.erase(E); + } + + locked = false; +} + +bool Area3D::is_monitoring() const { + + return monitoring; +} + +Array Area3D::get_overlapping_bodies() const { + + ERR_FAIL_COND_V(!monitoring, Array()); + Array ret; + ret.resize(body_map.size()); + int idx = 0; + for (const Map::Element *E = body_map.front(); E; E = E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize(ret.size() - 1); //ops + } else { + ret[idx++] = obj; + } + } + + return ret; +} + +void Area3D::set_monitorable(bool p_enable) { + + ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); + + if (p_enable == monitorable) + return; + + monitorable = p_enable; + + PhysicsServer::get_singleton()->area_set_monitorable(get_rid(), monitorable); +} + +bool Area3D::is_monitorable() const { + + return monitorable; +} + +Array Area3D::get_overlapping_areas() const { + + ERR_FAIL_COND_V(!monitoring, Array()); + Array ret; + ret.resize(area_map.size()); + int idx = 0; + for (const Map::Element *E = area_map.front(); E; E = E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize(ret.size() - 1); //ops + } else { + ret[idx++] = obj; + } + } + + return ret; +} + +bool Area3D::overlaps_area(Node *p_area) const { + + ERR_FAIL_NULL_V(p_area, false); + const Map::Element *E = area_map.find(p_area->get_instance_id()); + if (!E) + return false; + return E->get().in_tree; +} + +bool Area3D::overlaps_body(Node *p_body) const { + + ERR_FAIL_NULL_V(p_body, false); + const Map::Element *E = body_map.find(p_body->get_instance_id()); + if (!E) + return false; + return E->get().in_tree; +} +void Area3D::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; + PhysicsServer::get_singleton()->area_set_collision_mask(get_rid(), p_mask); +} + +uint32_t Area3D::get_collision_mask() const { + + return collision_mask; +} +void Area3D::set_collision_layer(uint32_t p_layer) { + + collision_layer = p_layer; + PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); +} + +uint32_t Area3D::get_collision_layer() const { + + return collision_layer; +} + +void Area3D::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool Area3D::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void Area3D::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t layer = get_collision_layer(); + if (p_value) + layer |= 1 << p_bit; + else + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +bool Area3D::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +void Area3D::set_audio_bus_override(bool p_override) { + + audio_bus_override = p_override; +} + +bool Area3D::is_overriding_audio_bus() const { + + return audio_bus_override; +} + +void Area3D::set_audio_bus(const StringName &p_audio_bus) { + + audio_bus = p_audio_bus; +} +StringName Area3D::get_audio_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { + return audio_bus; + } + } + return "Master"; +} + +void Area3D::set_use_reverb_bus(bool p_enable) { + + use_reverb_bus = p_enable; +} +bool Area3D::is_using_reverb_bus() const { + + return use_reverb_bus; +} + +void Area3D::set_reverb_bus(const StringName &p_audio_bus) { + + reverb_bus = p_audio_bus; +} +StringName Area3D::get_reverb_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) { + return reverb_bus; + } + } + return "Master"; +} + +void Area3D::set_reverb_amount(float p_amount) { + + reverb_amount = p_amount; +} +float Area3D::get_reverb_amount() const { + + return reverb_amount; +} + +void Area3D::set_reverb_uniformity(float p_uniformity) { + + reverb_uniformity = p_uniformity; +} +float Area3D::get_reverb_uniformity() const { + + return reverb_uniformity; +} + +void Area3D::_validate_property(PropertyInfo &property) const { + + if (property.name == "audio_bus_name" || property.name == "reverb_bus_name") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + +void Area3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_space_override_mode", "enable"), &Area3D::set_space_override_mode); + ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area3D::get_space_override_mode); + + ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area3D::set_gravity_is_point); + ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area3D::is_gravity_a_point); + + ClassDB::bind_method(D_METHOD("set_gravity_distance_scale", "distance_scale"), &Area3D::set_gravity_distance_scale); + ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area3D::get_gravity_distance_scale); + + ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area3D::set_gravity_vector); + ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area3D::get_gravity_vector); + + ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area3D::set_gravity); + ClassDB::bind_method(D_METHOD("get_gravity"), &Area3D::get_gravity); + + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &Area3D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &Area3D::get_angular_damp); + + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &Area3D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &Area3D::get_linear_damp); + + ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area3D::set_priority); + ClassDB::bind_method(D_METHOD("get_priority"), &Area3D::get_priority); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &Area3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &Area3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Area3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &Area3D::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &Area3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &Area3D::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &Area3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &Area3D::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area3D::set_monitorable); + ClassDB::bind_method(D_METHOD("is_monitorable"), &Area3D::is_monitorable); + + ClassDB::bind_method(D_METHOD("set_monitoring", "enable"), &Area3D::set_monitoring); + ClassDB::bind_method(D_METHOD("is_monitoring"), &Area3D::is_monitoring); + + ClassDB::bind_method(D_METHOD("get_overlapping_bodies"), &Area3D::get_overlapping_bodies); + ClassDB::bind_method(D_METHOD("get_overlapping_areas"), &Area3D::get_overlapping_areas); + + ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area3D::overlaps_body); + ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area3D::overlaps_area); + + ClassDB::bind_method(D_METHOD("_body_inout"), &Area3D::_body_inout); + ClassDB::bind_method(D_METHOD("_area_inout"), &Area3D::_area_inout); + + ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area3D::set_audio_bus_override); + ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area3D::is_overriding_audio_bus); + + ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area3D::set_audio_bus); + ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area3D::get_audio_bus); + + ClassDB::bind_method(D_METHOD("set_use_reverb_bus", "enable"), &Area3D::set_use_reverb_bus); + ClassDB::bind_method(D_METHOD("is_using_reverb_bus"), &Area3D::is_using_reverb_bus); + + ClassDB::bind_method(D_METHOD("set_reverb_bus", "name"), &Area3D::set_reverb_bus); + ClassDB::bind_method(D_METHOD("get_reverb_bus"), &Area3D::get_reverb_bus); + + ClassDB::bind_method(D_METHOD("set_reverb_amount", "amount"), &Area3D::set_reverb_amount); + ClassDB::bind_method(D_METHOD("get_reverb_amount"), &Area3D::get_reverb_amount); + + ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity); + ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity); + + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + + ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape"))); + ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); + ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity"); + 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::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_GROUP("Audio Bus", "audio_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); + ADD_GROUP("Reverb Bus", "reverb_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity"); + + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE); +} + +Area3D::Area3D() : + CollisionObject3D(PhysicsServer::get_singleton()->area_create(), true) { + + space_override = SPACE_OVERRIDE_DISABLED; + set_gravity(9.8); + locked = false; + set_gravity_vector(Vector3(0, -1, 0)); + gravity_is_point = false; + gravity_distance_scale = 0; + linear_damp = 0.1; + angular_damp = 0.1; + priority = 0; + monitoring = false; + monitorable = false; + collision_mask = 1; + collision_layer = 1; + set_monitoring(true); + set_monitorable(true); + + audio_bus_override = false; + audio_bus = "Master"; + + use_reverb_bus = false; + reverb_bus = "Master"; + reverb_amount = 0.0; + reverb_uniformity = 0.0; +} + +Area3D::~Area3D() { +} diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h new file mode 100644 index 0000000000..ff6c0b6b08 --- /dev/null +++ b/scene/3d/area_3d.h @@ -0,0 +1,217 @@ +/*************************************************************************/ +/* area_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef AREA_3D_H +#define AREA_3D_H + +#include "core/vset.h" +#include "scene/3d/collision_object_3d.h" + +class Area3D : public CollisionObject3D { + + GDCLASS(Area3D, CollisionObject3D); + +public: + enum SpaceOverride { + SPACE_OVERRIDE_DISABLED, + SPACE_OVERRIDE_COMBINE, + SPACE_OVERRIDE_COMBINE_REPLACE, + SPACE_OVERRIDE_REPLACE, + SPACE_OVERRIDE_REPLACE_COMBINE + }; + +private: + SpaceOverride space_override; + Vector3 gravity_vec; + real_t gravity; + bool gravity_is_point; + real_t gravity_distance_scale; + real_t angular_damp; + real_t linear_damp; + uint32_t collision_mask; + uint32_t collision_layer; + int priority; + bool monitoring; + bool monitorable; + bool locked; + + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape); + + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); + + struct ShapePair { + + int body_shape; + int area_shape; + bool operator<(const ShapePair &p_sp) const { + if (body_shape == p_sp.body_shape) + return area_shape < p_sp.area_shape; + else + return body_shape < p_sp.body_shape; + } + + ShapePair() {} + ShapePair(int p_bs, int p_as) { + body_shape = p_bs; + area_shape = p_as; + } + }; + + struct BodyState { + + int rc; + bool in_tree; + VSet shapes; + }; + + Map body_map; + + void _area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape); + + void _area_enter_tree(ObjectID p_id); + void _area_exit_tree(ObjectID p_id); + + struct AreaShapePair { + + int area_shape; + int self_shape; + bool operator<(const AreaShapePair &p_sp) const { + if (area_shape == p_sp.area_shape) + return self_shape < p_sp.self_shape; + else + return area_shape < p_sp.area_shape; + } + + AreaShapePair() {} + AreaShapePair(int p_bs, int p_as) { + area_shape = p_bs; + self_shape = p_as; + } + }; + + struct AreaState { + + int rc; + bool in_tree; + VSet shapes; + }; + + Map area_map; + void _clear_monitoring(); + + bool audio_bus_override; + StringName audio_bus; + + bool use_reverb_bus; + StringName reverb_bus; + float reverb_amount; + float reverb_uniformity; + + void _validate_property(PropertyInfo &property) const; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_space_override_mode() const; + + void set_gravity_is_point(bool p_enabled); + bool is_gravity_a_point() const; + + void set_gravity_distance_scale(real_t p_scale); + real_t get_gravity_distance_scale() const; + + void set_gravity_vector(const Vector3 &p_vec); + Vector3 get_gravity_vector() const; + + void set_gravity(real_t p_gravity); + real_t get_gravity() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_priority(real_t p_priority); + real_t get_priority() const; + + void set_monitoring(bool p_enable); + bool is_monitoring() const; + + void set_monitorable(bool p_enable); + bool is_monitorable() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + Array get_overlapping_bodies() const; + Array get_overlapping_areas() const; //function for script + + bool overlaps_area(Node *p_area) const; + bool overlaps_body(Node *p_body) const; + + void set_audio_bus_override(bool p_override); + bool is_overriding_audio_bus() const; + + void set_audio_bus(const StringName &p_audio_bus); + StringName get_audio_bus() const; + + void set_use_reverb_bus(bool p_enable); + bool is_using_reverb_bus() const; + + void set_reverb_bus(const StringName &p_audio_bus); + StringName get_reverb_bus() const; + + void set_reverb_amount(float p_amount); + float get_reverb_amount() const; + + void set_reverb_uniformity(float p_uniformity); + float get_reverb_uniformity() const; + + Area3D(); + ~Area3D(); +}; + +VARIANT_ENUM_CAST(Area3D::SpaceOverride); + +#endif // AREA__H diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index bea717b354..ce7c885a40 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -75,7 +75,7 @@ Vector3 ARVRCamera::project_local_ray_normal(const Point2 &p_pos) const { Ref arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass - return Camera::project_local_ray_normal(p_pos); + return Camera3D::project_local_ray_normal(p_pos); } ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); @@ -99,7 +99,7 @@ Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const { Ref arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass - return Camera::unproject_position(p_pos); + return Camera3D::unproject_position(p_pos); } ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene."); @@ -128,7 +128,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) con Ref arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass - return Camera::project_position(p_point, p_z_depth); + return Camera3D::project_position(p_point, p_z_depth); } ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); @@ -157,7 +157,7 @@ Vector ARVRCamera::get_frustum() const { Ref arvr_interface = arvr_server->get_primary_interface(); if (arvr_interface.is_null()) { // we might be in the editor or have VR turned off, just call superclass - return Camera::get_frustum(); + return Camera3D::get_frustum(); } ERR_FAIL_COND_V(!is_inside_world(), Vector()); diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h index e968e33c9d..bc5df2e174 100644 --- a/scene/3d/arvr_nodes.h +++ b/scene/3d/arvr_nodes.h @@ -31,8 +31,8 @@ #ifndef ARVR_NODES_H #define ARVR_NODES_H -#include "scene/3d/camera.h" -#include "scene/3d/spatial.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/node_3d.h" #include "scene/resources/mesh.h" #include "servers/arvr/arvr_positional_tracker.h" @@ -43,9 +43,9 @@ /* ARVRCamera is a subclass of camera which will register itself with its parent ARVROrigin and as a result is automatically positioned */ -class ARVRCamera : public Camera { +class ARVRCamera : public Camera3D { - GDCLASS(ARVRCamera, Camera); + GDCLASS(ARVRCamera, Camera3D); protected: void _notification(int p_what); @@ -68,9 +68,9 @@ public: It must be a child node of our ARVROrigin node */ -class ARVRController : public Spatial { +class ARVRController : public Node3D { - GDCLASS(ARVRController, Spatial); + GDCLASS(ARVRController, Node3D); private: int controller_id; @@ -110,8 +110,8 @@ public: It must be a child node of our ARVROrigin node */ -class ARVRAnchor : public Spatial { - GDCLASS(ARVRAnchor, Spatial); +class ARVRAnchor : public Node3D { + GDCLASS(ARVRAnchor, Node3D); private: int anchor_id; @@ -149,9 +149,9 @@ public: Our camera and controllers will always be child nodes and thus place relative to this origin point. This node will automatically locate any camera child nodes and update its position while our ARVRController node will handle tracked controllers. */ -class ARVROrigin : public Spatial { +class ARVROrigin : public Node3D { - GDCLASS(ARVROrigin, Spatial); + GDCLASS(ARVROrigin, Node3D); private: ARVRCamera *tracked_camera; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index f3020d4044..5cba16d346 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -30,9 +30,9 @@ #include "audio_stream_player_3d.h" #include "core/engine.h" -#include "scene/3d/area.h" -#include "scene/3d/camera.h" -#include "scene/3d/listener.h" +#include "scene/3d/area_3d.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/listener_3d.h" #include "scene/main/window.h" // Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004) @@ -400,13 +400,13 @@ void AudioStreamPlayer3D::_notification(int p_what) { PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set(), area_mask, false, true); - Area *area = NULL; + Area3D *area = NULL; for (int i = 0; i < areas; i++) { if (!sr[i].collider) continue; - Area *tarea = Object::cast_to(sr[i].collider); + Area3D *tarea = Object::cast_to(sr[i].collider); if (!tarea) continue; @@ -417,20 +417,20 @@ void AudioStreamPlayer3D::_notification(int p_what) { break; } - List cameras; + List cameras; world->get_camera_list(&cameras); - for (List::Element *E = cameras.front(); E; E = E->next()) { + for (List::Element *E = cameras.front(); E; E = E->next()) { - Camera *camera = E->get(); + Camera3D *camera = E->get(); Viewport *vp = camera->get_viewport(); if (!vp->is_audio_listener()) continue; bool listener_is_camera = true; - Spatial *listener_node = camera; + Node3D *listener_node = camera; - Listener *listener = vp->get_listener(); + Listener3D *listener = vp->get_listener(); if (listener) { listener_node = listener; listener_is_camera = false; diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 5b4c865475..1cce0c77d5 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -31,16 +31,16 @@ #ifndef AUDIO_STREAM_PLAYER_3D_H #define AUDIO_STREAM_PLAYER_3D_H -#include "scene/3d/spatial.h" -#include "scene/3d/spatial_velocity_tracker.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/velocity_tracker_3d.h" #include "servers/audio/audio_filter_sw.h" #include "servers/audio/audio_stream.h" #include "servers/audio_server.h" -class Camera; -class AudioStreamPlayer3D : public Spatial { +class Camera3D; +class AudioStreamPlayer3D : public Node3D { - GDCLASS(AudioStreamPlayer3D, Spatial); + GDCLASS(AudioStreamPlayer3D, Node3D); public: enum AttenuationModel { @@ -134,7 +134,7 @@ private: float max_distance; - Ref velocity_tracker; + Ref velocity_tracker; DopplerTracking doppler_tracking; diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp deleted file mode 100644 index b1cd9bfe8b..0000000000 --- a/scene/3d/bone_attachment.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************/ -/* bone_attachment.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "bone_attachment.h" - -void BoneAttachment::_validate_property(PropertyInfo &property) const { - - if (property.name == "bone_name") { - Skeleton *parent = Object::cast_to(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); - } - - property.hint = PROPERTY_HINT_ENUM; - property.hint_string = names; - } else { - - property.hint = PROPERTY_HINT_NONE; - property.hint_string = ""; - } - } -} - -void BoneAttachment::_check_bind() { - - Skeleton *sk = Object::cast_to(get_parent()); - if (sk) { - - int idx = sk->find_bone(bone_name); - if (idx != -1) { - sk->bind_child_node_to_bone(idx, this); - set_transform(sk->get_bone_global_pose(idx)); - bound = true; - } - } -} - -void BoneAttachment::_check_unbind() { - - if (bound) { - - Skeleton *sk = Object::cast_to(get_parent()); - if (sk) { - - int idx = sk->find_bone(bone_name); - if (idx != -1) { - sk->unbind_child_node_from_bone(idx, this); - } - } - bound = false; - } -} - -void BoneAttachment::set_bone_name(const String &p_name) { - - if (is_inside_tree()) - _check_unbind(); - - bone_name = p_name; - - if (is_inside_tree()) - _check_bind(); -} - -String BoneAttachment::get_bone_name() const { - - return bone_name; -} - -void BoneAttachment::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - _check_bind(); - } break; - case NOTIFICATION_EXIT_TREE: { - - _check_unbind(); - } break; - } -} - -BoneAttachment::BoneAttachment() { - bound = false; -} - -void BoneAttachment::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_bone_name", "bone_name"), &BoneAttachment::set_bone_name); - ClassDB::bind_method(D_METHOD("get_bone_name"), &BoneAttachment::get_bone_name); - - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name"); -} diff --git a/scene/3d/bone_attachment.h b/scene/3d/bone_attachment.h deleted file mode 100644 index 43c46dd759..0000000000 --- a/scene/3d/bone_attachment.h +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************/ -/* bone_attachment.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BONE_ATTACHMENT_H -#define BONE_ATTACHMENT_H - -#include "scene/3d/skeleton.h" - -class BoneAttachment : public Spatial { - - GDCLASS(BoneAttachment, Spatial); - - bool bound; - String bone_name; - - void _check_bind(); - void _check_unbind(); - -protected: - virtual void _validate_property(PropertyInfo &property) const; - void _notification(int p_what); - - static void _bind_methods(); - -public: - void set_bone_name(const String &p_name); - String get_bone_name() const; - - BoneAttachment(); -}; - -#endif // BONE_ATTACHMENT_H diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp new file mode 100644 index 0000000000..825cb39e2d --- /dev/null +++ b/scene/3d/bone_attachment_3d.cpp @@ -0,0 +1,127 @@ +/*************************************************************************/ +/* bone_attachment_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "bone_attachment_3d.h" + +void BoneAttachment3D::_validate_property(PropertyInfo &property) const { + + if (property.name == "bone_name") { + Skeleton3D *parent = Object::cast_to(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); + } + + property.hint = PROPERTY_HINT_ENUM; + property.hint_string = names; + } else { + + property.hint = PROPERTY_HINT_NONE; + property.hint_string = ""; + } + } +} + +void BoneAttachment3D::_check_bind() { + + Skeleton3D *sk = Object::cast_to(get_parent()); + if (sk) { + + int idx = sk->find_bone(bone_name); + if (idx != -1) { + sk->bind_child_node_to_bone(idx, this); + set_transform(sk->get_bone_global_pose(idx)); + bound = true; + } + } +} + +void BoneAttachment3D::_check_unbind() { + + if (bound) { + + Skeleton3D *sk = Object::cast_to(get_parent()); + if (sk) { + + int idx = sk->find_bone(bone_name); + if (idx != -1) { + sk->unbind_child_node_from_bone(idx, this); + } + } + bound = false; + } +} + +void BoneAttachment3D::set_bone_name(const String &p_name) { + + if (is_inside_tree()) + _check_unbind(); + + bone_name = p_name; + + if (is_inside_tree()) + _check_bind(); +} + +String BoneAttachment3D::get_bone_name() const { + + return bone_name; +} + +void BoneAttachment3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + _check_bind(); + } break; + case NOTIFICATION_EXIT_TREE: { + + _check_unbind(); + } break; + } +} + +BoneAttachment3D::BoneAttachment3D() { + bound = false; +} + +void BoneAttachment3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_bone_name", "bone_name"), &BoneAttachment3D::set_bone_name); + ClassDB::bind_method(D_METHOD("get_bone_name"), &BoneAttachment3D::get_bone_name); + + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name"); +} diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h new file mode 100644 index 0000000000..d2a3ffec90 --- /dev/null +++ b/scene/3d/bone_attachment_3d.h @@ -0,0 +1,59 @@ +/*************************************************************************/ +/* bone_attachment_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BONE_ATTACHMENT_H +#define BONE_ATTACHMENT_H + +#include "scene/3d/skeleton_3d.h" + +class BoneAttachment3D : public Node3D { + + GDCLASS(BoneAttachment3D, Node3D); + + bool bound; + String bone_name; + + void _check_bind(); + void _check_unbind(); + +protected: + virtual void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); + + static void _bind_methods(); + +public: + void set_bone_name(const String &p_name); + String get_bone_name() const; + + BoneAttachment3D(); +}; + +#endif // BONE_ATTACHMENT_H diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp deleted file mode 100644 index 741712025c..0000000000 --- a/scene/3d/camera.cpp +++ /dev/null @@ -1,954 +0,0 @@ -/*************************************************************************/ -/* camera.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "camera.h" - -#include "collision_object.h" -#include "core/engine.h" -#include "core/math/camera_matrix.h" -#include "scene/resources/material.h" -#include "scene/resources/surface_tool.h" -void Camera::_update_audio_listener_state() { -} - -void Camera::_request_camera_update() { - - _update_camera(); -} - -void Camera::_update_camera_mode() { - - force_change = true; - switch (mode) { - case PROJECTION_PERSPECTIVE: { - - set_perspective(fov, near, far); - - } break; - case PROJECTION_ORTHOGONAL: { - set_orthogonal(size, near, far); - } break; - case PROJECTION_FRUSTUM: { - set_frustum(size, frustum_offset, near, far); - } break; - } -} - -void Camera::_validate_property(PropertyInfo &p_property) const { - if (p_property.name == "fov") { - if (mode != PROJECTION_PERSPECTIVE) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; - } - } else if (p_property.name == "size") { - if (mode != PROJECTION_ORTHOGONAL && mode != PROJECTION_FRUSTUM) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; - } - } else if (p_property.name == "frustum_offset") { - if (mode != PROJECTION_FRUSTUM) { - p_property.usage = PROPERTY_USAGE_NOEDITOR; - } - } -} - -void Camera::_update_camera() { - - if (!is_inside_tree()) - return; - - VisualServer::get_singleton()->camera_set_transform(camera, get_camera_transform()); - - // here goes listener stuff - /* - if (viewport_ptr && is_inside_scene() && is_current()) - get_viewport()->_camera_transform_changed_notify(); - */ - - if (get_tree()->is_node_being_edited(this) || !is_current()) - return; - - get_viewport()->_camera_transform_changed_notify(); - - if (get_world().is_valid()) { - get_world()->_update_camera(this); - } -} - -void Camera::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_WORLD: { - - // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD - // and Spatial will handle it first, including clearing its reference to the Viewport, - // therefore making it impossible to subclasses to access it - viewport = get_viewport(); - ERR_FAIL_COND(!viewport); - - bool first_camera = viewport->_camera_add(this); - if (current || first_camera) - viewport->_camera_set(this); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - _request_camera_update(); - if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { - velocity_tracker->update_position(get_global_transform().origin); - } - } break; - case NOTIFICATION_EXIT_WORLD: { - - if (!get_tree()->is_node_being_edited(this)) { - if (is_current()) { - clear_current(); - current = true; //keep it true - - } else { - current = false; - } - } - - if (viewport) { - viewport->_camera_remove(this); - viewport = NULL; - } - - } break; - case NOTIFICATION_BECAME_CURRENT: { - if (viewport) { - viewport->find_world()->_register_camera(this); - } - } break; - case NOTIFICATION_LOST_CURRENT: { - if (viewport) { - viewport->find_world()->_remove_camera(this); - } - } break; - } -} - -Transform Camera::get_camera_transform() const { - - Transform tr = get_global_transform().orthonormalized(); - tr.origin += tr.basis.get_axis(1) * v_offset; - tr.origin += tr.basis.get_axis(0) * h_offset; - return tr; -} - -void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) { - - if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE) - return; - - fov = p_fovy_degrees; - near = p_z_near; - far = p_z_far; - mode = PROJECTION_PERSPECTIVE; - - VisualServer::get_singleton()->camera_set_perspective(camera, fov, near, far); - update_gizmo(); - force_change = false; -} -void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) { - - if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL) - return; - - size = p_size; - - near = p_z_near; - far = p_z_far; - mode = PROJECTION_ORTHOGONAL; - force_change = false; - - VisualServer::get_singleton()->camera_set_orthogonal(camera, size, near, far); - update_gizmo(); -} - -void Camera::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { - if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM) - return; - - size = p_size; - frustum_offset = p_offset; - - near = p_z_near; - far = p_z_far; - mode = PROJECTION_FRUSTUM; - force_change = false; - - VisualServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far); - update_gizmo(); -} - -void Camera::set_projection(Camera::Projection p_mode) { - if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) { - mode = p_mode; - _update_camera_mode(); - _change_notify(); - } -} - -RID Camera::get_camera() const { - - return camera; -}; - -void Camera::make_current() { - - current = true; - - if (!is_inside_tree()) - return; - - get_viewport()->_camera_set(this); - - //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); -} - -void Camera::clear_current(bool p_enable_next) { - - current = false; - if (!is_inside_tree()) - return; - - if (get_viewport()->get_camera() == this) { - get_viewport()->_camera_set(NULL); - - if (p_enable_next) { - get_viewport()->_camera_make_next_current(this); - } - } -} - -void Camera::set_current(bool p_current) { - if (p_current) { - make_current(); - } else { - clear_current(); - } -} - -bool Camera::is_current() const { - - if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { - - return get_viewport()->get_camera() == this; - } else - return current; -} - -bool Camera::_can_gizmo_scale() const { - - return false; -} - -Vector3 Camera::project_ray_normal(const Point2 &p_pos) const { - - Vector3 ray = project_local_ray_normal(p_pos); - return get_camera_transform().basis.xform(ray).normalized(); -}; - -Vector3 Camera::project_local_ray_normal(const Point2 &p_pos) const { - - ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - - Size2 viewport_size = get_viewport()->get_camera_rect_size(); - Vector2 cpos = get_viewport()->get_camera_coords(p_pos); - Vector3 ray; - - if (mode == PROJECTION_ORTHOGONAL) { - - ray = Vector3(0, 0, -1); - } else { - CameraMatrix cm; - cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - Vector2 screen_he = cm.get_viewport_half_extents(); - ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized(); - } - - return ray; -}; - -Vector3 Camera::project_ray_origin(const Point2 &p_pos) const { - - ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - - Size2 viewport_size = get_viewport()->get_camera_rect_size(); - Vector2 cpos = get_viewport()->get_camera_coords(p_pos); - ERR_FAIL_COND_V(viewport_size.y == 0, Vector3()); - - if (mode == PROJECTION_PERSPECTIVE) { - - return get_camera_transform().origin; - } else { - - Vector2 pos = cpos / viewport_size; - float vsize, hsize; - if (keep_aspect == KEEP_WIDTH) { - vsize = size / viewport_size.aspect(); - hsize = size; - } else { - hsize = size * viewport_size.aspect(); - vsize = size; - } - - Vector3 ray; - ray.x = pos.x * (hsize)-hsize / 2; - ray.y = (1.0 - pos.y) * (vsize)-vsize / 2; - ray.z = -near; - ray = get_camera_transform().xform(ray); - return ray; - }; -}; - -bool Camera::is_position_behind(const Vector3 &p_pos) const { - - Transform t = get_global_transform(); - Vector3 eyedir = -get_global_transform().basis.get_axis(2).normalized(); - return eyedir.dot(p_pos) < (eyedir.dot(t.origin) + near); -} - -Vector Camera::get_near_plane_points() const { - ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector(), "Camera is not inside scene."); - - Size2 viewport_size = get_viewport()->get_visible_rect().size; - - CameraMatrix cm; - - if (mode == PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - else - cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - - Vector3 endpoints[8]; - cm.get_endpoints(Transform(), endpoints); - - Vector points; - points.push_back(Vector3()); - for (int i = 0; i < 4; i++) { - points.push_back(endpoints[i + 4]); - } - return points; -} - -Point2 Camera::unproject_position(const Vector3 &p_pos) const { - - ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene."); - - Size2 viewport_size = get_viewport()->get_visible_rect().size; - - CameraMatrix cm; - - if (mode == PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - else - cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - - Plane p(get_camera_transform().xform_inv(p_pos), 1.0); - - p = cm.xform4(p); - p.normal /= p.d; - - Point2 res; - res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x; - res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y; - - return res; -} - -Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const { - - ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - - if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) { - return get_global_transform().origin; - } - Size2 viewport_size = get_viewport()->get_visible_rect().size; - - CameraMatrix cm; - - if (mode == PROJECTION_ORTHOGONAL) - cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); - else - cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); - - Vector2 vp_he = cm.get_viewport_half_extents(); - - Vector2 point; - point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0; - point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0; - point *= vp_he; - - Vector3 p(point.x, point.y, -p_z_depth); - - return get_camera_transform().xform(p); -} - -/* -void Camera::_camera_make_current(Node *p_camera) { - - - if (p_camera==this) { - VisualServer::get_singleton()->viewport_attach_camera(viewport_id,camera); - active=true; - } else { - if (active && p_camera==NULL) { - //detech camera because no one else will claim it - VisualServer::get_singleton()->viewport_attach_camera(viewport_id,RID()); - } - active=false; - } -} -*/ - -void Camera::set_environment(const Ref &p_environment) { - - environment = p_environment; - if (environment.is_valid()) - VS::get_singleton()->camera_set_environment(camera, environment->get_rid()); - else - VS::get_singleton()->camera_set_environment(camera, RID()); - _update_camera_mode(); -} - -Ref Camera::get_environment() const { - - return environment; -} - -void Camera::set_effects(const Ref &p_effects) { - - effects = p_effects; - if (effects.is_valid()) - VS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid()); - else - VS::get_singleton()->camera_set_camera_effects(camera, RID()); - _update_camera_mode(); -} - -Ref Camera::get_effects() const { - - return effects; -} - -void Camera::set_keep_aspect_mode(KeepAspect p_aspect) { - keep_aspect = p_aspect; - VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); - _update_camera_mode(); - _change_notify(); -} - -Camera::KeepAspect Camera::get_keep_aspect_mode() const { - - return keep_aspect; -} - -void Camera::set_doppler_tracking(DopplerTracking p_tracking) { - - if (doppler_tracking == p_tracking) - return; - - doppler_tracking = p_tracking; - if (p_tracking != DOPPLER_TRACKING_DISABLED) { - velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP); - if (is_inside_tree()) { - velocity_tracker->reset(get_global_transform().origin); - } - } - _update_camera_mode(); -} - -Camera::DopplerTracking Camera::get_doppler_tracking() const { - return doppler_tracking; -} - -void Camera::_bind_methods() { - - ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera::project_ray_normal); - ClassDB::bind_method(D_METHOD("project_local_ray_normal", "screen_point"), &Camera::project_local_ray_normal); - ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera::project_ray_origin); - ClassDB::bind_method(D_METHOD("unproject_position", "world_point"), &Camera::unproject_position); - ClassDB::bind_method(D_METHOD("is_position_behind", "world_point"), &Camera::is_position_behind); - ClassDB::bind_method(D_METHOD("project_position", "screen_point", "z_depth"), &Camera::project_position); - ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective); - ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal); - ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera::set_frustum); - ClassDB::bind_method(D_METHOD("make_current"), &Camera::make_current); - ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera::clear_current, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("set_current"), &Camera::set_current); - ClassDB::bind_method(D_METHOD("is_current"), &Camera::is_current); - ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera::get_camera_transform); - ClassDB::bind_method(D_METHOD("get_fov"), &Camera::get_fov); - ClassDB::bind_method(D_METHOD("get_frustum_offset"), &Camera::get_frustum_offset); - ClassDB::bind_method(D_METHOD("get_size"), &Camera::get_size); - ClassDB::bind_method(D_METHOD("get_zfar"), &Camera::get_zfar); - ClassDB::bind_method(D_METHOD("get_znear"), &Camera::get_znear); - ClassDB::bind_method(D_METHOD("set_fov"), &Camera::set_fov); - ClassDB::bind_method(D_METHOD("set_frustum_offset"), &Camera::set_frustum_offset); - ClassDB::bind_method(D_METHOD("set_size"), &Camera::set_size); - ClassDB::bind_method(D_METHOD("set_zfar"), &Camera::set_zfar); - ClassDB::bind_method(D_METHOD("set_znear"), &Camera::set_znear); - ClassDB::bind_method(D_METHOD("get_projection"), &Camera::get_projection); - ClassDB::bind_method(D_METHOD("set_projection"), &Camera::set_projection); - ClassDB::bind_method(D_METHOD("set_h_offset", "ofs"), &Camera::set_h_offset); - ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera::get_h_offset); - ClassDB::bind_method(D_METHOD("set_v_offset", "ofs"), &Camera::set_v_offset); - ClassDB::bind_method(D_METHOD("get_v_offset"), &Camera::get_v_offset); - ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Camera::set_cull_mask); - ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera::get_cull_mask); - ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera::set_environment); - ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment); - ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera::set_effects); - ClassDB::bind_method(D_METHOD("get_effects"), &Camera::get_effects); - ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode); - ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode); - ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking); - ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking); - ClassDB::bind_method(D_METHOD("get_frustum"), &Camera::get_frustum); - ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera::get_camera); - - ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera::set_cull_mask_bit); - ClassDB::bind_method(D_METHOD("get_cull_mask_bit", "layer"), &Camera::get_cull_mask_bit); - - //ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current ); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar"); - - BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); - BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL); - BIND_ENUM_CONSTANT(PROJECTION_FRUSTUM); - - BIND_ENUM_CONSTANT(KEEP_WIDTH); - BIND_ENUM_CONSTANT(KEEP_HEIGHT); - - BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED); - BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP); - BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP); -} - -float Camera::get_fov() const { - - return fov; -} - -float Camera::get_size() const { - - return size; -} - -float Camera::get_znear() const { - - return near; -} - -Vector2 Camera::get_frustum_offset() const { - return frustum_offset; -} - -float Camera::get_zfar() const { - - return far; -} - -Camera::Projection Camera::get_projection() const { - - return mode; -} - -void Camera::set_fov(float p_fov) { - ERR_FAIL_COND(p_fov < 1 || p_fov > 179); - fov = p_fov; - _update_camera_mode(); - _change_notify("fov"); -} - -void Camera::set_size(float p_size) { - ERR_FAIL_COND(p_size < 0.1 || p_size > 16384); - size = p_size; - _update_camera_mode(); - _change_notify("size"); -} - -void Camera::set_znear(float p_znear) { - near = p_znear; - _update_camera_mode(); -} - -void Camera::set_frustum_offset(Vector2 p_offset) { - frustum_offset = p_offset; - _update_camera_mode(); -} - -void Camera::set_zfar(float p_zfar) { - far = p_zfar; - _update_camera_mode(); -} - -void Camera::set_cull_mask(uint32_t p_layers) { - layers = p_layers; - VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); - _update_camera_mode(); -} - -uint32_t Camera::get_cull_mask() const { - - return layers; -} - -void Camera::set_cull_mask_bit(int p_layer, bool p_enable) { - ERR_FAIL_INDEX(p_layer, 32); - if (p_enable) { - set_cull_mask(layers | (1 << p_layer)); - } else { - set_cull_mask(layers & (~(1 << p_layer))); - } -} - -bool Camera::get_cull_mask_bit(int p_layer) const { - ERR_FAIL_INDEX_V(p_layer, 32, false); - return (layers & (1 << p_layer)); -} - -Vector Camera::get_frustum() const { - - ERR_FAIL_COND_V(!is_inside_world(), Vector()); - - Size2 viewport_size = get_viewport()->get_visible_rect().size; - CameraMatrix cm; - if (mode == PROJECTION_PERSPECTIVE) - cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - else - cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); - - return cm.get_projection_planes(get_camera_transform()); -} - -void Camera::set_v_offset(float p_offset) { - - v_offset = p_offset; - _update_camera(); -} - -float Camera::get_v_offset() const { - - return v_offset; -} - -void Camera::set_h_offset(float p_offset) { - h_offset = p_offset; - _update_camera(); -} - -float Camera::get_h_offset() const { - - return h_offset; -} - -Vector3 Camera::get_doppler_tracked_velocity() const { - - if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { - return velocity_tracker->get_tracked_linear_velocity(); - } else { - return Vector3(); - } -} -Camera::Camera() { - - camera = VisualServer::get_singleton()->camera_create(); - size = 1; - fov = 0; - frustum_offset = Vector2(); - near = 0; - far = 0; - current = false; - viewport = NULL; - force_change = false; - mode = PROJECTION_PERSPECTIVE; - set_perspective(70.0, 0.05, 100.0); - keep_aspect = KEEP_HEIGHT; - layers = 0xfffff; - v_offset = 0; - h_offset = 0; - VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); - //active=false; - velocity_tracker.instance(); - doppler_tracking = DOPPLER_TRACKING_DISABLED; - set_notify_transform(true); - set_disable_scale(true); -} - -Camera::~Camera() { - - VisualServer::get_singleton()->free(camera); -} - -//////////////////////////////////////// - -void ClippedCamera::set_margin(float p_margin) { - margin = p_margin; -} -float ClippedCamera::get_margin() const { - return margin; -} -void ClippedCamera::set_process_mode(ProcessMode p_mode) { - - if (process_mode == p_mode) { - return; - } - process_mode = p_mode; - set_process_internal(process_mode == CLIP_PROCESS_IDLE); - set_physics_process_internal(process_mode == CLIP_PROCESS_PHYSICS); -} -ClippedCamera::ProcessMode ClippedCamera::get_process_mode() const { - return process_mode; -} - -Transform ClippedCamera::get_camera_transform() const { - - Transform t = Camera::get_camera_transform(); - t.origin += -t.basis.get_axis(Vector3::AXIS_Z).normalized() * clip_offset; - return t; -} - -void ClippedCamera::_notification(int p_what) { - if (p_what == NOTIFICATION_INTERNAL_PROCESS || p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { - - Spatial *parent = Object::cast_to(get_parent()); - if (!parent) { - return; - } - - PhysicsDirectSpaceState *dspace = get_world()->get_direct_space_state(); - ERR_FAIL_COND(!dspace); // most likely physics set to threads - - Vector3 cam_fw = -get_global_transform().basis.get_axis(Vector3::AXIS_Z).normalized(); - Vector3 cam_pos = get_global_transform().origin; - Vector3 parent_pos = parent->get_global_transform().origin; - - Plane parent_plane(parent_pos, cam_fw); - - if (parent_plane.is_point_over(cam_pos)) { - //cam is beyond parent plane - return; - } - - Vector3 ray_from = parent_plane.project(cam_pos); - - clip_offset = 0; //reset by defau;t - - { //check if points changed - Vector local_points = get_near_plane_points(); - - bool all_equal = true; - - for (int i = 0; i < 5; i++) { - if (points[i] != local_points[i]) { - all_equal = false; - break; - } - } - - if (!all_equal) { - PhysicsServer::get_singleton()->shape_set_data(pyramid_shape, local_points); - points = local_points; - } - } - - Transform xf = get_global_transform(); - xf.origin = ray_from; - xf.orthonormalize(); - - float csafe, cunsafe; - if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, csafe, cunsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) { - clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * csafe); - } - - _update_camera(); - } - - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - update_gizmo(); - } -} - -void ClippedCamera::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; -} - -uint32_t ClippedCamera::get_collision_mask() const { - - return collision_mask; -} - -void ClippedCamera::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool ClippedCamera::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -void ClippedCamera::add_exception_rid(const RID &p_rid) { - - exclude.insert(p_rid); -} - -void ClippedCamera::add_exception(const Object *p_object) { - - ERR_FAIL_NULL(p_object); - const CollisionObject *co = Object::cast_to(p_object); - if (!co) - return; - add_exception_rid(co->get_rid()); -} - -void ClippedCamera::remove_exception_rid(const RID &p_rid) { - - exclude.erase(p_rid); -} - -void ClippedCamera::remove_exception(const Object *p_object) { - - ERR_FAIL_NULL(p_object); - const CollisionObject *co = Object::cast_to(p_object); - if (!co) - return; - remove_exception_rid(co->get_rid()); -} - -void ClippedCamera::clear_exceptions() { - - exclude.clear(); -} - -float ClippedCamera::get_clip_offset() const { - - return clip_offset; -} - -void ClippedCamera::set_clip_to_areas(bool p_clip) { - - clip_to_areas = p_clip; -} - -bool ClippedCamera::is_clip_to_areas_enabled() const { - - return clip_to_areas; -} - -void ClippedCamera::set_clip_to_bodies(bool p_clip) { - - clip_to_bodies = p_clip; -} - -bool ClippedCamera::is_clip_to_bodies_enabled() const { - - return clip_to_bodies; -} - -void ClippedCamera::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ClippedCamera::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &ClippedCamera::get_margin); - - ClassDB::bind_method(D_METHOD("set_process_mode", "process_mode"), &ClippedCamera::set_process_mode); - ClassDB::bind_method(D_METHOD("get_process_mode"), &ClippedCamera::get_process_mode); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ClippedCamera::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &ClippedCamera::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &ClippedCamera::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &ClippedCamera::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &ClippedCamera::add_exception_rid); - ClassDB::bind_method(D_METHOD("add_exception", "node"), &ClippedCamera::add_exception); - - ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &ClippedCamera::remove_exception_rid); - ClassDB::bind_method(D_METHOD("remove_exception", "node"), &ClippedCamera::remove_exception); - - ClassDB::bind_method(D_METHOD("set_clip_to_areas", "enable"), &ClippedCamera::set_clip_to_areas); - ClassDB::bind_method(D_METHOD("is_clip_to_areas_enabled"), &ClippedCamera::is_clip_to_areas_enabled); - - ClassDB::bind_method(D_METHOD("get_clip_offset"), &ClippedCamera::get_clip_offset); - - ClassDB::bind_method(D_METHOD("set_clip_to_bodies", "enable"), &ClippedCamera::set_clip_to_bodies); - ClassDB::bind_method(D_METHOD("is_clip_to_bodies_enabled"), &ClippedCamera::is_clip_to_bodies_enabled); - - ClassDB::bind_method(D_METHOD("clear_exceptions"), &ClippedCamera::clear_exceptions); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - - ADD_GROUP("Clip To", "clip_to"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_areas", "is_clip_to_areas_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_bodies", "is_clip_to_bodies_enabled"); - - BIND_ENUM_CONSTANT(CLIP_PROCESS_PHYSICS); - BIND_ENUM_CONSTANT(CLIP_PROCESS_IDLE); -} -ClippedCamera::ClippedCamera() { - margin = 0; - clip_offset = 0; - process_mode = CLIP_PROCESS_PHYSICS; - set_physics_process_internal(true); - collision_mask = 1; - set_notify_local_transform(Engine::get_singleton()->is_editor_hint()); - points.resize(5); - pyramid_shape = PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON); - clip_to_areas = false; - clip_to_bodies = true; -} -ClippedCamera::~ClippedCamera() { - PhysicsServer::get_singleton()->free(pyramid_shape); -} diff --git a/scene/3d/camera.h b/scene/3d/camera.h deleted file mode 100644 index feb7b39b1e..0000000000 --- a/scene/3d/camera.h +++ /dev/null @@ -1,246 +0,0 @@ -/*************************************************************************/ -/* camera.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CAMERA_H -#define CAMERA_H - -#include "scene/3d/spatial.h" -#include "scene/3d/spatial_velocity_tracker.h" -#include "scene/main/window.h" -#include "scene/resources/environment.h" - -class Camera : public Spatial { - - GDCLASS(Camera, Spatial); - -public: - enum Projection { - - PROJECTION_PERSPECTIVE, - PROJECTION_ORTHOGONAL, - PROJECTION_FRUSTUM - }; - - enum KeepAspect { - KEEP_WIDTH, - KEEP_HEIGHT - }; - - enum DopplerTracking { - DOPPLER_TRACKING_DISABLED, - DOPPLER_TRACKING_IDLE_STEP, - DOPPLER_TRACKING_PHYSICS_STEP - }; - -private: - bool force_change; - bool current; - Viewport *viewport; - - Projection mode; - - float fov; - float size; - Vector2 frustum_offset; - float near, far; - float v_offset; - float h_offset; - KeepAspect keep_aspect; - - RID camera; - RID scenario_id; - - //String camera_group; - - uint32_t layers; - - Ref environment; - Ref effects; - - virtual bool _can_gizmo_scale() const; - - //void _camera_make_current(Node *p_camera); - friend class Viewport; - void _update_audio_listener_state(); - - DopplerTracking doppler_tracking; - Ref velocity_tracker; - -protected: - void _update_camera(); - virtual void _request_camera_update(); - void _update_camera_mode(); - - void _notification(int p_what); - virtual void _validate_property(PropertyInfo &p_property) const; - - static void _bind_methods(); - -public: - enum { - - NOTIFICATION_BECAME_CURRENT = 50, - NOTIFICATION_LOST_CURRENT = 51 - }; - - void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far); - void set_orthogonal(float p_size, float p_z_near, float p_z_far); - void set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far); - void set_projection(Camera::Projection p_mode); - - void make_current(); - void clear_current(bool p_enable_next = true); - void set_current(bool p_current); - bool is_current() const; - - RID get_camera() const; - - float get_fov() const; - float get_size() const; - float get_zfar() const; - float get_znear() const; - Vector2 get_frustum_offset() const; - - Projection get_projection() const; - - void set_fov(float p_fov); - void set_size(float p_size); - void set_zfar(float p_zfar); - void set_znear(float p_znear); - void set_frustum_offset(Vector2 p_offset); - - virtual Transform get_camera_transform() const; - - virtual Vector3 project_ray_normal(const Point2 &p_pos) const; - virtual Vector3 project_ray_origin(const Point2 &p_pos) const; - virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const; - virtual Point2 unproject_position(const Vector3 &p_pos) const; - bool is_position_behind(const Vector3 &p_pos) const; - virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const; - - Vector get_near_plane_points() const; - - void set_cull_mask(uint32_t p_layers); - uint32_t get_cull_mask() const; - - void set_cull_mask_bit(int p_layer, bool p_enable); - bool get_cull_mask_bit(int p_layer) const; - - virtual Vector get_frustum() const; - - void set_environment(const Ref &p_environment); - Ref get_environment() const; - - void set_effects(const Ref &p_effects); - Ref get_effects() const; - - void set_keep_aspect_mode(KeepAspect p_aspect); - KeepAspect get_keep_aspect_mode() const; - - void set_v_offset(float p_offset); - float get_v_offset() const; - - void set_h_offset(float p_offset); - float get_h_offset() const; - - void set_doppler_tracking(DopplerTracking p_tracking); - DopplerTracking get_doppler_tracking() const; - - Vector3 get_doppler_tracked_velocity() const; - - Camera(); - ~Camera(); -}; - -VARIANT_ENUM_CAST(Camera::Projection); -VARIANT_ENUM_CAST(Camera::KeepAspect); -VARIANT_ENUM_CAST(Camera::DopplerTracking); - -class ClippedCamera : public Camera { - - GDCLASS(ClippedCamera, Camera); - -public: - enum ProcessMode { - CLIP_PROCESS_PHYSICS, - CLIP_PROCESS_IDLE, - }; - -private: - ProcessMode process_mode; - RID pyramid_shape; - float margin; - float clip_offset; - uint32_t collision_mask; - bool clip_to_areas; - bool clip_to_bodies; - - Set exclude; - - Vector points; - -protected: - void _notification(int p_what); - static void _bind_methods(); - virtual Transform get_camera_transform() const; - -public: - void set_clip_to_areas(bool p_clip); - bool is_clip_to_areas_enabled() const; - - void set_clip_to_bodies(bool p_clip); - bool is_clip_to_bodies_enabled() const; - - void set_margin(float p_margin); - float get_margin() const; - - void set_process_mode(ProcessMode p_mode); - ProcessMode get_process_mode() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - void add_exception_rid(const RID &p_rid); - void add_exception(const Object *p_object); - void remove_exception_rid(const RID &p_rid); - void remove_exception(const Object *p_object); - void clear_exceptions(); - - float get_clip_offset() const; - - ClippedCamera(); - ~ClippedCamera(); -}; - -VARIANT_ENUM_CAST(ClippedCamera::ProcessMode); -#endif diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp new file mode 100644 index 0000000000..bf216ba115 --- /dev/null +++ b/scene/3d/camera_3d.cpp @@ -0,0 +1,954 @@ +/*************************************************************************/ +/* camera_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "camera_3d.h" + +#include "collision_object_3d.h" +#include "core/engine.h" +#include "core/math/camera_matrix.h" +#include "scene/resources/material.h" +#include "scene/resources/surface_tool.h" +void Camera3D::_update_audio_listener_state() { +} + +void Camera3D::_request_camera_update() { + + _update_camera(); +} + +void Camera3D::_update_camera_mode() { + + force_change = true; + switch (mode) { + case PROJECTION_PERSPECTIVE: { + + set_perspective(fov, near, far); + + } break; + case PROJECTION_ORTHOGONAL: { + set_orthogonal(size, near, far); + } break; + case PROJECTION_FRUSTUM: { + set_frustum(size, frustum_offset, near, far); + } break; + } +} + +void Camera3D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "fov") { + if (mode != PROJECTION_PERSPECTIVE) { + p_property.usage = PROPERTY_USAGE_NOEDITOR; + } + } else if (p_property.name == "size") { + if (mode != PROJECTION_ORTHOGONAL && mode != PROJECTION_FRUSTUM) { + p_property.usage = PROPERTY_USAGE_NOEDITOR; + } + } else if (p_property.name == "frustum_offset") { + if (mode != PROJECTION_FRUSTUM) { + p_property.usage = PROPERTY_USAGE_NOEDITOR; + } + } +} + +void Camera3D::_update_camera() { + + if (!is_inside_tree()) + return; + + VisualServer::get_singleton()->camera_set_transform(camera, get_camera_transform()); + + // here goes listener stuff + /* + if (viewport_ptr && is_inside_scene() && is_current()) + get_viewport()->_camera_transform_changed_notify(); + */ + + if (get_tree()->is_node_being_edited(this) || !is_current()) + return; + + get_viewport()->_camera_transform_changed_notify(); + + if (get_world().is_valid()) { + get_world()->_update_camera(this); + } +} + +void Camera3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_WORLD: { + + // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD + // and Spatial will handle it first, including clearing its reference to the Viewport, + // therefore making it impossible to subclasses to access it + viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + + bool first_camera = viewport->_camera_add(this); + if (current || first_camera) + viewport->_camera_set(this); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + _request_camera_update(); + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + velocity_tracker->update_position(get_global_transform().origin); + } + } break; + case NOTIFICATION_EXIT_WORLD: { + + if (!get_tree()->is_node_being_edited(this)) { + if (is_current()) { + clear_current(); + current = true; //keep it true + + } else { + current = false; + } + } + + if (viewport) { + viewport->_camera_remove(this); + viewport = NULL; + } + + } break; + case NOTIFICATION_BECAME_CURRENT: { + if (viewport) { + viewport->find_world()->_register_camera(this); + } + } break; + case NOTIFICATION_LOST_CURRENT: { + if (viewport) { + viewport->find_world()->_remove_camera(this); + } + } break; + } +} + +Transform Camera3D::get_camera_transform() const { + + Transform tr = get_global_transform().orthonormalized(); + tr.origin += tr.basis.get_axis(1) * v_offset; + tr.origin += tr.basis.get_axis(0) * h_offset; + return tr; +} + +void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) { + + if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE) + return; + + fov = p_fovy_degrees; + near = p_z_near; + far = p_z_far; + mode = PROJECTION_PERSPECTIVE; + + VisualServer::get_singleton()->camera_set_perspective(camera, fov, near, far); + update_gizmo(); + force_change = false; +} +void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) { + + if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL) + return; + + size = p_size; + + near = p_z_near; + far = p_z_far; + mode = PROJECTION_ORTHOGONAL; + force_change = false; + + VisualServer::get_singleton()->camera_set_orthogonal(camera, size, near, far); + update_gizmo(); +} + +void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { + if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM) + return; + + size = p_size; + frustum_offset = p_offset; + + near = p_z_near; + far = p_z_far; + mode = PROJECTION_FRUSTUM; + force_change = false; + + VisualServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far); + update_gizmo(); +} + +void Camera3D::set_projection(Camera3D::Projection p_mode) { + if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) { + mode = p_mode; + _update_camera_mode(); + _change_notify(); + } +} + +RID Camera3D::get_camera() const { + + return camera; +}; + +void Camera3D::make_current() { + + current = true; + + if (!is_inside_tree()) + return; + + get_viewport()->_camera_set(this); + + //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); +} + +void Camera3D::clear_current(bool p_enable_next) { + + current = false; + if (!is_inside_tree()) + return; + + if (get_viewport()->get_camera() == this) { + get_viewport()->_camera_set(NULL); + + if (p_enable_next) { + get_viewport()->_camera_make_next_current(this); + } + } +} + +void Camera3D::set_current(bool p_current) { + if (p_current) { + make_current(); + } else { + clear_current(); + } +} + +bool Camera3D::is_current() const { + + if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { + + return get_viewport()->get_camera() == this; + } else + return current; +} + +bool Camera3D::_can_gizmo_scale() const { + + return false; +} + +Vector3 Camera3D::project_ray_normal(const Point2 &p_pos) const { + + Vector3 ray = project_local_ray_normal(p_pos); + return get_camera_transform().basis.xform(ray).normalized(); +}; + +Vector3 Camera3D::project_local_ray_normal(const Point2 &p_pos) const { + + ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); + + Size2 viewport_size = get_viewport()->get_camera_rect_size(); + Vector2 cpos = get_viewport()->get_camera_coords(p_pos); + Vector3 ray; + + if (mode == PROJECTION_ORTHOGONAL) { + + ray = Vector3(0, 0, -1); + } else { + CameraMatrix cm; + cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + Vector2 screen_he = cm.get_viewport_half_extents(); + ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized(); + } + + return ray; +}; + +Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const { + + ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); + + Size2 viewport_size = get_viewport()->get_camera_rect_size(); + Vector2 cpos = get_viewport()->get_camera_coords(p_pos); + ERR_FAIL_COND_V(viewport_size.y == 0, Vector3()); + + if (mode == PROJECTION_PERSPECTIVE) { + + return get_camera_transform().origin; + } else { + + Vector2 pos = cpos / viewport_size; + float vsize, hsize; + if (keep_aspect == KEEP_WIDTH) { + vsize = size / viewport_size.aspect(); + hsize = size; + } else { + hsize = size * viewport_size.aspect(); + vsize = size; + } + + Vector3 ray; + ray.x = pos.x * (hsize)-hsize / 2; + ray.y = (1.0 - pos.y) * (vsize)-vsize / 2; + ray.z = -near; + ray = get_camera_transform().xform(ray); + return ray; + }; +}; + +bool Camera3D::is_position_behind(const Vector3 &p_pos) const { + + Transform t = get_global_transform(); + Vector3 eyedir = -get_global_transform().basis.get_axis(2).normalized(); + return eyedir.dot(p_pos) < (eyedir.dot(t.origin) + near); +} + +Vector Camera3D::get_near_plane_points() const { + ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector(), "Camera is not inside scene."); + + Size2 viewport_size = get_viewport()->get_visible_rect().size; + + CameraMatrix cm; + + if (mode == PROJECTION_ORTHOGONAL) + cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + else + cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + + Vector3 endpoints[8]; + cm.get_endpoints(Transform(), endpoints); + + Vector points; + points.push_back(Vector3()); + for (int i = 0; i < 4; i++) { + points.push_back(endpoints[i + 4]); + } + return points; +} + +Point2 Camera3D::unproject_position(const Vector3 &p_pos) const { + + ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene."); + + Size2 viewport_size = get_viewport()->get_visible_rect().size; + + CameraMatrix cm; + + if (mode == PROJECTION_ORTHOGONAL) + cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + else + cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + + Plane p(get_camera_transform().xform_inv(p_pos), 1.0); + + p = cm.xform4(p); + p.normal /= p.d; + + Point2 res; + res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x; + res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y; + + return res; +} + +Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const { + + ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); + + if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) { + return get_global_transform().origin; + } + Size2 viewport_size = get_viewport()->get_visible_rect().size; + + CameraMatrix cm; + + if (mode == PROJECTION_ORTHOGONAL) + cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); + else + cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH); + + Vector2 vp_he = cm.get_viewport_half_extents(); + + Vector2 point; + point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0; + point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0; + point *= vp_he; + + Vector3 p(point.x, point.y, -p_z_depth); + + return get_camera_transform().xform(p); +} + +/* +void Camera::_camera_make_current(Node *p_camera) { + + + if (p_camera==this) { + VisualServer::get_singleton()->viewport_attach_camera(viewport_id,camera); + active=true; + } else { + if (active && p_camera==NULL) { + //detech camera because no one else will claim it + VisualServer::get_singleton()->viewport_attach_camera(viewport_id,RID()); + } + active=false; + } +} +*/ + +void Camera3D::set_environment(const Ref &p_environment) { + + environment = p_environment; + if (environment.is_valid()) + VS::get_singleton()->camera_set_environment(camera, environment->get_rid()); + else + VS::get_singleton()->camera_set_environment(camera, RID()); + _update_camera_mode(); +} + +Ref Camera3D::get_environment() const { + + return environment; +} + +void Camera3D::set_effects(const Ref &p_effects) { + + effects = p_effects; + if (effects.is_valid()) + VS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid()); + else + VS::get_singleton()->camera_set_camera_effects(camera, RID()); + _update_camera_mode(); +} + +Ref Camera3D::get_effects() const { + + return effects; +} + +void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) { + keep_aspect = p_aspect; + VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); + _update_camera_mode(); + _change_notify(); +} + +Camera3D::KeepAspect Camera3D::get_keep_aspect_mode() const { + + return keep_aspect; +} + +void Camera3D::set_doppler_tracking(DopplerTracking p_tracking) { + + if (doppler_tracking == p_tracking) + return; + + doppler_tracking = p_tracking; + if (p_tracking != DOPPLER_TRACKING_DISABLED) { + velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP); + if (is_inside_tree()) { + velocity_tracker->reset(get_global_transform().origin); + } + } + _update_camera_mode(); +} + +Camera3D::DopplerTracking Camera3D::get_doppler_tracking() const { + return doppler_tracking; +} + +void Camera3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera3D::project_ray_normal); + ClassDB::bind_method(D_METHOD("project_local_ray_normal", "screen_point"), &Camera3D::project_local_ray_normal); + ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera3D::project_ray_origin); + ClassDB::bind_method(D_METHOD("unproject_position", "world_point"), &Camera3D::unproject_position); + ClassDB::bind_method(D_METHOD("is_position_behind", "world_point"), &Camera3D::is_position_behind); + ClassDB::bind_method(D_METHOD("project_position", "screen_point", "z_depth"), &Camera3D::project_position); + ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera3D::set_perspective); + ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera3D::set_orthogonal); + ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera3D::set_frustum); + ClassDB::bind_method(D_METHOD("make_current"), &Camera3D::make_current); + ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera3D::clear_current, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("set_current"), &Camera3D::set_current); + ClassDB::bind_method(D_METHOD("is_current"), &Camera3D::is_current); + ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera3D::get_camera_transform); + ClassDB::bind_method(D_METHOD("get_fov"), &Camera3D::get_fov); + ClassDB::bind_method(D_METHOD("get_frustum_offset"), &Camera3D::get_frustum_offset); + ClassDB::bind_method(D_METHOD("get_size"), &Camera3D::get_size); + ClassDB::bind_method(D_METHOD("get_zfar"), &Camera3D::get_zfar); + ClassDB::bind_method(D_METHOD("get_znear"), &Camera3D::get_znear); + ClassDB::bind_method(D_METHOD("set_fov"), &Camera3D::set_fov); + ClassDB::bind_method(D_METHOD("set_frustum_offset"), &Camera3D::set_frustum_offset); + ClassDB::bind_method(D_METHOD("set_size"), &Camera3D::set_size); + ClassDB::bind_method(D_METHOD("set_zfar"), &Camera3D::set_zfar); + ClassDB::bind_method(D_METHOD("set_znear"), &Camera3D::set_znear); + ClassDB::bind_method(D_METHOD("get_projection"), &Camera3D::get_projection); + ClassDB::bind_method(D_METHOD("set_projection"), &Camera3D::set_projection); + ClassDB::bind_method(D_METHOD("set_h_offset", "ofs"), &Camera3D::set_h_offset); + ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera3D::get_h_offset); + ClassDB::bind_method(D_METHOD("set_v_offset", "ofs"), &Camera3D::set_v_offset); + ClassDB::bind_method(D_METHOD("get_v_offset"), &Camera3D::get_v_offset); + ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Camera3D::set_cull_mask); + ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera3D::get_cull_mask); + ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera3D::set_environment); + ClassDB::bind_method(D_METHOD("get_environment"), &Camera3D::get_environment); + ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera3D::set_effects); + ClassDB::bind_method(D_METHOD("get_effects"), &Camera3D::get_effects); + ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera3D::set_keep_aspect_mode); + ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera3D::get_keep_aspect_mode); + ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking); + ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera3D::get_doppler_tracking); + ClassDB::bind_method(D_METHOD("get_frustum"), &Camera3D::get_frustum); + ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera3D::get_camera); + + ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera3D::set_cull_mask_bit); + ClassDB::bind_method(D_METHOD("get_cull_mask_bit", "layer"), &Camera3D::get_cull_mask_bit); + + //ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current ); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar"); + + BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); + BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL); + BIND_ENUM_CONSTANT(PROJECTION_FRUSTUM); + + BIND_ENUM_CONSTANT(KEEP_WIDTH); + BIND_ENUM_CONSTANT(KEEP_HEIGHT); + + BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED); + BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP); + BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP); +} + +float Camera3D::get_fov() const { + + return fov; +} + +float Camera3D::get_size() const { + + return size; +} + +float Camera3D::get_znear() const { + + return near; +} + +Vector2 Camera3D::get_frustum_offset() const { + return frustum_offset; +} + +float Camera3D::get_zfar() const { + + return far; +} + +Camera3D::Projection Camera3D::get_projection() const { + + return mode; +} + +void Camera3D::set_fov(float p_fov) { + ERR_FAIL_COND(p_fov < 1 || p_fov > 179); + fov = p_fov; + _update_camera_mode(); + _change_notify("fov"); +} + +void Camera3D::set_size(float p_size) { + ERR_FAIL_COND(p_size < 0.1 || p_size > 16384); + size = p_size; + _update_camera_mode(); + _change_notify("size"); +} + +void Camera3D::set_znear(float p_znear) { + near = p_znear; + _update_camera_mode(); +} + +void Camera3D::set_frustum_offset(Vector2 p_offset) { + frustum_offset = p_offset; + _update_camera_mode(); +} + +void Camera3D::set_zfar(float p_zfar) { + far = p_zfar; + _update_camera_mode(); +} + +void Camera3D::set_cull_mask(uint32_t p_layers) { + layers = p_layers; + VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); + _update_camera_mode(); +} + +uint32_t Camera3D::get_cull_mask() const { + + return layers; +} + +void Camera3D::set_cull_mask_bit(int p_layer, bool p_enable) { + ERR_FAIL_INDEX(p_layer, 32); + if (p_enable) { + set_cull_mask(layers | (1 << p_layer)); + } else { + set_cull_mask(layers & (~(1 << p_layer))); + } +} + +bool Camera3D::get_cull_mask_bit(int p_layer) const { + ERR_FAIL_INDEX_V(p_layer, 32, false); + return (layers & (1 << p_layer)); +} + +Vector Camera3D::get_frustum() const { + + ERR_FAIL_COND_V(!is_inside_world(), Vector()); + + Size2 viewport_size = get_viewport()->get_visible_rect().size; + CameraMatrix cm; + if (mode == PROJECTION_PERSPECTIVE) + cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + else + cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); + + return cm.get_projection_planes(get_camera_transform()); +} + +void Camera3D::set_v_offset(float p_offset) { + + v_offset = p_offset; + _update_camera(); +} + +float Camera3D::get_v_offset() const { + + return v_offset; +} + +void Camera3D::set_h_offset(float p_offset) { + h_offset = p_offset; + _update_camera(); +} + +float Camera3D::get_h_offset() const { + + return h_offset; +} + +Vector3 Camera3D::get_doppler_tracked_velocity() const { + + if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { + return velocity_tracker->get_tracked_linear_velocity(); + } else { + return Vector3(); + } +} +Camera3D::Camera3D() { + + camera = VisualServer::get_singleton()->camera_create(); + size = 1; + fov = 0; + frustum_offset = Vector2(); + near = 0; + far = 0; + current = false; + viewport = NULL; + force_change = false; + mode = PROJECTION_PERSPECTIVE; + set_perspective(70.0, 0.05, 100.0); + keep_aspect = KEEP_HEIGHT; + layers = 0xfffff; + v_offset = 0; + h_offset = 0; + VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); + //active=false; + velocity_tracker.instance(); + doppler_tracking = DOPPLER_TRACKING_DISABLED; + set_notify_transform(true); + set_disable_scale(true); +} + +Camera3D::~Camera3D() { + + VisualServer::get_singleton()->free(camera); +} + +//////////////////////////////////////// + +void ClippedCamera::set_margin(float p_margin) { + margin = p_margin; +} +float ClippedCamera::get_margin() const { + return margin; +} +void ClippedCamera::set_process_mode(ProcessMode p_mode) { + + if (process_mode == p_mode) { + return; + } + process_mode = p_mode; + set_process_internal(process_mode == CLIP_PROCESS_IDLE); + set_physics_process_internal(process_mode == CLIP_PROCESS_PHYSICS); +} +ClippedCamera::ProcessMode ClippedCamera::get_process_mode() const { + return process_mode; +} + +Transform ClippedCamera::get_camera_transform() const { + + Transform t = Camera3D::get_camera_transform(); + t.origin += -t.basis.get_axis(Vector3::AXIS_Z).normalized() * clip_offset; + return t; +} + +void ClippedCamera::_notification(int p_what) { + if (p_what == NOTIFICATION_INTERNAL_PROCESS || p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { + + Node3D *parent = Object::cast_to(get_parent()); + if (!parent) { + return; + } + + PhysicsDirectSpaceState *dspace = get_world()->get_direct_space_state(); + ERR_FAIL_COND(!dspace); // most likely physics set to threads + + Vector3 cam_fw = -get_global_transform().basis.get_axis(Vector3::AXIS_Z).normalized(); + Vector3 cam_pos = get_global_transform().origin; + Vector3 parent_pos = parent->get_global_transform().origin; + + Plane parent_plane(parent_pos, cam_fw); + + if (parent_plane.is_point_over(cam_pos)) { + //cam is beyond parent plane + return; + } + + Vector3 ray_from = parent_plane.project(cam_pos); + + clip_offset = 0; //reset by defau;t + + { //check if points changed + Vector local_points = get_near_plane_points(); + + bool all_equal = true; + + for (int i = 0; i < 5; i++) { + if (points[i] != local_points[i]) { + all_equal = false; + break; + } + } + + if (!all_equal) { + PhysicsServer::get_singleton()->shape_set_data(pyramid_shape, local_points); + points = local_points; + } + } + + Transform xf = get_global_transform(); + xf.origin = ray_from; + xf.orthonormalize(); + + float csafe, cunsafe; + if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, csafe, cunsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) { + clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * csafe); + } + + _update_camera(); + } + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + update_gizmo(); + } +} + +void ClippedCamera::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; +} + +uint32_t ClippedCamera::get_collision_mask() const { + + return collision_mask; +} + +void ClippedCamera::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool ClippedCamera::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void ClippedCamera::add_exception_rid(const RID &p_rid) { + + exclude.insert(p_rid); +} + +void ClippedCamera::add_exception(const Object *p_object) { + + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to(p_object); + if (!co) + return; + add_exception_rid(co->get_rid()); +} + +void ClippedCamera::remove_exception_rid(const RID &p_rid) { + + exclude.erase(p_rid); +} + +void ClippedCamera::remove_exception(const Object *p_object) { + + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to(p_object); + if (!co) + return; + remove_exception_rid(co->get_rid()); +} + +void ClippedCamera::clear_exceptions() { + + exclude.clear(); +} + +float ClippedCamera::get_clip_offset() const { + + return clip_offset; +} + +void ClippedCamera::set_clip_to_areas(bool p_clip) { + + clip_to_areas = p_clip; +} + +bool ClippedCamera::is_clip_to_areas_enabled() const { + + return clip_to_areas; +} + +void ClippedCamera::set_clip_to_bodies(bool p_clip) { + + clip_to_bodies = p_clip; +} + +bool ClippedCamera::is_clip_to_bodies_enabled() const { + + return clip_to_bodies; +} + +void ClippedCamera::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ClippedCamera::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &ClippedCamera::get_margin); + + ClassDB::bind_method(D_METHOD("set_process_mode", "process_mode"), &ClippedCamera::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &ClippedCamera::get_process_mode); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ClippedCamera::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &ClippedCamera::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &ClippedCamera::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &ClippedCamera::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &ClippedCamera::add_exception_rid); + ClassDB::bind_method(D_METHOD("add_exception", "node"), &ClippedCamera::add_exception); + + ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &ClippedCamera::remove_exception_rid); + ClassDB::bind_method(D_METHOD("remove_exception", "node"), &ClippedCamera::remove_exception); + + ClassDB::bind_method(D_METHOD("set_clip_to_areas", "enable"), &ClippedCamera::set_clip_to_areas); + ClassDB::bind_method(D_METHOD("is_clip_to_areas_enabled"), &ClippedCamera::is_clip_to_areas_enabled); + + ClassDB::bind_method(D_METHOD("get_clip_offset"), &ClippedCamera::get_clip_offset); + + ClassDB::bind_method(D_METHOD("set_clip_to_bodies", "enable"), &ClippedCamera::set_clip_to_bodies); + ClassDB::bind_method(D_METHOD("is_clip_to_bodies_enabled"), &ClippedCamera::is_clip_to_bodies_enabled); + + ClassDB::bind_method(D_METHOD("clear_exceptions"), &ClippedCamera::clear_exceptions); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Clip To", "clip_to"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_areas", "is_clip_to_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_to_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_clip_to_bodies", "is_clip_to_bodies_enabled"); + + BIND_ENUM_CONSTANT(CLIP_PROCESS_PHYSICS); + BIND_ENUM_CONSTANT(CLIP_PROCESS_IDLE); +} +ClippedCamera::ClippedCamera() { + margin = 0; + clip_offset = 0; + process_mode = CLIP_PROCESS_PHYSICS; + set_physics_process_internal(true); + collision_mask = 1; + set_notify_local_transform(Engine::get_singleton()->is_editor_hint()); + points.resize(5); + pyramid_shape = PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON); + clip_to_areas = false; + clip_to_bodies = true; +} +ClippedCamera::~ClippedCamera() { + PhysicsServer::get_singleton()->free(pyramid_shape); +} diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h new file mode 100644 index 0000000000..3c743ccdff --- /dev/null +++ b/scene/3d/camera_3d.h @@ -0,0 +1,246 @@ +/*************************************************************************/ +/* camera_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CAMERA_3D_H +#define CAMERA_3D_H + +#include "scene/3d/node_3d.h" +#include "scene/3d/velocity_tracker_3d.h" +#include "scene/main/window.h" +#include "scene/resources/environment.h" + +class Camera3D : public Node3D { + + GDCLASS(Camera3D, Node3D); + +public: + enum Projection { + + PROJECTION_PERSPECTIVE, + PROJECTION_ORTHOGONAL, + PROJECTION_FRUSTUM + }; + + enum KeepAspect { + KEEP_WIDTH, + KEEP_HEIGHT + }; + + enum DopplerTracking { + DOPPLER_TRACKING_DISABLED, + DOPPLER_TRACKING_IDLE_STEP, + DOPPLER_TRACKING_PHYSICS_STEP + }; + +private: + bool force_change; + bool current; + Viewport *viewport; + + Projection mode; + + float fov; + float size; + Vector2 frustum_offset; + float near, far; + float v_offset; + float h_offset; + KeepAspect keep_aspect; + + RID camera; + RID scenario_id; + + //String camera_group; + + uint32_t layers; + + Ref environment; + Ref effects; + + virtual bool _can_gizmo_scale() const; + + //void _camera_make_current(Node *p_camera); + friend class Viewport; + void _update_audio_listener_state(); + + DopplerTracking doppler_tracking; + Ref velocity_tracker; + +protected: + void _update_camera(); + virtual void _request_camera_update(); + void _update_camera_mode(); + + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &p_property) const; + + static void _bind_methods(); + +public: + enum { + + NOTIFICATION_BECAME_CURRENT = 50, + NOTIFICATION_LOST_CURRENT = 51 + }; + + void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far); + void set_orthogonal(float p_size, float p_z_near, float p_z_far); + void set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far); + void set_projection(Camera3D::Projection p_mode); + + void make_current(); + void clear_current(bool p_enable_next = true); + void set_current(bool p_current); + bool is_current() const; + + RID get_camera() const; + + float get_fov() const; + float get_size() const; + float get_zfar() const; + float get_znear() const; + Vector2 get_frustum_offset() const; + + Projection get_projection() const; + + void set_fov(float p_fov); + void set_size(float p_size); + void set_zfar(float p_zfar); + void set_znear(float p_znear); + void set_frustum_offset(Vector2 p_offset); + + virtual Transform get_camera_transform() const; + + virtual Vector3 project_ray_normal(const Point2 &p_pos) const; + virtual Vector3 project_ray_origin(const Point2 &p_pos) const; + virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const; + virtual Point2 unproject_position(const Vector3 &p_pos) const; + bool is_position_behind(const Vector3 &p_pos) const; + virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const; + + Vector get_near_plane_points() const; + + void set_cull_mask(uint32_t p_layers); + uint32_t get_cull_mask() const; + + void set_cull_mask_bit(int p_layer, bool p_enable); + bool get_cull_mask_bit(int p_layer) const; + + virtual Vector get_frustum() const; + + void set_environment(const Ref &p_environment); + Ref get_environment() const; + + void set_effects(const Ref &p_effects); + Ref get_effects() const; + + void set_keep_aspect_mode(KeepAspect p_aspect); + KeepAspect get_keep_aspect_mode() const; + + void set_v_offset(float p_offset); + float get_v_offset() const; + + void set_h_offset(float p_offset); + float get_h_offset() const; + + void set_doppler_tracking(DopplerTracking p_tracking); + DopplerTracking get_doppler_tracking() const; + + Vector3 get_doppler_tracked_velocity() const; + + Camera3D(); + ~Camera3D(); +}; + +VARIANT_ENUM_CAST(Camera3D::Projection); +VARIANT_ENUM_CAST(Camera3D::KeepAspect); +VARIANT_ENUM_CAST(Camera3D::DopplerTracking); + +class ClippedCamera : public Camera3D { + + GDCLASS(ClippedCamera, Camera3D); + +public: + enum ProcessMode { + CLIP_PROCESS_PHYSICS, + CLIP_PROCESS_IDLE, + }; + +private: + ProcessMode process_mode; + RID pyramid_shape; + float margin; + float clip_offset; + uint32_t collision_mask; + bool clip_to_areas; + bool clip_to_bodies; + + Set exclude; + + Vector points; + +protected: + void _notification(int p_what); + static void _bind_methods(); + virtual Transform get_camera_transform() const; + +public: + void set_clip_to_areas(bool p_clip); + bool is_clip_to_areas_enabled() const; + + void set_clip_to_bodies(bool p_clip); + bool is_clip_to_bodies_enabled() const; + + void set_margin(float p_margin); + float get_margin() const; + + void set_process_mode(ProcessMode p_mode); + ProcessMode get_process_mode() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void add_exception_rid(const RID &p_rid); + void add_exception(const Object *p_object); + void remove_exception_rid(const RID &p_rid); + void remove_exception(const Object *p_object); + void clear_exceptions(); + + float get_clip_offset() const; + + ClippedCamera(); + ~ClippedCamera(); +}; + +VARIANT_ENUM_CAST(ClippedCamera::ProcessMode); +#endif diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp deleted file mode 100644 index c067ef34a6..0000000000 --- a/scene/3d/collision_object.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/*************************************************************************/ -/* collision_object.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_object.h" - -#include "scene/scene_string_names.h" -#include "servers/physics_server.h" - -void CollisionObject::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_WORLD: { - - if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); - else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - - RID space = get_world()->get_space(); - if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, space); - } else - PhysicsServer::get_singleton()->body_set_space(rid, space); - - _update_pickable(); - //get space - } break; - - case NOTIFICATION_TRANSFORM_CHANGED: { - - if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); - else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - - } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - - _update_pickable(); - - } break; - case NOTIFICATION_EXIT_WORLD: { - - if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, RID()); - } else - PhysicsServer::get_singleton()->body_set_space(rid, RID()); - - } break; - } -} - -void CollisionObject::_input_event(Node *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { - - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); - } - emit_signal(SceneStringNames::get_singleton()->input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); -} - -void CollisionObject::_mouse_enter() { - - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); - } - emit_signal(SceneStringNames::get_singleton()->mouse_entered); -} - -void CollisionObject::_mouse_exit() { - - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); - } - emit_signal(SceneStringNames::get_singleton()->mouse_exited); -} - -void CollisionObject::_update_pickable() { - if (!is_inside_tree()) - return; - - bool pickable = ray_pickable && is_visible_in_tree(); - if (area) - PhysicsServer::get_singleton()->area_set_ray_pickable(rid, pickable); - else - PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable); -} - -void CollisionObject::set_ray_pickable(bool p_ray_pickable) { - - ray_pickable = p_ray_pickable; - _update_pickable(); -} - -bool CollisionObject::is_ray_pickable() const { - - return ray_pickable; -} - -void CollisionObject::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject::set_ray_pickable); - ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject::is_ray_pickable); - ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject::set_capture_input_on_drag); - ClassDB::bind_method(D_METHOD("get_capture_input_on_drag"), &CollisionObject::get_capture_input_on_drag); - ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject::get_rid); - ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject::create_shape_owner); - ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject::remove_shape_owner); - ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject::_get_shape_owners); - ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform"), &CollisionObject::shape_owner_set_transform); - ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject::shape_owner_get_transform); - ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject::shape_owner_get_owner); - ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject::shape_owner_set_disabled); - ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject::is_shape_owner_disabled); - ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape"), &CollisionObject::shape_owner_add_shape); - ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject::shape_owner_get_shape_count); - ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape); - ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject::shape_owner_get_shape_index); - ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject::shape_owner_remove_shape); - ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject::shape_owner_clear_shapes); - ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner); - - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); - - ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); - ADD_SIGNAL(MethodInfo("mouse_entered")); - ADD_SIGNAL(MethodInfo("mouse_exited")); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); -} - -uint32_t CollisionObject::create_shape_owner(Object *p_owner) { - - ShapeData sd; - uint32_t id; - - if (shapes.size() == 0) { - id = 0; - } else { - id = shapes.back()->key() + 1; - } - - sd.owner = p_owner; - - shapes[id] = sd; - - return id; -} - -void CollisionObject::remove_shape_owner(uint32_t owner) { - - ERR_FAIL_COND(!shapes.has(owner)); - - shape_owner_clear_shapes(owner); - - shapes.erase(owner); -} - -void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled) { - ERR_FAIL_COND(!shapes.has(p_owner)); - - ShapeData &sd = shapes[p_owner]; - sd.disabled = p_disabled; - for (int i = 0; i < sd.shapes.size(); i++) { - if (area) { - PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); - } else { - PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); - } - } -} - -bool CollisionObject::is_shape_owner_disabled(uint32_t p_owner) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), false); - - return shapes[p_owner].disabled; -} - -void CollisionObject::get_shape_owners(List *r_owners) { - - for (Map::Element *E = shapes.front(); E; E = E->next()) { - r_owners->push_back(E->key()); - } -} - -Array CollisionObject::_get_shape_owners() { - - Array ret; - for (Map::Element *E = shapes.front(); E; E = E->next()) { - ret.push_back(E->key()); - } - - return ret; -} - -void CollisionObject::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) { - - ERR_FAIL_COND(!shapes.has(p_owner)); - - ShapeData &sd = shapes[p_owner]; - sd.xform = p_transform; - for (int i = 0; i < sd.shapes.size(); i++) { - if (area) { - PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); - } else { - PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); - } - } -} -Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), Transform()); - - return shapes[p_owner].xform; -} - -Object *CollisionObject::shape_owner_get_owner(uint32_t p_owner) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), NULL); - - return shapes[p_owner].owner; -} - -void CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref &p_shape) { - - ERR_FAIL_COND(!shapes.has(p_owner)); - ERR_FAIL_COND(p_shape.is_null()); - - ShapeData &sd = shapes[p_owner]; - ShapeData::ShapeBase s; - s.index = total_subshapes; - s.shape = p_shape; - if (area) { - PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); - } else { - PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); - } - sd.shapes.push_back(s); - - total_subshapes++; -} -int CollisionObject::shape_owner_get_shape_count(uint32_t p_owner) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), 0); - - return shapes[p_owner].shapes.size(); -} -Ref CollisionObject::shape_owner_get_shape(uint32_t p_owner, int p_shape) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), Ref()); - ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref()); - - return shapes[p_owner].shapes[p_shape].shape; -} -int CollisionObject::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const { - - ERR_FAIL_COND_V(!shapes.has(p_owner), -1); - ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1); - - return shapes[p_owner].shapes[p_shape].index; -} - -void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { - - ERR_FAIL_COND(!shapes.has(p_owner)); - ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); - - int index_to_remove = shapes[p_owner].shapes[p_shape].index; - if (area) { - PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); - } else { - PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); - } - - shapes[p_owner].shapes.remove(p_shape); - - for (Map::Element *E = shapes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().shapes.size(); i++) { - if (E->get().shapes[i].index > index_to_remove) { - E->get().shapes.write[i].index -= 1; - } - } - } - - total_subshapes--; -} - -void CollisionObject::shape_owner_clear_shapes(uint32_t p_owner) { - - ERR_FAIL_COND(!shapes.has(p_owner)); - - while (shape_owner_get_shape_count(p_owner) > 0) { - shape_owner_remove_shape(p_owner, 0); - } -} - -uint32_t CollisionObject::shape_find_owner(int p_shape_index) const { - - ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); - - for (const Map::Element *E = shapes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().shapes.size(); i++) { - if (E->get().shapes[i].index == p_shape_index) { - return E->key(); - } - } - } - - //in theory it should be unreachable - return 0; -} - -CollisionObject::CollisionObject(RID p_rid, bool p_area) { - - rid = p_rid; - area = p_area; - capture_input_on_drag = false; - ray_pickable = true; - set_notify_transform(true); - total_subshapes = 0; - - if (p_area) { - PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); - } else { - PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); - } - //set_transform_notify(true); -} - -void CollisionObject::set_capture_input_on_drag(bool p_capture) { - - capture_input_on_drag = p_capture; -} - -bool CollisionObject::get_capture_input_on_drag() const { - - return capture_input_on_drag; -} - -String CollisionObject::get_configuration_warning() const { - - String warning = Spatial::get_configuration_warning(); - - if (shapes.empty()) { - if (!warning.empty()) { - warning += "\n\n"; - } - warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape or CollisionPolygon as a child to define its shape."); - } - - return warning; -} - -CollisionObject::CollisionObject() { - - capture_input_on_drag = false; - ray_pickable = true; - set_notify_transform(true); - //owner= - - //set_transform_notify(true); -} - -CollisionObject::~CollisionObject() { - - PhysicsServer::get_singleton()->free(rid); -} diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h deleted file mode 100644 index 572e73d51b..0000000000 --- a/scene/3d/collision_object.h +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************/ -/* collision_object.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_OBJECT_H -#define COLLISION_OBJECT_H - -#include "scene/3d/spatial.h" -#include "scene/resources/shape.h" - -class CollisionObject : public Spatial { - - GDCLASS(CollisionObject, Spatial); - - bool area; - - RID rid; - - struct ShapeData { - - Object *owner; - Transform xform; - struct ShapeBase { - Ref shape; - int index; - }; - - Vector shapes; - bool disabled; - - ShapeData() { - disabled = false; - owner = NULL; - } - }; - - int total_subshapes; - - Map shapes; - - bool capture_input_on_drag; - bool ray_pickable; - - void _update_pickable(); - -protected: - CollisionObject(RID p_rid, bool p_area); - - void _notification(int p_what); - static void _bind_methods(); - friend class Viewport; - virtual void _input_event(Node *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); - virtual void _mouse_enter(); - virtual void _mouse_exit(); - -public: - uint32_t create_shape_owner(Object *p_owner); - void remove_shape_owner(uint32_t owner); - void get_shape_owners(List *r_owners); - Array _get_shape_owners(); - - void shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform); - Transform shape_owner_get_transform(uint32_t p_owner) const; - Object *shape_owner_get_owner(uint32_t p_owner) const; - - void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled); - bool is_shape_owner_disabled(uint32_t p_owner) const; - - void shape_owner_add_shape(uint32_t p_owner, const Ref &p_shape); - int shape_owner_get_shape_count(uint32_t p_owner) const; - Ref shape_owner_get_shape(uint32_t p_owner, int p_shape) const; - int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const; - - void shape_owner_remove_shape(uint32_t p_owner, int p_shape); - void shape_owner_clear_shapes(uint32_t p_owner); - - uint32_t shape_find_owner(int p_shape_index) const; - - void set_ray_pickable(bool p_ray_pickable); - bool is_ray_pickable() const; - - void set_capture_input_on_drag(bool p_capture); - bool get_capture_input_on_drag() const; - - _FORCE_INLINE_ RID get_rid() const { return rid; } - - virtual String get_configuration_warning() const; - - CollisionObject(); - ~CollisionObject(); -}; - -#endif // COLLISION_OBJECT__H diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp new file mode 100644 index 0000000000..9ae7371b6a --- /dev/null +++ b/scene/3d/collision_object_3d.cpp @@ -0,0 +1,396 @@ +/*************************************************************************/ +/* collision_object_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_object_3d.h" + +#include "scene/scene_string_names.h" +#include "servers/physics_server.h" + +void CollisionObject3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_WORLD: { + + if (area) + PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + else + PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + + RID space = get_world()->get_space(); + if (area) { + PhysicsServer::get_singleton()->area_set_space(rid, space); + } else + PhysicsServer::get_singleton()->body_set_space(rid, space); + + _update_pickable(); + //get space + } break; + + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (area) + PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + else + PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + + } break; + case NOTIFICATION_EXIT_WORLD: { + + if (area) { + PhysicsServer::get_singleton()->area_set_space(rid, RID()); + } else + PhysicsServer::get_singleton()->body_set_space(rid, RID()); + + } break; + } +} + +void CollisionObject3D::_input_event(Node *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); + } + emit_signal(SceneStringNames::get_singleton()->input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); +} + +void CollisionObject3D::_mouse_enter() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); + } + emit_signal(SceneStringNames::get_singleton()->mouse_entered); +} + +void CollisionObject3D::_mouse_exit() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); + } + emit_signal(SceneStringNames::get_singleton()->mouse_exited); +} + +void CollisionObject3D::_update_pickable() { + if (!is_inside_tree()) + return; + + bool pickable = ray_pickable && is_visible_in_tree(); + if (area) + PhysicsServer::get_singleton()->area_set_ray_pickable(rid, pickable); + else + PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable); +} + +void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) { + + ray_pickable = p_ray_pickable; + _update_pickable(); +} + +bool CollisionObject3D::is_ray_pickable() const { + + return ray_pickable; +} + +void CollisionObject3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable); + ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable); + ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag); + ClassDB::bind_method(D_METHOD("get_capture_input_on_drag"), &CollisionObject3D::get_capture_input_on_drag); + ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject3D::get_rid); + ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject3D::create_shape_owner); + ClassDB::bind_method(D_METHOD("remove_shape_owner", "owner_id"), &CollisionObject3D::remove_shape_owner); + ClassDB::bind_method(D_METHOD("get_shape_owners"), &CollisionObject3D::_get_shape_owners); + ClassDB::bind_method(D_METHOD("shape_owner_set_transform", "owner_id", "transform"), &CollisionObject3D::shape_owner_set_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_transform", "owner_id"), &CollisionObject3D::shape_owner_get_transform); + ClassDB::bind_method(D_METHOD("shape_owner_get_owner", "owner_id"), &CollisionObject3D::shape_owner_get_owner); + ClassDB::bind_method(D_METHOD("shape_owner_set_disabled", "owner_id", "disabled"), &CollisionObject3D::shape_owner_set_disabled); + ClassDB::bind_method(D_METHOD("is_shape_owner_disabled", "owner_id"), &CollisionObject3D::is_shape_owner_disabled); + ClassDB::bind_method(D_METHOD("shape_owner_add_shape", "owner_id", "shape"), &CollisionObject3D::shape_owner_add_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_count", "owner_id"), &CollisionObject3D::shape_owner_get_shape_count); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape", "owner_id", "shape_id"), &CollisionObject3D::shape_owner_get_shape); + ClassDB::bind_method(D_METHOD("shape_owner_get_shape_index", "owner_id", "shape_id"), &CollisionObject3D::shape_owner_get_shape_index); + ClassDB::bind_method(D_METHOD("shape_owner_remove_shape", "owner_id", "shape_id"), &CollisionObject3D::shape_owner_remove_shape); + ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes); + ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner); + + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); + + ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); + ADD_SIGNAL(MethodInfo("mouse_entered")); + ADD_SIGNAL(MethodInfo("mouse_exited")); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); +} + +uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) { + + ShapeData sd; + uint32_t id; + + if (shapes.size() == 0) { + id = 0; + } else { + id = shapes.back()->key() + 1; + } + + sd.owner = p_owner; + + shapes[id] = sd; + + return id; +} + +void CollisionObject3D::remove_shape_owner(uint32_t owner) { + + ERR_FAIL_COND(!shapes.has(owner)); + + shape_owner_clear_shapes(owner); + + shapes.erase(owner); +} + +void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled) { + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.disabled = p_disabled; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } else { + PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + } +} + +bool CollisionObject3D::is_shape_owner_disabled(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), false); + + return shapes[p_owner].disabled; +} + +void CollisionObject3D::get_shape_owners(List *r_owners) { + + for (Map::Element *E = shapes.front(); E; E = E->next()) { + r_owners->push_back(E->key()); + } +} + +Array CollisionObject3D::_get_shape_owners() { + + Array ret; + for (Map::Element *E = shapes.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + + return ret; +} + +void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.xform = p_transform; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } else { + PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + } +} +Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), Transform()); + + return shapes[p_owner].xform; +} + +Object *CollisionObject3D::shape_owner_get_owner(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), NULL); + + return shapes[p_owner].owner; +} + +void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref &p_shape) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_COND(p_shape.is_null()); + + ShapeData &sd = shapes[p_owner]; + ShapeData::ShapeBase s; + s.index = total_subshapes; + s.shape = p_shape; + if (area) { + PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + } else { + PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + } + sd.shapes.push_back(s); + + total_subshapes++; +} +int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), 0); + + return shapes[p_owner].shapes.size(); +} +Ref CollisionObject3D::shape_owner_get_shape(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), Ref()); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref()); + + return shapes[p_owner].shapes[p_shape].shape; +} +int CollisionObject3D::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), -1); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1); + + return shapes[p_owner].shapes[p_shape].index; +} + +void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); + + int index_to_remove = shapes[p_owner].shapes[p_shape].index; + if (area) { + PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); + } else { + PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + } + + shapes[p_owner].shapes.remove(p_shape); + + for (Map::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index > index_to_remove) { + E->get().shapes.write[i].index -= 1; + } + } + } + + total_subshapes--; +} + +void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + while (shape_owner_get_shape_count(p_owner) > 0) { + shape_owner_remove_shape(p_owner, 0); + } +} + +uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const { + + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); + + for (const Map::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index == p_shape_index) { + return E->key(); + } + } + } + + //in theory it should be unreachable + return 0; +} + +CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) { + + rid = p_rid; + area = p_area; + capture_input_on_drag = false; + ray_pickable = true; + set_notify_transform(true); + total_subshapes = 0; + + if (p_area) { + PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); + } else { + PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + } + //set_transform_notify(true); +} + +void CollisionObject3D::set_capture_input_on_drag(bool p_capture) { + + capture_input_on_drag = p_capture; +} + +bool CollisionObject3D::get_capture_input_on_drag() const { + + return capture_input_on_drag; +} + +String CollisionObject3D::get_configuration_warning() const { + + String warning = Node3D::get_configuration_warning(); + + if (shapes.empty()) { + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape or CollisionPolygon as a child to define its shape."); + } + + return warning; +} + +CollisionObject3D::CollisionObject3D() { + + capture_input_on_drag = false; + ray_pickable = true; + set_notify_transform(true); + //owner= + + //set_transform_notify(true); +} + +CollisionObject3D::~CollisionObject3D() { + + PhysicsServer::get_singleton()->free(rid); +} diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h new file mode 100644 index 0000000000..6a70f56caa --- /dev/null +++ b/scene/3d/collision_object_3d.h @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* collision_object_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_OBJECT_3D_H +#define COLLISION_OBJECT_3D_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/shape_3d.h" + +class CollisionObject3D : public Node3D { + + GDCLASS(CollisionObject3D, Node3D); + + bool area; + + RID rid; + + struct ShapeData { + + Object *owner; + Transform xform; + struct ShapeBase { + Ref shape; + int index; + }; + + Vector shapes; + bool disabled; + + ShapeData() { + disabled = false; + owner = NULL; + } + }; + + int total_subshapes; + + Map shapes; + + bool capture_input_on_drag; + bool ray_pickable; + + void _update_pickable(); + +protected: + CollisionObject3D(RID p_rid, bool p_area); + + void _notification(int p_what); + static void _bind_methods(); + friend class Viewport; + virtual void _input_event(Node *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); + virtual void _mouse_enter(); + virtual void _mouse_exit(); + +public: + uint32_t create_shape_owner(Object *p_owner); + void remove_shape_owner(uint32_t owner); + void get_shape_owners(List *r_owners); + Array _get_shape_owners(); + + void shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform); + Transform shape_owner_get_transform(uint32_t p_owner) const; + Object *shape_owner_get_owner(uint32_t p_owner) const; + + void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled); + bool is_shape_owner_disabled(uint32_t p_owner) const; + + void shape_owner_add_shape(uint32_t p_owner, const Ref &p_shape); + int shape_owner_get_shape_count(uint32_t p_owner) const; + Ref shape_owner_get_shape(uint32_t p_owner, int p_shape) const; + int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const; + + void shape_owner_remove_shape(uint32_t p_owner, int p_shape); + void shape_owner_clear_shapes(uint32_t p_owner); + + uint32_t shape_find_owner(int p_shape_index) const; + + void set_ray_pickable(bool p_ray_pickable); + bool is_ray_pickable() const; + + void set_capture_input_on_drag(bool p_capture); + bool get_capture_input_on_drag() const; + + _FORCE_INLINE_ RID get_rid() const { return rid; } + + virtual String get_configuration_warning() const; + + CollisionObject3D(); + ~CollisionObject3D(); +}; + +#endif // COLLISION_OBJECT__H diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp deleted file mode 100644 index 24c3a9eb41..0000000000 --- a/scene/3d/collision_polygon.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/*************************************************************************/ -/* collision_polygon.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_polygon.h" - -#include "collision_object.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" - -void CollisionPolygon::_build_polygon() { - - if (!parent) - return; - - parent->shape_owner_clear_shapes(owner_id); - - if (polygon.size() == 0) - return; - - Vector> decomp = Geometry::decompose_polygon_in_convex(polygon); - if (decomp.size() == 0) - return; - - //here comes the sun, lalalala - //decompose concave into multiple convex polygons and add them - - for (int i = 0; i < decomp.size(); i++) { - Ref convex = memnew(ConvexPolygonShape); - Vector cp; - int cs = decomp[i].size(); - cp.resize(cs * 2); - { - Vector3 *w = cp.ptrw(); - int idx = 0; - for (int j = 0; j < cs; j++) { - - Vector2 d = decomp[i][j]; - w[idx++] = Vector3(d.x, d.y, depth * 0.5); - w[idx++] = Vector3(d.x, d.y, -depth * 0.5); - } - } - - convex->set_points(cp); - parent->shape_owner_add_shape(owner_id, convex); - parent->shape_owner_set_disabled(owner_id, disabled); - } -} - -void CollisionPolygon::_update_in_shape_owner(bool p_xform_only) { - - parent->shape_owner_set_transform(owner_id, get_transform()); - if (p_xform_only) - return; - parent->shape_owner_set_disabled(owner_id, disabled); -} - -void CollisionPolygon::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_PARENTED: { - parent = Object::cast_to(get_parent()); - if (parent) { - owner_id = parent->create_shape_owner(this); - _build_polygon(); - _update_in_shape_owner(); - } - } break; - case NOTIFICATION_ENTER_TREE: { - - if (parent) { - _update_in_shape_owner(); - } - - } break; - case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - - if (parent) { - _update_in_shape_owner(true); - } - - } break; - case NOTIFICATION_UNPARENTED: { - if (parent) { - parent->remove_shape_owner(owner_id); - } - owner_id = 0; - parent = NULL; - } break; - } -} - -void CollisionPolygon::set_polygon(const Vector &p_polygon) { - - polygon = p_polygon; - if (parent) { - _build_polygon(); - } - update_configuration_warning(); - update_gizmo(); -} - -Vector CollisionPolygon::get_polygon() const { - - return polygon; -} - -AABB CollisionPolygon::get_item_rect() const { - - return aabb; -} - -void CollisionPolygon::set_depth(float p_depth) { - - depth = p_depth; - _build_polygon(); - update_gizmo(); -} - -float CollisionPolygon::get_depth() const { - - return depth; -} - -void CollisionPolygon::set_disabled(bool p_disabled) { - disabled = p_disabled; - update_gizmo(); - - if (parent) { - parent->shape_owner_set_disabled(owner_id, p_disabled); - } -} - -bool CollisionPolygon::is_disabled() const { - return disabled; -} - -String CollisionPolygon::get_configuration_warning() const { - - if (!Object::cast_to(get_parent())) { - return TTR("CollisionPolygon only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); - } - - if (polygon.empty()) { - return TTR("An empty CollisionPolygon has no effect on collision."); - } - - return String(); -} - -bool CollisionPolygon::_is_editable_3d_polygon() const { - return true; -} -void CollisionPolygon::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CollisionPolygon::get_depth); - - ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon::set_polygon); - ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon::get_polygon); - - ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon::set_disabled); - ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon::is_disabled); - - ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CollisionPolygon::_is_editable_3d_polygon); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth"), "set_depth", "get_depth"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); -} - -CollisionPolygon::CollisionPolygon() { - - aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - depth = 1.0; - set_notify_local_transform(true); - parent = NULL; - owner_id = 0; - disabled = false; -} diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h deleted file mode 100644 index 9ecdc02697..0000000000 --- a/scene/3d/collision_polygon.h +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* collision_polygon.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_POLYGON_H -#define COLLISION_POLYGON_H - -#include "scene/3d/spatial.h" -#include "scene/resources/shape.h" - -class CollisionObject; -class CollisionPolygon : public Spatial { - - GDCLASS(CollisionPolygon, Spatial); - -protected: - float depth; - AABB aabb; - Vector polygon; - - uint32_t owner_id; - CollisionObject *parent; - - bool disabled; - - void _build_polygon(); - - void _update_in_shape_owner(bool p_xform_only = false); - - bool _is_editable_3d_polygon() const; - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_depth(float p_depth); - float get_depth() const; - - void set_polygon(const Vector &p_polygon); - Vector get_polygon() const; - - void set_disabled(bool p_disabled); - bool is_disabled() const; - - virtual AABB get_item_rect() const; - - String get_configuration_warning() const; - - CollisionPolygon(); -}; - -#endif // COLLISION_POLYGON_H diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp new file mode 100644 index 0000000000..c8b1b728bc --- /dev/null +++ b/scene/3d/collision_polygon_3d.cpp @@ -0,0 +1,207 @@ +/*************************************************************************/ +/* collision_polygon_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_polygon_3d.h" + +#include "collision_object_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" + +void CollisionPolygon3D::_build_polygon() { + + if (!parent) + return; + + parent->shape_owner_clear_shapes(owner_id); + + if (polygon.size() == 0) + return; + + Vector> decomp = Geometry::decompose_polygon_in_convex(polygon); + if (decomp.size() == 0) + return; + + //here comes the sun, lalalala + //decompose concave into multiple convex polygons and add them + + for (int i = 0; i < decomp.size(); i++) { + Ref convex = memnew(ConvexPolygonShape3D); + Vector cp; + int cs = decomp[i].size(); + cp.resize(cs * 2); + { + Vector3 *w = cp.ptrw(); + int idx = 0; + for (int j = 0; j < cs; j++) { + + Vector2 d = decomp[i][j]; + w[idx++] = Vector3(d.x, d.y, depth * 0.5); + w[idx++] = Vector3(d.x, d.y, -depth * 0.5); + } + } + + convex->set_points(cp); + parent->shape_owner_add_shape(owner_id, convex); + parent->shape_owner_set_disabled(owner_id, disabled); + } +} + +void CollisionPolygon3D::_update_in_shape_owner(bool p_xform_only) { + + parent->shape_owner_set_transform(owner_id, get_transform()); + if (p_xform_only) + return; + parent->shape_owner_set_disabled(owner_id, disabled); +} + +void CollisionPolygon3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_PARENTED: { + parent = Object::cast_to(get_parent()); + if (parent) { + owner_id = parent->create_shape_owner(this); + _build_polygon(); + _update_in_shape_owner(); + } + } break; + case NOTIFICATION_ENTER_TREE: { + + if (parent) { + _update_in_shape_owner(); + } + + } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + + if (parent) { + _update_in_shape_owner(true); + } + + } break; + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); + } + owner_id = 0; + parent = NULL; + } break; + } +} + +void CollisionPolygon3D::set_polygon(const Vector &p_polygon) { + + polygon = p_polygon; + if (parent) { + _build_polygon(); + } + update_configuration_warning(); + update_gizmo(); +} + +Vector CollisionPolygon3D::get_polygon() const { + + return polygon; +} + +AABB CollisionPolygon3D::get_item_rect() const { + + return aabb; +} + +void CollisionPolygon3D::set_depth(float p_depth) { + + depth = p_depth; + _build_polygon(); + update_gizmo(); +} + +float CollisionPolygon3D::get_depth() const { + + return depth; +} + +void CollisionPolygon3D::set_disabled(bool p_disabled) { + disabled = p_disabled; + update_gizmo(); + + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } +} + +bool CollisionPolygon3D::is_disabled() const { + return disabled; +} + +String CollisionPolygon3D::get_configuration_warning() const { + + if (!Object::cast_to(get_parent())) { + return TTR("CollisionPolygon only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); + } + + if (polygon.empty()) { + return TTR("An empty CollisionPolygon has no effect on collision."); + } + + return String(); +} + +bool CollisionPolygon3D::_is_editable_3d_polygon() const { + return true; +} +void CollisionPolygon3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon3D::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &CollisionPolygon3D::get_depth); + + ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon3D::set_polygon); + ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon3D::get_polygon); + + ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon3D::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon3D::is_disabled); + + ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CollisionPolygon3D::_is_editable_3d_polygon); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); +} + +CollisionPolygon3D::CollisionPolygon3D() { + + aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + depth = 1.0; + set_notify_local_transform(true); + parent = NULL; + owner_id = 0; + disabled = false; +} diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h new file mode 100644 index 0000000000..256aee3d7e --- /dev/null +++ b/scene/3d/collision_polygon_3d.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* collision_polygon_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_POLYGON_3D_H +#define COLLISION_POLYGON_3D_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/shape_3d.h" + +class CollisionObject3D; +class CollisionPolygon3D : public Node3D { + + GDCLASS(CollisionPolygon3D, Node3D); + +protected: + float depth; + AABB aabb; + Vector polygon; + + uint32_t owner_id; + CollisionObject3D *parent; + + bool disabled; + + void _build_polygon(); + + void _update_in_shape_owner(bool p_xform_only = false); + + bool _is_editable_3d_polygon() const; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_depth(float p_depth); + float get_depth() const; + + void set_polygon(const Vector &p_polygon); + Vector get_polygon() const; + + void set_disabled(bool p_disabled); + bool is_disabled() const; + + virtual AABB get_item_rect() const; + + String get_configuration_warning() const; + + CollisionPolygon3D(); +}; + +#endif // COLLISION_POLYGON_H diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp deleted file mode 100644 index d825c8daf7..0000000000 --- a/scene/3d/collision_shape.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/*************************************************************************/ -/* collision_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_shape.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" -#include "scene/resources/ray_shape.h" -#include "scene/resources/sphere_shape.h" -#include "scene/resources/world_margin_shape.h" -#include "servers/visual_server.h" -//TODO: Implement CylinderShape and HeightMapShape? -#include "core/math/quick_hull.h" -#include "mesh_instance.h" -#include "physics_body.h" - -void CollisionShape::make_convex_from_brothers() { - - Node *p = get_parent(); - if (!p) - return; - - for (int i = 0; i < p->get_child_count(); i++) { - - Node *n = p->get_child(i); - MeshInstance *mi = Object::cast_to(n); - if (mi) { - - Ref m = mi->get_mesh(); - if (m.is_valid()) { - - Ref s = m->create_convex_shape(); - set_shape(s); - } - } - } -} - -void CollisionShape::_update_in_shape_owner(bool p_xform_only) { - parent->shape_owner_set_transform(owner_id, get_transform()); - if (p_xform_only) - return; - parent->shape_owner_set_disabled(owner_id, disabled); -} - -void CollisionShape::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_PARENTED: { - parent = Object::cast_to(get_parent()); - if (parent) { - owner_id = parent->create_shape_owner(this); - if (shape.is_valid()) { - parent->shape_owner_add_shape(owner_id, shape); - } - _update_in_shape_owner(); - } - } break; - case NOTIFICATION_ENTER_TREE: { - if (parent) { - _update_in_shape_owner(); - } - if (get_tree()->is_debugging_collisions_hint()) { - _update_debug_shape(); - } - } break; - case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (parent) { - _update_in_shape_owner(true); - } - } break; - case NOTIFICATION_UNPARENTED: { - if (parent) { - parent->remove_shape_owner(owner_id); - } - owner_id = 0; - parent = NULL; - } break; - } -} - -void CollisionShape::resource_changed(RES res) { - - update_gizmo(); -} - -String CollisionShape::get_configuration_warning() const { - - if (!Object::cast_to(get_parent())) { - return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); - } - - if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it."); - } - - if (Object::cast_to(get_parent())) { - if (Object::cast_to(*shape)) { - if (Object::cast_to(get_parent())->get_mode() != RigidBody::MODE_STATIC) { - return TTR("ConcavePolygonShape doesn't support RigidBody in another mode than static."); - } - } - } - - return String(); -} - -void CollisionShape::_bind_methods() { - - //not sure if this should do anything - ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape::resource_changed); - ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape::set_shape); - ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape::get_shape); - ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape::set_disabled); - ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape::is_disabled); - ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers); - ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape::_update_debug_shape); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); -} - -void CollisionShape::set_shape(const Ref &p_shape) { - - if (!shape.is_null()) { - shape->unregister_owner(this); - shape->disconnect("changed", callable_mp(this, &CollisionShape::_shape_changed)); - } - shape = p_shape; - if (!shape.is_null()) { - shape->register_owner(this); - shape->connect("changed", callable_mp(this, &CollisionShape::_shape_changed)); - } - update_gizmo(); - if (parent) { - parent->shape_owner_clear_shapes(owner_id); - if (shape.is_valid()) { - parent->shape_owner_add_shape(owner_id, shape); - } - } - - if (is_inside_tree()) - _shape_changed(); - update_configuration_warning(); -} - -Ref CollisionShape::get_shape() const { - - return shape; -} - -void CollisionShape::set_disabled(bool p_disabled) { - - disabled = p_disabled; - update_gizmo(); - if (parent) { - parent->shape_owner_set_disabled(owner_id, p_disabled); - } -} - -bool CollisionShape::is_disabled() const { - - return disabled; -} - -CollisionShape::CollisionShape() { - - //indicator = VisualServer::get_singleton()->mesh_create(); - disabled = false; - debug_shape = NULL; - parent = NULL; - owner_id = 0; - set_notify_local_transform(true); -} - -CollisionShape::~CollisionShape() { - if (!shape.is_null()) - shape->unregister_owner(this); - //VisualServer::get_singleton()->free(indicator); -} - -void CollisionShape::_update_debug_shape() { - debug_shape_dirty = false; - - if (debug_shape) { - debug_shape->queue_delete(); - debug_shape = NULL; - } - - Ref s = get_shape(); - if (s.is_null()) - return; - - Ref mesh = s->get_debug_mesh(); - MeshInstance *mi = memnew(MeshInstance); - mi->set_mesh(mesh); - add_child(mi); - debug_shape = mi; -} - -void CollisionShape::_shape_changed() { - // If this is a heightfield shape our center may have changed - if (parent) { - _update_in_shape_owner(true); - } - - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) { - debug_shape_dirty = true; - call_deferred("_update_debug_shape"); - } -} diff --git a/scene/3d/collision_shape.h b/scene/3d/collision_shape.h deleted file mode 100644 index 3150a41ebf..0000000000 --- a/scene/3d/collision_shape.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* collision_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_SHAPE_H -#define COLLISION_SHAPE_H - -#include "scene/3d/spatial.h" -#include "scene/resources/shape.h" -class CollisionObject; -class CollisionShape : public Spatial { - - GDCLASS(CollisionShape, Spatial); - OBJ_CATEGORY("3D Physics Nodes"); - - Ref shape; - - uint32_t owner_id; - CollisionObject *parent; - - Node *debug_shape; - bool debug_shape_dirty; - - void resource_changed(RES res); - bool disabled; - -protected: - void _update_debug_shape(); - void _shape_changed(); - - void _update_in_shape_owner(bool p_xform_only = false); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void make_convex_from_brothers(); - - void set_shape(const Ref &p_shape); - Ref get_shape() const; - - void set_disabled(bool p_disabled); - bool is_disabled() const; - - String get_configuration_warning() const; - - CollisionShape(); - ~CollisionShape(); -}; - -#endif // BODY_VOLUME_H diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp new file mode 100644 index 0000000000..cd171aad16 --- /dev/null +++ b/scene/3d/collision_shape_3d.cpp @@ -0,0 +1,242 @@ +/*************************************************************************/ +/* collision_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_shape_3d.h" +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" +#include "scene/resources/ray_shape.h" +#include "scene/resources/sphere_shape_3d.h" +#include "scene/resources/world_margin_shape_3d.h" +#include "servers/visual_server.h" +//TODO: Implement CylinderShape and HeightMapShape? +#include "core/math/quick_hull.h" +#include "mesh_instance_3d.h" +#include "physics_body_3d.h" + +void CollisionShape3D::make_convex_from_brothers() { + + Node *p = get_parent(); + if (!p) + return; + + for (int i = 0; i < p->get_child_count(); i++) { + + Node *n = p->get_child(i); + MeshInstance3D *mi = Object::cast_to(n); + if (mi) { + + Ref m = mi->get_mesh(); + if (m.is_valid()) { + + Ref s = m->create_convex_shape(); + set_shape(s); + } + } + } +} + +void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) { + parent->shape_owner_set_transform(owner_id, get_transform()); + if (p_xform_only) + return; + parent->shape_owner_set_disabled(owner_id, disabled); +} + +void CollisionShape3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_PARENTED: { + parent = Object::cast_to(get_parent()); + if (parent) { + owner_id = parent->create_shape_owner(this); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); + } + _update_in_shape_owner(); + } + } break; + case NOTIFICATION_ENTER_TREE: { + if (parent) { + _update_in_shape_owner(); + } + if (get_tree()->is_debugging_collisions_hint()) { + _update_debug_shape(); + } + } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (parent) { + _update_in_shape_owner(true); + } + } break; + case NOTIFICATION_UNPARENTED: { + if (parent) { + parent->remove_shape_owner(owner_id); + } + owner_id = 0; + parent = NULL; + } break; + } +} + +void CollisionShape3D::resource_changed(RES res) { + + update_gizmo(); +} + +String CollisionShape3D::get_configuration_warning() const { + + if (!Object::cast_to(get_parent())) { + return TTR("CollisionShape only serves to provide a collision shape to a CollisionObject derived node. Please only use it as a child of Area, StaticBody, RigidBody, KinematicBody, etc. to give them a shape."); + } + + if (!shape.is_valid()) { + return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it."); + } + + if (Object::cast_to(get_parent())) { + if (Object::cast_to(*shape)) { + if (Object::cast_to(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) { + return TTR("ConcavePolygonShape doesn't support RigidBody in another mode than static."); + } + } + } + + return String(); +} + +void CollisionShape3D::_bind_methods() { + + //not sure if this should do anything + ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &CollisionShape3D::resource_changed); + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape3D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape); + ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled); + ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled); + ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape3D::make_convex_from_brothers); + ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + + ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); +} + +void CollisionShape3D::set_shape(const Ref &p_shape) { + + if (!shape.is_null()) { + shape->unregister_owner(this); + shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed)); + } + shape = p_shape; + if (!shape.is_null()) { + shape->register_owner(this); + shape->connect("changed", callable_mp(this, &CollisionShape3D::_shape_changed)); + } + update_gizmo(); + if (parent) { + parent->shape_owner_clear_shapes(owner_id); + if (shape.is_valid()) { + parent->shape_owner_add_shape(owner_id, shape); + } + } + + if (is_inside_tree()) + _shape_changed(); + update_configuration_warning(); +} + +Ref CollisionShape3D::get_shape() const { + + return shape; +} + +void CollisionShape3D::set_disabled(bool p_disabled) { + + disabled = p_disabled; + update_gizmo(); + if (parent) { + parent->shape_owner_set_disabled(owner_id, p_disabled); + } +} + +bool CollisionShape3D::is_disabled() const { + + return disabled; +} + +CollisionShape3D::CollisionShape3D() { + + //indicator = VisualServer::get_singleton()->mesh_create(); + disabled = false; + debug_shape = NULL; + parent = NULL; + owner_id = 0; + set_notify_local_transform(true); +} + +CollisionShape3D::~CollisionShape3D() { + if (!shape.is_null()) + shape->unregister_owner(this); + //VisualServer::get_singleton()->free(indicator); +} + +void CollisionShape3D::_update_debug_shape() { + debug_shape_dirty = false; + + if (debug_shape) { + debug_shape->queue_delete(); + debug_shape = NULL; + } + + Ref s = get_shape(); + if (s.is_null()) + return; + + Ref mesh = s->get_debug_mesh(); + MeshInstance3D *mi = memnew(MeshInstance3D); + mi->set_mesh(mesh); + add_child(mi); + debug_shape = mi; +} + +void CollisionShape3D::_shape_changed() { + // If this is a heightfield shape our center may have changed + if (parent) { + _update_in_shape_owner(true); + } + + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) { + debug_shape_dirty = true; + call_deferred("_update_debug_shape"); + } +} diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h new file mode 100644 index 0000000000..8515d292af --- /dev/null +++ b/scene/3d/collision_shape_3d.h @@ -0,0 +1,78 @@ +/*************************************************************************/ +/* collision_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_SHAPE_H +#define COLLISION_SHAPE_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/shape_3d.h" +class CollisionObject3D; +class CollisionShape3D : public Node3D { + + GDCLASS(CollisionShape3D, Node3D); + OBJ_CATEGORY("3D Physics Nodes"); + + Ref shape; + + uint32_t owner_id; + CollisionObject3D *parent; + + Node *debug_shape; + bool debug_shape_dirty; + + void resource_changed(RES res); + bool disabled; + +protected: + void _update_debug_shape(); + void _shape_changed(); + + void _update_in_shape_owner(bool p_xform_only = false); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void make_convex_from_brothers(); + + void set_shape(const Ref &p_shape); + Ref get_shape() const; + + void set_disabled(bool p_disabled); + bool is_disabled() const; + + String get_configuration_warning() const; + + CollisionShape3D(); + ~CollisionShape3D(); +}; + +#endif // BODY_VOLUME_H diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp deleted file mode 100644 index bde578d0af..0000000000 --- a/scene/3d/cpu_particles.cpp +++ /dev/null @@ -1,1546 +0,0 @@ -/*************************************************************************/ -/* cpu_particles.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "cpu_particles.h" - -#include "scene/3d/camera.h" -#include "scene/3d/particles.h" -#include "scene/resources/particles_material.h" -#include "servers/visual_server.h" - -AABB CPUParticles::get_aabb() const { - - return AABB(); -} -Vector CPUParticles::get_faces(uint32_t p_usage_flags) const { - - return Vector(); -} - -void CPUParticles::set_emitting(bool p_emitting) { - - if (emitting == p_emitting) - return; - - emitting = p_emitting; - if (emitting) { - set_process_internal(true); - - // first update before rendering to avoid one frame delay after emitting starts - if (time == 0) - _update_internal(); - } -} - -void CPUParticles::set_amount(int p_amount) { - - ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles must be greater than 0."); - - particles.resize(p_amount); - { - Particle *w = particles.ptrw(); - - for (int i = 0; i < p_amount; i++) { - w[i].active = false; - } - } - - particle_data.resize((12 + 4 + 4) * p_amount); - VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true); - - particle_order.resize(p_amount); -} -void CPUParticles::set_lifetime(float p_lifetime) { - - ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); - lifetime = p_lifetime; -} - -void CPUParticles::set_one_shot(bool p_one_shot) { - - one_shot = p_one_shot; -} - -void CPUParticles::set_pre_process_time(float p_time) { - - pre_process_time = p_time; -} -void CPUParticles::set_explosiveness_ratio(float p_ratio) { - - explosiveness_ratio = p_ratio; -} -void CPUParticles::set_randomness_ratio(float p_ratio) { - - randomness_ratio = p_ratio; -} -void CPUParticles::set_lifetime_randomness(float p_random) { - - lifetime_randomness = p_random; -} -void CPUParticles::set_use_local_coordinates(bool p_enable) { - - local_coords = p_enable; -} -void CPUParticles::set_speed_scale(float p_scale) { - - speed_scale = p_scale; -} - -bool CPUParticles::is_emitting() const { - - return emitting; -} -int CPUParticles::get_amount() const { - - return particles.size(); -} -float CPUParticles::get_lifetime() const { - - return lifetime; -} -bool CPUParticles::get_one_shot() const { - - return one_shot; -} - -float CPUParticles::get_pre_process_time() const { - - return pre_process_time; -} -float CPUParticles::get_explosiveness_ratio() const { - - return explosiveness_ratio; -} -float CPUParticles::get_randomness_ratio() const { - - return randomness_ratio; -} -float CPUParticles::get_lifetime_randomness() const { - - return lifetime_randomness; -} - -bool CPUParticles::get_use_local_coordinates() const { - - return local_coords; -} - -float CPUParticles::get_speed_scale() const { - - return speed_scale; -} - -void CPUParticles::set_draw_order(DrawOrder p_order) { - - draw_order = p_order; -} - -CPUParticles::DrawOrder CPUParticles::get_draw_order() const { - - return draw_order; -} - -void CPUParticles::set_mesh(const Ref &p_mesh) { - - mesh = p_mesh; - if (mesh.is_valid()) { - VS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); - } else { - VS::get_singleton()->multimesh_set_mesh(multimesh, RID()); - } -} - -Ref CPUParticles::get_mesh() const { - - return mesh; -} - -void CPUParticles::set_fixed_fps(int p_count) { - fixed_fps = p_count; -} - -int CPUParticles::get_fixed_fps() const { - return fixed_fps; -} - -void CPUParticles::set_fractional_delta(bool p_enable) { - fractional_delta = p_enable; -} - -bool CPUParticles::get_fractional_delta() const { - return fractional_delta; -} - -String CPUParticles::get_configuration_warning() const { - - String warnings; - - bool mesh_found = false; - bool anim_material_found = false; - - if (get_mesh().is_valid()) { - mesh_found = true; - for (int j = 0; j < get_mesh()->get_surface_count(); j++) { - anim_material_found = Object::cast_to(get_mesh()->surface_get_material(j).ptr()) != NULL; - StandardMaterial3D *spat = Object::cast_to(get_mesh()->surface_get_material(j).ptr()); - anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); - } - } - - anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; - StandardMaterial3D *spat = Object::cast_to(get_material_override().ptr()); - anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); - - if (!mesh_found) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("Nothing is visible because no mesh has been assigned."); - } - - if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || - get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("CPUParticles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); - } - - return warnings; -} - -void CPUParticles::restart() { - - time = 0; - inactive_time = 0; - frame_remainder = 0; - cycle = 0; - emitting = false; - - { - int pc = particles.size(); - Particle *w = particles.ptrw(); - - for (int i = 0; i < pc; i++) { - w[i].active = false; - } - } - - set_emitting(true); -} - -void CPUParticles::set_direction(Vector3 p_direction) { - - direction = p_direction; -} - -Vector3 CPUParticles::get_direction() const { - - return direction; -} - -void CPUParticles::set_spread(float p_spread) { - - spread = p_spread; -} - -float CPUParticles::get_spread() const { - - return spread; -} - -void CPUParticles::set_flatness(float p_flatness) { - - flatness = p_flatness; -} -float CPUParticles::get_flatness() const { - - return flatness; -} - -void CPUParticles::set_param(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - parameters[p_param] = p_value; -} -float CPUParticles::get_param(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - - return parameters[p_param]; -} - -void CPUParticles::set_param_randomness(Parameter p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - randomness[p_param] = p_value; -} -float CPUParticles::get_param_randomness(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - - return randomness[p_param]; -} - -static void _adjust_curve_range(const Ref &p_curve, float p_min, float p_max) { - - Ref curve = p_curve; - if (!curve.is_valid()) - return; - - curve->ensure_default_setup(p_min, p_max); -} - -void CPUParticles::set_param_curve(Parameter p_param, const Ref &p_curve) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - - curve_parameters[p_param] = p_curve; - - switch (p_param) { - case PARAM_INITIAL_LINEAR_VELOCITY: { - //do none for this one - } break; - case PARAM_ANGULAR_VELOCITY: { - _adjust_curve_range(p_curve, -360, 360); - } break; - case PARAM_ORBIT_VELOCITY: { - _adjust_curve_range(p_curve, -500, 500); - } break; - case PARAM_LINEAR_ACCEL: { - _adjust_curve_range(p_curve, -200, 200); - } break; - case PARAM_RADIAL_ACCEL: { - _adjust_curve_range(p_curve, -200, 200); - } break; - case PARAM_TANGENTIAL_ACCEL: { - _adjust_curve_range(p_curve, -200, 200); - } break; - case PARAM_DAMPING: { - _adjust_curve_range(p_curve, 0, 100); - } break; - case PARAM_ANGLE: { - _adjust_curve_range(p_curve, -360, 360); - } break; - case PARAM_SCALE: { - - } break; - case PARAM_HUE_VARIATION: { - _adjust_curve_range(p_curve, -1, 1); - } break; - case PARAM_ANIM_SPEED: { - _adjust_curve_range(p_curve, 0, 200); - } break; - case PARAM_ANIM_OFFSET: { - } break; - default: { - } - } -} -Ref CPUParticles::get_param_curve(Parameter p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref()); - - return curve_parameters[p_param]; -} - -void CPUParticles::set_color(const Color &p_color) { - - color = p_color; -} - -Color CPUParticles::get_color() const { - - return color; -} - -void CPUParticles::set_color_ramp(const Ref &p_ramp) { - - color_ramp = p_ramp; -} - -Ref CPUParticles::get_color_ramp() const { - - return color_ramp; -} - -void CPUParticles::set_particle_flag(Flags p_flag, bool p_enable) { - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags[p_flag] = p_enable; - if (p_flag == FLAG_DISABLE_Z) { - _change_notify(); - } -} - -bool CPUParticles::get_particle_flag(Flags p_flag) const { - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags[p_flag]; -} - -void CPUParticles::set_emission_shape(EmissionShape p_shape) { - ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); - emission_shape = p_shape; -} - -void CPUParticles::set_emission_sphere_radius(float p_radius) { - - emission_sphere_radius = p_radius; -} - -void CPUParticles::set_emission_box_extents(Vector3 p_extents) { - - emission_box_extents = p_extents; -} - -void CPUParticles::set_emission_points(const Vector &p_points) { - - emission_points = p_points; -} - -void CPUParticles::set_emission_normals(const Vector &p_normals) { - - emission_normals = p_normals; -} - -void CPUParticles::set_emission_colors(const Vector &p_colors) { - - emission_colors = p_colors; -} - -float CPUParticles::get_emission_sphere_radius() const { - - return emission_sphere_radius; -} -Vector3 CPUParticles::get_emission_box_extents() const { - - return emission_box_extents; -} -Vector CPUParticles::get_emission_points() const { - - return emission_points; -} -Vector CPUParticles::get_emission_normals() const { - - return emission_normals; -} - -Vector CPUParticles::get_emission_colors() const { - - return emission_colors; -} - -CPUParticles::EmissionShape CPUParticles::get_emission_shape() const { - return emission_shape; -} -void CPUParticles::set_gravity(const Vector3 &p_gravity) { - - gravity = p_gravity; -} - -Vector3 CPUParticles::get_gravity() const { - - return gravity; -} - -void CPUParticles::_validate_property(PropertyInfo &property) const { - - if (property.name == "color" && color_ramp.is_valid()) { - property.usage = 0; - } - - if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { - property.usage = 0; - } - - if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { - property.usage = 0; - } - - if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { - property.usage = 0; - } - - if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { - property.usage = 0; - } - - if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { - property.usage = 0; - } -} - -static uint32_t idhash(uint32_t x) { - - x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b); - x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b); - x = (x >> uint32_t(16)) ^ x; - return x; -} - -static float rand_from_seed(uint32_t &seed) { - int k; - int s = int(seed); - if (s == 0) - s = 305420679; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - seed = uint32_t(s); - return float(seed % uint32_t(65536)) / 65535.0; -} - -void CPUParticles::_update_internal() { - - if (particles.size() == 0 || !is_visible_in_tree()) { - _set_redraw(false); - return; - } - - float delta = get_process_delta_time(); - if (emitting) { - inactive_time = 0; - } else { - inactive_time += delta; - if (inactive_time > lifetime * 1.2) { - set_process_internal(false); - _set_redraw(false); - - //reset variables - time = 0; - inactive_time = 0; - frame_remainder = 0; - cycle = 0; - return; - } - } - _set_redraw(true); - - bool processed = false; - - if (time == 0 && pre_process_time > 0.0) { - - float frame_time; - if (fixed_fps > 0) - frame_time = 1.0 / fixed_fps; - else - frame_time = 1.0 / 30.0; - - float todo = pre_process_time; - - while (todo >= 0) { - _particles_process(frame_time); - processed = true; - todo -= frame_time; - } - } - - if (fixed_fps > 0) { - float frame_time = 1.0 / fixed_fps; - float decr = frame_time; - - float ldelta = delta; - if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 - ldelta = 0.1; - } else if (ldelta <= 0.0) { //unlikely but.. - ldelta = 0.001; - } - float todo = frame_remainder + ldelta; - - while (todo >= frame_time) { - _particles_process(frame_time); - processed = true; - todo -= decr; - } - - frame_remainder = todo; - - } else { - _particles_process(delta); - processed = true; - } - - if (processed) { - _update_particle_data_buffer(); - } -} - -void CPUParticles::_particles_process(float p_delta) { - - p_delta *= speed_scale; - - int pcount = particles.size(); - Particle *w = particles.ptrw(); - - Particle *parray = w; - - float prev_time = time; - time += p_delta; - if (time > lifetime) { - time = Math::fmod(time, lifetime); - cycle++; - if (one_shot && cycle > 0) { - set_emitting(false); - _change_notify(); - } - } - - Transform emission_xform; - Basis velocity_xform; - if (!local_coords) { - emission_xform = get_global_transform(); - velocity_xform = emission_xform.basis; - } - - float system_phase = time / lifetime; - - for (int i = 0; i < pcount; i++) { - - Particle &p = parray[i]; - - if (!emitting && !p.active) - continue; - - float local_delta = p_delta; - - // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle. - // While we use time in tests later on, for randomness we use the phase as done in the - // original shader code, and we later multiply by lifetime to get the time. - float restart_phase = float(i) / float(pcount); - - if (randomness_ratio > 0.0) { - uint32_t seed = cycle; - if (restart_phase >= system_phase) { - seed -= uint32_t(1); - } - seed *= uint32_t(pcount); - seed += uint32_t(i); - float random = float(idhash(seed) % uint32_t(65536)) / 65536.0; - restart_phase += randomness_ratio * random * 1.0 / float(pcount); - } - - restart_phase *= (1.0 - explosiveness_ratio); - float restart_time = restart_phase * lifetime; - bool restart = false; - - if (time > prev_time) { - // restart_time >= prev_time is used so particles emit in the first frame they are processed - - if (restart_time >= prev_time && restart_time < time) { - restart = true; - if (fractional_delta) { - local_delta = time - restart_time; - } - } - - } else if (local_delta > 0.0) { - if (restart_time >= prev_time) { - restart = true; - if (fractional_delta) { - local_delta = lifetime - restart_time + time; - } - - } else if (restart_time < time) { - restart = true; - if (fractional_delta) { - local_delta = time - restart_time; - } - } - } - - if (p.time * (1.0 - explosiveness_ratio) > p.lifetime) { - restart = true; - } - - if (restart) { - - if (!emitting) { - p.active = false; - continue; - } - p.active = true; - - /*float tex_linear_velocity = 0; - if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0); - }*/ - - float tex_angle = 0.0; - if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(0); - } - - float tex_anim_offset = 0.0; - if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(0); - } - - p.seed = Math::rand(); - - p.angle_rand = Math::randf(); - p.scale_rand = Math::randf(); - p.hue_rot_rand = Math::randf(); - p.anim_offset_rand = Math::randf(); - - if (flags[FLAG_DISABLE_Z]) { - float angle1_rad = Math::atan2(direction.y, direction.x) + (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0; - Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0); - p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); - } else { - //initiate velocity spread in 3D - float angle1_rad = Math::atan2(direction.x, direction.z) + (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0; - float angle2_rad = Math::atan2(direction.y, Math::abs(direction.z)) + (Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * Math_PI * spread / 180.0; - - Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); - Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); - direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution - Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z); - direction.normalize(); - p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); - } - - float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); - p.custom[0] = Math::deg2rad(base_angle); //angle - p.custom[1] = 0.0; //phase - p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1) - p.transform = Transform(); - p.time = 0; - p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness); - p.base_color = Color(1, 1, 1, 1); - - switch (emission_shape) { - case EMISSION_SHAPE_POINT: { - //do none - } break; - case EMISSION_SHAPE_SPHERE: { - float s = 2.0 * Math::randf() - 1.0, t = 2.0 * Math_PI * Math::randf(); - float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s); - p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s); - } break; - case EMISSION_SHAPE_BOX: { - p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_box_extents; - } break; - case EMISSION_SHAPE_POINTS: - case EMISSION_SHAPE_DIRECTED_POINTS: { - - int pc = emission_points.size(); - if (pc == 0) - break; - - int random_idx = Math::rand() % pc; - - p.transform.origin = emission_points.get(random_idx); - - if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) { - if (flags[FLAG_DISABLE_Z]) { - /* - mat2 rotm; - "; - rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy; - rotm[1] = rotm[0].yx * vec2(1.0, -1.0); - VELOCITY.xy = rotm * VELOCITY.xy; - */ - } else { - Vector3 normal = emission_normals.get(random_idx); - Vector3 v0 = Math::abs(normal.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(0, 1.0, 0.0); - Vector3 tangent = v0.cross(normal).normalized(); - Vector3 bitangent = tangent.cross(normal).normalized(); - Basis m3; - m3.set_axis(0, tangent); - m3.set_axis(1, bitangent); - m3.set_axis(2, normal); - p.velocity = m3.xform(p.velocity); - } - } - - if (emission_colors.size() == pc) { - p.base_color = emission_colors.get(random_idx); - } - } break; - case EMISSION_SHAPE_MAX: { // Max value for validity check. - break; - } - } - - if (!local_coords) { - p.velocity = velocity_xform.xform(p.velocity); - p.transform = emission_xform * p.transform; - } - - if (flags[FLAG_DISABLE_Z]) { - p.velocity.z = 0.0; - p.transform.origin.z = 0.0; - } - - } else if (!p.active) { - continue; - } else if (p.time > p.lifetime) { - p.active = false; - } else { - - uint32_t alt_seed = p.seed; - - p.time += local_delta; - p.custom[1] = p.time / lifetime; - - float tex_linear_velocity = 0.0; - if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(p.custom[1]); - } - - float tex_orbit_velocity = 0.0; - if (flags[FLAG_DISABLE_Z]) { - if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { - tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(p.custom[1]); - } - } - - float tex_angular_velocity = 0.0; - if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { - tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(p.custom[1]); - } - - float tex_linear_accel = 0.0; - if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) { - tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(p.custom[1]); - } - - float tex_tangential_accel = 0.0; - if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { - tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(p.custom[1]); - } - - float tex_radial_accel = 0.0; - if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) { - tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(p.custom[1]); - } - - float tex_damping = 0.0; - if (curve_parameters[PARAM_DAMPING].is_valid()) { - tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(p.custom[1]); - } - - float tex_angle = 0.0; - if (curve_parameters[PARAM_ANGLE].is_valid()) { - tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(p.custom[1]); - } - float tex_anim_speed = 0.0; - if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) { - tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(p.custom[1]); - } - - float tex_anim_offset = 0.0; - if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) { - tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(p.custom[1]); - } - - Vector3 force = gravity; - Vector3 position = p.transform.origin; - if (flags[FLAG_DISABLE_Z]) { - position.z = 0.0; - } - //apply linear acceleration - force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector3(); - //apply radial acceleration - Vector3 org = emission_xform.origin; - Vector3 diff = position - org; - force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3(); - //apply tangential acceleration; - if (flags[FLAG_DISABLE_Z]) { - - Vector2 yx = Vector2(diff.y, diff.x); - Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized(); - force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3(); - - } else { - Vector3 crossDiff = diff.normalized().cross(gravity.normalized()); - force += crossDiff.length() > 0.0 ? crossDiff.normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3(); - } - //apply attractor forces - p.velocity += force * local_delta; - //orbit velocity - if (flags[FLAG_DISABLE_Z]) { - float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]); - if (orbit_amount != 0.0) { - float ang = orbit_amount * local_delta * Math_PI * 2.0; - // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, - // but we use -ang here to reproduce its behavior. - Transform2D rot = Transform2D(-ang, Vector2()); - Vector2 rotv = rot.basis_xform(Vector2(diff.x, diff.y)); - p.transform.origin -= Vector3(diff.x, diff.y, 0); - p.transform.origin += Vector3(rotv.x, rotv.y, 0); - } - } - if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - p.velocity = p.velocity.normalized() * tex_linear_velocity; - } - if (parameters[PARAM_DAMPING] + tex_damping > 0.0) { - - float v = p.velocity.length(); - float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]); - v -= damp * local_delta; - if (v < 0.0) { - p.velocity = Vector3(); - } else { - p.velocity = p.velocity.normalized() * v; - } - } - float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); - base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]); - p.custom[0] = Math::deg2rad(base_angle); //angle - p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); //angle - } - //apply color - //apply hue rotation - - float tex_scale = 1.0; - if (curve_parameters[PARAM_SCALE].is_valid()) { - tex_scale = curve_parameters[PARAM_SCALE]->interpolate(p.custom[1]); - } - - float tex_hue_variation = 0.0; - if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) { - tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(p.custom[1]); - } - - float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_PI * 2.0 * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]); - float hue_rot_c = Math::cos(hue_rot_angle); - float hue_rot_s = Math::sin(hue_rot_angle); - - Basis hue_rot_mat; - { - Basis mat1(0.299, 0.587, 0.114, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114); - Basis mat2(0.701, -0.587, -0.114, -0.299, 0.413, -0.114, -0.300, -0.588, 0.886); - Basis mat3(0.168, 0.330, -0.497, -0.328, 0.035, 0.292, 1.250, -1.050, -0.203); - - for (int j = 0; j < 3; j++) { - hue_rot_mat[j] = mat1[j] + mat2[j] * hue_rot_c + mat3[j] * hue_rot_s; - } - } - - if (color_ramp.is_valid()) { - p.color = color_ramp->get_color_at_offset(p.custom[1]) * color; - } else { - p.color = color; - } - - Vector3 color_rgb = hue_rot_mat.xform_inv(Vector3(p.color.r, p.color.g, p.color.b)); - p.color.r = color_rgb.x; - p.color.g = color_rgb.y; - p.color.b = color_rgb.z; - - p.color *= p.base_color; - - if (flags[FLAG_DISABLE_Z]) { - - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { - if (p.velocity.length() > 0.0) { - p.transform.basis.set_axis(1, p.velocity.normalized()); - } else { - p.transform.basis.set_axis(1, p.transform.basis.get_axis(1)); - } - p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); - p.transform.basis.set_axis(2, Vector3(0, 0, 1)); - - } else { - p.transform.basis.set_axis(0, Vector3(Math::cos(p.custom[0]), -Math::sin(p.custom[0]), 0.0)); - p.transform.basis.set_axis(1, Vector3(Math::sin(p.custom[0]), Math::cos(p.custom[0]), 0.0)); - p.transform.basis.set_axis(2, Vector3(0, 0, 1)); - } - - } else { - //orient particle Y towards velocity - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { - if (p.velocity.length() > 0.0) { - p.transform.basis.set_axis(1, p.velocity.normalized()); - } else { - p.transform.basis.set_axis(1, p.transform.basis.get_axis(1).normalized()); - } - if (p.transform.basis.get_axis(1) == p.transform.basis.get_axis(0)) { - p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); - p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized()); - } else { - p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized()); - p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); - } - } else { - p.transform.basis.orthonormalize(); - } - - //turn particle by rotation in Y - if (flags[FLAG_ROTATE_Y]) { - Basis rot_y(Vector3(0, 1, 0), p.custom[0]); - p.transform.basis = p.transform.basis * rot_y; - } - } - - //scale by scale - float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]); - if (base_scale < 0.000001) base_scale = 0.000001; - - p.transform.basis.scale(Vector3(1, 1, 1) * base_scale); - - if (flags[FLAG_DISABLE_Z]) { - p.velocity.z = 0.0; - p.transform.origin.z = 0.0; - } - - p.transform.origin += p.velocity * local_delta; - } -} - -void CPUParticles::_update_particle_data_buffer() { - MutexLock lock(update_mutex); - - int pc = particles.size(); - - int *ow; - int *order = NULL; - - float *w = particle_data.ptrw(); - const Particle *r = particles.ptr(); - float *ptr = w; - - if (draw_order != DRAW_ORDER_INDEX) { - ow = particle_order.ptrw(); - order = ow; - - for (int i = 0; i < pc; i++) { - order[i] = i; - } - if (draw_order == DRAW_ORDER_LIFETIME) { - SortArray sorter; - sorter.compare.particles = r; - sorter.sort(order, pc); - } else if (draw_order == DRAW_ORDER_VIEW_DEPTH) { - Camera *c = get_viewport()->get_camera(); - if (c) { - Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close - - if (local_coords) { - - // will look different from Particles in editor as this is based on the camera in the scenetree - // and not the editor camera - dir = inv_emission_transform.xform(dir).normalized(); - } else { - dir = dir.normalized(); - } - - SortArray sorter; - sorter.compare.particles = r; - sorter.compare.axis = dir; - sorter.sort(order, pc); - } - } - } - - for (int i = 0; i < pc; i++) { - - int idx = order ? order[i] : i; - - Transform t = r[idx].transform; - - if (!local_coords) { - t = inv_emission_transform * t; - } - - if (r[idx].active) { - ptr[0] = t.basis.elements[0][0]; - ptr[1] = t.basis.elements[0][1]; - ptr[2] = t.basis.elements[0][2]; - ptr[3] = t.origin.x; - ptr[4] = t.basis.elements[1][0]; - ptr[5] = t.basis.elements[1][1]; - ptr[6] = t.basis.elements[1][2]; - ptr[7] = t.origin.y; - ptr[8] = t.basis.elements[2][0]; - ptr[9] = t.basis.elements[2][1]; - ptr[10] = t.basis.elements[2][2]; - ptr[11] = t.origin.z; - } else { - zeromem(ptr, sizeof(float) * 12); - } - - Color c = r[idx].color; - - ptr[12] = c.r; - ptr[13] = c.g; - ptr[14] = c.b; - ptr[15] = c.a; - - ptr[16] = r[idx].custom[0]; - ptr[17] = r[idx].custom[1]; - ptr[18] = r[idx].custom[2]; - ptr[19] = r[idx].custom[3]; - - ptr += 20; - } - - can_update = true; -} - -void CPUParticles::_set_redraw(bool p_redraw) { - if (redraw == p_redraw) - return; - redraw = p_redraw; - - { - MutexLock lock(update_mutex); - - if (redraw) { - VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread)); - VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); - } else { - if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread))) { - VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles::_update_render_thread)); - } - VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); - } - } -} - -void CPUParticles::_update_render_thread() { - - MutexLock lock(update_mutex); - - if (can_update) { - VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); - can_update = false; //wait for next time - } -} - -void CPUParticles::_notification(int p_what) { - - if (p_what == NOTIFICATION_ENTER_TREE) { - set_process_internal(emitting); - - // first update before rendering to avoid one frame delay after emitting starts - if (emitting && (time == 0)) - _update_internal(); - } - - if (p_what == NOTIFICATION_EXIT_TREE) { - _set_redraw(false); - } - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - // first update before rendering to avoid one frame delay after emitting starts - if (emitting && (time == 0)) - _update_internal(); - } - - if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - _update_internal(); - } - - if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { - - inv_emission_transform = get_global_transform().affine_inverse(); - - if (!local_coords) { - - int pc = particles.size(); - - float *w = particle_data.ptrw(); - const Particle *r = particles.ptr(); - float *ptr = w; - - for (int i = 0; i < pc; i++) { - - Transform t = inv_emission_transform * r[i].transform; - - if (r[i].active) { - ptr[0] = t.basis.elements[0][0]; - ptr[1] = t.basis.elements[0][1]; - ptr[2] = t.basis.elements[0][2]; - ptr[3] = t.origin.x; - ptr[4] = t.basis.elements[1][0]; - ptr[5] = t.basis.elements[1][1]; - ptr[6] = t.basis.elements[1][2]; - ptr[7] = t.origin.y; - ptr[8] = t.basis.elements[2][0]; - ptr[9] = t.basis.elements[2][1]; - ptr[10] = t.basis.elements[2][2]; - ptr[11] = t.origin.z; - } else { - zeromem(ptr, sizeof(float) * 12); - } - - ptr += 20; - } - - can_update = true; - } - } -} - -void CPUParticles::convert_from_particles(Node *p_particles) { - - Particles *particles = Object::cast_to(p_particles); - ERR_FAIL_COND_MSG(!particles, "Only Particles nodes can be converted to CPUParticles."); - - set_emitting(particles->is_emitting()); - set_amount(particles->get_amount()); - set_lifetime(particles->get_lifetime()); - set_one_shot(particles->get_one_shot()); - set_pre_process_time(particles->get_pre_process_time()); - set_explosiveness_ratio(particles->get_explosiveness_ratio()); - set_randomness_ratio(particles->get_randomness_ratio()); - set_use_local_coordinates(particles->get_use_local_coordinates()); - set_fixed_fps(particles->get_fixed_fps()); - set_fractional_delta(particles->get_fractional_delta()); - set_speed_scale(particles->get_speed_scale()); - set_draw_order(DrawOrder(particles->get_draw_order())); - set_mesh(particles->get_draw_pass_mesh(0)); - - Ref material = particles->get_process_material(); - if (material.is_null()) - return; - - set_direction(material->get_direction()); - set_spread(material->get_spread()); - set_flatness(material->get_flatness()); - - set_color(material->get_color()); - - Ref gt = material->get_color_ramp(); - if (gt.is_valid()) { - set_color_ramp(gt->get_gradient()); - } - - set_particle_flag(FLAG_ALIGN_Y_TO_VELOCITY, material->get_flag(ParticlesMaterial::FLAG_ALIGN_Y_TO_VELOCITY)); - set_particle_flag(FLAG_ROTATE_Y, material->get_flag(ParticlesMaterial::FLAG_ROTATE_Y)); - set_particle_flag(FLAG_DISABLE_Z, material->get_flag(ParticlesMaterial::FLAG_DISABLE_Z)); - - set_emission_shape(EmissionShape(material->get_emission_shape())); - set_emission_sphere_radius(material->get_emission_sphere_radius()); - set_emission_box_extents(material->get_emission_box_extents()); - - set_gravity(material->get_gravity()); - set_lifetime_randomness(material->get_lifetime_randomness()); - -#define CONVERT_PARAM(m_param) \ - set_param(m_param, material->get_param(ParticlesMaterial::m_param)); \ - { \ - Ref ctex = material->get_param_texture(ParticlesMaterial::m_param); \ - if (ctex.is_valid()) set_param_curve(m_param, ctex->get_curve()); \ - } \ - set_param_randomness(m_param, material->get_param_randomness(ParticlesMaterial::m_param)); - - CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); - CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); - CONVERT_PARAM(PARAM_ORBIT_VELOCITY); - CONVERT_PARAM(PARAM_LINEAR_ACCEL); - CONVERT_PARAM(PARAM_RADIAL_ACCEL); - CONVERT_PARAM(PARAM_TANGENTIAL_ACCEL); - CONVERT_PARAM(PARAM_DAMPING); - CONVERT_PARAM(PARAM_ANGLE); - CONVERT_PARAM(PARAM_SCALE); - CONVERT_PARAM(PARAM_HUE_VARIATION); - CONVERT_PARAM(PARAM_ANIM_SPEED); - CONVERT_PARAM(PARAM_ANIM_OFFSET); - -#undef CONVERT_PARAM -} - -void CPUParticles::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles::set_emitting); - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles::set_amount); - ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles::set_lifetime); - ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles::set_one_shot); - ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles::set_pre_process_time); - ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &CPUParticles::set_explosiveness_ratio); - ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &CPUParticles::set_randomness_ratio); - ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "random"), &CPUParticles::set_lifetime_randomness); - ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &CPUParticles::set_use_local_coordinates); - ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles::set_fixed_fps); - ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles::set_fractional_delta); - ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &CPUParticles::set_speed_scale); - - ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles::is_emitting); - ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles::get_amount); - ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles::get_lifetime); - ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles::get_one_shot); - ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles::get_pre_process_time); - ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &CPUParticles::get_explosiveness_ratio); - ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &CPUParticles::get_randomness_ratio); - ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &CPUParticles::get_lifetime_randomness); - ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &CPUParticles::get_use_local_coordinates); - ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles::get_fixed_fps); - ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles::get_fractional_delta); - ClassDB::bind_method(D_METHOD("get_speed_scale"), &CPUParticles::get_speed_scale); - - ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &CPUParticles::set_draw_order); - - ClassDB::bind_method(D_METHOD("get_draw_order"), &CPUParticles::get_draw_order); - - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CPUParticles::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh"), &CPUParticles::get_mesh); - - ClassDB::bind_method(D_METHOD("restart"), &CPUParticles::restart); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); - ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); - ADD_GROUP("Drawing", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); - - BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); - BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); - BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); - - //////////////////////////////// - - ClassDB::bind_method(D_METHOD("set_direction", "direction"), &CPUParticles::set_direction); - ClassDB::bind_method(D_METHOD("get_direction"), &CPUParticles::get_direction); - - ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &CPUParticles::set_spread); - ClassDB::bind_method(D_METHOD("get_spread"), &CPUParticles::get_spread); - - ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &CPUParticles::set_flatness); - ClassDB::bind_method(D_METHOD("get_flatness"), &CPUParticles::get_flatness); - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &CPUParticles::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &CPUParticles::get_param); - - ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &CPUParticles::set_param_randomness); - ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &CPUParticles::get_param_randomness); - - ClassDB::bind_method(D_METHOD("set_param_curve", "param", "curve"), &CPUParticles::set_param_curve); - ClassDB::bind_method(D_METHOD("get_param_curve", "param"), &CPUParticles::get_param_curve); - - ClassDB::bind_method(D_METHOD("set_color", "color"), &CPUParticles::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &CPUParticles::get_color); - - ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &CPUParticles::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &CPUParticles::get_color_ramp); - - ClassDB::bind_method(D_METHOD("set_particle_flag", "flag", "enable"), &CPUParticles::set_particle_flag); - ClassDB::bind_method(D_METHOD("get_particle_flag", "flag"), &CPUParticles::get_particle_flag); - - ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles::set_emission_shape); - ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles::get_emission_shape); - - ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &CPUParticles::set_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &CPUParticles::get_emission_sphere_radius); - - ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &CPUParticles::set_emission_box_extents); - ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &CPUParticles::get_emission_box_extents); - - ClassDB::bind_method(D_METHOD("set_emission_points", "array"), &CPUParticles::set_emission_points); - ClassDB::bind_method(D_METHOD("get_emission_points"), &CPUParticles::get_emission_points); - - ClassDB::bind_method(D_METHOD("set_emission_normals", "array"), &CPUParticles::set_emission_normals); - ClassDB::bind_method(D_METHOD("get_emission_normals"), &CPUParticles::get_emission_normals); - - ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles::set_emission_colors); - ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles::get_emission_colors); - - ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles::get_gravity); - ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles::set_gravity); - - ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles::convert_from_particles); - - ADD_GROUP("Emission Shape", "emission_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals"); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors"); - ADD_GROUP("Flags", "flag_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_particle_flag", "get_particle_flag", FLAG_ROTATE_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_particle_flag", "get_particle_flag", FLAG_DISABLE_Z); - ADD_GROUP("Direction", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); - ADD_GROUP("Gravity", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); - ADD_GROUP("Initial Velocity", "initial_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); - ADD_GROUP("Angular Velocity", "angular_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY); - ADD_GROUP("Orbit Velocity", "orbit_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY); - ADD_GROUP("Linear Accel", "linear_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_LINEAR_ACCEL); - ADD_GROUP("Radial Accel", "radial_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_RADIAL_ACCEL); - ADD_GROUP("Tangential Accel", "tangential_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL); - ADD_GROUP("Damping", ""); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING); - ADD_GROUP("Angle", ""); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE); - ADD_GROUP("Scale", ""); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_amount_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_SCALE); - ADD_GROUP("Color", ""); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); - - ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION); - ADD_GROUP("Animation", "anim_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_OFFSET); - - BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL); - BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL); - BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL); - BIND_ENUM_CONSTANT(PARAM_DAMPING); - BIND_ENUM_CONSTANT(PARAM_ANGLE); - BIND_ENUM_CONSTANT(PARAM_SCALE); - BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION); - BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED); - BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET); - BIND_ENUM_CONSTANT(PARAM_MAX); - - BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); - BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); - BIND_ENUM_CONSTANT(FLAG_DISABLE_Z); - BIND_ENUM_CONSTANT(FLAG_MAX); - - BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); - BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); -} - -CPUParticles::CPUParticles() { - - time = 0; - inactive_time = 0; - frame_remainder = 0; - cycle = 0; - redraw = false; - emitting = false; - - set_notify_transform(true); - - multimesh = VisualServer::get_singleton()->multimesh_create(); - VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0); - set_base(multimesh); - - set_emitting(true); - set_one_shot(false); - set_amount(8); - set_lifetime(1); - set_fixed_fps(0); - set_fractional_delta(true); - set_pre_process_time(0); - set_explosiveness_ratio(0); - set_randomness_ratio(0); - set_lifetime_randomness(0); - set_use_local_coordinates(true); - - set_draw_order(DRAW_ORDER_INDEX); - set_speed_scale(1); - - set_direction(Vector3(1, 0, 0)); - set_spread(45); - set_flatness(0); - set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0); - set_param(PARAM_ANGULAR_VELOCITY, 0); - set_param(PARAM_ORBIT_VELOCITY, 0); - set_param(PARAM_LINEAR_ACCEL, 0); - set_param(PARAM_RADIAL_ACCEL, 0); - set_param(PARAM_TANGENTIAL_ACCEL, 0); - set_param(PARAM_DAMPING, 0); - set_param(PARAM_ANGLE, 0); - set_param(PARAM_SCALE, 1); - set_param(PARAM_HUE_VARIATION, 0); - set_param(PARAM_ANIM_SPEED, 0); - set_param(PARAM_ANIM_OFFSET, 0); - set_emission_shape(EMISSION_SHAPE_POINT); - set_emission_sphere_radius(1); - set_emission_box_extents(Vector3(1, 1, 1)); - - set_gravity(Vector3(0, -9.8, 0)); - - for (int i = 0; i < PARAM_MAX; i++) { - set_param_randomness(Parameter(i), 0); - } - - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; - } - - can_update = false; - - set_color(Color(1, 1, 1, 1)); -} - -CPUParticles::~CPUParticles() { - VS::get_singleton()->free(multimesh); -} diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h deleted file mode 100644 index 231e1f1ad9..0000000000 --- a/scene/3d/cpu_particles.h +++ /dev/null @@ -1,298 +0,0 @@ -/*************************************************************************/ -/* cpu_particles.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CPU_PARTICLES_H -#define CPU_PARTICLES_H - -#include "core/rid.h" -#include "scene/3d/visual_instance.h" - -class CPUParticles : public GeometryInstance { -private: - GDCLASS(CPUParticles, GeometryInstance); - -public: - enum DrawOrder { - DRAW_ORDER_INDEX, - DRAW_ORDER_LIFETIME, - DRAW_ORDER_VIEW_DEPTH, - }; - - enum Parameter { - - PARAM_INITIAL_LINEAR_VELOCITY, - PARAM_ANGULAR_VELOCITY, - PARAM_ORBIT_VELOCITY, - PARAM_LINEAR_ACCEL, - PARAM_RADIAL_ACCEL, - PARAM_TANGENTIAL_ACCEL, - PARAM_DAMPING, - PARAM_ANGLE, - PARAM_SCALE, - PARAM_HUE_VARIATION, - PARAM_ANIM_SPEED, - PARAM_ANIM_OFFSET, - PARAM_MAX - }; - - enum Flags { - FLAG_ALIGN_Y_TO_VELOCITY, - FLAG_ROTATE_Y, - FLAG_DISABLE_Z, - FLAG_MAX - }; - - enum EmissionShape { - EMISSION_SHAPE_POINT, - EMISSION_SHAPE_SPHERE, - EMISSION_SHAPE_BOX, - EMISSION_SHAPE_POINTS, - EMISSION_SHAPE_DIRECTED_POINTS, - EMISSION_SHAPE_MAX - }; - -private: - bool emitting; - - struct Particle { - Transform transform; - Color color; - float custom[4]; - Vector3 velocity; - bool active; - float angle_rand; - float scale_rand; - float hue_rot_rand; - float anim_offset_rand; - float time; - float lifetime; - Color base_color; - - uint32_t seed; - }; - - float time; - float inactive_time; - float frame_remainder; - int cycle; - bool redraw; - - RID multimesh; - - Vector particles; - Vector particle_data; - Vector particle_order; - - struct SortLifetime { - const Particle *particles; - - bool operator()(int p_a, int p_b) const { - return particles[p_a].time > particles[p_b].time; - } - }; - - struct SortAxis { - const Particle *particles; - Vector3 axis; - bool operator()(int p_a, int p_b) const { - - return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin); - } - }; - - // - - bool one_shot; - - float lifetime; - float pre_process_time; - float explosiveness_ratio; - float randomness_ratio; - float lifetime_randomness; - float speed_scale; - bool local_coords; - int fixed_fps; - bool fractional_delta; - - Transform inv_emission_transform; - - volatile bool can_update; - - DrawOrder draw_order; - - Ref mesh; - - //////// - - Vector3 direction; - float spread; - float flatness; - - float parameters[PARAM_MAX]; - float randomness[PARAM_MAX]; - - Ref curve_parameters[PARAM_MAX]; - Color color; - Ref color_ramp; - - bool flags[FLAG_MAX]; - - EmissionShape emission_shape; - float emission_sphere_radius; - Vector3 emission_box_extents; - Vector emission_points; - Vector emission_normals; - Vector emission_colors; - int emission_point_count; - - Vector3 gravity; - - void _update_internal(); - void _particles_process(float p_delta); - void _update_particle_data_buffer(); - - Mutex update_mutex; - - void _update_render_thread(); - - void _set_redraw(bool p_redraw); - -protected: - static void _bind_methods(); - void _notification(int p_what); - virtual void _validate_property(PropertyInfo &property) const; - -public: - AABB get_aabb() const; - Vector get_faces(uint32_t p_usage_flags) const; - - void set_emitting(bool p_emitting); - void set_amount(int p_amount); - void set_lifetime(float p_lifetime); - void set_one_shot(bool p_one_shot); - void set_pre_process_time(float p_time); - void set_explosiveness_ratio(float p_ratio); - void set_randomness_ratio(float p_ratio); - void set_lifetime_randomness(float p_random); - void set_visibility_aabb(const AABB &p_aabb); - void set_use_local_coordinates(bool p_enable); - void set_speed_scale(float p_scale); - - bool is_emitting() const; - int get_amount() const; - float get_lifetime() const; - bool get_one_shot() const; - float get_pre_process_time() const; - float get_explosiveness_ratio() const; - float get_randomness_ratio() const; - float get_lifetime_randomness() const; - AABB get_visibility_aabb() const; - bool get_use_local_coordinates() const; - float get_speed_scale() const; - - void set_fixed_fps(int p_count); - int get_fixed_fps() const; - - void set_fractional_delta(bool p_enable); - bool get_fractional_delta() const; - - void set_draw_order(DrawOrder p_order); - DrawOrder get_draw_order() const; - - void set_draw_passes(int p_count); - int get_draw_passes() const; - - void set_mesh(const Ref &p_mesh); - Ref get_mesh() const; - - /////////////////// - - void set_direction(Vector3 p_direction); - Vector3 get_direction() const; - - void set_spread(float p_spread); - float get_spread() const; - - void set_flatness(float p_flatness); - float get_flatness() const; - - void set_param(Parameter p_param, float p_value); - float get_param(Parameter p_param) const; - - void set_param_randomness(Parameter p_param, float p_value); - float get_param_randomness(Parameter p_param) const; - - void set_param_curve(Parameter p_param, const Ref &p_curve); - Ref get_param_curve(Parameter p_param) const; - - void set_color(const Color &p_color); - Color get_color() const; - - void set_color_ramp(const Ref &p_ramp); - Ref get_color_ramp() const; - - void set_particle_flag(Flags p_flag, bool p_enable); - bool get_particle_flag(Flags p_flag) const; - - void set_emission_shape(EmissionShape p_shape); - void set_emission_sphere_radius(float p_radius); - void set_emission_box_extents(Vector3 p_extents); - void set_emission_points(const Vector &p_points); - void set_emission_normals(const Vector &p_normals); - void set_emission_colors(const Vector &p_colors); - void set_emission_point_count(int p_count); - - EmissionShape get_emission_shape() const; - float get_emission_sphere_radius() const; - Vector3 get_emission_box_extents() const; - Vector get_emission_points() const; - Vector get_emission_normals() const; - Vector get_emission_colors() const; - int get_emission_point_count() const; - - void set_gravity(const Vector3 &p_gravity); - Vector3 get_gravity() const; - - virtual String get_configuration_warning() const; - - void restart(); - - void convert_from_particles(Node *p_particles); - - CPUParticles(); - ~CPUParticles(); -}; - -VARIANT_ENUM_CAST(CPUParticles::DrawOrder) -VARIANT_ENUM_CAST(CPUParticles::Parameter) -VARIANT_ENUM_CAST(CPUParticles::Flags) -VARIANT_ENUM_CAST(CPUParticles::EmissionShape) - -#endif // CPU_PARTICLES_H diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp new file mode 100644 index 0000000000..71e869e6e9 --- /dev/null +++ b/scene/3d/cpu_particles_3d.cpp @@ -0,0 +1,1546 @@ +/*************************************************************************/ +/* cpu_particles_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "cpu_particles_3d.h" + +#include "scene/3d/camera_3d.h" +#include "scene/3d/gpu_particles_3d.h" +#include "scene/resources/particles_material.h" +#include "servers/visual_server.h" + +AABB CPUParticles3D::get_aabb() const { + + return AABB(); +} +Vector CPUParticles3D::get_faces(uint32_t p_usage_flags) const { + + return Vector(); +} + +void CPUParticles3D::set_emitting(bool p_emitting) { + + if (emitting == p_emitting) + return; + + emitting = p_emitting; + if (emitting) { + set_process_internal(true); + + // first update before rendering to avoid one frame delay after emitting starts + if (time == 0) + _update_internal(); + } +} + +void CPUParticles3D::set_amount(int p_amount) { + + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles must be greater than 0."); + + particles.resize(p_amount); + { + Particle *w = particles.ptrw(); + + for (int i = 0; i < p_amount; i++) { + w[i].active = false; + } + } + + particle_data.resize((12 + 4 + 4) * p_amount); + VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true); + + particle_order.resize(p_amount); +} +void CPUParticles3D::set_lifetime(float p_lifetime) { + + ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); + lifetime = p_lifetime; +} + +void CPUParticles3D::set_one_shot(bool p_one_shot) { + + one_shot = p_one_shot; +} + +void CPUParticles3D::set_pre_process_time(float p_time) { + + pre_process_time = p_time; +} +void CPUParticles3D::set_explosiveness_ratio(float p_ratio) { + + explosiveness_ratio = p_ratio; +} +void CPUParticles3D::set_randomness_ratio(float p_ratio) { + + randomness_ratio = p_ratio; +} +void CPUParticles3D::set_lifetime_randomness(float p_random) { + + lifetime_randomness = p_random; +} +void CPUParticles3D::set_use_local_coordinates(bool p_enable) { + + local_coords = p_enable; +} +void CPUParticles3D::set_speed_scale(float p_scale) { + + speed_scale = p_scale; +} + +bool CPUParticles3D::is_emitting() const { + + return emitting; +} +int CPUParticles3D::get_amount() const { + + return particles.size(); +} +float CPUParticles3D::get_lifetime() const { + + return lifetime; +} +bool CPUParticles3D::get_one_shot() const { + + return one_shot; +} + +float CPUParticles3D::get_pre_process_time() const { + + return pre_process_time; +} +float CPUParticles3D::get_explosiveness_ratio() const { + + return explosiveness_ratio; +} +float CPUParticles3D::get_randomness_ratio() const { + + return randomness_ratio; +} +float CPUParticles3D::get_lifetime_randomness() const { + + return lifetime_randomness; +} + +bool CPUParticles3D::get_use_local_coordinates() const { + + return local_coords; +} + +float CPUParticles3D::get_speed_scale() const { + + return speed_scale; +} + +void CPUParticles3D::set_draw_order(DrawOrder p_order) { + + draw_order = p_order; +} + +CPUParticles3D::DrawOrder CPUParticles3D::get_draw_order() const { + + return draw_order; +} + +void CPUParticles3D::set_mesh(const Ref &p_mesh) { + + mesh = p_mesh; + if (mesh.is_valid()) { + VS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); + } else { + VS::get_singleton()->multimesh_set_mesh(multimesh, RID()); + } +} + +Ref CPUParticles3D::get_mesh() const { + + return mesh; +} + +void CPUParticles3D::set_fixed_fps(int p_count) { + fixed_fps = p_count; +} + +int CPUParticles3D::get_fixed_fps() const { + return fixed_fps; +} + +void CPUParticles3D::set_fractional_delta(bool p_enable) { + fractional_delta = p_enable; +} + +bool CPUParticles3D::get_fractional_delta() const { + return fractional_delta; +} + +String CPUParticles3D::get_configuration_warning() const { + + String warnings; + + bool mesh_found = false; + bool anim_material_found = false; + + if (get_mesh().is_valid()) { + mesh_found = true; + for (int j = 0; j < get_mesh()->get_surface_count(); j++) { + anim_material_found = Object::cast_to(get_mesh()->surface_get_material(j).ptr()) != NULL; + StandardMaterial3D *spat = Object::cast_to(get_mesh()->surface_get_material(j).ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); + } + } + + anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; + StandardMaterial3D *spat = Object::cast_to(get_material_override().ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); + + if (!mesh_found) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Nothing is visible because no mesh has been assigned."); + } + + if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || + get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("CPUParticles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); + } + + return warnings; +} + +void CPUParticles3D::restart() { + + time = 0; + inactive_time = 0; + frame_remainder = 0; + cycle = 0; + emitting = false; + + { + int pc = particles.size(); + Particle *w = particles.ptrw(); + + for (int i = 0; i < pc; i++) { + w[i].active = false; + } + } + + set_emitting(true); +} + +void CPUParticles3D::set_direction(Vector3 p_direction) { + + direction = p_direction; +} + +Vector3 CPUParticles3D::get_direction() const { + + return direction; +} + +void CPUParticles3D::set_spread(float p_spread) { + + spread = p_spread; +} + +float CPUParticles3D::get_spread() const { + + return spread; +} + +void CPUParticles3D::set_flatness(float p_flatness) { + + flatness = p_flatness; +} +float CPUParticles3D::get_flatness() const { + + return flatness; +} + +void CPUParticles3D::set_param(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + parameters[p_param] = p_value; +} +float CPUParticles3D::get_param(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + + return parameters[p_param]; +} + +void CPUParticles3D::set_param_randomness(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + randomness[p_param] = p_value; +} +float CPUParticles3D::get_param_randomness(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + + return randomness[p_param]; +} + +static void _adjust_curve_range(const Ref &p_curve, float p_min, float p_max) { + + Ref curve = p_curve; + if (!curve.is_valid()) + return; + + curve->ensure_default_setup(p_min, p_max); +} + +void CPUParticles3D::set_param_curve(Parameter p_param, const Ref &p_curve) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + curve_parameters[p_param] = p_curve; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + //do none for this one + } break; + case PARAM_ANGULAR_VELOCITY: { + _adjust_curve_range(p_curve, -360, 360); + } break; + case PARAM_ORBIT_VELOCITY: { + _adjust_curve_range(p_curve, -500, 500); + } break; + case PARAM_LINEAR_ACCEL: { + _adjust_curve_range(p_curve, -200, 200); + } break; + case PARAM_RADIAL_ACCEL: { + _adjust_curve_range(p_curve, -200, 200); + } break; + case PARAM_TANGENTIAL_ACCEL: { + _adjust_curve_range(p_curve, -200, 200); + } break; + case PARAM_DAMPING: { + _adjust_curve_range(p_curve, 0, 100); + } break; + case PARAM_ANGLE: { + _adjust_curve_range(p_curve, -360, 360); + } break; + case PARAM_SCALE: { + + } break; + case PARAM_HUE_VARIATION: { + _adjust_curve_range(p_curve, -1, 1); + } break; + case PARAM_ANIM_SPEED: { + _adjust_curve_range(p_curve, 0, 200); + } break; + case PARAM_ANIM_OFFSET: { + } break; + default: { + } + } +} +Ref CPUParticles3D::get_param_curve(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref()); + + return curve_parameters[p_param]; +} + +void CPUParticles3D::set_color(const Color &p_color) { + + color = p_color; +} + +Color CPUParticles3D::get_color() const { + + return color; +} + +void CPUParticles3D::set_color_ramp(const Ref &p_ramp) { + + color_ramp = p_ramp; +} + +Ref CPUParticles3D::get_color_ramp() const { + + return color_ramp; +} + +void CPUParticles3D::set_particle_flag(Flags p_flag, bool p_enable) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags[p_flag] = p_enable; + if (p_flag == FLAG_DISABLE_Z) { + _change_notify(); + } +} + +bool CPUParticles3D::get_particle_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +void CPUParticles3D::set_emission_shape(EmissionShape p_shape) { + ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); + emission_shape = p_shape; +} + +void CPUParticles3D::set_emission_sphere_radius(float p_radius) { + + emission_sphere_radius = p_radius; +} + +void CPUParticles3D::set_emission_box_extents(Vector3 p_extents) { + + emission_box_extents = p_extents; +} + +void CPUParticles3D::set_emission_points(const Vector &p_points) { + + emission_points = p_points; +} + +void CPUParticles3D::set_emission_normals(const Vector &p_normals) { + + emission_normals = p_normals; +} + +void CPUParticles3D::set_emission_colors(const Vector &p_colors) { + + emission_colors = p_colors; +} + +float CPUParticles3D::get_emission_sphere_radius() const { + + return emission_sphere_radius; +} +Vector3 CPUParticles3D::get_emission_box_extents() const { + + return emission_box_extents; +} +Vector CPUParticles3D::get_emission_points() const { + + return emission_points; +} +Vector CPUParticles3D::get_emission_normals() const { + + return emission_normals; +} + +Vector CPUParticles3D::get_emission_colors() const { + + return emission_colors; +} + +CPUParticles3D::EmissionShape CPUParticles3D::get_emission_shape() const { + return emission_shape; +} +void CPUParticles3D::set_gravity(const Vector3 &p_gravity) { + + gravity = p_gravity; +} + +Vector3 CPUParticles3D::get_gravity() const { + + return gravity; +} + +void CPUParticles3D::_validate_property(PropertyInfo &property) const { + + if (property.name == "color" && color_ramp.is_valid()) { + property.usage = 0; + } + + if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { + property.usage = 0; + } + + if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { + property.usage = 0; + } + + if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) { + property.usage = 0; + } + + if (property.name == "emission_normals" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { + property.usage = 0; + } + + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { + property.usage = 0; + } +} + +static uint32_t idhash(uint32_t x) { + + x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b); + x = ((x >> uint32_t(16)) ^ x) * uint32_t(0x45d9f3b); + x = (x >> uint32_t(16)) ^ x; + return x; +} + +static float rand_from_seed(uint32_t &seed) { + int k; + int s = int(seed); + if (s == 0) + s = 305420679; + k = s / 127773; + s = 16807 * (s - k * 127773) - 2836 * k; + if (s < 0) + s += 2147483647; + seed = uint32_t(s); + return float(seed % uint32_t(65536)) / 65535.0; +} + +void CPUParticles3D::_update_internal() { + + if (particles.size() == 0 || !is_visible_in_tree()) { + _set_redraw(false); + return; + } + + float delta = get_process_delta_time(); + if (emitting) { + inactive_time = 0; + } else { + inactive_time += delta; + if (inactive_time > lifetime * 1.2) { + set_process_internal(false); + _set_redraw(false); + + //reset variables + time = 0; + inactive_time = 0; + frame_remainder = 0; + cycle = 0; + return; + } + } + _set_redraw(true); + + bool processed = false; + + if (time == 0 && pre_process_time > 0.0) { + + float frame_time; + if (fixed_fps > 0) + frame_time = 1.0 / fixed_fps; + else + frame_time = 1.0 / 30.0; + + float todo = pre_process_time; + + while (todo >= 0) { + _particles_process(frame_time); + processed = true; + todo -= frame_time; + } + } + + if (fixed_fps > 0) { + float frame_time = 1.0 / fixed_fps; + float decr = frame_time; + + float ldelta = delta; + if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10 + ldelta = 0.1; + } else if (ldelta <= 0.0) { //unlikely but.. + ldelta = 0.001; + } + float todo = frame_remainder + ldelta; + + while (todo >= frame_time) { + _particles_process(frame_time); + processed = true; + todo -= decr; + } + + frame_remainder = todo; + + } else { + _particles_process(delta); + processed = true; + } + + if (processed) { + _update_particle_data_buffer(); + } +} + +void CPUParticles3D::_particles_process(float p_delta) { + + p_delta *= speed_scale; + + int pcount = particles.size(); + Particle *w = particles.ptrw(); + + Particle *parray = w; + + float prev_time = time; + time += p_delta; + if (time > lifetime) { + time = Math::fmod(time, lifetime); + cycle++; + if (one_shot && cycle > 0) { + set_emitting(false); + _change_notify(); + } + } + + Transform emission_xform; + Basis velocity_xform; + if (!local_coords) { + emission_xform = get_global_transform(); + velocity_xform = emission_xform.basis; + } + + float system_phase = time / lifetime; + + for (int i = 0; i < pcount; i++) { + + Particle &p = parray[i]; + + if (!emitting && !p.active) + continue; + + float local_delta = p_delta; + + // The phase is a ratio between 0 (birth) and 1 (end of life) for each particle. + // While we use time in tests later on, for randomness we use the phase as done in the + // original shader code, and we later multiply by lifetime to get the time. + float restart_phase = float(i) / float(pcount); + + if (randomness_ratio > 0.0) { + uint32_t seed = cycle; + if (restart_phase >= system_phase) { + seed -= uint32_t(1); + } + seed *= uint32_t(pcount); + seed += uint32_t(i); + float random = float(idhash(seed) % uint32_t(65536)) / 65536.0; + restart_phase += randomness_ratio * random * 1.0 / float(pcount); + } + + restart_phase *= (1.0 - explosiveness_ratio); + float restart_time = restart_phase * lifetime; + bool restart = false; + + if (time > prev_time) { + // restart_time >= prev_time is used so particles emit in the first frame they are processed + + if (restart_time >= prev_time && restart_time < time) { + restart = true; + if (fractional_delta) { + local_delta = time - restart_time; + } + } + + } else if (local_delta > 0.0) { + if (restart_time >= prev_time) { + restart = true; + if (fractional_delta) { + local_delta = lifetime - restart_time + time; + } + + } else if (restart_time < time) { + restart = true; + if (fractional_delta) { + local_delta = time - restart_time; + } + } + } + + if (p.time * (1.0 - explosiveness_ratio) > p.lifetime) { + restart = true; + } + + if (restart) { + + if (!emitting) { + p.active = false; + continue; + } + p.active = true; + + /*float tex_linear_velocity = 0; + if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0); + }*/ + + float tex_angle = 0.0; + if (curve_parameters[PARAM_ANGLE].is_valid()) { + tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(0); + } + + float tex_anim_offset = 0.0; + if (curve_parameters[PARAM_ANGLE].is_valid()) { + tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(0); + } + + p.seed = Math::rand(); + + p.angle_rand = Math::randf(); + p.scale_rand = Math::randf(); + p.hue_rot_rand = Math::randf(); + p.anim_offset_rand = Math::randf(); + + if (flags[FLAG_DISABLE_Z]) { + float angle1_rad = Math::atan2(direction.y, direction.x) + (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0; + Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0); + p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); + } else { + //initiate velocity spread in 3D + float angle1_rad = Math::atan2(direction.x, direction.z) + (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0; + float angle2_rad = Math::atan2(direction.y, Math::abs(direction.z)) + (Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * Math_PI * spread / 180.0; + + Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); + Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); + direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution + Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z); + direction.normalize(); + p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); + } + + float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); + p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[1] = 0.0; //phase + p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1) + p.transform = Transform(); + p.time = 0; + p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness); + p.base_color = Color(1, 1, 1, 1); + + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + float s = 2.0 * Math::randf() - 1.0, t = 2.0 * Math_PI * Math::randf(); + float radius = emission_sphere_radius * Math::sqrt(1.0 - s * s); + p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s); + } break; + case EMISSION_SHAPE_BOX: { + p.transform.origin = Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * emission_box_extents; + } break; + case EMISSION_SHAPE_POINTS: + case EMISSION_SHAPE_DIRECTED_POINTS: { + + int pc = emission_points.size(); + if (pc == 0) + break; + + int random_idx = Math::rand() % pc; + + p.transform.origin = emission_points.get(random_idx); + + if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) { + if (flags[FLAG_DISABLE_Z]) { + /* + mat2 rotm; + "; + rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy; + rotm[1] = rotm[0].yx * vec2(1.0, -1.0); + VELOCITY.xy = rotm * VELOCITY.xy; + */ + } else { + Vector3 normal = emission_normals.get(random_idx); + Vector3 v0 = Math::abs(normal.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(0, 1.0, 0.0); + Vector3 tangent = v0.cross(normal).normalized(); + Vector3 bitangent = tangent.cross(normal).normalized(); + Basis m3; + m3.set_axis(0, tangent); + m3.set_axis(1, bitangent); + m3.set_axis(2, normal); + p.velocity = m3.xform(p.velocity); + } + } + + if (emission_colors.size() == pc) { + p.base_color = emission_colors.get(random_idx); + } + } break; + case EMISSION_SHAPE_MAX: { // Max value for validity check. + break; + } + } + + if (!local_coords) { + p.velocity = velocity_xform.xform(p.velocity); + p.transform = emission_xform * p.transform; + } + + if (flags[FLAG_DISABLE_Z]) { + p.velocity.z = 0.0; + p.transform.origin.z = 0.0; + } + + } else if (!p.active) { + continue; + } else if (p.time > p.lifetime) { + p.active = false; + } else { + + uint32_t alt_seed = p.seed; + + p.time += local_delta; + p.custom[1] = p.time / lifetime; + + float tex_linear_velocity = 0.0; + if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(p.custom[1]); + } + + float tex_orbit_velocity = 0.0; + if (flags[FLAG_DISABLE_Z]) { + if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { + tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(p.custom[1]); + } + } + + float tex_angular_velocity = 0.0; + if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { + tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(p.custom[1]); + } + + float tex_linear_accel = 0.0; + if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) { + tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(p.custom[1]); + } + + float tex_tangential_accel = 0.0; + if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { + tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(p.custom[1]); + } + + float tex_radial_accel = 0.0; + if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) { + tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(p.custom[1]); + } + + float tex_damping = 0.0; + if (curve_parameters[PARAM_DAMPING].is_valid()) { + tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(p.custom[1]); + } + + float tex_angle = 0.0; + if (curve_parameters[PARAM_ANGLE].is_valid()) { + tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(p.custom[1]); + } + float tex_anim_speed = 0.0; + if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) { + tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(p.custom[1]); + } + + float tex_anim_offset = 0.0; + if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) { + tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(p.custom[1]); + } + + Vector3 force = gravity; + Vector3 position = p.transform.origin; + if (flags[FLAG_DISABLE_Z]) { + position.z = 0.0; + } + //apply linear acceleration + force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector3(); + //apply radial acceleration + Vector3 org = emission_xform.origin; + Vector3 diff = position - org; + force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3(); + //apply tangential acceleration; + if (flags[FLAG_DISABLE_Z]) { + + Vector2 yx = Vector2(diff.y, diff.x); + Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized(); + force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3(); + + } else { + Vector3 crossDiff = diff.normalized().cross(gravity.normalized()); + force += crossDiff.length() > 0.0 ? crossDiff.normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3(); + } + //apply attractor forces + p.velocity += force * local_delta; + //orbit velocity + if (flags[FLAG_DISABLE_Z]) { + float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]); + if (orbit_amount != 0.0) { + float ang = orbit_amount * local_delta * Math_PI * 2.0; + // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, + // but we use -ang here to reproduce its behavior. + Transform2D rot = Transform2D(-ang, Vector2()); + Vector2 rotv = rot.basis_xform(Vector2(diff.x, diff.y)); + p.transform.origin -= Vector3(diff.x, diff.y, 0); + p.transform.origin += Vector3(rotv.x, rotv.y, 0); + } + } + if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + p.velocity = p.velocity.normalized() * tex_linear_velocity; + } + if (parameters[PARAM_DAMPING] + tex_damping > 0.0) { + + float v = p.velocity.length(); + float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]); + v -= damp * local_delta; + if (v < 0.0) { + p.velocity = Vector3(); + } else { + p.velocity = p.velocity.normalized() * v; + } + } + float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]); + base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]); + p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); //angle + } + //apply color + //apply hue rotation + + float tex_scale = 1.0; + if (curve_parameters[PARAM_SCALE].is_valid()) { + tex_scale = curve_parameters[PARAM_SCALE]->interpolate(p.custom[1]); + } + + float tex_hue_variation = 0.0; + if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) { + tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(p.custom[1]); + } + + float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_PI * 2.0 * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]); + float hue_rot_c = Math::cos(hue_rot_angle); + float hue_rot_s = Math::sin(hue_rot_angle); + + Basis hue_rot_mat; + { + Basis mat1(0.299, 0.587, 0.114, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114); + Basis mat2(0.701, -0.587, -0.114, -0.299, 0.413, -0.114, -0.300, -0.588, 0.886); + Basis mat3(0.168, 0.330, -0.497, -0.328, 0.035, 0.292, 1.250, -1.050, -0.203); + + for (int j = 0; j < 3; j++) { + hue_rot_mat[j] = mat1[j] + mat2[j] * hue_rot_c + mat3[j] * hue_rot_s; + } + } + + if (color_ramp.is_valid()) { + p.color = color_ramp->get_color_at_offset(p.custom[1]) * color; + } else { + p.color = color; + } + + Vector3 color_rgb = hue_rot_mat.xform_inv(Vector3(p.color.r, p.color.g, p.color.b)); + p.color.r = color_rgb.x; + p.color.g = color_rgb.y; + p.color.b = color_rgb.z; + + p.color *= p.base_color; + + if (flags[FLAG_DISABLE_Z]) { + + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + if (p.velocity.length() > 0.0) { + p.transform.basis.set_axis(1, p.velocity.normalized()); + } else { + p.transform.basis.set_axis(1, p.transform.basis.get_axis(1)); + } + p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); + p.transform.basis.set_axis(2, Vector3(0, 0, 1)); + + } else { + p.transform.basis.set_axis(0, Vector3(Math::cos(p.custom[0]), -Math::sin(p.custom[0]), 0.0)); + p.transform.basis.set_axis(1, Vector3(Math::sin(p.custom[0]), Math::cos(p.custom[0]), 0.0)); + p.transform.basis.set_axis(2, Vector3(0, 0, 1)); + } + + } else { + //orient particle Y towards velocity + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + if (p.velocity.length() > 0.0) { + p.transform.basis.set_axis(1, p.velocity.normalized()); + } else { + p.transform.basis.set_axis(1, p.transform.basis.get_axis(1).normalized()); + } + if (p.transform.basis.get_axis(1) == p.transform.basis.get_axis(0)) { + p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); + p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized()); + } else { + p.transform.basis.set_axis(2, p.transform.basis.get_axis(0).cross(p.transform.basis.get_axis(1)).normalized()); + p.transform.basis.set_axis(0, p.transform.basis.get_axis(1).cross(p.transform.basis.get_axis(2)).normalized()); + } + } else { + p.transform.basis.orthonormalize(); + } + + //turn particle by rotation in Y + if (flags[FLAG_ROTATE_Y]) { + Basis rot_y(Vector3(0, 1, 0), p.custom[0]); + p.transform.basis = p.transform.basis * rot_y; + } + } + + //scale by scale + float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]); + if (base_scale < 0.000001) base_scale = 0.000001; + + p.transform.basis.scale(Vector3(1, 1, 1) * base_scale); + + if (flags[FLAG_DISABLE_Z]) { + p.velocity.z = 0.0; + p.transform.origin.z = 0.0; + } + + p.transform.origin += p.velocity * local_delta; + } +} + +void CPUParticles3D::_update_particle_data_buffer() { + MutexLock lock(update_mutex); + + int pc = particles.size(); + + int *ow; + int *order = NULL; + + float *w = particle_data.ptrw(); + const Particle *r = particles.ptr(); + float *ptr = w; + + if (draw_order != DRAW_ORDER_INDEX) { + ow = particle_order.ptrw(); + order = ow; + + for (int i = 0; i < pc; i++) { + order[i] = i; + } + if (draw_order == DRAW_ORDER_LIFETIME) { + SortArray sorter; + sorter.compare.particles = r; + sorter.sort(order, pc); + } else if (draw_order == DRAW_ORDER_VIEW_DEPTH) { + Camera3D *c = get_viewport()->get_camera(); + if (c) { + Vector3 dir = c->get_global_transform().basis.get_axis(2); //far away to close + + if (local_coords) { + + // will look different from Particles in editor as this is based on the camera in the scenetree + // and not the editor camera + dir = inv_emission_transform.xform(dir).normalized(); + } else { + dir = dir.normalized(); + } + + SortArray sorter; + sorter.compare.particles = r; + sorter.compare.axis = dir; + sorter.sort(order, pc); + } + } + } + + for (int i = 0; i < pc; i++) { + + int idx = order ? order[i] : i; + + Transform t = r[idx].transform; + + if (!local_coords) { + t = inv_emission_transform * t; + } + + if (r[idx].active) { + ptr[0] = t.basis.elements[0][0]; + ptr[1] = t.basis.elements[0][1]; + ptr[2] = t.basis.elements[0][2]; + ptr[3] = t.origin.x; + ptr[4] = t.basis.elements[1][0]; + ptr[5] = t.basis.elements[1][1]; + ptr[6] = t.basis.elements[1][2]; + ptr[7] = t.origin.y; + ptr[8] = t.basis.elements[2][0]; + ptr[9] = t.basis.elements[2][1]; + ptr[10] = t.basis.elements[2][2]; + ptr[11] = t.origin.z; + } else { + zeromem(ptr, sizeof(float) * 12); + } + + Color c = r[idx].color; + + ptr[12] = c.r; + ptr[13] = c.g; + ptr[14] = c.b; + ptr[15] = c.a; + + ptr[16] = r[idx].custom[0]; + ptr[17] = r[idx].custom[1]; + ptr[18] = r[idx].custom[2]; + ptr[19] = r[idx].custom[3]; + + ptr += 20; + } + + can_update = true; +} + +void CPUParticles3D::_set_redraw(bool p_redraw) { + if (redraw == p_redraw) + return; + redraw = p_redraw; + + { + MutexLock lock(update_mutex); + + if (redraw) { + VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true); + VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); + } else { + if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread))) { + VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); + } + VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false); + VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); + } + } +} + +void CPUParticles3D::_update_render_thread() { + + MutexLock lock(update_mutex); + + if (can_update) { + VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); + can_update = false; //wait for next time + } +} + +void CPUParticles3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + set_process_internal(emitting); + + // first update before rendering to avoid one frame delay after emitting starts + if (emitting && (time == 0)) + _update_internal(); + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + _set_redraw(false); + } + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + // first update before rendering to avoid one frame delay after emitting starts + if (emitting && (time == 0)) + _update_internal(); + } + + if (p_what == NOTIFICATION_INTERNAL_PROCESS) { + _update_internal(); + } + + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + + inv_emission_transform = get_global_transform().affine_inverse(); + + if (!local_coords) { + + int pc = particles.size(); + + float *w = particle_data.ptrw(); + const Particle *r = particles.ptr(); + float *ptr = w; + + for (int i = 0; i < pc; i++) { + + Transform t = inv_emission_transform * r[i].transform; + + if (r[i].active) { + ptr[0] = t.basis.elements[0][0]; + ptr[1] = t.basis.elements[0][1]; + ptr[2] = t.basis.elements[0][2]; + ptr[3] = t.origin.x; + ptr[4] = t.basis.elements[1][0]; + ptr[5] = t.basis.elements[1][1]; + ptr[6] = t.basis.elements[1][2]; + ptr[7] = t.origin.y; + ptr[8] = t.basis.elements[2][0]; + ptr[9] = t.basis.elements[2][1]; + ptr[10] = t.basis.elements[2][2]; + ptr[11] = t.origin.z; + } else { + zeromem(ptr, sizeof(float) * 12); + } + + ptr += 20; + } + + can_update = true; + } + } +} + +void CPUParticles3D::convert_from_particles(Node *p_particles) { + + GPUParticles3D *particles = Object::cast_to(p_particles); + ERR_FAIL_COND_MSG(!particles, "Only Particles nodes can be converted to CPUParticles."); + + set_emitting(particles->is_emitting()); + set_amount(particles->get_amount()); + set_lifetime(particles->get_lifetime()); + set_one_shot(particles->get_one_shot()); + set_pre_process_time(particles->get_pre_process_time()); + set_explosiveness_ratio(particles->get_explosiveness_ratio()); + set_randomness_ratio(particles->get_randomness_ratio()); + set_use_local_coordinates(particles->get_use_local_coordinates()); + set_fixed_fps(particles->get_fixed_fps()); + set_fractional_delta(particles->get_fractional_delta()); + set_speed_scale(particles->get_speed_scale()); + set_draw_order(DrawOrder(particles->get_draw_order())); + set_mesh(particles->get_draw_pass_mesh(0)); + + Ref material = particles->get_process_material(); + if (material.is_null()) + return; + + set_direction(material->get_direction()); + set_spread(material->get_spread()); + set_flatness(material->get_flatness()); + + set_color(material->get_color()); + + Ref gt = material->get_color_ramp(); + if (gt.is_valid()) { + set_color_ramp(gt->get_gradient()); + } + + set_particle_flag(FLAG_ALIGN_Y_TO_VELOCITY, material->get_flag(ParticlesMaterial::FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(FLAG_ROTATE_Y, material->get_flag(ParticlesMaterial::FLAG_ROTATE_Y)); + set_particle_flag(FLAG_DISABLE_Z, material->get_flag(ParticlesMaterial::FLAG_DISABLE_Z)); + + set_emission_shape(EmissionShape(material->get_emission_shape())); + set_emission_sphere_radius(material->get_emission_sphere_radius()); + set_emission_box_extents(material->get_emission_box_extents()); + + set_gravity(material->get_gravity()); + set_lifetime_randomness(material->get_lifetime_randomness()); + +#define CONVERT_PARAM(m_param) \ + set_param(m_param, material->get_param(ParticlesMaterial::m_param)); \ + { \ + Ref ctex = material->get_param_texture(ParticlesMaterial::m_param); \ + if (ctex.is_valid()) set_param_curve(m_param, ctex->get_curve()); \ + } \ + set_param_randomness(m_param, material->get_param_randomness(ParticlesMaterial::m_param)); + + CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); + CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); + CONVERT_PARAM(PARAM_ORBIT_VELOCITY); + CONVERT_PARAM(PARAM_LINEAR_ACCEL); + CONVERT_PARAM(PARAM_RADIAL_ACCEL); + CONVERT_PARAM(PARAM_TANGENTIAL_ACCEL); + CONVERT_PARAM(PARAM_DAMPING); + CONVERT_PARAM(PARAM_ANGLE); + CONVERT_PARAM(PARAM_SCALE); + CONVERT_PARAM(PARAM_HUE_VARIATION); + CONVERT_PARAM(PARAM_ANIM_SPEED); + CONVERT_PARAM(PARAM_ANIM_OFFSET); + +#undef CONVERT_PARAM +} + +void CPUParticles3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &CPUParticles3D::set_emitting); + ClassDB::bind_method(D_METHOD("set_amount", "amount"), &CPUParticles3D::set_amount); + ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &CPUParticles3D::set_lifetime); + ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &CPUParticles3D::set_one_shot); + ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles3D::set_pre_process_time); + ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &CPUParticles3D::set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &CPUParticles3D::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "random"), &CPUParticles3D::set_lifetime_randomness); + ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &CPUParticles3D::set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles3D::set_fixed_fps); + ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles3D::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &CPUParticles3D::set_speed_scale); + + ClassDB::bind_method(D_METHOD("is_emitting"), &CPUParticles3D::is_emitting); + ClassDB::bind_method(D_METHOD("get_amount"), &CPUParticles3D::get_amount); + ClassDB::bind_method(D_METHOD("get_lifetime"), &CPUParticles3D::get_lifetime); + ClassDB::bind_method(D_METHOD("get_one_shot"), &CPUParticles3D::get_one_shot); + ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles3D::get_pre_process_time); + ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &CPUParticles3D::get_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &CPUParticles3D::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &CPUParticles3D::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &CPUParticles3D::get_use_local_coordinates); + ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles3D::get_fixed_fps); + ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles3D::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &CPUParticles3D::get_speed_scale); + + ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &CPUParticles3D::set_draw_order); + + ClassDB::bind_method(D_METHOD("get_draw_order"), &CPUParticles3D::get_draw_order); + + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CPUParticles3D::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &CPUParticles3D::get_mesh); + + ClassDB::bind_method(D_METHOD("restart"), &CPUParticles3D::restart); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); + ADD_GROUP("Time", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_GROUP("Drawing", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + + BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); + BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); + BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + + //////////////////////////////// + + ClassDB::bind_method(D_METHOD("set_direction", "direction"), &CPUParticles3D::set_direction); + ClassDB::bind_method(D_METHOD("get_direction"), &CPUParticles3D::get_direction); + + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &CPUParticles3D::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &CPUParticles3D::get_spread); + + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &CPUParticles3D::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &CPUParticles3D::get_flatness); + + ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &CPUParticles3D::set_param); + ClassDB::bind_method(D_METHOD("get_param", "param"), &CPUParticles3D::get_param); + + ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &CPUParticles3D::set_param_randomness); + ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &CPUParticles3D::get_param_randomness); + + ClassDB::bind_method(D_METHOD("set_param_curve", "param", "curve"), &CPUParticles3D::set_param_curve); + ClassDB::bind_method(D_METHOD("get_param_curve", "param"), &CPUParticles3D::get_param_curve); + + ClassDB::bind_method(D_METHOD("set_color", "color"), &CPUParticles3D::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &CPUParticles3D::get_color); + + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &CPUParticles3D::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &CPUParticles3D::get_color_ramp); + + ClassDB::bind_method(D_METHOD("set_particle_flag", "flag", "enable"), &CPUParticles3D::set_particle_flag); + ClassDB::bind_method(D_METHOD("get_particle_flag", "flag"), &CPUParticles3D::get_particle_flag); + + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles3D::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles3D::get_emission_shape); + + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &CPUParticles3D::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &CPUParticles3D::get_emission_sphere_radius); + + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &CPUParticles3D::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &CPUParticles3D::get_emission_box_extents); + + ClassDB::bind_method(D_METHOD("set_emission_points", "array"), &CPUParticles3D::set_emission_points); + ClassDB::bind_method(D_METHOD("get_emission_points"), &CPUParticles3D::get_emission_points); + + ClassDB::bind_method(D_METHOD("set_emission_normals", "array"), &CPUParticles3D::set_emission_normals); + ClassDB::bind_method(D_METHOD("get_emission_normals"), &CPUParticles3D::get_emission_normals); + + ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles3D::set_emission_colors); + ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles3D::get_emission_colors); + + ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles3D::get_gravity); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles3D::set_gravity); + + ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles); + + ADD_GROUP("Emission Shape", "emission_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors"); + ADD_GROUP("Flags", "flag_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_particle_flag", "get_particle_flag", FLAG_ROTATE_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_particle_flag", "get_particle_flag", FLAG_DISABLE_Z); + ADD_GROUP("Direction", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); + ADD_GROUP("Gravity", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); + ADD_GROUP("Initial Velocity", "initial_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_GROUP("Angular Velocity", "angular_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGULAR_VELOCITY); + ADD_GROUP("Orbit Velocity", "orbit_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ORBIT_VELOCITY); + ADD_GROUP("Linear Accel", "linear_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_LINEAR_ACCEL); + ADD_GROUP("Radial Accel", "radial_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_RADIAL_ACCEL); + ADD_GROUP("Tangential Accel", "tangential_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL); + ADD_GROUP("Damping", ""); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING); + ADD_GROUP("Angle", ""); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANGLE); + ADD_GROUP("Scale", ""); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_amount_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_amount_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_SCALE); + ADD_GROUP("Color", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp"); + + ADD_GROUP("Hue Variation", "hue_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION); + ADD_GROUP("Animation", "anim_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_ANIM_OFFSET); + + BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_LINEAR_ACCEL); + BIND_ENUM_CONSTANT(PARAM_RADIAL_ACCEL); + BIND_ENUM_CONSTANT(PARAM_TANGENTIAL_ACCEL); + BIND_ENUM_CONSTANT(PARAM_DAMPING); + BIND_ENUM_CONSTANT(PARAM_ANGLE); + BIND_ENUM_CONSTANT(PARAM_SCALE); + BIND_ENUM_CONSTANT(PARAM_HUE_VARIATION); + BIND_ENUM_CONSTANT(PARAM_ANIM_SPEED); + BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET); + BIND_ENUM_CONSTANT(PARAM_MAX); + + BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); + BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); + BIND_ENUM_CONSTANT(FLAG_DISABLE_Z); + BIND_ENUM_CONSTANT(FLAG_MAX); + + BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); + BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); +} + +CPUParticles3D::CPUParticles3D() { + + time = 0; + inactive_time = 0; + frame_remainder = 0; + cycle = 0; + redraw = false; + emitting = false; + + set_notify_transform(true); + + multimesh = VisualServer::get_singleton()->multimesh_create(); + VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0); + set_base(multimesh); + + set_emitting(true); + set_one_shot(false); + set_amount(8); + set_lifetime(1); + set_fixed_fps(0); + set_fractional_delta(true); + set_pre_process_time(0); + set_explosiveness_ratio(0); + set_randomness_ratio(0); + set_lifetime_randomness(0); + set_use_local_coordinates(true); + + set_draw_order(DRAW_ORDER_INDEX); + set_speed_scale(1); + + set_direction(Vector3(1, 0, 0)); + set_spread(45); + set_flatness(0); + set_param(PARAM_INITIAL_LINEAR_VELOCITY, 0); + set_param(PARAM_ANGULAR_VELOCITY, 0); + set_param(PARAM_ORBIT_VELOCITY, 0); + set_param(PARAM_LINEAR_ACCEL, 0); + set_param(PARAM_RADIAL_ACCEL, 0); + set_param(PARAM_TANGENTIAL_ACCEL, 0); + set_param(PARAM_DAMPING, 0); + set_param(PARAM_ANGLE, 0); + set_param(PARAM_SCALE, 1); + set_param(PARAM_HUE_VARIATION, 0); + set_param(PARAM_ANIM_SPEED, 0); + set_param(PARAM_ANIM_OFFSET, 0); + set_emission_shape(EMISSION_SHAPE_POINT); + set_emission_sphere_radius(1); + set_emission_box_extents(Vector3(1, 1, 1)); + + set_gravity(Vector3(0, -9.8, 0)); + + for (int i = 0; i < PARAM_MAX; i++) { + set_param_randomness(Parameter(i), 0); + } + + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + + can_update = false; + + set_color(Color(1, 1, 1, 1)); +} + +CPUParticles3D::~CPUParticles3D() { + VS::get_singleton()->free(multimesh); +} diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h new file mode 100644 index 0000000000..ffe0ecc9a9 --- /dev/null +++ b/scene/3d/cpu_particles_3d.h @@ -0,0 +1,298 @@ +/*************************************************************************/ +/* cpu_particles_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CPU_PARTICLES_H +#define CPU_PARTICLES_H + +#include "core/rid.h" +#include "scene/3d/visual_instance_3d.h" + +class CPUParticles3D : public GeometryInstance3D { +private: + GDCLASS(CPUParticles3D, GeometryInstance3D); + +public: + enum DrawOrder { + DRAW_ORDER_INDEX, + DRAW_ORDER_LIFETIME, + DRAW_ORDER_VIEW_DEPTH, + }; + + enum Parameter { + + PARAM_INITIAL_LINEAR_VELOCITY, + PARAM_ANGULAR_VELOCITY, + PARAM_ORBIT_VELOCITY, + PARAM_LINEAR_ACCEL, + PARAM_RADIAL_ACCEL, + PARAM_TANGENTIAL_ACCEL, + PARAM_DAMPING, + PARAM_ANGLE, + PARAM_SCALE, + PARAM_HUE_VARIATION, + PARAM_ANIM_SPEED, + PARAM_ANIM_OFFSET, + PARAM_MAX + }; + + enum Flags { + FLAG_ALIGN_Y_TO_VELOCITY, + FLAG_ROTATE_Y, + FLAG_DISABLE_Z, + FLAG_MAX + }; + + enum EmissionShape { + EMISSION_SHAPE_POINT, + EMISSION_SHAPE_SPHERE, + EMISSION_SHAPE_BOX, + EMISSION_SHAPE_POINTS, + EMISSION_SHAPE_DIRECTED_POINTS, + EMISSION_SHAPE_MAX + }; + +private: + bool emitting; + + struct Particle { + Transform transform; + Color color; + float custom[4]; + Vector3 velocity; + bool active; + float angle_rand; + float scale_rand; + float hue_rot_rand; + float anim_offset_rand; + float time; + float lifetime; + Color base_color; + + uint32_t seed; + }; + + float time; + float inactive_time; + float frame_remainder; + int cycle; + bool redraw; + + RID multimesh; + + Vector particles; + Vector particle_data; + Vector particle_order; + + struct SortLifetime { + const Particle *particles; + + bool operator()(int p_a, int p_b) const { + return particles[p_a].time > particles[p_b].time; + } + }; + + struct SortAxis { + const Particle *particles; + Vector3 axis; + bool operator()(int p_a, int p_b) const { + + return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin); + } + }; + + // + + bool one_shot; + + float lifetime; + float pre_process_time; + float explosiveness_ratio; + float randomness_ratio; + float lifetime_randomness; + float speed_scale; + bool local_coords; + int fixed_fps; + bool fractional_delta; + + Transform inv_emission_transform; + + volatile bool can_update; + + DrawOrder draw_order; + + Ref mesh; + + //////// + + Vector3 direction; + float spread; + float flatness; + + float parameters[PARAM_MAX]; + float randomness[PARAM_MAX]; + + Ref curve_parameters[PARAM_MAX]; + Color color; + Ref color_ramp; + + bool flags[FLAG_MAX]; + + EmissionShape emission_shape; + float emission_sphere_radius; + Vector3 emission_box_extents; + Vector emission_points; + Vector emission_normals; + Vector emission_colors; + int emission_point_count; + + Vector3 gravity; + + void _update_internal(); + void _particles_process(float p_delta); + void _update_particle_data_buffer(); + + Mutex update_mutex; + + void _update_render_thread(); + + void _set_redraw(bool p_redraw); + +protected: + static void _bind_methods(); + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; + +public: + AABB get_aabb() const; + Vector get_faces(uint32_t p_usage_flags) const; + + void set_emitting(bool p_emitting); + void set_amount(int p_amount); + void set_lifetime(float p_lifetime); + void set_one_shot(bool p_one_shot); + void set_pre_process_time(float p_time); + void set_explosiveness_ratio(float p_ratio); + void set_randomness_ratio(float p_ratio); + void set_lifetime_randomness(float p_random); + void set_visibility_aabb(const AABB &p_aabb); + void set_use_local_coordinates(bool p_enable); + void set_speed_scale(float p_scale); + + bool is_emitting() const; + int get_amount() const; + float get_lifetime() const; + bool get_one_shot() const; + float get_pre_process_time() const; + float get_explosiveness_ratio() const; + float get_randomness_ratio() const; + float get_lifetime_randomness() const; + AABB get_visibility_aabb() const; + bool get_use_local_coordinates() const; + float get_speed_scale() const; + + void set_fixed_fps(int p_count); + int get_fixed_fps() const; + + void set_fractional_delta(bool p_enable); + bool get_fractional_delta() const; + + void set_draw_order(DrawOrder p_order); + DrawOrder get_draw_order() const; + + void set_draw_passes(int p_count); + int get_draw_passes() const; + + void set_mesh(const Ref &p_mesh); + Ref get_mesh() const; + + /////////////////// + + void set_direction(Vector3 p_direction); + Vector3 get_direction() const; + + void set_spread(float p_spread); + float get_spread() const; + + void set_flatness(float p_flatness); + float get_flatness() const; + + void set_param(Parameter p_param, float p_value); + float get_param(Parameter p_param) const; + + void set_param_randomness(Parameter p_param, float p_value); + float get_param_randomness(Parameter p_param) const; + + void set_param_curve(Parameter p_param, const Ref &p_curve); + Ref get_param_curve(Parameter p_param) const; + + void set_color(const Color &p_color); + Color get_color() const; + + void set_color_ramp(const Ref &p_ramp); + Ref get_color_ramp() const; + + void set_particle_flag(Flags p_flag, bool p_enable); + bool get_particle_flag(Flags p_flag) const; + + void set_emission_shape(EmissionShape p_shape); + void set_emission_sphere_radius(float p_radius); + void set_emission_box_extents(Vector3 p_extents); + void set_emission_points(const Vector &p_points); + void set_emission_normals(const Vector &p_normals); + void set_emission_colors(const Vector &p_colors); + void set_emission_point_count(int p_count); + + EmissionShape get_emission_shape() const; + float get_emission_sphere_radius() const; + Vector3 get_emission_box_extents() const; + Vector get_emission_points() const; + Vector get_emission_normals() const; + Vector get_emission_colors() const; + int get_emission_point_count() const; + + void set_gravity(const Vector3 &p_gravity); + Vector3 get_gravity() const; + + virtual String get_configuration_warning() const; + + void restart(); + + void convert_from_particles(Node *p_particles); + + CPUParticles3D(); + ~CPUParticles3D(); +}; + +VARIANT_ENUM_CAST(CPUParticles3D::DrawOrder) +VARIANT_ENUM_CAST(CPUParticles3D::Parameter) +VARIANT_ENUM_CAST(CPUParticles3D::Flags) +VARIANT_ENUM_CAST(CPUParticles3D::EmissionShape) + +#endif // CPU_PARTICLES_H diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 76549f7e51..413d5a2b1d 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" #include "core/method_bind_ext.gen.inc" -#include "mesh_instance.h" +#include "mesh_instance_3d.h" #include "voxelizer.h" void GIProbeData::_set_data(const Dictionary &p_data) { @@ -347,8 +347,8 @@ Vector3 GIProbe::get_extents() const { void GIProbe::_find_meshes(Node *p_at_node, List &plot_meshes) { - MeshInstance *mi = Object::cast_to(p_at_node); - if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { + MeshInstance3D *mi = Object::cast_to(p_at_node); + if (mi && mi->get_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { Ref mesh = mi->get_mesh(); if (mesh.is_valid()) { @@ -369,7 +369,7 @@ void GIProbe::_find_meshes(Node *p_at_node, List &plot_meshes) { } } - Spatial *s = Object::cast_to(p_at_node); + Node3D *s = Object::cast_to(p_at_node); if (s) { if (s->is_visible_in_tree()) { @@ -468,7 +468,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { //create the data for visual server if (p_create_visual_debug) { - MultiMeshInstance *mmi = memnew(MultiMeshInstance); + MultiMeshInstance3D *mmi = memnew(MultiMeshInstance3D); mmi->set_multimesh(baker.create_debug_multimesh()); add_child(mmi); #ifdef TOOLS_ENABLED diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index f991843883..c00ee2cb73 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -31,8 +31,8 @@ #ifndef GIPROBE_H #define GIPROBE_H -#include "multimesh_instance.h" -#include "scene/3d/visual_instance.h" +#include "multimesh_instance_3d.h" +#include "scene/3d/visual_instance_3d.h" class GIProbeData : public Resource { @@ -108,8 +108,8 @@ public: ~GIProbeData(); }; -class GIProbe : public VisualInstance { - GDCLASS(GIProbe, VisualInstance); +class GIProbe : public VisualInstance3D { + GDCLASS(GIProbe, VisualInstance3D); public: enum Subdiv { diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp new file mode 100644 index 0000000000..a283ec41b2 --- /dev/null +++ b/scene/3d/gpu_particles_3d.cpp @@ -0,0 +1,441 @@ +/*************************************************************************/ +/* gpu_particles_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "gpu_particles_3d.h" + +#include "core/os/os.h" +#include "scene/resources/particles_material.h" + +#include "servers/visual_server.h" + +AABB GPUParticles3D::get_aabb() const { + + return AABB(); +} +Vector GPUParticles3D::get_faces(uint32_t p_usage_flags) const { + + return Vector(); +} + +void GPUParticles3D::set_emitting(bool p_emitting) { + + VS::get_singleton()->particles_set_emitting(particles, p_emitting); + + if (p_emitting && one_shot) { + set_process_internal(true); + } else if (!p_emitting) { + set_process_internal(false); + } +} + +void GPUParticles3D::set_amount(int p_amount) { + + ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles cannot be smaller than 1."); + amount = p_amount; + VS::get_singleton()->particles_set_amount(particles, amount); +} +void GPUParticles3D::set_lifetime(float p_lifetime) { + + ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); + lifetime = p_lifetime; + VS::get_singleton()->particles_set_lifetime(particles, lifetime); +} + +void GPUParticles3D::set_one_shot(bool p_one_shot) { + + one_shot = p_one_shot; + VS::get_singleton()->particles_set_one_shot(particles, one_shot); + + if (is_emitting()) { + + set_process_internal(true); + if (!one_shot) + VisualServer::get_singleton()->particles_restart(particles); + } + + if (!one_shot) + set_process_internal(false); +} + +void GPUParticles3D::set_pre_process_time(float p_time) { + + pre_process_time = p_time; + VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); +} +void GPUParticles3D::set_explosiveness_ratio(float p_ratio) { + + explosiveness_ratio = p_ratio; + VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); +} +void GPUParticles3D::set_randomness_ratio(float p_ratio) { + + randomness_ratio = p_ratio; + VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); +} +void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) { + + visibility_aabb = p_aabb; + VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); + update_gizmo(); + _change_notify("visibility_aabb"); +} +void GPUParticles3D::set_use_local_coordinates(bool p_enable) { + + local_coords = p_enable; + VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); +} +void GPUParticles3D::set_process_material(const Ref &p_material) { + + process_material = p_material; + RID material_rid; + if (process_material.is_valid()) + material_rid = process_material->get_rid(); + VS::get_singleton()->particles_set_process_material(particles, material_rid); + + update_configuration_warning(); +} + +void GPUParticles3D::set_speed_scale(float p_scale) { + + speed_scale = p_scale; + VS::get_singleton()->particles_set_speed_scale(particles, p_scale); +} + +bool GPUParticles3D::is_emitting() const { + + return VS::get_singleton()->particles_get_emitting(particles); +} +int GPUParticles3D::get_amount() const { + + return amount; +} +float GPUParticles3D::get_lifetime() const { + + return lifetime; +} +bool GPUParticles3D::get_one_shot() const { + + return one_shot; +} + +float GPUParticles3D::get_pre_process_time() const { + + return pre_process_time; +} +float GPUParticles3D::get_explosiveness_ratio() const { + + return explosiveness_ratio; +} +float GPUParticles3D::get_randomness_ratio() const { + + return randomness_ratio; +} +AABB GPUParticles3D::get_visibility_aabb() const { + + return visibility_aabb; +} +bool GPUParticles3D::get_use_local_coordinates() const { + + return local_coords; +} +Ref GPUParticles3D::get_process_material() const { + + return process_material; +} + +float GPUParticles3D::get_speed_scale() const { + + return speed_scale; +} + +void GPUParticles3D::set_draw_order(DrawOrder p_order) { + + draw_order = p_order; + VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); +} + +GPUParticles3D::DrawOrder GPUParticles3D::get_draw_order() const { + + return draw_order; +} + +void GPUParticles3D::set_draw_passes(int p_count) { + + ERR_FAIL_COND(p_count < 1); + draw_passes.resize(p_count); + VS::get_singleton()->particles_set_draw_passes(particles, p_count); + _change_notify(); +} +int GPUParticles3D::get_draw_passes() const { + + return draw_passes.size(); +} + +void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref &p_mesh) { + + ERR_FAIL_INDEX(p_pass, draw_passes.size()); + + draw_passes.write[p_pass] = p_mesh; + + RID mesh_rid; + if (p_mesh.is_valid()) + mesh_rid = p_mesh->get_rid(); + + VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); + + update_configuration_warning(); +} + +Ref GPUParticles3D::get_draw_pass_mesh(int p_pass) const { + + ERR_FAIL_INDEX_V(p_pass, draw_passes.size(), Ref()); + + return draw_passes[p_pass]; +} + +void GPUParticles3D::set_fixed_fps(int p_count) { + fixed_fps = p_count; + VS::get_singleton()->particles_set_fixed_fps(particles, p_count); +} + +int GPUParticles3D::get_fixed_fps() const { + return fixed_fps; +} + +void GPUParticles3D::set_fractional_delta(bool p_enable) { + fractional_delta = p_enable; + VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); +} + +bool GPUParticles3D::get_fractional_delta() const { + return fractional_delta; +} + +String GPUParticles3D::get_configuration_warning() const { + + if (VisualServer::get_singleton()->is_low_end()) { + return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); + } + + String warnings; + + bool meshes_found = false; + bool anim_material_found = false; + + for (int i = 0; i < draw_passes.size(); i++) { + if (draw_passes[i].is_valid()) { + meshes_found = true; + for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) { + anim_material_found = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()) != NULL; + StandardMaterial3D *spat = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); + } + if (anim_material_found) break; + } + } + + anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; + StandardMaterial3D *spat = Object::cast_to(get_material_override().ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); + + if (!meshes_found) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes."); + } + + if (process_material.is_null()) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + } else { + const ParticlesMaterial *process = Object::cast_to(process_material.ptr()); + if (!anim_material_found && process && + (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); + } + } + + return warnings; +} + +void GPUParticles3D::restart() { + + VisualServer::get_singleton()->particles_restart(particles); + VisualServer::get_singleton()->particles_set_emitting(particles, true); +} + +AABB GPUParticles3D::capture_aabb() const { + + return VS::get_singleton()->particles_get_current_aabb(particles); +} + +void GPUParticles3D::_validate_property(PropertyInfo &property) const { + + if (property.name.begins_with("draw_pass_")) { + int index = property.name.get_slicec('_', 2).to_int() - 1; + if (index >= draw_passes.size()) { + property.usage = 0; + return; + } + } +} + +void GPUParticles3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { + if (can_process()) { + VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); + } else { + + VS::get_singleton()->particles_set_speed_scale(particles, 0); + } + } + + // Use internal process when emitting and one_shot are on so that when + // the shot ends the editor can properly update + if (p_what == NOTIFICATION_INTERNAL_PROCESS) { + + if (one_shot && !is_emitting()) { + _change_notify(); + set_process_internal(false); + } + } + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + // make sure particles are updated before rendering occurs if they were active before + if (is_visible_in_tree() && !VS::get_singleton()->particles_is_inactive(particles)) { + VS::get_singleton()->particles_request_process(particles); + } + } +} + +void GPUParticles3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &GPUParticles3D::set_emitting); + ClassDB::bind_method(D_METHOD("set_amount", "amount"), &GPUParticles3D::set_amount); + ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &GPUParticles3D::set_lifetime); + ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &GPUParticles3D::set_one_shot); + ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &GPUParticles3D::set_pre_process_time); + ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &GPUParticles3D::set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &GPUParticles3D::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_visibility_aabb", "aabb"), &GPUParticles3D::set_visibility_aabb); + ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &GPUParticles3D::set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &GPUParticles3D::set_fixed_fps); + ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &GPUParticles3D::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles3D::set_process_material); + ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles3D::set_speed_scale); + + ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles3D::is_emitting); + ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles3D::get_amount); + ClassDB::bind_method(D_METHOD("get_lifetime"), &GPUParticles3D::get_lifetime); + ClassDB::bind_method(D_METHOD("get_one_shot"), &GPUParticles3D::get_one_shot); + ClassDB::bind_method(D_METHOD("get_pre_process_time"), &GPUParticles3D::get_pre_process_time); + ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &GPUParticles3D::get_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &GPUParticles3D::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_visibility_aabb"), &GPUParticles3D::get_visibility_aabb); + ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &GPUParticles3D::get_use_local_coordinates); + ClassDB::bind_method(D_METHOD("get_fixed_fps"), &GPUParticles3D::get_fixed_fps); + ClassDB::bind_method(D_METHOD("get_fractional_delta"), &GPUParticles3D::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles3D::get_process_material); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles3D::get_speed_scale); + + ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order); + + ClassDB::bind_method(D_METHOD("get_draw_order"), &GPUParticles3D::get_draw_order); + + ClassDB::bind_method(D_METHOD("set_draw_passes", "passes"), &GPUParticles3D::set_draw_passes); + ClassDB::bind_method(D_METHOD("set_draw_pass_mesh", "pass", "mesh"), &GPUParticles3D::set_draw_pass_mesh); + + ClassDB::bind_method(D_METHOD("get_draw_passes"), &GPUParticles3D::get_draw_passes); + ClassDB::bind_method(D_METHOD("get_draw_pass_mesh", "pass"), &GPUParticles3D::get_draw_pass_mesh); + + ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart); + ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); + ADD_GROUP("Time", ""); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_GROUP("Drawing", ""); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); + ADD_GROUP("Process Material", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_GROUP("Draw Passes", "draw_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); + for (int i = 0; i < MAX_DRAW_PASSES; i++) { + + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "draw_pass_" + itos(i + 1), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_draw_pass_mesh", "get_draw_pass_mesh", i); + } + + BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); + BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); + BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + + BIND_CONSTANT(MAX_DRAW_PASSES); +} + +GPUParticles3D::GPUParticles3D() { + + particles = VS::get_singleton()->particles_create(); + set_base(particles); + one_shot = false; // Needed so that set_emitting doesn't access uninitialized values + set_emitting(true); + set_one_shot(false); + set_amount(8); + set_lifetime(1); + set_fixed_fps(0); + set_fractional_delta(true); + set_pre_process_time(0); + set_explosiveness_ratio(0); + set_randomness_ratio(0); + set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))); + set_use_local_coordinates(true); + set_draw_passes(1); + set_draw_order(DRAW_ORDER_INDEX); + set_speed_scale(1); +} + +GPUParticles3D::~GPUParticles3D() { + + VS::get_singleton()->free(particles); +} diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h new file mode 100644 index 0000000000..0c6653294b --- /dev/null +++ b/scene/3d/gpu_particles_3d.h @@ -0,0 +1,133 @@ +/*************************************************************************/ +/* gpu_particles_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PARTICLES_H +#define PARTICLES_H + +#include "core/rid.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/material.h" + +class GPUParticles3D : public GeometryInstance3D { +private: + GDCLASS(GPUParticles3D, GeometryInstance3D); + +public: + enum DrawOrder { + DRAW_ORDER_INDEX, + DRAW_ORDER_LIFETIME, + DRAW_ORDER_VIEW_DEPTH, + }; + + enum { + MAX_DRAW_PASSES = 4 + }; + +private: + RID particles; + + bool one_shot; + int amount; + float lifetime; + float pre_process_time; + float explosiveness_ratio; + float randomness_ratio; + float speed_scale; + AABB visibility_aabb; + bool local_coords; + int fixed_fps; + bool fractional_delta; + + Ref process_material; + + DrawOrder draw_order; + + Vector> draw_passes; + +protected: + static void _bind_methods(); + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; + +public: + AABB get_aabb() const; + Vector get_faces(uint32_t p_usage_flags) const; + + void set_emitting(bool p_emitting); + void set_amount(int p_amount); + void set_lifetime(float p_lifetime); + void set_one_shot(bool p_one_shot); + void set_pre_process_time(float p_time); + void set_explosiveness_ratio(float p_ratio); + void set_randomness_ratio(float p_ratio); + void set_visibility_aabb(const AABB &p_aabb); + void set_use_local_coordinates(bool p_enable); + void set_process_material(const Ref &p_material); + void set_speed_scale(float p_scale); + + bool is_emitting() const; + int get_amount() const; + float get_lifetime() const; + bool get_one_shot() const; + float get_pre_process_time() const; + float get_explosiveness_ratio() const; + float get_randomness_ratio() const; + AABB get_visibility_aabb() const; + bool get_use_local_coordinates() const; + Ref get_process_material() const; + float get_speed_scale() const; + + void set_fixed_fps(int p_count); + int get_fixed_fps() const; + + void set_fractional_delta(bool p_enable); + bool get_fractional_delta() const; + + void set_draw_order(DrawOrder p_order); + DrawOrder get_draw_order() const; + + void set_draw_passes(int p_count); + int get_draw_passes() const; + + void set_draw_pass_mesh(int p_pass, const Ref &p_mesh); + Ref get_draw_pass_mesh(int p_pass) const; + + virtual String get_configuration_warning() const; + + void restart(); + + AABB capture_aabb() const; + GPUParticles3D(); + ~GPUParticles3D(); +}; + +VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder) + +#endif // PARTICLES_H diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp deleted file mode 100644 index f5b08b86e1..0000000000 --- a/scene/3d/immediate_geometry.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "immediate_geometry.h" - -void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive, const Ref &p_texture) { - - VS::get_singleton()->immediate_begin(im, (VS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); - if (p_texture.is_valid()) - cached_textures.push_back(p_texture); -} - -void ImmediateGeometry::set_normal(const Vector3 &p_normal) { - - VS::get_singleton()->immediate_normal(im, p_normal); -} - -void ImmediateGeometry::set_tangent(const Plane &p_tangent) { - - VS::get_singleton()->immediate_tangent(im, p_tangent); -} - -void ImmediateGeometry::set_color(const Color &p_color) { - - VS::get_singleton()->immediate_color(im, p_color); -} - -void ImmediateGeometry::set_uv(const Vector2 &p_uv) { - - VS::get_singleton()->immediate_uv(im, p_uv); -} - -void ImmediateGeometry::set_uv2(const Vector2 &p_uv2) { - - VS::get_singleton()->immediate_uv2(im, p_uv2); -} - -void ImmediateGeometry::add_vertex(const Vector3 &p_vertex) { - - VS::get_singleton()->immediate_vertex(im, p_vertex); - if (empty) { - aabb.position = p_vertex; - aabb.size = Vector3(); - empty = false; - } else { - aabb.expand_to(p_vertex); - } -} - -void ImmediateGeometry::end() { - - VS::get_singleton()->immediate_end(im); -} - -void ImmediateGeometry::clear() { - - VS::get_singleton()->immediate_clear(im); - empty = true; - cached_textures.clear(); -} - -AABB ImmediateGeometry::get_aabb() const { - - return aabb; -} -Vector ImmediateGeometry::get_faces(uint32_t p_usage_flags) const { - - return Vector(); -} - -void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { - - for (int i = 1; i <= p_lats; i++) { - double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double)i / p_lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for (int j = p_lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double)(j) / p_lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v[4] = { - Vector3(x1 * zr0, z0, y1 * zr0), - Vector3(x1 * zr1, z1, y1 * zr1), - Vector3(x0 * zr1, z1, y0 * zr1), - Vector3(x0 * zr0, z0, y0 * zr0) - }; - -#define ADD_POINT(m_idx) \ - if (p_add_uv) { \ - set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \ - set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \ - } \ - set_normal(v[m_idx]); \ - add_vertex(v[m_idx] * p_radius); - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } -} - -void ImmediateGeometry::_bind_methods() { - - ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry::begin, DEFVAL(Ref())); - ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry::set_normal); - ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry::set_tangent); - ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry::set_color); - ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry::set_uv); - ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry::set_uv2); - ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry::add_vertex); - ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry::add_sphere, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry::end); - ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry::clear); -} - -ImmediateGeometry::ImmediateGeometry() { - - im = VisualServer::get_singleton()->immediate_create(); - set_base(im); - empty = true; -} - -ImmediateGeometry::~ImmediateGeometry() { - - VisualServer::get_singleton()->free(im); -} diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h deleted file mode 100644 index f9222c75fa..0000000000 --- a/scene/3d/immediate_geometry.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef IMMEDIATE_GEOMETRY_H -#define IMMEDIATE_GEOMETRY_H - -#include "scene/3d/visual_instance.h" -#include "scene/resources/mesh.h" - -class ImmediateGeometry : public GeometryInstance { - - GDCLASS(ImmediateGeometry, GeometryInstance); - - RID im; - //a list of textures drawn need to be kept, to avoid references - // in VisualServer from becoming invalid if the texture is no longer used - List> cached_textures; - bool empty; - AABB aabb; - -protected: - static void _bind_methods(); - -public: - void begin(Mesh::PrimitiveType p_primitive, const Ref &p_texture = Ref()); - void set_normal(const Vector3 &p_normal); - void set_tangent(const Plane &p_tangent); - void set_color(const Color &p_color); - void set_uv(const Vector2 &p_uv); - void set_uv2(const Vector2 &p_uv2); - - void add_vertex(const Vector3 &p_vertex); - - void end(); - void clear(); - - void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true); - - virtual AABB get_aabb() const; - virtual Vector get_faces(uint32_t p_usage_flags) const; - - ImmediateGeometry(); - ~ImmediateGeometry(); -}; - -#endif // IMMEDIATE_GEOMETRY_H diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp new file mode 100644 index 0000000000..acc1f407f9 --- /dev/null +++ b/scene/3d/immediate_geometry_3d.cpp @@ -0,0 +1,169 @@ +/*************************************************************************/ +/* immediate_geometry_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "immediate_geometry_3d.h" + +void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref &p_texture) { + + VS::get_singleton()->immediate_begin(im, (VS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); + if (p_texture.is_valid()) + cached_textures.push_back(p_texture); +} + +void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) { + + VS::get_singleton()->immediate_normal(im, p_normal); +} + +void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) { + + VS::get_singleton()->immediate_tangent(im, p_tangent); +} + +void ImmediateGeometry3D::set_color(const Color &p_color) { + + VS::get_singleton()->immediate_color(im, p_color); +} + +void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) { + + VS::get_singleton()->immediate_uv(im, p_uv); +} + +void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) { + + VS::get_singleton()->immediate_uv2(im, p_uv2); +} + +void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) { + + VS::get_singleton()->immediate_vertex(im, p_vertex); + if (empty) { + aabb.position = p_vertex; + aabb.size = Vector3(); + empty = false; + } else { + aabb.expand_to(p_vertex); + } +} + +void ImmediateGeometry3D::end() { + + VS::get_singleton()->immediate_end(im); +} + +void ImmediateGeometry3D::clear() { + + VS::get_singleton()->immediate_clear(im); + empty = true; + cached_textures.clear(); +} + +AABB ImmediateGeometry3D::get_aabb() const { + + return aabb; +} +Vector ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const { + + return Vector(); +} + +void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { + + for (int i = 1; i <= p_lats; i++) { + double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double)i / p_lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for (int j = p_lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double)(j) / p_lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + Vector3 v[4] = { + Vector3(x1 * zr0, z0, y1 * zr0), + Vector3(x1 * zr1, z1, y1 * zr1), + Vector3(x0 * zr1, z1, y0 * zr1), + Vector3(x0 * zr0, z0, y0 * zr0) + }; + +#define ADD_POINT(m_idx) \ + if (p_add_uv) { \ + set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \ + set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \ + } \ + set_normal(v[m_idx]); \ + add_vertex(v[m_idx] * p_radius); + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } +} + +void ImmediateGeometry3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal); + ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent); + ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry3D::set_color); + ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry3D::set_uv); + ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry3D::set_uv2); + ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry3D::add_vertex); + ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry3D::add_sphere, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry3D::end); + ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry3D::clear); +} + +ImmediateGeometry3D::ImmediateGeometry3D() { + + im = VisualServer::get_singleton()->immediate_create(); + set_base(im); + empty = true; +} + +ImmediateGeometry3D::~ImmediateGeometry3D() { + + VisualServer::get_singleton()->free(im); +} diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h new file mode 100644 index 0000000000..d968187ba3 --- /dev/null +++ b/scene/3d/immediate_geometry_3d.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* immediate_geometry_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef IMMEDIATE_GEOMETRY_3D_H +#define IMMEDIATE_GEOMETRY_3D_H + +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/mesh.h" + +class ImmediateGeometry3D : public GeometryInstance3D { + + GDCLASS(ImmediateGeometry3D, GeometryInstance3D); + + RID im; + //a list of textures drawn need to be kept, to avoid references + // in VisualServer from becoming invalid if the texture is no longer used + List> cached_textures; + bool empty; + AABB aabb; + +protected: + static void _bind_methods(); + +public: + void begin(Mesh::PrimitiveType p_primitive, const Ref &p_texture = Ref()); + void set_normal(const Vector3 &p_normal); + void set_tangent(const Plane &p_tangent); + void set_color(const Color &p_color); + void set_uv(const Vector2 &p_uv); + void set_uv2(const Vector2 &p_uv2); + + void add_vertex(const Vector3 &p_vertex); + + void end(); + void clear(); + + void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true); + + virtual AABB get_aabb() const; + virtual Vector get_faces(uint32_t p_usage_flags) const; + + ImmediateGeometry3D(); + ~ImmediateGeometry3D(); +}; + +#endif // IMMEDIATE_GEOMETRY_H diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp deleted file mode 100644 index 592d592a38..0000000000 --- a/scene/3d/interpolated_camera.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/*************************************************************************/ -/* interpolated_camera.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "interpolated_camera.h" - -#include "core/engine.h" - -void InterpolatedCamera::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - - if (Engine::get_singleton()->is_editor_hint() && enabled) - set_process_internal(false); - - } break; - case NOTIFICATION_INTERNAL_PROCESS: { - - if (!enabled) - break; - if (has_node(target)) { - - Spatial *node = Object::cast_to(get_node(target)); - if (!node) - break; - - float delta = speed * get_process_delta_time(); - Transform target_xform = node->get_global_transform(); - Transform local_transform = get_global_transform(); - local_transform = local_transform.interpolate_with(target_xform, delta); - set_global_transform(local_transform); - Camera *cam = Object::cast_to(node); - if (cam) { - - if (cam->get_projection() == get_projection()) { - - float new_near = Math::lerp(get_znear(), cam->get_znear(), delta); - float new_far = Math::lerp(get_zfar(), cam->get_zfar(), delta); - - if (cam->get_projection() == PROJECTION_ORTHOGONAL) { - - float size = Math::lerp(get_size(), cam->get_size(), delta); - set_orthogonal(size, new_near, new_far); - } else { - - float fov = Math::lerp(get_fov(), cam->get_fov(), delta); - set_perspective(fov, new_near, new_far); - } - } - } - } - - } break; - } -} - -void InterpolatedCamera::_set_target(const Object *p_target) { - - ERR_FAIL_NULL(p_target); - set_target(Object::cast_to(p_target)); -} - -void InterpolatedCamera::set_target(const Spatial *p_target) { - - ERR_FAIL_NULL(p_target); - target = get_path_to(p_target); -} - -void InterpolatedCamera::set_target_path(const NodePath &p_path) { - - target = p_path; -} - -NodePath InterpolatedCamera::get_target_path() const { - - return target; -} - -void InterpolatedCamera::set_interpolation_enabled(bool p_enable) { - - if (enabled == p_enable) - return; - enabled = p_enable; - if (p_enable) { - if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) - return; - set_process_internal(true); - } else - set_process_internal(false); -} - -bool InterpolatedCamera::is_interpolation_enabled() const { - - return enabled; -} - -void InterpolatedCamera::set_speed(real_t p_speed) { - - speed = p_speed; -} - -real_t InterpolatedCamera::get_speed() const { - - return speed; -} - -void InterpolatedCamera::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_target_path", "target_path"), &InterpolatedCamera::set_target_path); - ClassDB::bind_method(D_METHOD("get_target_path"), &InterpolatedCamera::get_target_path); - ClassDB::bind_method(D_METHOD("set_target", "target"), &InterpolatedCamera::_set_target); - - ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InterpolatedCamera::set_speed); - ClassDB::bind_method(D_METHOD("get_speed"), &InterpolatedCamera::get_speed); - - ClassDB::bind_method(D_METHOD("set_interpolation_enabled", "target_path"), &InterpolatedCamera::set_interpolation_enabled); - ClassDB::bind_method(D_METHOD("is_interpolation_enabled"), &InterpolatedCamera::is_interpolation_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target"), "set_target_path", "get_target_path"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed"), "set_speed", "get_speed"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_interpolation_enabled", "is_interpolation_enabled"); -} - -InterpolatedCamera::InterpolatedCamera() { - - enabled = false; - speed = 1; -} diff --git a/scene/3d/interpolated_camera.h b/scene/3d/interpolated_camera.h deleted file mode 100644 index 7b160c66fa..0000000000 --- a/scene/3d/interpolated_camera.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************/ -/* interpolated_camera.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef INTERPOLATED_CAMERA_H -#define INTERPOLATED_CAMERA_H - -#include "scene/3d/camera.h" - -class InterpolatedCamera : public Camera { - - GDCLASS(InterpolatedCamera, Camera); - - bool enabled; - real_t speed; - NodePath target; - -protected: - void _notification(int p_what); - static void _bind_methods(); - void _set_target(const Object *p_target); - -public: - void set_target(const Spatial *p_target); - void set_target_path(const NodePath &p_path); - NodePath get_target_path() const; - - void set_speed(real_t p_speed); - real_t get_speed() const; - - void set_interpolation_enabled(bool p_enable); - bool is_interpolation_enabled() const; - - InterpolatedCamera(); -}; - -#endif // INTERPOLATED_CAMERA_H diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp deleted file mode 100644 index 7c922ce1cd..0000000000 --- a/scene/3d/light.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/*************************************************************************/ -/* light.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "light.h" - -#include "core/engine.h" -#include "core/project_settings.h" -#include "scene/resources/surface_tool.h" - -bool Light::_can_gizmo_scale() const { - - return false; -} - -void Light::set_param(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - param[p_param] = p_value; - - VS::get_singleton()->light_set_param(light, VS::LightParam(p_param), p_value); - - if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) { - update_gizmo(); - - if (p_param == PARAM_SPOT_ANGLE) { - _change_notify("spot_angle"); - update_configuration_warning(); - } else if (p_param == PARAM_RANGE) { - _change_notify("omni_range"); - _change_notify("spot_range"); - } - } -} - -float Light::get_param(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return param[p_param]; -} - -void Light::set_shadow(bool p_enable) { - - shadow = p_enable; - VS::get_singleton()->light_set_shadow(light, p_enable); - - if (type == VisualServer::LIGHT_SPOT) { - update_configuration_warning(); - } -} -bool Light::has_shadow() const { - - return shadow; -} - -void Light::set_negative(bool p_enable) { - - negative = p_enable; - VS::get_singleton()->light_set_negative(light, p_enable); -} -bool Light::is_negative() const { - - return negative; -} - -void Light::set_cull_mask(uint32_t p_cull_mask) { - - cull_mask = p_cull_mask; - VS::get_singleton()->light_set_cull_mask(light, p_cull_mask); -} -uint32_t Light::get_cull_mask() const { - - return cull_mask; -} - -void Light::set_color(const Color &p_color) { - - color = p_color; - VS::get_singleton()->light_set_color(light, p_color); - // The gizmo color depends on the light color, so update it. - update_gizmo(); -} -Color Light::get_color() const { - - return color; -} - -void Light::set_shadow_color(const Color &p_shadow_color) { - - shadow_color = p_shadow_color; - VS::get_singleton()->light_set_shadow_color(light, p_shadow_color); -} - -Color Light::get_shadow_color() const { - - return shadow_color; -} - -void Light::set_shadow_reverse_cull_face(bool p_enable) { - reverse_cull = p_enable; - VS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull); -} - -bool Light::get_shadow_reverse_cull_face() const { - - return reverse_cull; -} - -AABB Light::get_aabb() const { - - if (type == VisualServer::LIGHT_DIRECTIONAL) { - - return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - - } else if (type == VisualServer::LIGHT_OMNI) { - - return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]); - - } else if (type == VisualServer::LIGHT_SPOT) { - - float len = param[PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; - return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); - } - - return AABB(); -} - -Vector Light::get_faces(uint32_t p_usage_flags) const { - - return Vector(); -} - -void Light::set_bake_mode(BakeMode p_mode) { - bake_mode = p_mode; - VS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED); -} - -Light::BakeMode Light::get_bake_mode() const { - return bake_mode; -} - -void Light::_update_visibility() { - - if (!is_inside_tree()) - return; - - bool editor_ok = true; - -#ifdef TOOLS_ENABLED - if (editor_only) { - if (!Engine::get_singleton()->is_editor_hint()) { - editor_ok = false; - } else { - editor_ok = (get_tree()->get_edited_scene_root() && (this == get_tree()->get_edited_scene_root() || get_owner() == get_tree()->get_edited_scene_root())); - } - } -#else - if (editor_only) { - editor_ok = false; - } -#endif - - VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok); - - _change_notify("geometry/visible"); -} - -void Light::_notification(int p_what) { - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - - _update_visibility(); - } - - if (p_what == NOTIFICATION_ENTER_TREE) { - _update_visibility(); - } -} - -void Light::set_editor_only(bool p_editor_only) { - - editor_only = p_editor_only; - _update_visibility(); -} - -bool Light::is_editor_only() const { - - return editor_only; -} - -void Light::_validate_property(PropertyInfo &property) const { - - if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } -} - -void Light::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light::set_editor_only); - ClassDB::bind_method(D_METHOD("is_editor_only"), &Light::is_editor_only); - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &Light::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &Light::get_param); - - ClassDB::bind_method(D_METHOD("set_shadow", "enabled"), &Light::set_shadow); - ClassDB::bind_method(D_METHOD("has_shadow"), &Light::has_shadow); - - ClassDB::bind_method(D_METHOD("set_negative", "enabled"), &Light::set_negative); - ClassDB::bind_method(D_METHOD("is_negative"), &Light::is_negative); - - ClassDB::bind_method(D_METHOD("set_cull_mask", "cull_mask"), &Light::set_cull_mask); - ClassDB::bind_method(D_METHOD("get_cull_mask"), &Light::get_cull_mask); - - ClassDB::bind_method(D_METHOD("set_color", "color"), &Light::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &Light::get_color); - - ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light::set_shadow_reverse_cull_face); - ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light::get_shadow_reverse_cull_face); - - ClassDB::bind_method(D_METHOD("set_shadow_color", "shadow_color"), &Light::set_shadow_color); - ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light::get_shadow_color); - - ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light::set_bake_mode); - ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light::get_bake_mode); - - ADD_GROUP("Light", "light_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); - ADD_GROUP("Shadow", "shadow_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face"); - ADD_GROUP("Editor", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only"); - ADD_GROUP("", ""); - - BIND_ENUM_CONSTANT(PARAM_ENERGY); - BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY); - BIND_ENUM_CONSTANT(PARAM_SPECULAR); - BIND_ENUM_CONSTANT(PARAM_RANGE); - BIND_ENUM_CONSTANT(PARAM_ATTENUATION); - BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE); - BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION); - BIND_ENUM_CONSTANT(PARAM_CONTACT_SHADOW_SIZE); - BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE); - BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET); - BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET); - BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET); - BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START); - BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS); - BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS); - BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE); - BIND_ENUM_CONSTANT(PARAM_MAX); - - BIND_ENUM_CONSTANT(BAKE_DISABLED); - BIND_ENUM_CONSTANT(BAKE_INDIRECT); - BIND_ENUM_CONSTANT(BAKE_ALL); -} - -Light::Light(VisualServer::LightType p_type) { - - type = p_type; - switch (p_type) { - case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break; - case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break; - case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break; - default: { - }; - } - - VS::get_singleton()->instance_set_base(get_instance(), light); - - reverse_cull = false; - bake_mode = BAKE_INDIRECT; - - editor_only = false; - set_color(Color(1, 1, 1, 1)); - set_shadow(false); - set_negative(false); - set_cull_mask(0xFFFFFFFF); - - set_param(PARAM_ENERGY, 1); - set_param(PARAM_INDIRECT_ENERGY, 1); - set_param(PARAM_SPECULAR, 0.5); - set_param(PARAM_RANGE, 5); - set_param(PARAM_ATTENUATION, 1); - set_param(PARAM_SPOT_ANGLE, 45); - set_param(PARAM_SPOT_ATTENUATION, 1); - set_param(PARAM_CONTACT_SHADOW_SIZE, 0); - set_param(PARAM_SHADOW_MAX_DISTANCE, 0); - set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1); - set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2); - set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5); - set_param(PARAM_SHADOW_FADE_START, 0.8); - set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0); - set_param(PARAM_SHADOW_BIAS, 0.15); - set_param(PARAM_SHADOW_FADE_START, 1); - set_disable_scale(true); -} - -Light::Light() { - - type = VisualServer::LIGHT_DIRECTIONAL; - ERR_PRINT("Light should not be instanced directly; use the DirectionalLight, OmniLight or SpotLight subtypes instead."); -} - -Light::~Light() { - - VS::get_singleton()->instance_set_base(get_instance(), RID()); - - if (light.is_valid()) - VisualServer::get_singleton()->free(light); -} -///////////////////////////////////////// - -void DirectionalLight::set_shadow_mode(ShadowMode p_mode) { - - shadow_mode = p_mode; - VS::get_singleton()->light_directional_set_shadow_mode(light, VS::LightDirectionalShadowMode(p_mode)); -} - -DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const { - - return shadow_mode; -} - -void DirectionalLight::set_shadow_depth_range(ShadowDepthRange p_range) { - shadow_depth_range = p_range; - VS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, VS::LightDirectionalShadowDepthRangeMode(p_range)); -} - -DirectionalLight::ShadowDepthRange DirectionalLight::get_shadow_depth_range() const { - - return shadow_depth_range; -} - -void DirectionalLight::set_blend_splits(bool p_enable) { - - blend_splits = p_enable; - VS::get_singleton()->light_directional_set_blend_splits(light, p_enable); -} - -bool DirectionalLight::is_blend_splits_enabled() const { - - return blend_splits; -} - -void DirectionalLight::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight::set_shadow_mode); - ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight::get_shadow_mode); - - ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight::set_shadow_depth_range); - ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight::get_shadow_depth_range); - - ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight::set_blend_splits); - ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled); - - ADD_GROUP("Directional Shadow", "directional_shadow_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), "set_shadow_mode", "get_shadow_mode"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE); - ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); - - BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); - BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); - BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); - - BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE); - BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_OPTIMIZED); -} - -DirectionalLight::DirectionalLight() : - Light(VisualServer::LIGHT_DIRECTIONAL) { - - set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8); - set_param(PARAM_SHADOW_BIAS, 0.1); - set_param(PARAM_SHADOW_MAX_DISTANCE, 100); - set_param(PARAM_SHADOW_FADE_START, 0.8); - set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25); - set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); - set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE); - - blend_splits = false; -} - -void OmniLight::set_shadow_mode(ShadowMode p_mode) { - - shadow_mode = p_mode; - VS::get_singleton()->light_omni_set_shadow_mode(light, VS::LightOmniShadowMode(p_mode)); -} - -OmniLight::ShadowMode OmniLight::get_shadow_mode() const { - - return shadow_mode; -} - -void OmniLight::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight::set_shadow_mode); - ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight::get_shadow_mode); - - ADD_GROUP("Omni", "omni_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION); - ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode"); - - BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID); - BIND_ENUM_CONSTANT(SHADOW_CUBE); -} - -OmniLight::OmniLight() : - Light(VisualServer::LIGHT_OMNI) { - - set_shadow_mode(SHADOW_CUBE); -} - -String SpotLight::get_configuration_warning() const { - String warning = Light::get_configuration_warning(); - - if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { - if (warning != String()) { - warning += "\n\n"; - } - - warning += TTR("A SpotLight with an angle wider than 90 degrees cannot cast shadows."); - } - - return warning; -} - -void SpotLight::_bind_methods() { - - ADD_GROUP("Spot", "spot_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION); -} diff --git a/scene/3d/light.h b/scene/3d/light.h deleted file mode 100644 index 16e0c47083..0000000000 --- a/scene/3d/light.h +++ /dev/null @@ -1,216 +0,0 @@ -/*************************************************************************/ -/* light.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef LIGHT_H -#define LIGHT_H - -#include "scene/3d/visual_instance.h" -#include "scene/resources/texture.h" -#include "servers/visual_server.h" - -class Light : public VisualInstance { - - GDCLASS(Light, VisualInstance); - OBJ_CATEGORY("3D Light Nodes"); - -public: - enum Param { - PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY, - PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY, - PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR, - PARAM_RANGE = VS::LIGHT_PARAM_RANGE, - PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION, - PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE, - PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION, - PARAM_CONTACT_SHADOW_SIZE = VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE, - PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, - PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, - PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, - PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, - PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START, - PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, - PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS, - PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, - PARAM_MAX = VS::LIGHT_PARAM_MAX - }; - - enum BakeMode { - BAKE_DISABLED, - BAKE_INDIRECT, - BAKE_ALL - }; - -private: - Color color; - float param[PARAM_MAX]; - Color shadow_color; - bool shadow; - bool negative; - bool reverse_cull; - uint32_t cull_mask; - VS::LightType type; - bool editor_only; - void _update_visibility(); - BakeMode bake_mode; - - // bind helpers - -protected: - RID light; - - virtual bool _can_gizmo_scale() const; - - static void _bind_methods(); - void _notification(int p_what); - virtual void _validate_property(PropertyInfo &property) const; - - Light(VisualServer::LightType p_type); - -public: - VS::LightType get_light_type() const { return type; } - - void set_editor_only(bool p_editor_only); - bool is_editor_only() const; - - void set_param(Param p_param, float p_value); - float get_param(Param p_param) const; - - void set_shadow(bool p_enable); - bool has_shadow() const; - - void set_negative(bool p_enable); - bool is_negative() const; - - void set_cull_mask(uint32_t p_cull_mask); - uint32_t get_cull_mask() const; - - void set_color(const Color &p_color); - Color get_color() const; - - void set_shadow_color(const Color &p_shadow_color); - Color get_shadow_color() const; - - void set_shadow_reverse_cull_face(bool p_enable); - bool get_shadow_reverse_cull_face() const; - - void set_bake_mode(BakeMode p_mode); - BakeMode get_bake_mode() const; - - virtual AABB get_aabb() const; - virtual Vector get_faces(uint32_t p_usage_flags) const; - - Light(); - ~Light(); -}; - -VARIANT_ENUM_CAST(Light::Param); -VARIANT_ENUM_CAST(Light::BakeMode); - -class DirectionalLight : public Light { - - GDCLASS(DirectionalLight, Light); - -public: - enum ShadowMode { - SHADOW_ORTHOGONAL, - SHADOW_PARALLEL_2_SPLITS, - SHADOW_PARALLEL_4_SPLITS - }; - - enum ShadowDepthRange { - SHADOW_DEPTH_RANGE_STABLE = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, - SHADOW_DEPTH_RANGE_OPTIMIZED = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, - }; - -private: - bool blend_splits; - ShadowMode shadow_mode; - ShadowDepthRange shadow_depth_range; - -protected: - static void _bind_methods(); - -public: - void set_shadow_mode(ShadowMode p_mode); - ShadowMode get_shadow_mode() const; - - void set_shadow_depth_range(ShadowDepthRange p_range); - ShadowDepthRange get_shadow_depth_range() const; - - void set_blend_splits(bool p_enable); - bool is_blend_splits_enabled() const; - - DirectionalLight(); -}; - -VARIANT_ENUM_CAST(DirectionalLight::ShadowMode) -VARIANT_ENUM_CAST(DirectionalLight::ShadowDepthRange) - -class OmniLight : public Light { - - GDCLASS(OmniLight, Light); - -public: - // omni light - enum ShadowMode { - SHADOW_DUAL_PARABOLOID, - SHADOW_CUBE, - }; - -private: - ShadowMode shadow_mode; - -protected: - static void _bind_methods(); - -public: - void set_shadow_mode(ShadowMode p_mode); - ShadowMode get_shadow_mode() const; - - OmniLight(); -}; - -VARIANT_ENUM_CAST(OmniLight::ShadowMode) - -class SpotLight : public Light { - - GDCLASS(SpotLight, Light); - -protected: - static void _bind_methods(); - -public: - virtual String get_configuration_warning() const; - - SpotLight() : - Light(VisualServer::LIGHT_SPOT) {} -}; - -#endif diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp new file mode 100644 index 0000000000..434f35fc57 --- /dev/null +++ b/scene/3d/light_3d.cpp @@ -0,0 +1,480 @@ +/*************************************************************************/ +/* light_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "light_3d.h" + +#include "core/engine.h" +#include "core/project_settings.h" +#include "scene/resources/surface_tool.h" + +bool Light3D::_can_gizmo_scale() const { + + return false; +} + +void Light3D::set_param(Param p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + param[p_param] = p_value; + + VS::get_singleton()->light_set_param(light, VS::LightParam(p_param), p_value); + + if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) { + update_gizmo(); + + if (p_param == PARAM_SPOT_ANGLE) { + _change_notify("spot_angle"); + update_configuration_warning(); + } else if (p_param == PARAM_RANGE) { + _change_notify("omni_range"); + _change_notify("spot_range"); + } + } +} + +float Light3D::get_param(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return param[p_param]; +} + +void Light3D::set_shadow(bool p_enable) { + + shadow = p_enable; + VS::get_singleton()->light_set_shadow(light, p_enable); + + if (type == VisualServer::LIGHT_SPOT) { + update_configuration_warning(); + } +} +bool Light3D::has_shadow() const { + + return shadow; +} + +void Light3D::set_negative(bool p_enable) { + + negative = p_enable; + VS::get_singleton()->light_set_negative(light, p_enable); +} +bool Light3D::is_negative() const { + + return negative; +} + +void Light3D::set_cull_mask(uint32_t p_cull_mask) { + + cull_mask = p_cull_mask; + VS::get_singleton()->light_set_cull_mask(light, p_cull_mask); +} +uint32_t Light3D::get_cull_mask() const { + + return cull_mask; +} + +void Light3D::set_color(const Color &p_color) { + + color = p_color; + VS::get_singleton()->light_set_color(light, p_color); + // The gizmo color depends on the light color, so update it. + update_gizmo(); +} +Color Light3D::get_color() const { + + return color; +} + +void Light3D::set_shadow_color(const Color &p_shadow_color) { + + shadow_color = p_shadow_color; + VS::get_singleton()->light_set_shadow_color(light, p_shadow_color); +} + +Color Light3D::get_shadow_color() const { + + return shadow_color; +} + +void Light3D::set_shadow_reverse_cull_face(bool p_enable) { + reverse_cull = p_enable; + VS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull); +} + +bool Light3D::get_shadow_reverse_cull_face() const { + + return reverse_cull; +} + +AABB Light3D::get_aabb() const { + + if (type == VisualServer::LIGHT_DIRECTIONAL) { + + return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + + } else if (type == VisualServer::LIGHT_OMNI) { + + return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]); + + } else if (type == VisualServer::LIGHT_SPOT) { + + float len = param[PARAM_RANGE]; + float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; + return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); + } + + return AABB(); +} + +Vector Light3D::get_faces(uint32_t p_usage_flags) const { + + return Vector(); +} + +void Light3D::set_bake_mode(BakeMode p_mode) { + bake_mode = p_mode; + VS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED); +} + +Light3D::BakeMode Light3D::get_bake_mode() const { + return bake_mode; +} + +void Light3D::_update_visibility() { + + if (!is_inside_tree()) + return; + + bool editor_ok = true; + +#ifdef TOOLS_ENABLED + if (editor_only) { + if (!Engine::get_singleton()->is_editor_hint()) { + editor_ok = false; + } else { + editor_ok = (get_tree()->get_edited_scene_root() && (this == get_tree()->get_edited_scene_root() || get_owner() == get_tree()->get_edited_scene_root())); + } + } +#else + if (editor_only) { + editor_ok = false; + } +#endif + + VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok); + + _change_notify("geometry/visible"); +} + +void Light3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + _update_visibility(); + } + + if (p_what == NOTIFICATION_ENTER_TREE) { + _update_visibility(); + } +} + +void Light3D::set_editor_only(bool p_editor_only) { + + editor_only = p_editor_only; + _update_visibility(); +} + +bool Light3D::is_editor_only() const { + + return editor_only; +} + +void Light3D::_validate_property(PropertyInfo &property) const { + + if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } +} + +void Light3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light3D::set_editor_only); + ClassDB::bind_method(D_METHOD("is_editor_only"), &Light3D::is_editor_only); + + ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &Light3D::set_param); + ClassDB::bind_method(D_METHOD("get_param", "param"), &Light3D::get_param); + + ClassDB::bind_method(D_METHOD("set_shadow", "enabled"), &Light3D::set_shadow); + ClassDB::bind_method(D_METHOD("has_shadow"), &Light3D::has_shadow); + + ClassDB::bind_method(D_METHOD("set_negative", "enabled"), &Light3D::set_negative); + ClassDB::bind_method(D_METHOD("is_negative"), &Light3D::is_negative); + + ClassDB::bind_method(D_METHOD("set_cull_mask", "cull_mask"), &Light3D::set_cull_mask); + ClassDB::bind_method(D_METHOD("get_cull_mask"), &Light3D::get_cull_mask); + + ClassDB::bind_method(D_METHOD("set_color", "color"), &Light3D::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &Light3D::get_color); + + ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light3D::set_shadow_reverse_cull_face); + ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light3D::get_shadow_reverse_cull_face); + + ClassDB::bind_method(D_METHOD("set_shadow_color", "shadow_color"), &Light3D::set_shadow_color); + ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light3D::get_shadow_color); + + ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode); + ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode); + + ADD_GROUP("Light", "light_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); + ADD_GROUP("Shadow", "shadow_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_contact", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face"); + ADD_GROUP("Editor", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only"); + ADD_GROUP("", ""); + + BIND_ENUM_CONSTANT(PARAM_ENERGY); + BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY); + BIND_ENUM_CONSTANT(PARAM_SPECULAR); + BIND_ENUM_CONSTANT(PARAM_RANGE); + BIND_ENUM_CONSTANT(PARAM_ATTENUATION); + BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE); + BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION); + BIND_ENUM_CONSTANT(PARAM_CONTACT_SHADOW_SIZE); + BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE); + BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET); + BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET); + BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET); + BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START); + BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS); + BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS); + BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_ENUM_CONSTANT(PARAM_MAX); + + BIND_ENUM_CONSTANT(BAKE_DISABLED); + BIND_ENUM_CONSTANT(BAKE_INDIRECT); + BIND_ENUM_CONSTANT(BAKE_ALL); +} + +Light3D::Light3D(VisualServer::LightType p_type) { + + type = p_type; + switch (p_type) { + case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break; + case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break; + case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break; + default: { + }; + } + + VS::get_singleton()->instance_set_base(get_instance(), light); + + reverse_cull = false; + bake_mode = BAKE_INDIRECT; + + editor_only = false; + set_color(Color(1, 1, 1, 1)); + set_shadow(false); + set_negative(false); + set_cull_mask(0xFFFFFFFF); + + set_param(PARAM_ENERGY, 1); + set_param(PARAM_INDIRECT_ENERGY, 1); + set_param(PARAM_SPECULAR, 0.5); + set_param(PARAM_RANGE, 5); + set_param(PARAM_ATTENUATION, 1); + set_param(PARAM_SPOT_ANGLE, 45); + set_param(PARAM_SPOT_ATTENUATION, 1); + set_param(PARAM_CONTACT_SHADOW_SIZE, 0); + set_param(PARAM_SHADOW_MAX_DISTANCE, 0); + set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1); + set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2); + set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5); + set_param(PARAM_SHADOW_FADE_START, 0.8); + set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0); + set_param(PARAM_SHADOW_BIAS, 0.15); + set_param(PARAM_SHADOW_FADE_START, 1); + set_disable_scale(true); +} + +Light3D::Light3D() { + + type = VisualServer::LIGHT_DIRECTIONAL; + ERR_PRINT("Light should not be instanced directly; use the DirectionalLight, OmniLight or SpotLight subtypes instead."); +} + +Light3D::~Light3D() { + + VS::get_singleton()->instance_set_base(get_instance(), RID()); + + if (light.is_valid()) + VisualServer::get_singleton()->free(light); +} +///////////////////////////////////////// + +void DirectionalLight3D::set_shadow_mode(ShadowMode p_mode) { + + shadow_mode = p_mode; + VS::get_singleton()->light_directional_set_shadow_mode(light, VS::LightDirectionalShadowMode(p_mode)); +} + +DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const { + + return shadow_mode; +} + +void DirectionalLight3D::set_shadow_depth_range(ShadowDepthRange p_range) { + shadow_depth_range = p_range; + VS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, VS::LightDirectionalShadowDepthRangeMode(p_range)); +} + +DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range() const { + + return shadow_depth_range; +} + +void DirectionalLight3D::set_blend_splits(bool p_enable) { + + blend_splits = p_enable; + VS::get_singleton()->light_directional_set_blend_splits(light, p_enable); +} + +bool DirectionalLight3D::is_blend_splits_enabled() const { + + return blend_splits; +} + +void DirectionalLight3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode); + ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode); + + ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight3D::set_shadow_depth_range); + ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight3D::get_shadow_depth_range); + + ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight3D::set_blend_splits); + ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled); + + ADD_GROUP("Directional Shadow", "directional_shadow_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), "set_shadow_mode", "get_shadow_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE); + ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); + + BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); + BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); + BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); + + BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE); + BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_OPTIMIZED); +} + +DirectionalLight3D::DirectionalLight3D() : + Light3D(VisualServer::LIGHT_DIRECTIONAL) { + + set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8); + set_param(PARAM_SHADOW_BIAS, 0.1); + set_param(PARAM_SHADOW_MAX_DISTANCE, 100); + set_param(PARAM_SHADOW_FADE_START, 0.8); + set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25); + set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); + set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE); + + blend_splits = false; +} + +void OmniLight3D::set_shadow_mode(ShadowMode p_mode) { + + shadow_mode = p_mode; + VS::get_singleton()->light_omni_set_shadow_mode(light, VS::LightOmniShadowMode(p_mode)); +} + +OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const { + + return shadow_mode; +} + +void OmniLight3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight3D::set_shadow_mode); + ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight3D::get_shadow_mode); + + ADD_GROUP("Omni", "omni_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION); + ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode"); + + BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID); + BIND_ENUM_CONSTANT(SHADOW_CUBE); +} + +OmniLight3D::OmniLight3D() : + Light3D(VisualServer::LIGHT_OMNI) { + + set_shadow_mode(SHADOW_CUBE); +} + +String SpotLight3D::get_configuration_warning() const { + String warning = Light3D::get_configuration_warning(); + + if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { + if (warning != String()) { + warning += "\n\n"; + } + + warning += TTR("A SpotLight with an angle wider than 90 degrees cannot cast shadows."); + } + + return warning; +} + +void SpotLight3D::_bind_methods() { + + ADD_GROUP("Spot", "spot_"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION); +} diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h new file mode 100644 index 0000000000..7b3273e1e4 --- /dev/null +++ b/scene/3d/light_3d.h @@ -0,0 +1,216 @@ +/*************************************************************************/ +/* light_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHT_H +#define LIGHT_H + +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/texture.h" +#include "servers/visual_server.h" + +class Light3D : public VisualInstance3D { + + GDCLASS(Light3D, VisualInstance3D); + OBJ_CATEGORY("3D Light Nodes"); + +public: + enum Param { + PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY, + PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY, + PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR, + PARAM_RANGE = VS::LIGHT_PARAM_RANGE, + PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION, + PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE, + PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION, + PARAM_CONTACT_SHADOW_SIZE = VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE, + PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, + PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, + PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, + PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, + PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START, + PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, + PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS, + PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, + PARAM_MAX = VS::LIGHT_PARAM_MAX + }; + + enum BakeMode { + BAKE_DISABLED, + BAKE_INDIRECT, + BAKE_ALL + }; + +private: + Color color; + float param[PARAM_MAX]; + Color shadow_color; + bool shadow; + bool negative; + bool reverse_cull; + uint32_t cull_mask; + VS::LightType type; + bool editor_only; + void _update_visibility(); + BakeMode bake_mode; + + // bind helpers + +protected: + RID light; + + virtual bool _can_gizmo_scale() const; + + static void _bind_methods(); + void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const; + + Light3D(VisualServer::LightType p_type); + +public: + VS::LightType get_light_type() const { return type; } + + void set_editor_only(bool p_editor_only); + bool is_editor_only() const; + + void set_param(Param p_param, float p_value); + float get_param(Param p_param) const; + + void set_shadow(bool p_enable); + bool has_shadow() const; + + void set_negative(bool p_enable); + bool is_negative() const; + + void set_cull_mask(uint32_t p_cull_mask); + uint32_t get_cull_mask() const; + + void set_color(const Color &p_color); + Color get_color() const; + + void set_shadow_color(const Color &p_shadow_color); + Color get_shadow_color() const; + + void set_shadow_reverse_cull_face(bool p_enable); + bool get_shadow_reverse_cull_face() const; + + void set_bake_mode(BakeMode p_mode); + BakeMode get_bake_mode() const; + + virtual AABB get_aabb() const; + virtual Vector get_faces(uint32_t p_usage_flags) const; + + Light3D(); + ~Light3D(); +}; + +VARIANT_ENUM_CAST(Light3D::Param); +VARIANT_ENUM_CAST(Light3D::BakeMode); + +class DirectionalLight3D : public Light3D { + + GDCLASS(DirectionalLight3D, Light3D); + +public: + enum ShadowMode { + SHADOW_ORTHOGONAL, + SHADOW_PARALLEL_2_SPLITS, + SHADOW_PARALLEL_4_SPLITS + }; + + enum ShadowDepthRange { + SHADOW_DEPTH_RANGE_STABLE = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, + SHADOW_DEPTH_RANGE_OPTIMIZED = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, + }; + +private: + bool blend_splits; + ShadowMode shadow_mode; + ShadowDepthRange shadow_depth_range; + +protected: + static void _bind_methods(); + +public: + void set_shadow_mode(ShadowMode p_mode); + ShadowMode get_shadow_mode() const; + + void set_shadow_depth_range(ShadowDepthRange p_range); + ShadowDepthRange get_shadow_depth_range() const; + + void set_blend_splits(bool p_enable); + bool is_blend_splits_enabled() const; + + DirectionalLight3D(); +}; + +VARIANT_ENUM_CAST(DirectionalLight3D::ShadowMode) +VARIANT_ENUM_CAST(DirectionalLight3D::ShadowDepthRange) + +class OmniLight3D : public Light3D { + + GDCLASS(OmniLight3D, Light3D); + +public: + // omni light + enum ShadowMode { + SHADOW_DUAL_PARABOLOID, + SHADOW_CUBE, + }; + +private: + ShadowMode shadow_mode; + +protected: + static void _bind_methods(); + +public: + void set_shadow_mode(ShadowMode p_mode); + ShadowMode get_shadow_mode() const; + + OmniLight3D(); +}; + +VARIANT_ENUM_CAST(OmniLight3D::ShadowMode) + +class SpotLight3D : public Light3D { + + GDCLASS(SpotLight3D, Light3D); + +protected: + static void _bind_methods(); + +public: + virtual String get_configuration_warning() const; + + SpotLight3D() : + Light3D(VisualServer::LIGHT_SPOT) {} +}; + +#endif diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp deleted file mode 100644 index 2779d14b57..0000000000 --- a/scene/3d/listener.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/*************************************************************************/ -/* listener.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "listener.h" - -#include "scene/resources/mesh.h" - -void Listener::_update_audio_listener_state() { -} - -void Listener::_request_listener_update() { - - _update_listener(); -} - -bool Listener::_set(const StringName &p_name, const Variant &p_value) { - - if (p_name == "current") { - if (p_value.operator bool()) { - make_current(); - } else { - clear_current(); - } - } else - return false; - - return true; -} -bool Listener::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == "current") { - if (is_inside_tree() && get_tree()->is_node_being_edited(this)) { - r_ret = current; - } else { - r_ret = is_current(); - } - } else - return false; - - return true; -} - -void Listener::_get_property_list(List *p_list) const { - - p_list->push_back(PropertyInfo(Variant::BOOL, "current")); -} - -void Listener::_update_listener() { - - if (is_inside_tree() && is_current()) { - get_viewport()->_listener_transform_changed_notify(); - } -} - -void Listener::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_WORLD: { - bool first_listener = get_viewport()->_listener_add(this); - if (!get_tree()->is_node_being_edited(this) && (current || first_listener)) - make_current(); - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - _request_listener_update(); - } break; - case NOTIFICATION_EXIT_WORLD: { - - if (!get_tree()->is_node_being_edited(this)) { - if (is_current()) { - clear_current(); - current = true; //keep it true - - } else { - current = false; - } - } - - get_viewport()->_listener_remove(this); - - } break; - } -} - -Transform Listener::get_listener_transform() const { - - return get_global_transform().orthonormalized(); -} - -void Listener::make_current() { - - current = true; - - if (!is_inside_tree()) - return; - - get_viewport()->_listener_set(this); -} - -void Listener::clear_current() { - - current = false; - if (!is_inside_tree()) - return; - - if (get_viewport()->get_listener() == this) { - get_viewport()->_listener_set(NULL); - get_viewport()->_listener_make_next_current(this); - } -} - -bool Listener::is_current() const { - - if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { - - return get_viewport()->get_listener() == this; - } else - return current; - - return false; -} - -bool Listener::_can_gizmo_scale() const { - - return false; -} - -RES Listener::_get_gizmo_geometry() const { - Ref mesh = memnew(ArrayMesh); - - return mesh; -} - -void Listener::_bind_methods() { - - ClassDB::bind_method(D_METHOD("make_current"), &Listener::make_current); - ClassDB::bind_method(D_METHOD("clear_current"), &Listener::clear_current); - ClassDB::bind_method(D_METHOD("is_current"), &Listener::is_current); - ClassDB::bind_method(D_METHOD("get_listener_transform"), &Listener::get_listener_transform); -} - -Listener::Listener() { - - current = false; - force_change = false; - set_notify_transform(true); - //active=false; -} - -Listener::~Listener() { -} diff --git a/scene/3d/listener.h b/scene/3d/listener.h deleted file mode 100644 index 17ff1d9397..0000000000 --- a/scene/3d/listener.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* listener.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef LISTENER_H -#define LISTENER_H - -#include "scene/3d/spatial.h" -#include "scene/main/window.h" - -class Listener : public Spatial { - - GDCLASS(Listener, Spatial); - -private: - bool force_change; - bool current; - - RID scenario_id; - - virtual bool _can_gizmo_scale() const; - virtual RES _get_gizmo_geometry() const; - - friend class Viewport; - void _update_audio_listener_state(); - -protected: - void _update_listener(); - virtual void _request_listener_update(); - - 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 *p_list) const; - void _notification(int p_what); - - static void _bind_methods(); - -public: - void make_current(); - void clear_current(); - bool is_current() const; - - virtual Transform get_listener_transform() const; - - void set_visible_layers(uint32_t p_layers); - uint32_t get_visible_layers() const; - - Listener(); - ~Listener(); -}; - -#endif diff --git a/scene/3d/listener_3d.cpp b/scene/3d/listener_3d.cpp new file mode 100644 index 0000000000..f352eb24b1 --- /dev/null +++ b/scene/3d/listener_3d.cpp @@ -0,0 +1,178 @@ +/*************************************************************************/ +/* listener_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "listener_3d.h" + +#include "scene/resources/mesh.h" + +void Listener3D::_update_audio_listener_state() { +} + +void Listener3D::_request_listener_update() { + + _update_listener(); +} + +bool Listener3D::_set(const StringName &p_name, const Variant &p_value) { + + if (p_name == "current") { + if (p_value.operator bool()) { + make_current(); + } else { + clear_current(); + } + } else + return false; + + return true; +} +bool Listener3D::_get(const StringName &p_name, Variant &r_ret) const { + + if (p_name == "current") { + if (is_inside_tree() && get_tree()->is_node_being_edited(this)) { + r_ret = current; + } else { + r_ret = is_current(); + } + } else + return false; + + return true; +} + +void Listener3D::_get_property_list(List *p_list) const { + + p_list->push_back(PropertyInfo(Variant::BOOL, "current")); +} + +void Listener3D::_update_listener() { + + if (is_inside_tree() && is_current()) { + get_viewport()->_listener_transform_changed_notify(); + } +} + +void Listener3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_WORLD: { + bool first_listener = get_viewport()->_listener_add(this); + if (!get_tree()->is_node_being_edited(this) && (current || first_listener)) + make_current(); + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + _request_listener_update(); + } break; + case NOTIFICATION_EXIT_WORLD: { + + if (!get_tree()->is_node_being_edited(this)) { + if (is_current()) { + clear_current(); + current = true; //keep it true + + } else { + current = false; + } + } + + get_viewport()->_listener_remove(this); + + } break; + } +} + +Transform Listener3D::get_listener_transform() const { + + return get_global_transform().orthonormalized(); +} + +void Listener3D::make_current() { + + current = true; + + if (!is_inside_tree()) + return; + + get_viewport()->_listener_set(this); +} + +void Listener3D::clear_current() { + + current = false; + if (!is_inside_tree()) + return; + + if (get_viewport()->get_listener() == this) { + get_viewport()->_listener_set(NULL); + get_viewport()->_listener_make_next_current(this); + } +} + +bool Listener3D::is_current() const { + + if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { + + return get_viewport()->get_listener() == this; + } else + return current; + + return false; +} + +bool Listener3D::_can_gizmo_scale() const { + + return false; +} + +RES Listener3D::_get_gizmo_geometry() const { + Ref mesh = memnew(ArrayMesh); + + return mesh; +} + +void Listener3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("make_current"), &Listener3D::make_current); + ClassDB::bind_method(D_METHOD("clear_current"), &Listener3D::clear_current); + ClassDB::bind_method(D_METHOD("is_current"), &Listener3D::is_current); + ClassDB::bind_method(D_METHOD("get_listener_transform"), &Listener3D::get_listener_transform); +} + +Listener3D::Listener3D() { + + current = false; + force_change = false; + set_notify_transform(true); + //active=false; +} + +Listener3D::~Listener3D() { +} diff --git a/scene/3d/listener_3d.h b/scene/3d/listener_3d.h new file mode 100644 index 0000000000..3383d6725e --- /dev/null +++ b/scene/3d/listener_3d.h @@ -0,0 +1,78 @@ +/*************************************************************************/ +/* listener_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LISTENER_3D_H +#define LISTENER_3D_H + +#include "scene/3d/node_3d.h" +#include "scene/main/window.h" + +class Listener3D : public Node3D { + + GDCLASS(Listener3D, Node3D); + +private: + bool force_change; + bool current; + + RID scenario_id; + + virtual bool _can_gizmo_scale() const; + virtual RES _get_gizmo_geometry() const; + + friend class Viewport; + void _update_audio_listener_state(); + +protected: + void _update_listener(); + virtual void _request_listener_update(); + + 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 *p_list) const; + void _notification(int p_what); + + static void _bind_methods(); + +public: + void make_current(); + void clear_current(); + bool is_current() const; + + virtual Transform get_listener_transform() const; + + void set_visible_layers(uint32_t p_layers); + uint32_t get_visible_layers() const; + + Listener3D(); + ~Listener3D(); +}; + +#endif diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp deleted file mode 100644 index 4ca139ebbc..0000000000 --- a/scene/3d/mesh_instance.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/*************************************************************************/ -/* mesh_instance.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "mesh_instance.h" - -#include "collision_shape.h" -#include "core/core_string_names.h" -#include "physics_body.h" -#include "scene/resources/material.h" -#include "skeleton.h" - -bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) { - - //this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else. - //add to it that it's probably found on first call to _set anyway. - - if (!get_instance().is_valid()) - return false; - - Map::Element *E = blend_shape_tracks.find(p_name); - if (E) { - E->get().value = p_value; - VisualServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), E->get().idx, E->get().value); - return true; - } - - if (p_name.operator String().begins_with("material/")) { - int idx = p_name.operator String().get_slicec('/', 1).to_int(); - if (idx >= materials.size() || idx < 0) - return false; - - set_surface_material(idx, p_value); - return true; - } - - return false; -} - -bool MeshInstance::_get(const StringName &p_name, Variant &r_ret) const { - - if (!get_instance().is_valid()) - return false; - - const Map::Element *E = blend_shape_tracks.find(p_name); - if (E) { - r_ret = E->get().value; - return true; - } - - if (p_name.operator String().begins_with("material/")) { - int idx = p_name.operator String().get_slicec('/', 1).to_int(); - if (idx >= materials.size() || idx < 0) - return false; - r_ret = materials[idx]; - return true; - } - return false; -} - -void MeshInstance::_get_property_list(List *p_list) const { - - List ls; - for (const Map::Element *E = blend_shape_tracks.front(); E; E = E->next()) { - - ls.push_back(E->key()); - } - - ls.sort(); - - for (List::Element *E = ls.front(); E; E = E->next()) { - p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "0,1,0.00001")); - } - - if (mesh.is_valid()) { - for (int i = 0; i < mesh->get_surface_count(); i++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE)); - } - } -} - -void MeshInstance::set_mesh(const Ref &p_mesh) { - - if (mesh == p_mesh) - return; - - if (mesh.is_valid()) { - mesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance::_mesh_changed)); - materials.clear(); - } - - mesh = p_mesh; - - blend_shape_tracks.clear(); - if (mesh.is_valid()) { - - for (int i = 0; i < mesh->get_blend_shape_count(); i++) { - - BlendShapeTrack mt; - mt.idx = i; - mt.value = 0; - blend_shape_tracks["blend_shapes/" + String(mesh->get_blend_shape_name(i))] = mt; - } - - mesh->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance::_mesh_changed)); - materials.resize(mesh->get_surface_count()); - - set_base(mesh->get_rid()); - } else { - - set_base(RID()); - } - - update_gizmo(); - - _change_notify(); -} -Ref MeshInstance::get_mesh() const { - - return mesh; -} - -void MeshInstance::_resolve_skeleton_path() { - - Ref new_skin_reference; - - if (!skeleton_path.is_empty()) { - Skeleton *skeleton = Object::cast_to(get_node(skeleton_path)); - if (skeleton) { - new_skin_reference = skeleton->register_skin(skin_internal); - if (skin_internal.is_null()) { - //a skin was created for us - skin_internal = new_skin_reference->get_skin(); - _change_notify(); - } - } - } - - skin_ref = new_skin_reference; - - if (skin_ref.is_valid()) { - VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton()); - } else { - VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), RID()); - } -} - -void MeshInstance::set_skin(const Ref &p_skin) { - skin_internal = p_skin; - skin = p_skin; - if (!is_inside_tree()) - return; - _resolve_skeleton_path(); -} - -Ref MeshInstance::get_skin() const { - return skin; -} - -void MeshInstance::set_skeleton_path(const NodePath &p_skeleton) { - - skeleton_path = p_skeleton; - if (!is_inside_tree()) - return; - _resolve_skeleton_path(); -} - -NodePath MeshInstance::get_skeleton_path() { - return skeleton_path; -} - -AABB MeshInstance::get_aabb() const { - - if (!mesh.is_null()) - return mesh->get_aabb(); - - return AABB(); -} - -Vector MeshInstance::get_faces(uint32_t p_usage_flags) const { - - if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) - return Vector(); - - if (mesh.is_null()) - return Vector(); - - return mesh->get_faces(); -} - -Node *MeshInstance::create_trimesh_collision_node() { - - if (mesh.is_null()) - return NULL; - - Ref shape = mesh->create_trimesh_shape(); - if (shape.is_null()) - return NULL; - - StaticBody *static_body = memnew(StaticBody); - CollisionShape *cshape = memnew(CollisionShape); - cshape->set_shape(shape); - static_body->add_child(cshape); - return static_body; -} - -void MeshInstance::create_trimesh_collision() { - - StaticBody *static_body = Object::cast_to(create_trimesh_collision_node()); - ERR_FAIL_COND(!static_body); - static_body->set_name(String(get_name()) + "_col"); - - add_child(static_body); - if (get_owner()) { - CollisionShape *cshape = Object::cast_to(static_body->get_child(0)); - static_body->set_owner(get_owner()); - cshape->set_owner(get_owner()); - } -} - -Node *MeshInstance::create_convex_collision_node() { - - if (mesh.is_null()) - return NULL; - - Ref shape = mesh->create_convex_shape(); - if (shape.is_null()) - return NULL; - - StaticBody *static_body = memnew(StaticBody); - CollisionShape *cshape = memnew(CollisionShape); - cshape->set_shape(shape); - static_body->add_child(cshape); - return static_body; -} - -void MeshInstance::create_convex_collision() { - - StaticBody *static_body = Object::cast_to(create_convex_collision_node()); - ERR_FAIL_COND(!static_body); - static_body->set_name(String(get_name()) + "_col"); - - add_child(static_body); - if (get_owner()) { - CollisionShape *cshape = Object::cast_to(static_body->get_child(0)); - static_body->set_owner(get_owner()); - cshape->set_owner(get_owner()); - } -} - -void MeshInstance::_notification(int p_what) { - - if (p_what == NOTIFICATION_ENTER_TREE) { - _resolve_skeleton_path(); - } -} - -int MeshInstance::get_surface_material_count() const { - - return materials.size(); -} - -void MeshInstance::set_surface_material(int p_surface, const Ref &p_material) { - - ERR_FAIL_INDEX(p_surface, materials.size()); - - materials.write[p_surface] = p_material; - - if (materials[p_surface].is_valid()) - VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); - else - VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID()); -} - -Ref MeshInstance::get_surface_material(int p_surface) const { - - ERR_FAIL_INDEX_V(p_surface, materials.size(), Ref()); - - return materials[p_surface]; -} - -void MeshInstance::_mesh_changed() { - - materials.resize(mesh->get_surface_count()); -} - -void MeshInstance::create_debug_tangents() { - - Vector lines; - Vector colors; - - Ref mesh = get_mesh(); - if (!mesh.is_valid()) - return; - - for (int i = 0; i < mesh->get_surface_count(); i++) { - Array arrays = mesh->surface_get_arrays(i); - Vector verts = arrays[Mesh::ARRAY_VERTEX]; - Vector norms = arrays[Mesh::ARRAY_NORMAL]; - if (norms.size() == 0) - continue; - Vector tangents = arrays[Mesh::ARRAY_TANGENT]; - if (tangents.size() == 0) - continue; - - for (int j = 0; j < verts.size(); j++) { - Vector3 v = verts[j]; - Vector3 n = norms[j]; - Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]); - Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3]; - - lines.push_back(v); //normal - colors.push_back(Color(0, 0, 1)); //color - lines.push_back(v + n * 0.04); //normal - colors.push_back(Color(0, 0, 1)); //color - - lines.push_back(v); //tangent - colors.push_back(Color(1, 0, 0)); //color - lines.push_back(v + t * 0.04); //tangent - colors.push_back(Color(1, 0, 0)); //color - - lines.push_back(v); //binormal - colors.push_back(Color(0, 1, 0)); //color - lines.push_back(v + b * 0.04); //binormal - colors.push_back(Color(0, 1, 0)); //color - } - } - - if (lines.size()) { - - Ref sm; - sm.instance(); - - sm->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - sm->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); - sm->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - - Ref am; - am.instance(); - Array a; - a.resize(Mesh::ARRAY_MAX); - a[Mesh::ARRAY_VERTEX] = lines; - a[Mesh::ARRAY_COLOR] = colors; - - am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); - am->surface_set_material(0, sm); - - MeshInstance *mi = memnew(MeshInstance); - mi->set_mesh(am); - mi->set_name("DebugTangents"); - add_child(mi); -#ifdef TOOLS_ENABLED - - if (this == get_tree()->get_edited_scene_root()) - mi->set_owner(this); - else - mi->set_owner(get_owner()); -#endif - } -} - -void MeshInstance::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance::get_mesh); - ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance::set_skeleton_path); - ClassDB::bind_method(D_METHOD("get_skeleton_path"), &MeshInstance::get_skeleton_path); - ClassDB::bind_method(D_METHOD("set_skin", "skin"), &MeshInstance::set_skin); - ClassDB::bind_method(D_METHOD("get_skin"), &MeshInstance::get_skin); - - ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance::get_surface_material_count); - ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance::set_surface_material); - ClassDB::bind_method(D_METHOD("get_surface_material", "surface"), &MeshInstance::get_surface_material); - - ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance::create_trimesh_collision); - ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT); - ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance::create_convex_collision); - ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT); - - ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents); - ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); - ADD_GROUP("Skeleton", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path"); - ADD_GROUP("", ""); -} - -MeshInstance::MeshInstance() { - skeleton_path = NodePath(".."); -} - -MeshInstance::~MeshInstance() { -} diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h deleted file mode 100644 index a6190e7660..0000000000 --- a/scene/3d/mesh_instance.h +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************/ -/* mesh_instance.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef MESH_INSTANCE_H -#define MESH_INSTANCE_H - -#include "scene/3d/skeleton.h" -#include "scene/3d/visual_instance.h" -#include "scene/resources/mesh.h" -#include "scene/resources/skin.h" - -class MeshInstance : public GeometryInstance { - - GDCLASS(MeshInstance, GeometryInstance); - -protected: - Ref mesh; - Ref skin; - Ref skin_internal; - Ref skin_ref; - NodePath skeleton_path; - - struct BlendShapeTrack { - - int idx; - float value; - BlendShapeTrack() { - idx = 0; - value = 0; - } - }; - - Map blend_shape_tracks; - Vector> materials; - - void _mesh_changed(); - void _resolve_skeleton_path(); - -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 *p_list) const; - - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_mesh(const Ref &p_mesh); - Ref get_mesh() const; - - void set_skin(const Ref &p_skin); - Ref get_skin() const; - - void set_skeleton_path(const NodePath &p_skeleton); - NodePath get_skeleton_path(); - - int get_surface_material_count() const; - void set_surface_material(int p_surface, const Ref &p_material); - Ref get_surface_material(int p_surface) const; - - Node *create_trimesh_collision_node(); - void create_trimesh_collision(); - - Node *create_convex_collision_node(); - void create_convex_collision(); - - void create_debug_tangents(); - - virtual AABB get_aabb() const; - virtual Vector get_faces(uint32_t p_usage_flags) const; - - MeshInstance(); - ~MeshInstance(); -}; - -#endif diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp new file mode 100644 index 0000000000..5f826505b4 --- /dev/null +++ b/scene/3d/mesh_instance_3d.cpp @@ -0,0 +1,421 @@ +/*************************************************************************/ +/* mesh_instance_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "mesh_instance_3d.h" + +#include "collision_shape_3d.h" +#include "core/core_string_names.h" +#include "physics_body_3d.h" +#include "scene/resources/material.h" +#include "skeleton_3d.h" + +bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) { + + //this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else. + //add to it that it's probably found on first call to _set anyway. + + if (!get_instance().is_valid()) + return false; + + Map::Element *E = blend_shape_tracks.find(p_name); + if (E) { + E->get().value = p_value; + VisualServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), E->get().idx, E->get().value); + return true; + } + + if (p_name.operator String().begins_with("material/")) { + int idx = p_name.operator String().get_slicec('/', 1).to_int(); + if (idx >= materials.size() || idx < 0) + return false; + + set_surface_material(idx, p_value); + return true; + } + + return false; +} + +bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const { + + if (!get_instance().is_valid()) + return false; + + const Map::Element *E = blend_shape_tracks.find(p_name); + if (E) { + r_ret = E->get().value; + return true; + } + + if (p_name.operator String().begins_with("material/")) { + int idx = p_name.operator String().get_slicec('/', 1).to_int(); + if (idx >= materials.size() || idx < 0) + return false; + r_ret = materials[idx]; + return true; + } + return false; +} + +void MeshInstance3D::_get_property_list(List *p_list) const { + + List ls; + for (const Map::Element *E = blend_shape_tracks.front(); E; E = E->next()) { + + ls.push_back(E->key()); + } + + ls.sort(); + + for (List::Element *E = ls.front(); E; E = E->next()) { + p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "0,1,0.00001")); + } + + if (mesh.is_valid()) { + for (int i = 0; i < mesh->get_surface_count(); i++) { + p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE)); + } + } +} + +void MeshInstance3D::set_mesh(const Ref &p_mesh) { + + if (mesh == p_mesh) + return; + + if (mesh.is_valid()) { + mesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed)); + materials.clear(); + } + + mesh = p_mesh; + + blend_shape_tracks.clear(); + if (mesh.is_valid()) { + + for (int i = 0; i < mesh->get_blend_shape_count(); i++) { + + BlendShapeTrack mt; + mt.idx = i; + mt.value = 0; + blend_shape_tracks["blend_shapes/" + String(mesh->get_blend_shape_name(i))] = mt; + } + + mesh->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed)); + materials.resize(mesh->get_surface_count()); + + set_base(mesh->get_rid()); + } else { + + set_base(RID()); + } + + update_gizmo(); + + _change_notify(); +} +Ref MeshInstance3D::get_mesh() const { + + return mesh; +} + +void MeshInstance3D::_resolve_skeleton_path() { + + Ref new_skin_reference; + + if (!skeleton_path.is_empty()) { + Skeleton3D *skeleton = Object::cast_to(get_node(skeleton_path)); + if (skeleton) { + new_skin_reference = skeleton->register_skin(skin_internal); + if (skin_internal.is_null()) { + //a skin was created for us + skin_internal = new_skin_reference->get_skin(); + _change_notify(); + } + } + } + + skin_ref = new_skin_reference; + + if (skin_ref.is_valid()) { + VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton()); + } else { + VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), RID()); + } +} + +void MeshInstance3D::set_skin(const Ref &p_skin) { + skin_internal = p_skin; + skin = p_skin; + if (!is_inside_tree()) + return; + _resolve_skeleton_path(); +} + +Ref MeshInstance3D::get_skin() const { + return skin; +} + +void MeshInstance3D::set_skeleton_path(const NodePath &p_skeleton) { + + skeleton_path = p_skeleton; + if (!is_inside_tree()) + return; + _resolve_skeleton_path(); +} + +NodePath MeshInstance3D::get_skeleton_path() { + return skeleton_path; +} + +AABB MeshInstance3D::get_aabb() const { + + if (!mesh.is_null()) + return mesh->get_aabb(); + + return AABB(); +} + +Vector MeshInstance3D::get_faces(uint32_t p_usage_flags) const { + + if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) + return Vector(); + + if (mesh.is_null()) + return Vector(); + + return mesh->get_faces(); +} + +Node *MeshInstance3D::create_trimesh_collision_node() { + + if (mesh.is_null()) + return NULL; + + Ref shape = mesh->create_trimesh_shape(); + if (shape.is_null()) + return NULL; + + StaticBody3D *static_body = memnew(StaticBody3D); + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(shape); + static_body->add_child(cshape); + return static_body; +} + +void MeshInstance3D::create_trimesh_collision() { + + StaticBody3D *static_body = Object::cast_to(create_trimesh_collision_node()); + ERR_FAIL_COND(!static_body); + static_body->set_name(String(get_name()) + "_col"); + + add_child(static_body); + if (get_owner()) { + CollisionShape3D *cshape = Object::cast_to(static_body->get_child(0)); + static_body->set_owner(get_owner()); + cshape->set_owner(get_owner()); + } +} + +Node *MeshInstance3D::create_convex_collision_node() { + + if (mesh.is_null()) + return NULL; + + Ref shape = mesh->create_convex_shape(); + if (shape.is_null()) + return NULL; + + StaticBody3D *static_body = memnew(StaticBody3D); + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(shape); + static_body->add_child(cshape); + return static_body; +} + +void MeshInstance3D::create_convex_collision() { + + StaticBody3D *static_body = Object::cast_to(create_convex_collision_node()); + ERR_FAIL_COND(!static_body); + static_body->set_name(String(get_name()) + "_col"); + + add_child(static_body); + if (get_owner()) { + CollisionShape3D *cshape = Object::cast_to(static_body->get_child(0)); + static_body->set_owner(get_owner()); + cshape->set_owner(get_owner()); + } +} + +void MeshInstance3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + _resolve_skeleton_path(); + } +} + +int MeshInstance3D::get_surface_material_count() const { + + return materials.size(); +} + +void MeshInstance3D::set_surface_material(int p_surface, const Ref &p_material) { + + ERR_FAIL_INDEX(p_surface, materials.size()); + + materials.write[p_surface] = p_material; + + if (materials[p_surface].is_valid()) + VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); + else + VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID()); +} + +Ref MeshInstance3D::get_surface_material(int p_surface) const { + + ERR_FAIL_INDEX_V(p_surface, materials.size(), Ref()); + + return materials[p_surface]; +} + +void MeshInstance3D::_mesh_changed() { + + materials.resize(mesh->get_surface_count()); +} + +void MeshInstance3D::create_debug_tangents() { + + Vector lines; + Vector colors; + + Ref mesh = get_mesh(); + if (!mesh.is_valid()) + return; + + for (int i = 0; i < mesh->get_surface_count(); i++) { + Array arrays = mesh->surface_get_arrays(i); + Vector verts = arrays[Mesh::ARRAY_VERTEX]; + Vector norms = arrays[Mesh::ARRAY_NORMAL]; + if (norms.size() == 0) + continue; + Vector tangents = arrays[Mesh::ARRAY_TANGENT]; + if (tangents.size() == 0) + continue; + + for (int j = 0; j < verts.size(); j++) { + Vector3 v = verts[j]; + Vector3 n = norms[j]; + Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]); + Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3]; + + lines.push_back(v); //normal + colors.push_back(Color(0, 0, 1)); //color + lines.push_back(v + n * 0.04); //normal + colors.push_back(Color(0, 0, 1)); //color + + lines.push_back(v); //tangent + colors.push_back(Color(1, 0, 0)); //color + lines.push_back(v + t * 0.04); //tangent + colors.push_back(Color(1, 0, 0)); //color + + lines.push_back(v); //binormal + colors.push_back(Color(0, 1, 0)); //color + lines.push_back(v + b * 0.04); //binormal + colors.push_back(Color(0, 1, 0)); //color + } + } + + if (lines.size()) { + + Ref sm; + sm.instance(); + + sm->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + sm->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + sm->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + + Ref am; + am.instance(); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX] = lines; + a[Mesh::ARRAY_COLOR] = colors; + + am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); + am->surface_set_material(0, sm); + + MeshInstance3D *mi = memnew(MeshInstance3D); + mi->set_mesh(am); + mi->set_name("DebugTangents"); + add_child(mi); +#ifdef TOOLS_ENABLED + + if (this == get_tree()->get_edited_scene_root()) + mi->set_owner(this); + else + mi->set_owner(get_owner()); +#endif + } +} + +void MeshInstance3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance3D::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance3D::get_mesh); + ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance3D::set_skeleton_path); + ClassDB::bind_method(D_METHOD("get_skeleton_path"), &MeshInstance3D::get_skeleton_path); + ClassDB::bind_method(D_METHOD("set_skin", "skin"), &MeshInstance3D::set_skin); + ClassDB::bind_method(D_METHOD("get_skin"), &MeshInstance3D::get_skin); + + ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance3D::get_surface_material_count); + ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance3D::set_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_material", "surface"), &MeshInstance3D::get_surface_material); + + ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance3D::create_trimesh_collision); + ClassDB::set_method_flags("MeshInstance3D", "create_trimesh_collision", METHOD_FLAGS_DEFAULT); + ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance3D::create_convex_collision); + ClassDB::set_method_flags("MeshInstance3D", "create_convex_collision", METHOD_FLAGS_DEFAULT); + + ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance3D::create_debug_tangents); + ClassDB::set_method_flags("MeshInstance3D", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_GROUP("Skeleton", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton3D"), "set_skeleton_path", "get_skeleton_path"); + ADD_GROUP("", ""); +} + +MeshInstance3D::MeshInstance3D() { + skeleton_path = NodePath(".."); +} + +MeshInstance3D::~MeshInstance3D() { +} diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h new file mode 100644 index 0000000000..e45f68e295 --- /dev/null +++ b/scene/3d/mesh_instance_3d.h @@ -0,0 +1,103 @@ +/*************************************************************************/ +/* mesh_instance_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MESH_INSTANCE_H +#define MESH_INSTANCE_H + +#include "scene/3d/skeleton_3d.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/mesh.h" +#include "scene/resources/skin.h" + +class MeshInstance3D : public GeometryInstance3D { + + GDCLASS(MeshInstance3D, GeometryInstance3D); + +protected: + Ref mesh; + Ref skin; + Ref skin_internal; + Ref skin_ref; + NodePath skeleton_path; + + struct BlendShapeTrack { + + int idx; + float value; + BlendShapeTrack() { + idx = 0; + value = 0; + } + }; + + Map blend_shape_tracks; + Vector> materials; + + void _mesh_changed(); + void _resolve_skeleton_path(); + +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 *p_list) const; + + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_mesh(const Ref &p_mesh); + Ref get_mesh() const; + + void set_skin(const Ref &p_skin); + Ref get_skin() const; + + void set_skeleton_path(const NodePath &p_skeleton); + NodePath get_skeleton_path(); + + int get_surface_material_count() const; + void set_surface_material(int p_surface, const Ref &p_material); + Ref get_surface_material(int p_surface) const; + + Node *create_trimesh_collision_node(); + void create_trimesh_collision(); + + Node *create_convex_collision_node(); + void create_convex_collision(); + + void create_debug_tangents(); + + virtual AABB get_aabb() const; + virtual Vector get_faces(uint32_t p_usage_flags) const; + + MeshInstance3D(); + ~MeshInstance3D(); +}; + +#endif diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp deleted file mode 100644 index 075eb0a1ec..0000000000 --- a/scene/3d/multimesh_instance.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************/ -/* multimesh_instance.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "multimesh_instance.h" - -void MultiMeshInstance::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance::set_multimesh); - ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance::get_multimesh); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh"); -} - -void MultiMeshInstance::set_multimesh(const Ref &p_multimesh) { - - multimesh = p_multimesh; - if (multimesh.is_valid()) - set_base(multimesh->get_rid()); - else - set_base(RID()); -} - -Ref MultiMeshInstance::get_multimesh() const { - - return multimesh; -} - -Vector MultiMeshInstance::get_faces(uint32_t p_usage_flags) const { - - return Vector(); -} - -AABB MultiMeshInstance::get_aabb() const { - - if (multimesh.is_null()) - return AABB(); - else - return multimesh->get_aabb(); -} - -MultiMeshInstance::MultiMeshInstance() { -} - -MultiMeshInstance::~MultiMeshInstance() { -} diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h deleted file mode 100644 index 2b59c3b96c..0000000000 --- a/scene/3d/multimesh_instance.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* multimesh_instance.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef MULTIMESH_INSTANCE_H -#define MULTIMESH_INSTANCE_H - -#include "scene/3d/visual_instance.h" -#include "scene/resources/multimesh.h" - -class MultiMeshInstance : public GeometryInstance { - GDCLASS(MultiMeshInstance, GeometryInstance); - - Ref multimesh; - -protected: - static void _bind_methods(); - // bind helpers - -public: - virtual Vector get_faces(uint32_t p_usage_flags) const; - - void set_multimesh(const Ref &p_multimesh); - Ref get_multimesh() const; - - virtual AABB get_aabb() const; - - MultiMeshInstance(); - ~MultiMeshInstance(); -}; - -#endif // MULTIMESH_INSTANCE_H diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp new file mode 100644 index 0000000000..a625a34283 --- /dev/null +++ b/scene/3d/multimesh_instance_3d.cpp @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* multimesh_instance_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "multimesh_instance_3d.h" + +void MultiMeshInstance3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance3D::set_multimesh); + ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance3D::get_multimesh); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh"); +} + +void MultiMeshInstance3D::set_multimesh(const Ref &p_multimesh) { + + multimesh = p_multimesh; + if (multimesh.is_valid()) + set_base(multimesh->get_rid()); + else + set_base(RID()); +} + +Ref MultiMeshInstance3D::get_multimesh() const { + + return multimesh; +} + +Vector MultiMeshInstance3D::get_faces(uint32_t p_usage_flags) const { + + return Vector(); +} + +AABB MultiMeshInstance3D::get_aabb() const { + + if (multimesh.is_null()) + return AABB(); + else + return multimesh->get_aabb(); +} + +MultiMeshInstance3D::MultiMeshInstance3D() { +} + +MultiMeshInstance3D::~MultiMeshInstance3D() { +} diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h new file mode 100644 index 0000000000..87ec9e120e --- /dev/null +++ b/scene/3d/multimesh_instance_3d.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* multimesh_instance_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef MULTIMESH_INSTANCE_3D_H +#define MULTIMESH_INSTANCE_3D_H + +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/multimesh.h" + +class MultiMeshInstance3D : public GeometryInstance3D { + GDCLASS(MultiMeshInstance3D, GeometryInstance3D); + + Ref multimesh; + +protected: + static void _bind_methods(); + // bind helpers + +public: + virtual Vector get_faces(uint32_t p_usage_flags) const; + + void set_multimesh(const Ref &p_multimesh); + Ref get_multimesh() const; + + virtual AABB get_aabb() const; + + MultiMeshInstance3D(); + ~MultiMeshInstance3D(); +}; + +#endif // MULTIMESH_INSTANCE_H diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp deleted file mode 100644 index 8c543bc97f..0000000000 --- a/scene/3d/navigation.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/*************************************************************************/ -/* navigation.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation.h" - -#include "servers/navigation_server.h" - -Vector Navigation::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const { - - return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); -} - -Vector3 Navigation::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const { - return NavigationServer::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision); -} - -Vector3 Navigation::get_closest_point(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point(map, p_point); -} - -Vector3 Navigation::get_closest_point_normal(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point_normal(map, p_point); -} - -RID Navigation::get_closest_point_owner(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point_owner(map, p_point); -} - -void Navigation::set_up_vector(const Vector3 &p_up) { - - up = p_up; - NavigationServer::get_singleton()->map_set_up(map, up); -} - -Vector3 Navigation::get_up_vector() const { - - return up; -} - -void Navigation::set_cell_size(float p_cell_size) { - cell_size = p_cell_size; - NavigationServer::get_singleton()->map_set_cell_size(map, cell_size); -} - -void Navigation::set_edge_connection_margin(float p_edge_connection_margin) { - edge_connection_margin = p_edge_connection_margin; - NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); -} - -void Navigation::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_rid"), &Navigation::get_rid); - - ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation::get_simple_path, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation::get_closest_point_to_segment, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation::get_closest_point); - ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation::get_closest_point_normal); - ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation::get_closest_point_owner); - - ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation::set_up_vector); - ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation::get_up_vector); - - ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation::set_cell_size); - ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation::get_cell_size); - - ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation::set_edge_connection_margin); - ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation::get_edge_connection_margin); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); -} - -void Navigation::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - NavigationServer::get_singleton()->map_set_active(map, true); - } break; - case NOTIFICATION_EXIT_TREE: { - - NavigationServer::get_singleton()->map_set_active(map, false); - } break; - } -} - -Navigation::Navigation() { - - map = NavigationServer::get_singleton()->map_create(); - - set_cell_size(0.3); - set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius - - up = Vector3(0, 1, 0); -} - -Navigation::~Navigation() { - NavigationServer::get_singleton()->free(map); -} diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h deleted file mode 100644 index 08f306611f..0000000000 --- a/scene/3d/navigation.h +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* navigation.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_H -#define NAVIGATION_H - -#include "scene/3d/navigation_region.h" -#include "scene/3d/spatial.h" - -class Navigation : public Spatial { - - GDCLASS(Navigation, Spatial); - - RID map; - - Vector3 up; - real_t cell_size; - real_t edge_connection_margin; - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - RID get_rid() const { - return map; - } - - void set_up_vector(const Vector3 &p_up); - Vector3 get_up_vector() const; - - void set_cell_size(float p_cell_size); - float get_cell_size() const { - return cell_size; - } - - void set_edge_connection_margin(float p_edge_connection_margin); - float get_edge_connection_margin() const { - return edge_connection_margin; - } - - Vector get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const; - Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const; - Vector3 get_closest_point(const Vector3 &p_point) const; - Vector3 get_closest_point_normal(const Vector3 &p_point) const; - RID get_closest_point_owner(const Vector3 &p_point) const; - - Navigation(); - ~Navigation(); -}; - -#endif // NAVIGATION_H diff --git a/scene/3d/navigation_3d.cpp b/scene/3d/navigation_3d.cpp new file mode 100644 index 0000000000..28da04fcbe --- /dev/null +++ b/scene/3d/navigation_3d.cpp @@ -0,0 +1,125 @@ +/*************************************************************************/ +/* navigation_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_3d.h" + +#include "servers/navigation_server.h" + +Vector Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const { + + return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); +} + +Vector3 Navigation3D::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const { + return NavigationServer::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision); +} + +Vector3 Navigation3D::get_closest_point(const Vector3 &p_point) const { + return NavigationServer::get_singleton()->map_get_closest_point(map, p_point); +} + +Vector3 Navigation3D::get_closest_point_normal(const Vector3 &p_point) const { + return NavigationServer::get_singleton()->map_get_closest_point_normal(map, p_point); +} + +RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const { + return NavigationServer::get_singleton()->map_get_closest_point_owner(map, p_point); +} + +void Navigation3D::set_up_vector(const Vector3 &p_up) { + + up = p_up; + NavigationServer::get_singleton()->map_set_up(map, up); +} + +Vector3 Navigation3D::get_up_vector() const { + + return up; +} + +void Navigation3D::set_cell_size(float p_cell_size) { + cell_size = p_cell_size; + NavigationServer::get_singleton()->map_set_cell_size(map, cell_size); +} + +void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) { + edge_connection_margin = p_edge_connection_margin; + NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); +} + +void Navigation3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_rid"), &Navigation3D::get_rid); + + ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation3D::get_simple_path, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation3D::get_closest_point_to_segment, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation3D::get_closest_point); + ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation3D::get_closest_point_normal); + ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation3D::get_closest_point_owner); + + ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation3D::set_up_vector); + ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation3D::get_up_vector); + + ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation3D::set_cell_size); + ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation3D::get_cell_size); + + ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation3D::set_edge_connection_margin); + ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation3D::get_edge_connection_margin); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); +} + +void Navigation3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + NavigationServer::get_singleton()->map_set_active(map, true); + } break; + case NOTIFICATION_EXIT_TREE: { + + NavigationServer::get_singleton()->map_set_active(map, false); + } break; + } +} + +Navigation3D::Navigation3D() { + + map = NavigationServer::get_singleton()->map_create(); + + set_cell_size(0.3); + set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius + + up = Vector3(0, 1, 0); +} + +Navigation3D::~Navigation3D() { + NavigationServer::get_singleton()->free(map); +} diff --git a/scene/3d/navigation_3d.h b/scene/3d/navigation_3d.h new file mode 100644 index 0000000000..daa9558125 --- /dev/null +++ b/scene/3d/navigation_3d.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* navigation_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_3D_H +#define NAVIGATION_3D_H + +#include "scene/3d/navigation_region_3d.h" +#include "scene/3d/node_3d.h" + +class Navigation3D : public Node3D { + + GDCLASS(Navigation3D, Node3D); + + RID map; + + Vector3 up; + real_t cell_size; + real_t edge_connection_margin; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + RID get_rid() const { + return map; + } + + void set_up_vector(const Vector3 &p_up); + Vector3 get_up_vector() const; + + void set_cell_size(float p_cell_size); + float get_cell_size() const { + return cell_size; + } + + void set_edge_connection_margin(float p_edge_connection_margin); + float get_edge_connection_margin() const { + return edge_connection_margin; + } + + Vector get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const; + Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const; + Vector3 get_closest_point(const Vector3 &p_point) const; + Vector3 get_closest_point_normal(const Vector3 &p_point) const; + RID get_closest_point_owner(const Vector3 &p_point) const; + + Navigation3D(); + ~Navigation3D(); +}; + +#endif // NAVIGATION_H diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp deleted file mode 100644 index 3da1ea66d6..0000000000 --- a/scene/3d/navigation_agent.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/*************************************************************************/ -/* navigation_agent.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation_agent.h" - -#include "core/engine.h" -#include "scene/3d/navigation.h" -#include "servers/navigation_server.h" - -void NavigationAgent::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent::set_target_desired_distance); - ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent::get_target_desired_distance); - - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent::get_radius); - - ClassDB::bind_method(D_METHOD("set_agent_height_offset", "agent_height_offset"), &NavigationAgent::set_agent_height_offset); - ClassDB::bind_method(D_METHOD("get_agent_height_offset"), &NavigationAgent::get_agent_height_offset); - - ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent::set_ignore_y); - ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent::get_ignore_y); - - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent::get_navigation_node); - - ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent::set_neighbor_dist); - ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent::get_neighbor_dist); - - ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent::set_max_neighbors); - ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent::get_max_neighbors); - - ClassDB::bind_method(D_METHOD("set_time_horizon", "time_horizon"), &NavigationAgent::set_time_horizon); - ClassDB::bind_method(D_METHOD("get_time_horizon"), &NavigationAgent::get_time_horizon); - - ClassDB::bind_method(D_METHOD("set_max_speed", "max_speed"), &NavigationAgent::set_max_speed); - ClassDB::bind_method(D_METHOD("get_max_speed"), &NavigationAgent::get_max_speed); - - ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent::set_path_max_distance); - ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent::get_path_max_distance); - - ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent::set_target_location); - ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent::get_target_location); - ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent::get_next_location); - ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent::distance_to_target); - ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent::set_velocity); - ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent::get_nav_path); - ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent::get_nav_path_index); - ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent::is_target_reached); - ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent::is_target_reachable); - ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent::is_navigation_finished); - ClassDB::bind_method(D_METHOD("get_final_location"), &NavigationAgent::get_final_location); - - ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent::_avoidance_done); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01"), "set_agent_height_offset", "get_agent_height_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_neighbor_dist", "get_neighbor_dist"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_time_horizon", "get_time_horizon"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_max_speed", "get_max_speed"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1"), "set_path_max_distance", "get_path_max_distance"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); - - ADD_SIGNAL(MethodInfo("path_changed")); - ADD_SIGNAL(MethodInfo("target_reached")); - ADD_SIGNAL(MethodInfo("navigation_finished")); - ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); -} - -void NavigationAgent::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - - agent_parent = Object::cast_to(get_parent()); - - NavigationServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); - - // Search the navigation node and set it - { - Navigation *nav = NULL; - Node *p = get_parent(); - while (p != NULL) { - nav = Object::cast_to(p); - if (nav != NULL) - p = NULL; - else - p = p->get_parent(); - } - - set_navigation(nav); - } - - set_physics_process_internal(true); - } break; - case NOTIFICATION_EXIT_TREE: { - agent_parent = NULL; - set_navigation(NULL); - set_physics_process_internal(false); - } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - if (agent_parent) { - - NavigationServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); - if (!target_reached) { - if (distance_to_target() < target_desired_distance) { - emit_signal("target_reached"); - target_reached = true; - } - } - } - } break; - } -} - -NavigationAgent::NavigationAgent() : - agent_parent(NULL), - navigation(NULL), - agent(RID()), - target_desired_distance(1.0), - navigation_height_offset(0.0), - path_max_distance(3.0), - velocity_submitted(false), - target_reached(false), - navigation_finished(true) { - agent = NavigationServer::get_singleton()->agent_create(); - set_neighbor_dist(50.0); - set_max_neighbors(10); - set_time_horizon(5.0); - set_radius(1.0); - set_max_speed(10.0); - set_ignore_y(true); -} - -NavigationAgent::~NavigationAgent() { - NavigationServer::get_singleton()->free(agent); - agent = RID(); // Pointless -} - -void NavigationAgent::set_navigation(Navigation *p_nav) { - if (navigation == p_nav) - return; // Pointless - - navigation = p_nav; - NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); -} - -void NavigationAgent::set_navigation_node(Node *p_nav) { - Navigation *nav = Object::cast_to(p_nav); - ERR_FAIL_COND(nav == NULL); - set_navigation(nav); -} - -Node *NavigationAgent::get_navigation_node() const { - return Object::cast_to(navigation); -} - -void NavigationAgent::set_target_desired_distance(real_t p_dd) { - target_desired_distance = p_dd; -} - -void NavigationAgent::set_radius(real_t p_radius) { - radius = p_radius; - NavigationServer::get_singleton()->agent_set_radius(agent, radius); -} - -void NavigationAgent::set_agent_height_offset(real_t p_hh) { - navigation_height_offset = p_hh; -} - -void NavigationAgent::set_ignore_y(bool p_ignore_y) { - ignore_y = p_ignore_y; - NavigationServer::get_singleton()->agent_set_ignore_y(agent, ignore_y); -} - -void NavigationAgent::set_neighbor_dist(real_t p_dist) { - neighbor_dist = p_dist; - NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); -} - -void NavigationAgent::set_max_neighbors(int p_count) { - max_neighbors = p_count; - NavigationServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); -} - -void NavigationAgent::set_time_horizon(real_t p_time) { - time_horizon = p_time; - NavigationServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); -} - -void NavigationAgent::set_max_speed(real_t p_max_speed) { - max_speed = p_max_speed; - NavigationServer::get_singleton()->agent_set_max_speed(agent, max_speed); -} - -void NavigationAgent::set_path_max_distance(real_t p_pmd) { - path_max_distance = p_pmd; -} - -real_t NavigationAgent::get_path_max_distance() { - return path_max_distance; -} - -void NavigationAgent::set_target_location(Vector3 p_location) { - target_location = p_location; - navigation_path.clear(); - target_reached = false; - navigation_finished = false; - update_frame_id = 0; -} - -Vector3 NavigationAgent::get_target_location() const { - return target_location; -} - -Vector3 NavigationAgent::get_next_location() { - update_navigation(); - if (navigation_path.size() == 0) { - ERR_FAIL_COND_V(agent_parent == NULL, Vector3()); - return agent_parent->get_global_transform().origin; - } else { - return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0); - } -} - -real_t NavigationAgent::distance_to_target() const { - ERR_FAIL_COND_V(agent_parent == NULL, 0.0); - return agent_parent->get_global_transform().origin.distance_to(target_location); -} - -bool NavigationAgent::is_target_reached() const { - return target_reached; -} - -bool NavigationAgent::is_target_reachable() { - return target_desired_distance >= get_final_location().distance_to(target_location); -} - -bool NavigationAgent::is_navigation_finished() { - update_navigation(); - return navigation_finished; -} - -Vector3 NavigationAgent::get_final_location() { - update_navigation(); - if (navigation_path.size() == 0) { - return Vector3(); - } - return navigation_path[navigation_path.size() - 1]; -} - -void NavigationAgent::set_velocity(Vector3 p_velocity) { - target_velocity = p_velocity; - NavigationServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); - NavigationServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); - velocity_submitted = true; -} - -void NavigationAgent::_avoidance_done(Vector3 p_new_velocity) { - prev_safe_velocity = p_new_velocity; - - if (!velocity_submitted) { - target_velocity = Vector3(); - return; - } - velocity_submitted = false; - - emit_signal("velocity_computed", p_new_velocity); -} - -String NavigationAgent::get_configuration_warning() const { - if (!Object::cast_to(get_parent())) { - return TTR("The NavigationAgent can be used only under a spatial node."); - } - - return String(); -} - -void NavigationAgent::update_navigation() { - - if (agent_parent == NULL) return; - if (navigation == NULL) return; - if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return; - - update_frame_id = Engine::get_singleton()->get_physics_frames(); - - Vector3 o = agent_parent->get_global_transform().origin; - - bool reload_path = false; - - if (NavigationServer::get_singleton()->agent_is_map_changed(agent)) { - reload_path = true; - } else if (navigation_path.size() == 0) { - reload_path = true; - } else { - // Check if too far from the navigation path - if (nav_path_index > 0) { - Vector3 segment[2]; - segment[0] = navigation_path[nav_path_index - 1]; - segment[1] = navigation_path[nav_path_index]; - segment[0].y -= navigation_height_offset; - segment[1].y -= navigation_height_offset; - Vector3 p = Geometry::get_closest_point_to_segment(o, segment); - if (o.distance_to(p) >= path_max_distance) { - // To faraway, reload path - reload_path = true; - } - } - } - - if (reload_path) { - navigation_path = NavigationServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); - navigation_finished = false; - nav_path_index = 0; - emit_signal("path_changed"); - } - - if (navigation_path.size() == 0) - return; - - // Check if we can advance the navigation path - if (navigation_finished == false) { - // Advances to the next far away location. - while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < target_desired_distance) { - nav_path_index += 1; - if (nav_path_index == navigation_path.size()) { - nav_path_index -= 1; - navigation_finished = true; - emit_signal("navigation_finished"); - break; - } - } - } -} diff --git a/scene/3d/navigation_agent.h b/scene/3d/navigation_agent.h deleted file mode 100644 index 200d5db475..0000000000 --- a/scene/3d/navigation_agent.h +++ /dev/null @@ -1,162 +0,0 @@ -/*************************************************************************/ -/* navigation_agent.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_AGENT_H -#define NAVIGATION_AGENT_H - -#include "core/vector.h" -#include "scene/main/node.h" - -class Spatial; -class Navigation; - -class NavigationAgent : public Node { - GDCLASS(NavigationAgent, Node); - - Spatial *agent_parent; - Navigation *navigation; - - RID agent; - - real_t target_desired_distance; - real_t radius; - real_t navigation_height_offset; - bool ignore_y; - real_t neighbor_dist; - int max_neighbors; - real_t time_horizon; - real_t max_speed; - - real_t path_max_distance; - - Vector3 target_location; - Vector navigation_path; - int nav_path_index; - bool velocity_submitted; - Vector3 prev_safe_velocity; - /// The submitted target velocity - Vector3 target_velocity; - bool target_reached; - bool navigation_finished; - // No initialized on purpose - uint32_t update_frame_id; - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - NavigationAgent(); - virtual ~NavigationAgent(); - - void set_navigation(Navigation *p_nav); - const Navigation *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - - RID get_rid() const { - return agent; - } - - void set_target_desired_distance(real_t p_dd); - real_t get_target_desired_distance() const { - return target_desired_distance; - } - - void set_radius(real_t p_radius); - real_t get_radius() const { - return radius; - } - - void set_agent_height_offset(real_t p_hh); - real_t get_agent_height_offset() const { - return navigation_height_offset; - } - - void set_ignore_y(bool p_ignore_y); - bool get_ignore_y() const { - return ignore_y; - } - - void set_neighbor_dist(real_t p_dist); - real_t get_neighbor_dist() const { - return neighbor_dist; - } - - void set_max_neighbors(int p_count); - int get_max_neighbors() const { - return max_neighbors; - } - - void set_time_horizon(real_t p_time); - real_t get_time_horizon() const { - return time_horizon; - } - - void set_max_speed(real_t p_max_speed); - real_t get_max_speed() const { - return max_speed; - } - - void set_path_max_distance(real_t p_pmd); - real_t get_path_max_distance(); - - void set_target_location(Vector3 p_location); - Vector3 get_target_location() const; - - Vector3 get_next_location(); - - Vector get_nav_path() const { - return navigation_path; - } - - int get_nav_path_index() const { - return nav_path_index; - } - - real_t distance_to_target() const; - bool is_target_reached() const; - bool is_target_reachable(); - bool is_navigation_finished(); - Vector3 get_final_location(); - - void set_velocity(Vector3 p_velocity); - void _avoidance_done(Vector3 p_new_velocity); - - virtual String get_configuration_warning() const; - -private: - void update_navigation(); -}; - -#endif diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp new file mode 100644 index 0000000000..219e868f29 --- /dev/null +++ b/scene/3d/navigation_agent_3d.cpp @@ -0,0 +1,362 @@ +/*************************************************************************/ +/* navigation_agent_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_agent_3d.h" + +#include "core/engine.h" +#include "scene/3d/navigation_3d.h" +#include "servers/navigation_server.h" + +void NavigationAgent3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent3D::set_target_desired_distance); + ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent3D::get_target_desired_distance); + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent3D::get_radius); + + ClassDB::bind_method(D_METHOD("set_agent_height_offset", "agent_height_offset"), &NavigationAgent3D::set_agent_height_offset); + ClassDB::bind_method(D_METHOD("get_agent_height_offset"), &NavigationAgent3D::get_agent_height_offset); + + ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent3D::set_ignore_y); + ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent3D::get_ignore_y); + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent3D::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent3D::get_navigation_node); + + ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent3D::set_neighbor_dist); + ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent3D::get_neighbor_dist); + + ClassDB::bind_method(D_METHOD("set_max_neighbors", "max_neighbors"), &NavigationAgent3D::set_max_neighbors); + ClassDB::bind_method(D_METHOD("get_max_neighbors"), &NavigationAgent3D::get_max_neighbors); + + ClassDB::bind_method(D_METHOD("set_time_horizon", "time_horizon"), &NavigationAgent3D::set_time_horizon); + ClassDB::bind_method(D_METHOD("get_time_horizon"), &NavigationAgent3D::get_time_horizon); + + ClassDB::bind_method(D_METHOD("set_max_speed", "max_speed"), &NavigationAgent3D::set_max_speed); + ClassDB::bind_method(D_METHOD("get_max_speed"), &NavigationAgent3D::get_max_speed); + + ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent3D::set_path_max_distance); + ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent3D::get_path_max_distance); + + ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent3D::set_target_location); + ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent3D::get_target_location); + ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location); + ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent3D::distance_to_target); + ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent3D::set_velocity); + ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent3D::get_nav_path); + ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent3D::get_nav_path_index); + ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent3D::is_target_reached); + ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent3D::is_target_reachable); + ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent3D::is_navigation_finished); + ClassDB::bind_method(D_METHOD("get_final_location"), &NavigationAgent3D::get_final_location); + + ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent3D::_avoidance_done); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01"), "set_agent_height_offset", "get_agent_height_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_neighbor_dist", "get_neighbor_dist"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); + + ADD_SIGNAL(MethodInfo("path_changed")); + ADD_SIGNAL(MethodInfo("target_reached")); + ADD_SIGNAL(MethodInfo("navigation_finished")); + ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); +} + +void NavigationAgent3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + agent_parent = Object::cast_to(get_parent()); + + NavigationServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + + // Search the navigation node and set it + { + Navigation3D *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + agent_parent = NULL; + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (agent_parent) { + + NavigationServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); + if (!target_reached) { + if (distance_to_target() < target_desired_distance) { + emit_signal("target_reached"); + target_reached = true; + } + } + } + } break; + } +} + +NavigationAgent3D::NavigationAgent3D() : + agent_parent(NULL), + navigation(NULL), + agent(RID()), + target_desired_distance(1.0), + navigation_height_offset(0.0), + path_max_distance(3.0), + velocity_submitted(false), + target_reached(false), + navigation_finished(true) { + agent = NavigationServer::get_singleton()->agent_create(); + set_neighbor_dist(50.0); + set_max_neighbors(10); + set_time_horizon(5.0); + set_radius(1.0); + set_max_speed(10.0); + set_ignore_y(true); +} + +NavigationAgent3D::~NavigationAgent3D() { + NavigationServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationAgent3D::set_navigation(Navigation3D *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationAgent3D::set_navigation_node(Node *p_nav) { + Navigation3D *nav = Object::cast_to(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationAgent3D::get_navigation_node() const { + return Object::cast_to(navigation); +} + +void NavigationAgent3D::set_target_desired_distance(real_t p_dd) { + target_desired_distance = p_dd; +} + +void NavigationAgent3D::set_radius(real_t p_radius) { + radius = p_radius; + NavigationServer::get_singleton()->agent_set_radius(agent, radius); +} + +void NavigationAgent3D::set_agent_height_offset(real_t p_hh) { + navigation_height_offset = p_hh; +} + +void NavigationAgent3D::set_ignore_y(bool p_ignore_y) { + ignore_y = p_ignore_y; + NavigationServer::get_singleton()->agent_set_ignore_y(agent, ignore_y); +} + +void NavigationAgent3D::set_neighbor_dist(real_t p_dist) { + neighbor_dist = p_dist; + NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); +} + +void NavigationAgent3D::set_max_neighbors(int p_count) { + max_neighbors = p_count; + NavigationServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); +} + +void NavigationAgent3D::set_time_horizon(real_t p_time) { + time_horizon = p_time; + NavigationServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); +} + +void NavigationAgent3D::set_max_speed(real_t p_max_speed) { + max_speed = p_max_speed; + NavigationServer::get_singleton()->agent_set_max_speed(agent, max_speed); +} + +void NavigationAgent3D::set_path_max_distance(real_t p_pmd) { + path_max_distance = p_pmd; +} + +real_t NavigationAgent3D::get_path_max_distance() { + return path_max_distance; +} + +void NavigationAgent3D::set_target_location(Vector3 p_location) { + target_location = p_location; + navigation_path.clear(); + target_reached = false; + navigation_finished = false; + update_frame_id = 0; +} + +Vector3 NavigationAgent3D::get_target_location() const { + return target_location; +} + +Vector3 NavigationAgent3D::get_next_location() { + update_navigation(); + if (navigation_path.size() == 0) { + ERR_FAIL_COND_V(agent_parent == NULL, Vector3()); + return agent_parent->get_global_transform().origin; + } else { + return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0); + } +} + +real_t NavigationAgent3D::distance_to_target() const { + ERR_FAIL_COND_V(agent_parent == NULL, 0.0); + return agent_parent->get_global_transform().origin.distance_to(target_location); +} + +bool NavigationAgent3D::is_target_reached() const { + return target_reached; +} + +bool NavigationAgent3D::is_target_reachable() { + return target_desired_distance >= get_final_location().distance_to(target_location); +} + +bool NavigationAgent3D::is_navigation_finished() { + update_navigation(); + return navigation_finished; +} + +Vector3 NavigationAgent3D::get_final_location() { + update_navigation(); + if (navigation_path.size() == 0) { + return Vector3(); + } + return navigation_path[navigation_path.size() - 1]; +} + +void NavigationAgent3D::set_velocity(Vector3 p_velocity) { + target_velocity = p_velocity; + NavigationServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); + NavigationServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); + velocity_submitted = true; +} + +void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) { + prev_safe_velocity = p_new_velocity; + + if (!velocity_submitted) { + target_velocity = Vector3(); + return; + } + velocity_submitted = false; + + emit_signal("velocity_computed", p_new_velocity); +} + +String NavigationAgent3D::get_configuration_warning() const { + if (!Object::cast_to(get_parent())) { + return TTR("The NavigationAgent can be used only under a spatial node."); + } + + return String(); +} + +void NavigationAgent3D::update_navigation() { + + if (agent_parent == NULL) return; + if (navigation == NULL) return; + if (update_frame_id == Engine::get_singleton()->get_physics_frames()) return; + + update_frame_id = Engine::get_singleton()->get_physics_frames(); + + Vector3 o = agent_parent->get_global_transform().origin; + + bool reload_path = false; + + if (NavigationServer::get_singleton()->agent_is_map_changed(agent)) { + reload_path = true; + } else if (navigation_path.size() == 0) { + reload_path = true; + } else { + // Check if too far from the navigation path + if (nav_path_index > 0) { + Vector3 segment[2]; + segment[0] = navigation_path[nav_path_index - 1]; + segment[1] = navigation_path[nav_path_index]; + segment[0].y -= navigation_height_offset; + segment[1].y -= navigation_height_offset; + Vector3 p = Geometry::get_closest_point_to_segment(o, segment); + if (o.distance_to(p) >= path_max_distance) { + // To faraway, reload path + reload_path = true; + } + } + } + + if (reload_path) { + navigation_path = NavigationServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_finished = false; + nav_path_index = 0; + emit_signal("path_changed"); + } + + if (navigation_path.size() == 0) + return; + + // Check if we can advance the navigation path + if (navigation_finished == false) { + // Advances to the next far away location. + while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < target_desired_distance) { + nav_path_index += 1; + if (nav_path_index == navigation_path.size()) { + nav_path_index -= 1; + navigation_finished = true; + emit_signal("navigation_finished"); + break; + } + } + } +} diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h new file mode 100644 index 0000000000..3558b4e51b --- /dev/null +++ b/scene/3d/navigation_agent_3d.h @@ -0,0 +1,162 @@ +/*************************************************************************/ +/* navigation_agent_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_AGENT_H +#define NAVIGATION_AGENT_H + +#include "core/vector.h" +#include "scene/main/node.h" + +class Node3D; +class Navigation3D; + +class NavigationAgent3D : public Node { + GDCLASS(NavigationAgent3D, Node); + + Node3D *agent_parent; + Navigation3D *navigation; + + RID agent; + + real_t target_desired_distance; + real_t radius; + real_t navigation_height_offset; + bool ignore_y; + real_t neighbor_dist; + int max_neighbors; + real_t time_horizon; + real_t max_speed; + + real_t path_max_distance; + + Vector3 target_location; + Vector navigation_path; + int nav_path_index; + bool velocity_submitted; + Vector3 prev_safe_velocity; + /// The submitted target velocity + Vector3 target_velocity; + bool target_reached; + bool navigation_finished; + // No initialized on purpose + uint32_t update_frame_id; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + NavigationAgent3D(); + virtual ~NavigationAgent3D(); + + void set_navigation(Navigation3D *p_nav); + const Navigation3D *get_navigation() const { + return navigation; + } + + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + void set_target_desired_distance(real_t p_dd); + real_t get_target_desired_distance() const { + return target_desired_distance; + } + + void set_radius(real_t p_radius); + real_t get_radius() const { + return radius; + } + + void set_agent_height_offset(real_t p_hh); + real_t get_agent_height_offset() const { + return navigation_height_offset; + } + + void set_ignore_y(bool p_ignore_y); + bool get_ignore_y() const { + return ignore_y; + } + + void set_neighbor_dist(real_t p_dist); + real_t get_neighbor_dist() const { + return neighbor_dist; + } + + void set_max_neighbors(int p_count); + int get_max_neighbors() const { + return max_neighbors; + } + + void set_time_horizon(real_t p_time); + real_t get_time_horizon() const { + return time_horizon; + } + + void set_max_speed(real_t p_max_speed); + real_t get_max_speed() const { + return max_speed; + } + + void set_path_max_distance(real_t p_pmd); + real_t get_path_max_distance(); + + void set_target_location(Vector3 p_location); + Vector3 get_target_location() const; + + Vector3 get_next_location(); + + Vector get_nav_path() const { + return navigation_path; + } + + int get_nav_path_index() const { + return nav_path_index; + } + + real_t distance_to_target() const; + bool is_target_reached() const; + bool is_target_reachable(); + bool is_navigation_finished(); + Vector3 get_final_location(); + + void set_velocity(Vector3 p_velocity); + void _avoidance_done(Vector3 p_new_velocity); + + virtual String get_configuration_warning() const; + +private: + void update_navigation(); +}; + +#endif diff --git a/scene/3d/navigation_obstacle.cpp b/scene/3d/navigation_obstacle.cpp deleted file mode 100644 index befc41eee5..0000000000 --- a/scene/3d/navigation_obstacle.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************/ -/* navigation_obstacle.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation_obstacle.h" - -#include "scene/3d/collision_shape.h" -#include "scene/3d/navigation.h" -#include "scene/3d/physics_body.h" -#include "servers/navigation_server.h" - -void NavigationObstacle::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle::set_navigation_node); - ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle::get_navigation_node); -} - -void NavigationObstacle::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_READY: { - - update_agent_shape(); - - // Search the navigation node and set it - { - Navigation *nav = NULL; - Node *p = get_parent(); - while (p != NULL) { - nav = Object::cast_to(p); - if (nav != NULL) - p = NULL; - else - p = p->get_parent(); - } - - set_navigation(nav); - } - - set_physics_process_internal(true); - } break; - case NOTIFICATION_EXIT_TREE: { - set_navigation(NULL); - set_physics_process_internal(false); - } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - Spatial *spatial = Object::cast_to(get_parent()); - if (spatial) { - NavigationServer::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); - } - - PhysicsBody *rigid = Object::cast_to(get_parent()); - if (rigid) { - - Vector3 v = rigid->get_linear_velocity(); - NavigationServer::get_singleton()->agent_set_velocity(agent, v); - NavigationServer::get_singleton()->agent_set_target_velocity(agent, v); - } - - } break; - } -} - -NavigationObstacle::NavigationObstacle() : - navigation(NULL), - agent(RID()) { - agent = NavigationServer::get_singleton()->agent_create(); -} - -NavigationObstacle::~NavigationObstacle() { - NavigationServer::get_singleton()->free(agent); - agent = RID(); // Pointless -} - -void NavigationObstacle::set_navigation(Navigation *p_nav) { - if (navigation == p_nav) - return; // Pointless - - navigation = p_nav; - NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); -} - -void NavigationObstacle::set_navigation_node(Node *p_nav) { - Navigation *nav = Object::cast_to(p_nav); - ERR_FAIL_COND(nav == NULL); - set_navigation(nav); -} - -Node *NavigationObstacle::get_navigation_node() const { - return Object::cast_to(navigation); -} - -String NavigationObstacle::get_configuration_warning() const { - if (!Object::cast_to(get_parent())) { - - return TTR("The NavigationObstacle only serves to provide collision avoidance to a spatial object."); - } - - return String(); -} - -void NavigationObstacle::update_agent_shape() { - Node *node = get_parent(); - - // Estimate the radius of this physics body - real_t radius = 0.0; - for (int i(0); i < node->get_child_count(); i++) { - // For each collision shape - CollisionShape *cs = Object::cast_to(node->get_child(i)); - if (cs) { - // Take the distance between the Body center to the shape center - real_t r = cs->get_transform().origin.length(); - if (cs->get_shape().is_valid()) { - // and add the enclosing shape radius - r += cs->get_shape()->get_enclosing_radius(); - } - Vector3 s = cs->get_global_transform().basis.get_scale(); - r *= MAX(s.x, MAX(s.y, s.z)); - // Takes the biggest radius - radius = MAX(radius, r); - } - } - Spatial *spa = Object::cast_to(node); - if (spa) { - Vector3 s = spa->get_global_transform().basis.get_scale(); - radius *= MAX(s.x, MAX(s.y, s.z)); - } - - if (radius == 0.0) - radius = 1.0; // Never a 0 radius - - // Initialize the Agent as an object - NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); - NavigationServer::get_singleton()->agent_set_max_neighbors(agent, 0); - NavigationServer::get_singleton()->agent_set_time_horizon(agent, 0.0); - NavigationServer::get_singleton()->agent_set_radius(agent, radius); - NavigationServer::get_singleton()->agent_set_max_speed(agent, 0.0); -} diff --git a/scene/3d/navigation_obstacle.h b/scene/3d/navigation_obstacle.h deleted file mode 100644 index 7257a43150..0000000000 --- a/scene/3d/navigation_obstacle.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************/ -/* navigation_obstacle.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_OBSTACLE_H -#define NAVIGATION_OBSTACLE_H - -#include "scene/main/node.h" - -class Navigation; - -class NavigationObstacle : public Node { - GDCLASS(NavigationObstacle, Node); - - Navigation *navigation; - - RID agent; - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - NavigationObstacle(); - virtual ~NavigationObstacle(); - - void set_navigation(Navigation *p_nav); - const Navigation *get_navigation() const { - return navigation; - } - - void set_navigation_node(Node *p_nav); - Node *get_navigation_node() const; - - RID get_rid() const { - return agent; - } - - virtual String get_configuration_warning() const; - -private: - void update_agent_shape(); -}; - -#endif diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp new file mode 100644 index 0000000000..9eef4a1340 --- /dev/null +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* navigation_obstacle_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_obstacle_3d.h" + +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "servers/navigation_server.h" + +void NavigationObstacle3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle3D::set_navigation_node); + ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle3D::get_navigation_node); +} + +void NavigationObstacle3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + + update_agent_shape(); + + // Search the navigation node and set it + { + Navigation3D *nav = NULL; + Node *p = get_parent(); + while (p != NULL) { + nav = Object::cast_to(p); + if (nav != NULL) + p = NULL; + else + p = p->get_parent(); + } + + set_navigation(nav); + } + + set_physics_process_internal(true); + } break; + case NOTIFICATION_EXIT_TREE: { + set_navigation(NULL); + set_physics_process_internal(false); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + Node3D *spatial = Object::cast_to(get_parent()); + if (spatial) { + NavigationServer::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); + } + + PhysicsBody3D *rigid = Object::cast_to(get_parent()); + if (rigid) { + + Vector3 v = rigid->get_linear_velocity(); + NavigationServer::get_singleton()->agent_set_velocity(agent, v); + NavigationServer::get_singleton()->agent_set_target_velocity(agent, v); + } + + } break; + } +} + +NavigationObstacle3D::NavigationObstacle3D() : + navigation(NULL), + agent(RID()) { + agent = NavigationServer::get_singleton()->agent_create(); +} + +NavigationObstacle3D::~NavigationObstacle3D() { + NavigationServer::get_singleton()->free(agent); + agent = RID(); // Pointless +} + +void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) { + if (navigation == p_nav) + return; // Pointless + + navigation = p_nav; + NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); +} + +void NavigationObstacle3D::set_navigation_node(Node *p_nav) { + Navigation3D *nav = Object::cast_to(p_nav); + ERR_FAIL_COND(nav == NULL); + set_navigation(nav); +} + +Node *NavigationObstacle3D::get_navigation_node() const { + return Object::cast_to(navigation); +} + +String NavigationObstacle3D::get_configuration_warning() const { + if (!Object::cast_to(get_parent())) { + + return TTR("The NavigationObstacle only serves to provide collision avoidance to a spatial object."); + } + + return String(); +} + +void NavigationObstacle3D::update_agent_shape() { + Node *node = get_parent(); + + // Estimate the radius of this physics body + real_t radius = 0.0; + for (int i(0); i < node->get_child_count(); i++) { + // For each collision shape + CollisionShape3D *cs = Object::cast_to(node->get_child(i)); + if (cs) { + // Take the distance between the Body center to the shape center + real_t r = cs->get_transform().origin.length(); + if (cs->get_shape().is_valid()) { + // and add the enclosing shape radius + r += cs->get_shape()->get_enclosing_radius(); + } + Vector3 s = cs->get_global_transform().basis.get_scale(); + r *= MAX(s.x, MAX(s.y, s.z)); + // Takes the biggest radius + radius = MAX(radius, r); + } + } + Node3D *spa = Object::cast_to(node); + if (spa) { + Vector3 s = spa->get_global_transform().basis.get_scale(); + radius *= MAX(s.x, MAX(s.y, s.z)); + } + + if (radius == 0.0) + radius = 1.0; // Never a 0 radius + + // Initialize the Agent as an object + NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer::get_singleton()->agent_set_radius(agent, radius); + NavigationServer::get_singleton()->agent_set_max_speed(agent, 0.0); +} diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h new file mode 100644 index 0000000000..b58d7c4991 --- /dev/null +++ b/scene/3d/navigation_obstacle_3d.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* navigation_obstacle_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_OBSTACLE_H +#define NAVIGATION_OBSTACLE_H + +#include "scene/main/node.h" + +class Navigation3D; + +class NavigationObstacle3D : public Node { + GDCLASS(NavigationObstacle3D, Node); + + Navigation3D *navigation; + + RID agent; + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + NavigationObstacle3D(); + virtual ~NavigationObstacle3D(); + + void set_navigation(Navigation3D *p_nav); + const Navigation3D *get_navigation() const { + return navigation; + } + + void set_navigation_node(Node *p_nav); + Node *get_navigation_node() const; + + RID get_rid() const { + return agent; + } + + virtual String get_configuration_warning() const; + +private: + void update_agent_shape(); +}; + +#endif diff --git a/scene/3d/navigation_region.cpp b/scene/3d/navigation_region.cpp deleted file mode 100644 index 53b707a29a..0000000000 --- a/scene/3d/navigation_region.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/*************************************************************************/ -/* navigation_region.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "navigation_region.h" -#include "core/os/thread.h" -#include "mesh_instance.h" -#include "navigation.h" -#include "servers/navigation_server.h" - -void NavigationRegion::set_enabled(bool p_enabled) { - - if (enabled == p_enabled) - return; - enabled = p_enabled; - - if (!is_inside_tree()) - return; - - if (!enabled) { - - NavigationServer::get_singleton()->region_set_map(region, RID()); - } else { - - if (navigation) { - - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); - } - } - - if (debug_view) { - MeshInstance *dm = Object::cast_to(debug_view); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); - } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); - } - } - - update_gizmo(); -} - -bool NavigationRegion::is_enabled() const { - - return enabled; -} - -///////////////////////////// - -void NavigationRegion::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - - Spatial *c = this; - while (c) { - - navigation = Object::cast_to(c); - if (navigation) { - - if (enabled) { - - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); - } - break; - } - - c = c->get_parent_spatial(); - } - - if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { - - MeshInstance *dm = memnew(MeshInstance); - dm->set_mesh(navmesh->get_debug_mesh()); - if (is_enabled()) { - dm->set_material_override(get_tree()->get_debug_navigation_material()); - } else { - dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); - } - add_child(dm); - debug_view = dm; - } - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - NavigationServer::get_singleton()->region_set_transform(region, get_global_transform()); - - } break; - case NOTIFICATION_EXIT_TREE: { - - if (navigation) { - - NavigationServer::get_singleton()->region_set_map(region, RID()); - } - - if (debug_view) { - debug_view->queue_delete(); - debug_view = NULL; - } - navigation = NULL; - } break; - } -} - -void NavigationRegion::set_navigation_mesh(const Ref &p_navmesh) { - - if (p_navmesh == navmesh) - return; - - if (navmesh.is_valid()) { - navmesh->remove_change_receptor(this); - } - - navmesh = p_navmesh; - - if (navmesh.is_valid()) { - navmesh->add_change_receptor(this); - } - - NavigationServer::get_singleton()->region_set_navmesh(region, p_navmesh); - - if (debug_view && navmesh.is_valid()) { - Object::cast_to(debug_view)->set_mesh(navmesh->get_debug_mesh()); - } - - emit_signal("navigation_mesh_changed"); - - update_gizmo(); - update_configuration_warning(); -} - -Ref NavigationRegion::get_navigation_mesh() const { - - return navmesh; -} - -struct BakeThreadsArgs { - NavigationRegion *nav_region; -}; - -void _bake_navigation_mesh(void *p_user_data) { - BakeThreadsArgs *args = static_cast(p_user_data); - - if (args->nav_region->get_navigation_mesh().is_valid()) { - Ref nav_mesh = args->nav_region->get_navigation_mesh()->duplicate(); - - NavigationServer::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region); - args->nav_region->call_deferred("_bake_finished", nav_mesh); - memdelete(args); - } else { - - ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist"); - args->nav_region->call_deferred("_bake_finished", Ref()); - memdelete(args); - } -} - -void NavigationRegion::bake_navigation_mesh() { - ERR_FAIL_COND(bake_thread != NULL); - - BakeThreadsArgs *args = memnew(BakeThreadsArgs); - args->nav_region = this; - - bake_thread = Thread::create(_bake_navigation_mesh, args); - ERR_FAIL_COND(bake_thread == NULL); -} - -void NavigationRegion::_bake_finished(Ref p_nav_mesh) { - set_navigation_mesh(p_nav_mesh); - bake_thread = NULL; -} - -String NavigationRegion::get_configuration_warning() const { - - if (!is_visible_in_tree() || !is_inside_tree()) - return String(); - - if (!navmesh.is_valid()) { - return TTR("A NavigationMesh resource must be set or created for this node to work."); - } - const Spatial *c = this; - while (c) { - - if (Object::cast_to(c)) - return String(); - - c = Object::cast_to(c->get_parent()); - } - - return TTR("NavigationRegion must be a child or grandchild to a Navigation node. It only provides navigation data."); -} - -void NavigationRegion::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion::set_navigation_mesh); - ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion::get_navigation_mesh); - - ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion::set_enabled); - ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion::is_enabled); - - ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion::bake_navigation_mesh); - ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion::_bake_finished); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); - - ADD_SIGNAL(MethodInfo("navigation_mesh_changed")); - ADD_SIGNAL(MethodInfo("bake_finished")); -} - -void NavigationRegion::_changed_callback(Object *p_changed, const char *p_prop) { - update_gizmo(); - update_configuration_warning(); -} - -NavigationRegion::NavigationRegion() { - - enabled = true; - set_notify_transform(true); - region = NavigationServer::get_singleton()->region_create(); - - navigation = NULL; - debug_view = NULL; - bake_thread = NULL; -} - -NavigationRegion::~NavigationRegion() { - if (navmesh.is_valid()) - navmesh->remove_change_receptor(this); - NavigationServer::get_singleton()->free(region); -} diff --git a/scene/3d/navigation_region.h b/scene/3d/navigation_region.h deleted file mode 100644 index f215e92c97..0000000000 --- a/scene/3d/navigation_region.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************/ -/* navigation_region.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NAVIGATION_REGION_H -#define NAVIGATION_REGION_H - -#include "scene/3d/spatial.h" -#include "scene/resources/mesh.h" -#include "scene/resources/navigation_mesh.h" - -class Navigation; - -class NavigationRegion : public Spatial { - - GDCLASS(NavigationRegion, Spatial); - - bool enabled; - RID region; - Ref navmesh; - - Navigation *navigation; - Node *debug_view; - Thread *bake_thread; - -protected: - void _notification(int p_what); - static void _bind_methods(); - void _changed_callback(Object *p_changed, const char *p_prop); - -public: - void set_enabled(bool p_enabled); - bool is_enabled() const; - - void set_navigation_mesh(const Ref &p_navmesh); - Ref get_navigation_mesh() const; - - /// Bakes the navigation mesh in a dedicated thread; once done, automatically - /// sets the new navigation mesh and emits a signal - void bake_navigation_mesh(); - void _bake_finished(Ref p_nav_mesh); - - String get_configuration_warning() const; - - NavigationRegion(); - ~NavigationRegion(); -}; - -#endif // NAVIGATION_REGION_H diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp new file mode 100644 index 0000000000..8035e6149d --- /dev/null +++ b/scene/3d/navigation_region_3d.cpp @@ -0,0 +1,258 @@ +/*************************************************************************/ +/* navigation_region_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_region_3d.h" +#include "core/os/thread.h" +#include "mesh_instance_3d.h" +#include "navigation_3d.h" +#include "servers/navigation_server.h" + +void NavigationRegion3D::set_enabled(bool p_enabled) { + + if (enabled == p_enabled) + return; + enabled = p_enabled; + + if (!is_inside_tree()) + return; + + if (!enabled) { + + NavigationServer::get_singleton()->region_set_map(region, RID()); + } else { + + if (navigation) { + + NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + } + } + + if (debug_view) { + MeshInstance3D *dm = Object::cast_to(debug_view); + if (is_enabled()) { + dm->set_material_override(get_tree()->get_debug_navigation_material()); + } else { + dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + } + } + + update_gizmo(); +} + +bool NavigationRegion3D::is_enabled() const { + + return enabled; +} + +///////////////////////////// + +void NavigationRegion3D::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + + Node3D *c = this; + while (c) { + + navigation = Object::cast_to(c); + if (navigation) { + + if (enabled) { + + NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + } + break; + } + + c = c->get_parent_spatial(); + } + + if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { + + MeshInstance3D *dm = memnew(MeshInstance3D); + dm->set_mesh(navmesh->get_debug_mesh()); + if (is_enabled()) { + dm->set_material_override(get_tree()->get_debug_navigation_material()); + } else { + dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); + } + add_child(dm); + debug_view = dm; + } + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + NavigationServer::get_singleton()->region_set_transform(region, get_global_transform()); + + } break; + case NOTIFICATION_EXIT_TREE: { + + if (navigation) { + + NavigationServer::get_singleton()->region_set_map(region, RID()); + } + + if (debug_view) { + debug_view->queue_delete(); + debug_view = NULL; + } + navigation = NULL; + } break; + } +} + +void NavigationRegion3D::set_navigation_mesh(const Ref &p_navmesh) { + + if (p_navmesh == navmesh) + return; + + if (navmesh.is_valid()) { + navmesh->remove_change_receptor(this); + } + + navmesh = p_navmesh; + + if (navmesh.is_valid()) { + navmesh->add_change_receptor(this); + } + + NavigationServer::get_singleton()->region_set_navmesh(region, p_navmesh); + + if (debug_view && navmesh.is_valid()) { + Object::cast_to(debug_view)->set_mesh(navmesh->get_debug_mesh()); + } + + emit_signal("navigation_mesh_changed"); + + update_gizmo(); + update_configuration_warning(); +} + +Ref NavigationRegion3D::get_navigation_mesh() const { + + return navmesh; +} + +struct BakeThreadsArgs { + NavigationRegion3D *nav_region; +}; + +void _bake_navigation_mesh(void *p_user_data) { + BakeThreadsArgs *args = static_cast(p_user_data); + + if (args->nav_region->get_navigation_mesh().is_valid()) { + Ref nav_mesh = args->nav_region->get_navigation_mesh()->duplicate(); + + NavigationServer::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region); + args->nav_region->call_deferred("_bake_finished", nav_mesh); + memdelete(args); + } else { + + ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist"); + args->nav_region->call_deferred("_bake_finished", Ref()); + memdelete(args); + } +} + +void NavigationRegion3D::bake_navigation_mesh() { + ERR_FAIL_COND(bake_thread != NULL); + + BakeThreadsArgs *args = memnew(BakeThreadsArgs); + args->nav_region = this; + + bake_thread = Thread::create(_bake_navigation_mesh, args); + ERR_FAIL_COND(bake_thread == NULL); +} + +void NavigationRegion3D::_bake_finished(Ref p_nav_mesh) { + set_navigation_mesh(p_nav_mesh); + bake_thread = NULL; +} + +String NavigationRegion3D::get_configuration_warning() const { + + if (!is_visible_in_tree() || !is_inside_tree()) + return String(); + + if (!navmesh.is_valid()) { + return TTR("A NavigationMesh resource must be set or created for this node to work."); + } + const Node3D *c = this; + while (c) { + + if (Object::cast_to(c)) + return String(); + + c = Object::cast_to(c->get_parent()); + } + + return TTR("NavigationRegion must be a child or grandchild to a Navigation node. It only provides navigation data."); +} + +void NavigationRegion3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion3D::set_navigation_mesh); + ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh); + + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion3D::is_enabled); + + ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationRegion3D::bake_navigation_mesh); + ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion3D::_bake_finished); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + + ADD_SIGNAL(MethodInfo("navigation_mesh_changed")); + ADD_SIGNAL(MethodInfo("bake_finished")); +} + +void NavigationRegion3D::_changed_callback(Object *p_changed, const char *p_prop) { + update_gizmo(); + update_configuration_warning(); +} + +NavigationRegion3D::NavigationRegion3D() { + + enabled = true; + set_notify_transform(true); + region = NavigationServer::get_singleton()->region_create(); + + navigation = NULL; + debug_view = NULL; + bake_thread = NULL; +} + +NavigationRegion3D::~NavigationRegion3D() { + if (navmesh.is_valid()) + navmesh->remove_change_receptor(this); + NavigationServer::get_singleton()->free(region); +} diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h new file mode 100644 index 0000000000..ae071e6b7a --- /dev/null +++ b/scene/3d/navigation_region_3d.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* navigation_region_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_REGION_H +#define NAVIGATION_REGION_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/mesh.h" +#include "scene/resources/navigation_mesh.h" + +class Navigation3D; + +class NavigationRegion3D : public Node3D { + + GDCLASS(NavigationRegion3D, Node3D); + + bool enabled; + RID region; + Ref navmesh; + + Navigation3D *navigation; + Node *debug_view; + Thread *bake_thread; + +protected: + void _notification(int p_what); + static void _bind_methods(); + void _changed_callback(Object *p_changed, const char *p_prop); + +public: + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_navigation_mesh(const Ref &p_navmesh); + Ref get_navigation_mesh() const; + + /// Bakes the navigation mesh in a dedicated thread; once done, automatically + /// sets the new navigation mesh and emits a signal + void bake_navigation_mesh(); + void _bake_finished(Ref p_nav_mesh); + + String get_configuration_warning() const; + + NavigationRegion3D(); + ~NavigationRegion3D(); +}; + +#endif // NAVIGATION_REGION_H diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp new file mode 100644 index 0000000000..594eca284c --- /dev/null +++ b/scene/3d/node_3d.cpp @@ -0,0 +1,848 @@ +/*************************************************************************/ +/* node_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "node_3d.h" + +#include "core/engine.h" +#include "core/message_queue.h" +#include "scene/main/scene_tree.h" +#include "scene/main/window.h" +#include "scene/scene_string_names.h" + +/* + + possible algorithms: + + Algorithm 1: (current) + + definition of invalidation: global is invalid + + 1) If a node sets a LOCAL, it produces an invalidation of everything above + a) If above is invalid, don't keep invalidating upwards + 2) If a node sets a GLOBAL, it is converted to LOCAL (and forces validation of everything pending below) + + drawback: setting/reading globals is useful and used very very often, and using affine inverses is slow + +--- + + Algorithm 2: (no longer current) + + definition of invalidation: NONE dirty, LOCAL dirty, GLOBAL dirty + + 1) If a node sets a LOCAL, it must climb the tree and set it as GLOBAL dirty + a) marking GLOBALs as dirty up all the tree must be done always + 2) If a node sets a GLOBAL, it marks local as dirty, and that's all? + + //is clearing the dirty state correct in this case? + + drawback: setting a local down the tree forces many tree walks often + +-- + +future: no idea + + */ + +Node3DGizmo::Node3DGizmo() { +} + +void Node3D::_notify_dirty() { + +#ifdef TOOLS_ENABLED + if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { +#else + if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { + +#endif + get_tree()->xform_change_list.add(&xform_change); + } +} + +void Node3D::_update_local_transform() const { + data.local_transform.basis.set_euler_scale(data.rotation, data.scale); + + data.dirty &= ~DIRTY_LOCAL; +} +void Node3D::_propagate_transform_changed(Node3D *p_origin) { + + if (!is_inside_tree()) { + return; + } + + /* + if (data.dirty&DIRTY_GLOBAL) + return; //already dirty + */ + + data.children_lock++; + + for (List::Element *E = data.children.front(); E; E = E->next()) { + + if (E->get()->data.toplevel_active) + continue; //don't propagate to a toplevel + E->get()->_propagate_transform_changed(p_origin); + } +#ifdef TOOLS_ENABLED + if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { +#else + if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { +#endif + get_tree()->xform_change_list.add(&xform_change); + } + data.dirty |= DIRTY_GLOBAL; + + data.children_lock--; +} + +void Node3D::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + ERR_FAIL_COND(!get_tree()); + + Node *p = get_parent(); + if (p) + data.parent = Object::cast_to(p); + + if (data.parent) + data.C = data.parent->data.children.push_back(this); + else + data.C = NULL; + + if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) { + + if (data.parent) { + data.local_transform = data.parent->get_global_transform() * get_transform(); + data.dirty = DIRTY_VECTORS; //global is always dirty upon entering a scene + } + data.toplevel_active = true; + } + + data.dirty |= DIRTY_GLOBAL; //global is always dirty upon entering a scene + _notify_dirty(); + + notification(NOTIFICATION_ENTER_WORLD); + + } break; + case NOTIFICATION_EXIT_TREE: { + + notification(NOTIFICATION_EXIT_WORLD, true); + if (xform_change.in_list()) + get_tree()->xform_change_list.remove(&xform_change); + if (data.C) + data.parent->data.children.erase(data.C); + data.parent = NULL; + data.C = NULL; + data.toplevel_active = false; + } break; + case NOTIFICATION_ENTER_WORLD: { + + data.inside_world = true; + data.viewport = NULL; + Node *parent = get_parent(); + while (parent && !data.viewport) { + data.viewport = Object::cast_to(parent); + parent = parent->get_parent(); + } + + ERR_FAIL_COND(!data.viewport); + + if (get_script_instance()) { + + get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, NULL, 0); + } +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { + + //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); + get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); + if (!data.gizmo_disabled) { + + if (data.gizmo.is_valid()) { + data.gizmo->create(); + if (is_visible_in_tree()) { + data.gizmo->redraw(); + } + data.gizmo->transform(); + } + } + } +#endif + + } break; + case NOTIFICATION_EXIT_WORLD: { + +#ifdef TOOLS_ENABLED + if (data.gizmo.is_valid()) { + data.gizmo->free(); + data.gizmo.unref(); + } +#endif + + if (get_script_instance()) { + + get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, NULL, 0); + } + + data.viewport = NULL; + data.inside_world = false; + + } break; + + case NOTIFICATION_TRANSFORM_CHANGED: { + +#ifdef TOOLS_ENABLED + if (data.gizmo.is_valid()) { + data.gizmo->transform(); + } +#endif + } break; + + default: { + } + } +} + +void Node3D::set_transform(const Transform &p_transform) { + + data.local_transform = p_transform; + data.dirty |= DIRTY_VECTORS; + _change_notify("translation"); + _change_notify("rotation"); + _change_notify("rotation_degrees"); + _change_notify("scale"); + _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } +} + +void Node3D::set_global_transform(const Transform &p_transform) { + + Transform xform = + (data.parent && !data.toplevel_active) ? + data.parent->get_global_transform().affine_inverse() * p_transform : + p_transform; + + set_transform(xform); +} + +Transform Node3D::get_transform() const { + + if (data.dirty & DIRTY_LOCAL) { + + _update_local_transform(); + } + + return data.local_transform; +} +Transform Node3D::get_global_transform() const { + + ERR_FAIL_COND_V(!is_inside_tree(), Transform()); + + if (data.dirty & DIRTY_GLOBAL) { + + if (data.dirty & DIRTY_LOCAL) { + + _update_local_transform(); + } + + if (data.parent && !data.toplevel_active) { + + data.global_transform = data.parent->get_global_transform() * data.local_transform; + } else { + + data.global_transform = data.local_transform; + } + + if (data.disable_scale) { + data.global_transform.basis.orthonormalize(); + } + + data.dirty &= ~DIRTY_GLOBAL; + } + + return data.global_transform; +} + +#ifdef TOOLS_ENABLED +Transform Node3D::get_global_gizmo_transform() const { + return get_global_transform(); +} + +Transform Node3D::get_local_gizmo_transform() const { + return get_transform(); +} +#endif + +Node3D *Node3D::get_parent_spatial() const { + + return data.parent; +} + +Transform Node3D::get_relative_transform(const Node *p_parent) const { + + if (p_parent == this) + return Transform(); + + ERR_FAIL_COND_V(!data.parent, Transform()); + + if (p_parent == data.parent) + return get_transform(); + else + return data.parent->get_relative_transform(p_parent) * get_transform(); +} + +void Node3D::set_translation(const Vector3 &p_translation) { + + data.local_transform.origin = p_translation; + _change_notify("transform"); + _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } +} + +void Node3D::set_rotation(const Vector3 &p_euler_rad) { + + if (data.dirty & DIRTY_VECTORS) { + data.scale = data.local_transform.basis.get_scale(); + data.dirty &= ~DIRTY_VECTORS; + } + + data.rotation = p_euler_rad; + data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); + _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } +} + +void Node3D::set_rotation_degrees(const Vector3 &p_euler_deg) { + + set_rotation(p_euler_deg * Math_PI / 180.0); +} + +void Node3D::set_scale(const Vector3 &p_scale) { + + if (data.dirty & DIRTY_VECTORS) { + data.rotation = data.local_transform.basis.get_rotation(); + data.dirty &= ~DIRTY_VECTORS; + } + + data.scale = p_scale; + data.dirty |= DIRTY_LOCAL; + _change_notify("transform"); + _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } +} + +Vector3 Node3D::get_translation() const { + + return data.local_transform.origin; +} + +Vector3 Node3D::get_rotation() const { + + if (data.dirty & DIRTY_VECTORS) { + data.scale = data.local_transform.basis.get_scale(); + data.rotation = data.local_transform.basis.get_rotation(); + + data.dirty &= ~DIRTY_VECTORS; + } + + return data.rotation; +} + +Vector3 Node3D::get_rotation_degrees() const { + + return get_rotation() * 180.0 / Math_PI; +} + +Vector3 Node3D::get_scale() const { + + if (data.dirty & DIRTY_VECTORS) { + data.scale = data.local_transform.basis.get_scale(); + data.rotation = data.local_transform.basis.get_rotation(); + + data.dirty &= ~DIRTY_VECTORS; + } + + return data.scale; +} + +void Node3D::update_gizmo() { + +#ifdef TOOLS_ENABLED + if (!is_inside_world()) + return; + if (!data.gizmo.is_valid()) + get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); + if (!data.gizmo.is_valid()) + return; + if (data.gizmo_dirty) + return; + data.gizmo_dirty = true; + MessageQueue::get_singleton()->push_call(this, "_update_gizmo"); +#endif +} + +void Node3D::set_gizmo(const Ref &p_gizmo) { + +#ifdef TOOLS_ENABLED + + if (data.gizmo_disabled) + return; + if (data.gizmo.is_valid() && is_inside_world()) + data.gizmo->free(); + data.gizmo = p_gizmo; + if (data.gizmo.is_valid() && is_inside_world()) { + + data.gizmo->create(); + if (is_visible_in_tree()) { + data.gizmo->redraw(); + } + data.gizmo->transform(); + } + +#endif +} + +Ref Node3D::get_gizmo() const { + +#ifdef TOOLS_ENABLED + + return data.gizmo; +#else + + return Ref(); +#endif +} + +void Node3D::_update_gizmo() { + +#ifdef TOOLS_ENABLED + if (!is_inside_world()) + return; + data.gizmo_dirty = false; + if (data.gizmo.is_valid()) { + if (is_visible_in_tree()) + data.gizmo->redraw(); + else + data.gizmo->clear(); + } +#endif +} + +#ifdef TOOLS_ENABLED +void Node3D::set_disable_gizmo(bool p_enabled) { + + data.gizmo_disabled = p_enabled; + if (!p_enabled && data.gizmo.is_valid()) + data.gizmo = Ref(); +} + +#endif + +void Node3D::set_disable_scale(bool p_enabled) { + + data.disable_scale = p_enabled; +} + +bool Node3D::is_scale_disabled() const { + return data.disable_scale; +} + +void Node3D::set_as_toplevel(bool p_enabled) { + + if (data.toplevel == p_enabled) + return; + if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { + + if (p_enabled) + set_transform(get_global_transform()); + else if (data.parent) + set_transform(data.parent->get_global_transform().affine_inverse() * get_global_transform()); + + data.toplevel = p_enabled; + data.toplevel_active = p_enabled; + + } else { + data.toplevel = p_enabled; + } +} + +bool Node3D::is_set_as_toplevel() const { + + return data.toplevel; +} + +Ref Node3D::get_world() const { + + ERR_FAIL_COND_V(!is_inside_world(), Ref()); + ERR_FAIL_COND_V(!data.viewport, Ref()); + + return data.viewport->find_world(); +} + +void Node3D::_propagate_visibility_changed() { + + notification(NOTIFICATION_VISIBILITY_CHANGED); + emit_signal(SceneStringNames::get_singleton()->visibility_changed); + _change_notify("visible"); +#ifdef TOOLS_ENABLED + if (data.gizmo.is_valid()) + _update_gizmo(); +#endif + + for (List::Element *E = data.children.front(); E; E = E->next()) { + + Node3D *c = E->get(); + if (!c || !c->data.visible) + continue; + c->_propagate_visibility_changed(); + } +} + +void Node3D::show() { + + if (data.visible) + return; + + data.visible = true; + + if (!is_inside_tree()) + return; + + _propagate_visibility_changed(); +} + +void Node3D::hide() { + + if (!data.visible) + return; + + data.visible = false; + + if (!is_inside_tree()) + return; + + _propagate_visibility_changed(); +} + +bool Node3D::is_visible_in_tree() const { + + const Node3D *s = this; + + while (s) { + if (!s->data.visible) { + return false; + } + s = s->data.parent; + } + + return true; +} + +void Node3D::set_visible(bool p_visible) { + + if (p_visible) + show(); + else + hide(); +} + +bool Node3D::is_visible() const { + + return data.visible; +} + +void Node3D::rotate_object_local(const Vector3 &p_axis, float p_angle) { + Transform t = get_transform(); + t.basis.rotate_local(p_axis, p_angle); + set_transform(t); +} + +void Node3D::rotate(const Vector3 &p_axis, float p_angle) { + + Transform t = get_transform(); + t.basis.rotate(p_axis, p_angle); + set_transform(t); +} + +void Node3D::rotate_x(float p_angle) { + + Transform t = get_transform(); + t.basis.rotate(Vector3(1, 0, 0), p_angle); + set_transform(t); +} + +void Node3D::rotate_y(float p_angle) { + + Transform t = get_transform(); + t.basis.rotate(Vector3(0, 1, 0), p_angle); + set_transform(t); +} +void Node3D::rotate_z(float p_angle) { + + Transform t = get_transform(); + t.basis.rotate(Vector3(0, 0, 1), p_angle); + set_transform(t); +} + +void Node3D::translate(const Vector3 &p_offset) { + + Transform t = get_transform(); + t.translate(p_offset); + set_transform(t); +} + +void Node3D::translate_object_local(const Vector3 &p_offset) { + Transform t = get_transform(); + + Transform s; + s.translate(p_offset); + set_transform(t * s); +} + +void Node3D::scale(const Vector3 &p_ratio) { + + Transform t = get_transform(); + t.basis.scale(p_ratio); + set_transform(t); +} + +void Node3D::scale_object_local(const Vector3 &p_scale) { + Transform t = get_transform(); + t.basis.scale_local(p_scale); + set_transform(t); +} + +void Node3D::global_rotate(const Vector3 &p_axis, float p_angle) { + + Transform t = get_global_transform(); + t.basis.rotate(p_axis, p_angle); + set_global_transform(t); +} + +void Node3D::global_scale(const Vector3 &p_scale) { + + Transform t = get_global_transform(); + t.basis.scale(p_scale); + set_global_transform(t); +} + +void Node3D::global_translate(const Vector3 &p_offset) { + Transform t = get_global_transform(); + t.origin += p_offset; + set_global_transform(t); +} + +void Node3D::orthonormalize() { + + Transform t = get_transform(); + t.orthonormalize(); + set_transform(t); +} + +void Node3D::set_identity() { + + set_transform(Transform()); +} + +void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) { + + Vector3 origin(get_global_transform().origin); + look_at_from_position(origin, p_target, p_up); +} + +void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) { + + ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed."); + ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed."); + + Transform lookat; + lookat.origin = p_pos; + + Vector3 original_scale(get_scale()); + lookat = lookat.looking_at(p_target, p_up); + set_global_transform(lookat); + set_scale(original_scale); +} + +Vector3 Node3D::to_local(Vector3 p_global) const { + + return get_global_transform().affine_inverse().xform(p_global); +} + +Vector3 Node3D::to_global(Vector3 p_local) const { + + return get_global_transform().xform(p_local); +} + +void Node3D::set_notify_transform(bool p_enable) { + data.notify_transform = p_enable; +} + +bool Node3D::is_transform_notification_enabled() const { + return data.notify_transform; +} + +void Node3D::set_notify_local_transform(bool p_enable) { + data.notify_local_transform = p_enable; +} + +bool Node3D::is_local_transform_notification_enabled() const { + return data.notify_local_transform; +} + +void Node3D::force_update_transform() { + ERR_FAIL_COND(!is_inside_tree()); + if (!xform_change.in_list()) { + return; //nothing to update + } + get_tree()->xform_change_list.remove(&xform_change); + + notification(NOTIFICATION_TRANSFORM_CHANGED); +} + +void Node3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_transform", "local"), &Node3D::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform); + ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Node3D::set_translation); + ClassDB::bind_method(D_METHOD("get_translation"), &Node3D::get_translation); + ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation); + ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation); + ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Node3D::set_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node3D::get_rotation_degrees); + ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node3D::set_scale); + ClassDB::bind_method(D_METHOD("get_scale"), &Node3D::get_scale); + ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Node3D::set_global_transform); + ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform); + ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Node3D::get_parent_spatial); + ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification); + ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Node3D::set_as_toplevel); + ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Node3D::is_set_as_toplevel); + ClassDB::bind_method(D_METHOD("set_disable_scale", "disable"), &Node3D::set_disable_scale); + ClassDB::bind_method(D_METHOD("is_scale_disabled"), &Node3D::is_scale_disabled); + ClassDB::bind_method(D_METHOD("get_world"), &Node3D::get_world); + + ClassDB::bind_method(D_METHOD("force_update_transform"), &Node3D::force_update_transform); + + ClassDB::bind_method(D_METHOD("_update_gizmo"), &Node3D::_update_gizmo); + + ClassDB::bind_method(D_METHOD("update_gizmo"), &Node3D::update_gizmo); + ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Node3D::set_gizmo); + ClassDB::bind_method(D_METHOD("get_gizmo"), &Node3D::get_gizmo); + + ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Node3D::set_visible); + ClassDB::bind_method(D_METHOD("is_visible"), &Node3D::is_visible); + ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &Node3D::is_visible_in_tree); + ClassDB::bind_method(D_METHOD("show"), &Node3D::show); + ClassDB::bind_method(D_METHOD("hide"), &Node3D::hide); + + ClassDB::bind_method(D_METHOD("set_notify_local_transform", "enable"), &Node3D::set_notify_local_transform); + ClassDB::bind_method(D_METHOD("is_local_transform_notification_enabled"), &Node3D::is_local_transform_notification_enabled); + + ClassDB::bind_method(D_METHOD("set_notify_transform", "enable"), &Node3D::set_notify_transform); + ClassDB::bind_method(D_METHOD("is_transform_notification_enabled"), &Node3D::is_transform_notification_enabled); + + ClassDB::bind_method(D_METHOD("rotate", "axis", "angle"), &Node3D::rotate); + ClassDB::bind_method(D_METHOD("global_rotate", "axis", "angle"), &Node3D::global_rotate); + ClassDB::bind_method(D_METHOD("global_scale", "scale"), &Node3D::global_scale); + ClassDB::bind_method(D_METHOD("global_translate", "offset"), &Node3D::global_translate); + ClassDB::bind_method(D_METHOD("rotate_object_local", "axis", "angle"), &Node3D::rotate_object_local); + ClassDB::bind_method(D_METHOD("scale_object_local", "scale"), &Node3D::scale_object_local); + ClassDB::bind_method(D_METHOD("translate_object_local", "offset"), &Node3D::translate_object_local); + ClassDB::bind_method(D_METHOD("rotate_x", "angle"), &Node3D::rotate_x); + ClassDB::bind_method(D_METHOD("rotate_y", "angle"), &Node3D::rotate_y); + ClassDB::bind_method(D_METHOD("rotate_z", "angle"), &Node3D::rotate_z); + ClassDB::bind_method(D_METHOD("translate", "offset"), &Node3D::translate); + ClassDB::bind_method(D_METHOD("orthonormalize"), &Node3D::orthonormalize); + ClassDB::bind_method(D_METHOD("set_identity"), &Node3D::set_identity); + + ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Node3D::look_at); + ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Node3D::look_at_from_position); + + ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node3D::to_local); + ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node3D::to_global); + + BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED); + BIND_CONSTANT(NOTIFICATION_ENTER_WORLD); + BIND_CONSTANT(NOTIFICATION_EXIT_WORLD); + BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); + + //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ; + ADD_GROUP("Transform", ""); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); + ADD_GROUP("Matrix", ""); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); + ADD_GROUP("Visibility", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "Node3DGizmo", 0), "set_gizmo", "get_gizmo"); + + ADD_SIGNAL(MethodInfo("visibility_changed")); +} + +Node3D::Node3D() : + xform_change(this) { + + data.dirty = DIRTY_NONE; + data.children_lock = 0; + + data.ignore_notification = false; + data.toplevel = false; + data.toplevel_active = false; + data.scale = Vector3(1, 1, 1); + data.viewport = NULL; + data.inside_world = false; + data.visible = true; + data.disable_scale = false; + +#ifdef TOOLS_ENABLED + data.gizmo_disabled = false; + data.gizmo_dirty = false; +#endif + data.notify_local_transform = false; + data.notify_transform = false; + data.parent = NULL; + data.C = NULL; +} + +Node3D::~Node3D() { +} diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h new file mode 100644 index 0000000000..fd14bc730f --- /dev/null +++ b/scene/3d/node_3d.h @@ -0,0 +1,207 @@ +/*************************************************************************/ +/* node_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NODE_3D_H +#define NODE_3D_H + +#include "scene/main/node.h" +#include "scene/main/scene_tree.h" + +class Node3DGizmo : public Reference { + + GDCLASS(Node3DGizmo, Reference); + +public: + virtual void create() = 0; + virtual void transform() = 0; + virtual void clear() = 0; + virtual void redraw() = 0; + virtual void free() = 0; + + Node3DGizmo(); + virtual ~Node3DGizmo() {} +}; + +class Node3D : public Node { + + GDCLASS(Node3D, Node); + OBJ_CATEGORY("3D"); + + enum TransformDirty { + DIRTY_NONE = 0, + DIRTY_VECTORS = 1, + DIRTY_LOCAL = 2, + DIRTY_GLOBAL = 4 + }; + + mutable SelfList xform_change; + + struct Data { + + mutable Transform global_transform; + mutable Transform local_transform; + mutable Vector3 rotation; + mutable Vector3 scale; + + mutable int dirty; + + Viewport *viewport; + + bool toplevel_active; + bool toplevel; + bool inside_world; + + int children_lock; + Node3D *parent; + List children; + List::Element *C; + + bool ignore_notification; + bool notify_local_transform; + bool notify_transform; + + bool visible; + bool disable_scale; + +#ifdef TOOLS_ENABLED + Ref gizmo; + bool gizmo_disabled; + bool gizmo_dirty; +#endif + + } data; + + void _update_gizmo(); + void _notify_dirty(); + void _propagate_transform_changed(Node3D *p_origin); + + void _propagate_visibility_changed(); + +protected: + _FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) { data.ignore_notification = p_ignore; } + + _FORCE_INLINE_ void _update_local_transform() const; + + void _notification(int p_what); + static void _bind_methods(); + +public: + enum { + + NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED, + NOTIFICATION_ENTER_WORLD = 41, + NOTIFICATION_EXIT_WORLD = 42, + NOTIFICATION_VISIBILITY_CHANGED = 43, + NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 44, + }; + + Node3D *get_parent_spatial() const; + + Ref get_world() const; + + void set_translation(const Vector3 &p_translation); + void set_rotation(const Vector3 &p_euler_rad); + void set_rotation_degrees(const Vector3 &p_euler_deg); + void set_scale(const Vector3 &p_scale); + + Vector3 get_translation() const; + Vector3 get_rotation() const; + Vector3 get_rotation_degrees() const; + Vector3 get_scale() const; + + void set_transform(const Transform &p_transform); + void set_global_transform(const Transform &p_transform); + + Transform get_transform() const; + Transform get_global_transform() const; + +#ifdef TOOLS_ENABLED + virtual Transform get_global_gizmo_transform() const; + virtual Transform get_local_gizmo_transform() const; +#endif + + void set_as_toplevel(bool p_enabled); + bool is_set_as_toplevel() const; + + void set_disable_scale(bool p_enabled); + bool is_scale_disabled() const; + + void set_disable_gizmo(bool p_enabled); + void update_gizmo(); + void set_gizmo(const Ref &p_gizmo); + Ref get_gizmo() const; + + _FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; } + + Transform get_relative_transform(const Node *p_parent) const; + + void rotate(const Vector3 &p_axis, float p_angle); + void rotate_x(float p_angle); + void rotate_y(float p_angle); + void rotate_z(float p_angle); + void translate(const Vector3 &p_offset); + void scale(const Vector3 &p_ratio); + + void rotate_object_local(const Vector3 &p_axis, float p_angle); + void scale_object_local(const Vector3 &p_scale); + void translate_object_local(const Vector3 &p_offset); + + void global_rotate(const Vector3 &p_axis, float p_angle); + void global_scale(const Vector3 &p_scale); + void global_translate(const Vector3 &p_offset); + + void look_at(const Vector3 &p_target, const Vector3 &p_up); + void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up); + + Vector3 to_local(Vector3 p_global) const; + Vector3 to_global(Vector3 p_local) const; + + void set_notify_transform(bool p_enable); + bool is_transform_notification_enabled() const; + + void set_notify_local_transform(bool p_enable); + bool is_local_transform_notification_enabled() const; + + void orthonormalize(); + void set_identity(); + + void set_visible(bool p_visible); + bool is_visible() const; + void show(); + void hide(); + bool is_visible_in_tree() const; + + void force_update_transform(); + + Node3D(); + ~Node3D(); +}; + +#endif // NODE_3D_H diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp deleted file mode 100644 index 7a1eeb105a..0000000000 --- a/scene/3d/particles.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/*************************************************************************/ -/* particles.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "particles.h" - -#include "core/os/os.h" -#include "scene/resources/particles_material.h" - -#include "servers/visual_server.h" - -AABB Particles::get_aabb() const { - - return AABB(); -} -Vector Particles::get_faces(uint32_t p_usage_flags) const { - - return Vector(); -} - -void Particles::set_emitting(bool p_emitting) { - - VS::get_singleton()->particles_set_emitting(particles, p_emitting); - - if (p_emitting && one_shot) { - set_process_internal(true); - } else if (!p_emitting) { - set_process_internal(false); - } -} - -void Particles::set_amount(int p_amount) { - - ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles cannot be smaller than 1."); - amount = p_amount; - VS::get_singleton()->particles_set_amount(particles, amount); -} -void Particles::set_lifetime(float p_lifetime) { - - ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); - lifetime = p_lifetime; - VS::get_singleton()->particles_set_lifetime(particles, lifetime); -} - -void Particles::set_one_shot(bool p_one_shot) { - - one_shot = p_one_shot; - VS::get_singleton()->particles_set_one_shot(particles, one_shot); - - if (is_emitting()) { - - set_process_internal(true); - if (!one_shot) - VisualServer::get_singleton()->particles_restart(particles); - } - - if (!one_shot) - set_process_internal(false); -} - -void Particles::set_pre_process_time(float p_time) { - - pre_process_time = p_time; - VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); -} -void Particles::set_explosiveness_ratio(float p_ratio) { - - explosiveness_ratio = p_ratio; - VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); -} -void Particles::set_randomness_ratio(float p_ratio) { - - randomness_ratio = p_ratio; - VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); -} -void Particles::set_visibility_aabb(const AABB &p_aabb) { - - visibility_aabb = p_aabb; - VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); - update_gizmo(); - _change_notify("visibility_aabb"); -} -void Particles::set_use_local_coordinates(bool p_enable) { - - local_coords = p_enable; - VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); -} -void Particles::set_process_material(const Ref &p_material) { - - process_material = p_material; - RID material_rid; - if (process_material.is_valid()) - material_rid = process_material->get_rid(); - VS::get_singleton()->particles_set_process_material(particles, material_rid); - - update_configuration_warning(); -} - -void Particles::set_speed_scale(float p_scale) { - - speed_scale = p_scale; - VS::get_singleton()->particles_set_speed_scale(particles, p_scale); -} - -bool Particles::is_emitting() const { - - return VS::get_singleton()->particles_get_emitting(particles); -} -int Particles::get_amount() const { - - return amount; -} -float Particles::get_lifetime() const { - - return lifetime; -} -bool Particles::get_one_shot() const { - - return one_shot; -} - -float Particles::get_pre_process_time() const { - - return pre_process_time; -} -float Particles::get_explosiveness_ratio() const { - - return explosiveness_ratio; -} -float Particles::get_randomness_ratio() const { - - return randomness_ratio; -} -AABB Particles::get_visibility_aabb() const { - - return visibility_aabb; -} -bool Particles::get_use_local_coordinates() const { - - return local_coords; -} -Ref Particles::get_process_material() const { - - return process_material; -} - -float Particles::get_speed_scale() const { - - return speed_scale; -} - -void Particles::set_draw_order(DrawOrder p_order) { - - draw_order = p_order; - VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); -} - -Particles::DrawOrder Particles::get_draw_order() const { - - return draw_order; -} - -void Particles::set_draw_passes(int p_count) { - - ERR_FAIL_COND(p_count < 1); - draw_passes.resize(p_count); - VS::get_singleton()->particles_set_draw_passes(particles, p_count); - _change_notify(); -} -int Particles::get_draw_passes() const { - - return draw_passes.size(); -} - -void Particles::set_draw_pass_mesh(int p_pass, const Ref &p_mesh) { - - ERR_FAIL_INDEX(p_pass, draw_passes.size()); - - draw_passes.write[p_pass] = p_mesh; - - RID mesh_rid; - if (p_mesh.is_valid()) - mesh_rid = p_mesh->get_rid(); - - VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); - - update_configuration_warning(); -} - -Ref Particles::get_draw_pass_mesh(int p_pass) const { - - ERR_FAIL_INDEX_V(p_pass, draw_passes.size(), Ref()); - - return draw_passes[p_pass]; -} - -void Particles::set_fixed_fps(int p_count) { - fixed_fps = p_count; - VS::get_singleton()->particles_set_fixed_fps(particles, p_count); -} - -int Particles::get_fixed_fps() const { - return fixed_fps; -} - -void Particles::set_fractional_delta(bool p_enable) { - fractional_delta = p_enable; - VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); -} - -bool Particles::get_fractional_delta() const { - return fractional_delta; -} - -String Particles::get_configuration_warning() const { - - if (VisualServer::get_singleton()->is_low_end()) { - return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); - } - - String warnings; - - bool meshes_found = false; - bool anim_material_found = false; - - for (int i = 0; i < draw_passes.size(); i++) { - if (draw_passes[i].is_valid()) { - meshes_found = true; - for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) { - anim_material_found = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()) != NULL; - StandardMaterial3D *spat = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()); - anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); - } - if (anim_material_found) break; - } - } - - anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; - StandardMaterial3D *spat = Object::cast_to(get_material_override().ptr()); - anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); - - if (!meshes_found) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes."); - } - - if (process_material.is_null()) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); - } else { - const ParticlesMaterial *process = Object::cast_to(process_material.ptr()); - if (!anim_material_found && process && - (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || - process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); - } - } - - return warnings; -} - -void Particles::restart() { - - VisualServer::get_singleton()->particles_restart(particles); - VisualServer::get_singleton()->particles_set_emitting(particles, true); -} - -AABB Particles::capture_aabb() const { - - return VS::get_singleton()->particles_get_current_aabb(particles); -} - -void Particles::_validate_property(PropertyInfo &property) const { - - if (property.name.begins_with("draw_pass_")) { - int index = property.name.get_slicec('_', 2).to_int() - 1; - if (index >= draw_passes.size()) { - property.usage = 0; - return; - } - } -} - -void Particles::_notification(int p_what) { - - if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { - if (can_process()) { - VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); - } else { - - VS::get_singleton()->particles_set_speed_scale(particles, 0); - } - } - - // Use internal process when emitting and one_shot are on so that when - // the shot ends the editor can properly update - if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - - if (one_shot && !is_emitting()) { - _change_notify(); - set_process_internal(false); - } - } - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - // make sure particles are updated before rendering occurs if they were active before - if (is_visible_in_tree() && !VS::get_singleton()->particles_is_inactive(particles)) { - VS::get_singleton()->particles_request_process(particles); - } - } -} - -void Particles::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &Particles::set_emitting); - ClassDB::bind_method(D_METHOD("set_amount", "amount"), &Particles::set_amount); - ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &Particles::set_lifetime); - ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &Particles::set_one_shot); - ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles::set_pre_process_time); - ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles::set_explosiveness_ratio); - ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles::set_randomness_ratio); - ClassDB::bind_method(D_METHOD("set_visibility_aabb", "aabb"), &Particles::set_visibility_aabb); - ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &Particles::set_use_local_coordinates); - ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &Particles::set_fixed_fps); - ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &Particles::set_fractional_delta); - ClassDB::bind_method(D_METHOD("set_process_material", "material"), &Particles::set_process_material); - ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &Particles::set_speed_scale); - - ClassDB::bind_method(D_METHOD("is_emitting"), &Particles::is_emitting); - ClassDB::bind_method(D_METHOD("get_amount"), &Particles::get_amount); - ClassDB::bind_method(D_METHOD("get_lifetime"), &Particles::get_lifetime); - ClassDB::bind_method(D_METHOD("get_one_shot"), &Particles::get_one_shot); - ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles::get_pre_process_time); - ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles::get_explosiveness_ratio); - ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles::get_randomness_ratio); - ClassDB::bind_method(D_METHOD("get_visibility_aabb"), &Particles::get_visibility_aabb); - ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &Particles::get_use_local_coordinates); - ClassDB::bind_method(D_METHOD("get_fixed_fps"), &Particles::get_fixed_fps); - ClassDB::bind_method(D_METHOD("get_fractional_delta"), &Particles::get_fractional_delta); - ClassDB::bind_method(D_METHOD("get_process_material"), &Particles::get_process_material); - ClassDB::bind_method(D_METHOD("get_speed_scale"), &Particles::get_speed_scale); - - ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &Particles::set_draw_order); - - ClassDB::bind_method(D_METHOD("get_draw_order"), &Particles::get_draw_order); - - ClassDB::bind_method(D_METHOD("set_draw_passes", "passes"), &Particles::set_draw_passes); - ClassDB::bind_method(D_METHOD("set_draw_pass_mesh", "pass", "mesh"), &Particles::set_draw_pass_mesh); - - ClassDB::bind_method(D_METHOD("get_draw_passes"), &Particles::get_draw_passes); - ClassDB::bind_method(D_METHOD("get_draw_pass_mesh", "pass"), &Particles::get_draw_pass_mesh); - - ClassDB::bind_method(D_METHOD("restart"), &Particles::restart); - ClassDB::bind_method(D_METHOD("capture_aabb"), &Particles::capture_aabb); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); - ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_EXP_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); - ADD_GROUP("Drawing", ""); - ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); - ADD_GROUP("Process Material", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); - ADD_GROUP("Draw Passes", "draw_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); - for (int i = 0; i < MAX_DRAW_PASSES; i++) { - - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "draw_pass_" + itos(i + 1), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_draw_pass_mesh", "get_draw_pass_mesh", i); - } - - BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); - BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); - BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); - - BIND_CONSTANT(MAX_DRAW_PASSES); -} - -Particles::Particles() { - - particles = VS::get_singleton()->particles_create(); - set_base(particles); - one_shot = false; // Needed so that set_emitting doesn't access uninitialized values - set_emitting(true); - set_one_shot(false); - set_amount(8); - set_lifetime(1); - set_fixed_fps(0); - set_fractional_delta(true); - set_pre_process_time(0); - set_explosiveness_ratio(0); - set_randomness_ratio(0); - set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))); - set_use_local_coordinates(true); - set_draw_passes(1); - set_draw_order(DRAW_ORDER_INDEX); - set_speed_scale(1); -} - -Particles::~Particles() { - - VS::get_singleton()->free(particles); -} diff --git a/scene/3d/particles.h b/scene/3d/particles.h deleted file mode 100644 index cf461f25e9..0000000000 --- a/scene/3d/particles.h +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************/ -/* particles.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PARTICLES_H -#define PARTICLES_H - -#include "core/rid.h" -#include "scene/3d/visual_instance.h" -#include "scene/resources/material.h" - -class Particles : public GeometryInstance { -private: - GDCLASS(Particles, GeometryInstance); - -public: - enum DrawOrder { - DRAW_ORDER_INDEX, - DRAW_ORDER_LIFETIME, - DRAW_ORDER_VIEW_DEPTH, - }; - - enum { - MAX_DRAW_PASSES = 4 - }; - -private: - RID particles; - - bool one_shot; - int amount; - float lifetime; - float pre_process_time; - float explosiveness_ratio; - float randomness_ratio; - float speed_scale; - AABB visibility_aabb; - bool local_coords; - int fixed_fps; - bool fractional_delta; - - Ref process_material; - - DrawOrder draw_order; - - Vector> draw_passes; - -protected: - static void _bind_methods(); - void _notification(int p_what); - virtual void _validate_property(PropertyInfo &property) const; - -public: - AABB get_aabb() const; - Vector get_faces(uint32_t p_usage_flags) const; - - void set_emitting(bool p_emitting); - void set_amount(int p_amount); - void set_lifetime(float p_lifetime); - void set_one_shot(bool p_one_shot); - void set_pre_process_time(float p_time); - void set_explosiveness_ratio(float p_ratio); - void set_randomness_ratio(float p_ratio); - void set_visibility_aabb(const AABB &p_aabb); - void set_use_local_coordinates(bool p_enable); - void set_process_material(const Ref &p_material); - void set_speed_scale(float p_scale); - - bool is_emitting() const; - int get_amount() const; - float get_lifetime() const; - bool get_one_shot() const; - float get_pre_process_time() const; - float get_explosiveness_ratio() const; - float get_randomness_ratio() const; - AABB get_visibility_aabb() const; - bool get_use_local_coordinates() const; - Ref get_process_material() const; - float get_speed_scale() const; - - void set_fixed_fps(int p_count); - int get_fixed_fps() const; - - void set_fractional_delta(bool p_enable); - bool get_fractional_delta() const; - - void set_draw_order(DrawOrder p_order); - DrawOrder get_draw_order() const; - - void set_draw_passes(int p_count); - int get_draw_passes() const; - - void set_draw_pass_mesh(int p_pass, const Ref &p_mesh); - Ref get_draw_pass_mesh(int p_pass) const; - - virtual String get_configuration_warning() const; - - void restart(); - - AABB capture_aabb() const; - Particles(); - ~Particles(); -}; - -VARIANT_ENUM_CAST(Particles::DrawOrder) - -#endif // PARTICLES_H diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp deleted file mode 100644 index f93485d79f..0000000000 --- a/scene/3d/path.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/*************************************************************************/ -/* path.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "path.h" - -#include "core/engine.h" -#include "scene/scene_string_names.h" - -void Path::_notification(int p_what) { -} - -void Path::_curve_changed() { - - if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) - update_gizmo(); - if (is_inside_tree()) { - emit_signal("curve_changed"); - } - - // update the configuration warnings of all children of type PathFollow - // previously used for PathFollowOriented (now enforced orientation is done in PathFollow) - if (is_inside_tree()) { - for (int i = 0; i < get_child_count(); i++) { - PathFollow *child = Object::cast_to(get_child(i)); - if (child) { - child->update_configuration_warning(); - } - } - } -} - -void Path::set_curve(const Ref &p_curve) { - - if (curve.is_valid()) { - curve->disconnect("changed", callable_mp(this, &Path::_curve_changed)); - } - - curve = p_curve; - - if (curve.is_valid()) { - curve->connect("changed", callable_mp(this, &Path::_curve_changed)); - } - _curve_changed(); -} - -Ref Path::get_curve() const { - - return curve; -} - -void Path::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path::set_curve); - ClassDB::bind_method(D_METHOD("get_curve"), &Path::get_curve); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve"); - - ADD_SIGNAL(MethodInfo("curve_changed")); -} - -Path::Path() { - - set_curve(Ref(memnew(Curve3D))); //create one by default -} - -////////////// - -void PathFollow::_update_transform() { - - if (!path) - return; - - Ref c = path->get_curve(); - if (!c.is_valid()) - return; - - if (delta_offset == 0) { - return; - } - - float bl = c->get_baked_length(); - if (bl == 0.0) { - return; - } - float bi = c->get_bake_interval(); - float o_next = offset + bi; - - if (loop) { - o_next = Math::fposmod(o_next, bl); - } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) { - o_next = bl; - } - - Vector3 pos = c->interpolate_baked(offset, cubic); - Transform t = get_transform(); - // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases - // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used - - if (rotation_mode == ROTATION_ORIENTED) { - - Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; - - if (forward.length_squared() < CMP_EPSILON2) - forward = Vector3(0, 0, 1); - else - forward.normalize(); - - Vector3 up = c->interpolate_baked_up_vector(offset, true); - - if (o_next < offset) { - Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); - Vector3 axis = up.cross(up1); - - if (axis.length_squared() < CMP_EPSILON2) - axis = forward; - else - axis.normalize(); - - up.rotate(axis, up.angle_to(up1) * 0.5f); - } - - Vector3 scale = t.basis.get_scale(); - Vector3 sideways = up.cross(forward).normalized(); - up = forward.cross(sideways).normalized(); - - t.basis.set(sideways, up, forward); - t.basis.scale_local(scale); - - t.origin = pos + sideways * h_offset + up * v_offset; - } else if (rotation_mode != ROTATION_NONE) { - // perform parallel transport - // - // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example - // for a discussion about why not Frenet frame. - - t.origin = pos; - - Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized(); - Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized(); - - Vector3 axis = t_prev.cross(t_cur); - float dot = t_prev.dot(t_cur); - float angle = Math::acos(CLAMP(dot, -1, 1)); - - if (likely(!Math::is_zero_approx(angle))) { - if (rotation_mode == ROTATION_Y) { - // assuming we're referring to global Y-axis. is this correct? - axis.x = 0; - axis.z = 0; - } else if (rotation_mode == ROTATION_XY) { - axis.z = 0; - } else if (rotation_mode == ROTATION_XYZ) { - // all components are allowed - } - - if (likely(!Math::is_zero_approx(axis.length()))) { - t.rotate_basis(axis.normalized(), angle); - } - } - - // do the additional tilting - float tilt_angle = c->interpolate_baked_tilt(offset); - Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? - - if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { - if (rotation_mode == ROTATION_Y) { - tilt_axis.x = 0; - tilt_axis.z = 0; - } else if (rotation_mode == ROTATION_XY) { - tilt_axis.z = 0; - } else if (rotation_mode == ROTATION_XYZ) { - // all components are allowed - } - - if (likely(!Math::is_zero_approx(tilt_axis.length()))) { - t.rotate_basis(tilt_axis.normalized(), tilt_angle); - } - } - - t.translate(Vector3(h_offset, v_offset, 0)); - } else { - t.origin = pos + Vector3(h_offset, v_offset, 0); - } - - set_transform(t); -} - -void PathFollow::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - Node *parent = get_parent(); - if (parent) { - path = Object::cast_to(parent); - if (path) { - _update_transform(); - } - } - - } break; - case NOTIFICATION_EXIT_TREE: { - - path = NULL; - } break; - } -} - -void PathFollow::set_cubic_interpolation(bool p_enable) { - - cubic = p_enable; -} - -bool PathFollow::get_cubic_interpolation() const { - - return cubic; -} - -void PathFollow::_validate_property(PropertyInfo &property) const { - - if (property.name == "offset") { - - float max = 10000; - if (path && path->get_curve().is_valid()) - max = path->get_curve()->get_baked_length(); - - property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater"; - } -} - -String PathFollow::get_configuration_warning() const { - - if (!is_visible_in_tree() || !is_inside_tree()) - return String(); - - if (!Object::cast_to(get_parent())) { - return TTR("PathFollow only works when set as a child of a Path node."); - } else { - Path *path = Object::cast_to(get_parent()); - if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { - return TTR("PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path's Curve resource."); - } - } - - return String(); -} - -void PathFollow::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow::get_offset); - - ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow::set_h_offset); - ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow::get_h_offset); - - ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow::set_v_offset); - ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow::get_v_offset); - - ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow::set_unit_offset); - ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow::get_unit_offset); - - ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow::set_rotation_mode); - ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow::get_rotation_mode); - - ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &PathFollow::set_cubic_interpolation); - ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow::get_cubic_interpolation); - - ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow::set_loop); - ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow::has_loop); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); - - BIND_ENUM_CONSTANT(ROTATION_NONE); - BIND_ENUM_CONSTANT(ROTATION_Y); - BIND_ENUM_CONSTANT(ROTATION_XY); - BIND_ENUM_CONSTANT(ROTATION_XYZ); - BIND_ENUM_CONSTANT(ROTATION_ORIENTED); -} - -void PathFollow::set_offset(float p_offset) { - delta_offset = p_offset - offset; - offset = p_offset; - - if (path) { - if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { - float path_length = path->get_curve()->get_baked_length(); - - if (loop) { - while (offset > path_length) - offset -= path_length; - - while (offset < 0) - offset += path_length; - - } else { - offset = CLAMP(offset, 0, path_length); - } - } - - _update_transform(); - } - _change_notify("offset"); - _change_notify("unit_offset"); -} - -void PathFollow::set_h_offset(float p_h_offset) { - - h_offset = p_h_offset; - if (path) - _update_transform(); -} - -float PathFollow::get_h_offset() const { - - return h_offset; -} - -void PathFollow::set_v_offset(float p_v_offset) { - - v_offset = p_v_offset; - if (path) - _update_transform(); -} - -float PathFollow::get_v_offset() const { - - return v_offset; -} - -float PathFollow::get_offset() const { - - return offset; -} - -void PathFollow::set_unit_offset(float p_unit_offset) { - - if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) - set_offset(p_unit_offset * path->get_curve()->get_baked_length()); -} - -float PathFollow::get_unit_offset() const { - - if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) - return get_offset() / path->get_curve()->get_baked_length(); - else - return 0; -} - -void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) { - - rotation_mode = p_rotation_mode; - - update_configuration_warning(); - _update_transform(); -} - -PathFollow::RotationMode PathFollow::get_rotation_mode() const { - - return rotation_mode; -} - -void PathFollow::set_loop(bool p_loop) { - - loop = p_loop; -} - -bool PathFollow::has_loop() const { - - return loop; -} - -PathFollow::PathFollow() { - - offset = 0; - delta_offset = 0; - h_offset = 0; - v_offset = 0; - path = NULL; - rotation_mode = ROTATION_XYZ; - cubic = true; - loop = true; -} diff --git a/scene/3d/path.h b/scene/3d/path.h deleted file mode 100644 index 497913b925..0000000000 --- a/scene/3d/path.h +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************/ -/* path.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PATH_H -#define PATH_H - -#include "scene/3d/spatial.h" -#include "scene/resources/curve.h" - -class Path : public Spatial { - - GDCLASS(Path, Spatial); - - Ref curve; - - void _curve_changed(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_curve(const Ref &p_curve); - Ref get_curve() const; - - Path(); -}; - -class PathFollow : public Spatial { - - GDCLASS(PathFollow, Spatial); - -public: - enum RotationMode { - - ROTATION_NONE, - ROTATION_Y, - ROTATION_XY, - ROTATION_XYZ, - ROTATION_ORIENTED - }; - -private: - Path *path; - real_t delta_offset; // change in offset since last _update_transform - real_t offset; - real_t h_offset; - real_t v_offset; - bool cubic; - bool loop; - RotationMode rotation_mode; - - void _update_transform(); - -protected: - virtual void _validate_property(PropertyInfo &property) const; - - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_offset(float p_offset); - float get_offset() const; - - void set_h_offset(float p_h_offset); - float get_h_offset() const; - - void set_v_offset(float p_v_offset); - float get_v_offset() const; - - void set_unit_offset(float p_unit_offset); - float get_unit_offset() const; - - void set_loop(bool p_loop); - bool has_loop() const; - - void set_rotation_mode(RotationMode p_rotation_mode); - RotationMode get_rotation_mode() const; - - void set_cubic_interpolation(bool p_enable); - bool get_cubic_interpolation() const; - - String get_configuration_warning() const; - - PathFollow(); -}; - -VARIANT_ENUM_CAST(PathFollow::RotationMode); - -#endif // PATH_H diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp new file mode 100644 index 0000000000..2169f664ea --- /dev/null +++ b/scene/3d/path_3d.cpp @@ -0,0 +1,416 @@ +/*************************************************************************/ +/* path_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "path_3d.h" + +#include "core/engine.h" +#include "scene/scene_string_names.h" + +void Path3D::_notification(int p_what) { +} + +void Path3D::_curve_changed() { + + if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) + update_gizmo(); + if (is_inside_tree()) { + emit_signal("curve_changed"); + } + + // update the configuration warnings of all children of type PathFollow + // previously used for PathFollowOriented (now enforced orientation is done in PathFollow) + if (is_inside_tree()) { + for (int i = 0; i < get_child_count(); i++) { + PathFollow3D *child = Object::cast_to(get_child(i)); + if (child) { + child->update_configuration_warning(); + } + } + } +} + +void Path3D::set_curve(const Ref &p_curve) { + + if (curve.is_valid()) { + curve->disconnect("changed", callable_mp(this, &Path3D::_curve_changed)); + } + + curve = p_curve; + + if (curve.is_valid()) { + curve->connect("changed", callable_mp(this, &Path3D::_curve_changed)); + } + _curve_changed(); +} + +Ref Path3D::get_curve() const { + + return curve; +} + +void Path3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path3D::set_curve); + ClassDB::bind_method(D_METHOD("get_curve"), &Path3D::get_curve); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve"); + + ADD_SIGNAL(MethodInfo("curve_changed")); +} + +Path3D::Path3D() { + + set_curve(Ref(memnew(Curve3D))); //create one by default +} + +////////////// + +void PathFollow3D::_update_transform() { + + if (!path) + return; + + Ref c = path->get_curve(); + if (!c.is_valid()) + return; + + if (delta_offset == 0) { + return; + } + + float bl = c->get_baked_length(); + if (bl == 0.0) { + return; + } + float bi = c->get_bake_interval(); + float o_next = offset + bi; + + if (loop) { + o_next = Math::fposmod(o_next, bl); + } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) { + o_next = bl; + } + + Vector3 pos = c->interpolate_baked(offset, cubic); + Transform t = get_transform(); + // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases + // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used + + if (rotation_mode == ROTATION_ORIENTED) { + + Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; + + if (forward.length_squared() < CMP_EPSILON2) + forward = Vector3(0, 0, 1); + else + forward.normalize(); + + Vector3 up = c->interpolate_baked_up_vector(offset, true); + + if (o_next < offset) { + Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); + Vector3 axis = up.cross(up1); + + if (axis.length_squared() < CMP_EPSILON2) + axis = forward; + else + axis.normalize(); + + up.rotate(axis, up.angle_to(up1) * 0.5f); + } + + Vector3 scale = t.basis.get_scale(); + Vector3 sideways = up.cross(forward).normalized(); + up = forward.cross(sideways).normalized(); + + t.basis.set(sideways, up, forward); + t.basis.scale_local(scale); + + t.origin = pos + sideways * h_offset + up * v_offset; + } else if (rotation_mode != ROTATION_NONE) { + // perform parallel transport + // + // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example + // for a discussion about why not Frenet frame. + + t.origin = pos; + + Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized(); + Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized(); + + Vector3 axis = t_prev.cross(t_cur); + float dot = t_prev.dot(t_cur); + float angle = Math::acos(CLAMP(dot, -1, 1)); + + if (likely(!Math::is_zero_approx(angle))) { + if (rotation_mode == ROTATION_Y) { + // assuming we're referring to global Y-axis. is this correct? + axis.x = 0; + axis.z = 0; + } else if (rotation_mode == ROTATION_XY) { + axis.z = 0; + } else if (rotation_mode == ROTATION_XYZ) { + // all components are allowed + } + + if (likely(!Math::is_zero_approx(axis.length()))) { + t.rotate_basis(axis.normalized(), angle); + } + } + + // do the additional tilting + float tilt_angle = c->interpolate_baked_tilt(offset); + Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? + + if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) { + if (rotation_mode == ROTATION_Y) { + tilt_axis.x = 0; + tilt_axis.z = 0; + } else if (rotation_mode == ROTATION_XY) { + tilt_axis.z = 0; + } else if (rotation_mode == ROTATION_XYZ) { + // all components are allowed + } + + if (likely(!Math::is_zero_approx(tilt_axis.length()))) { + t.rotate_basis(tilt_axis.normalized(), tilt_angle); + } + } + + t.translate(Vector3(h_offset, v_offset, 0)); + } else { + t.origin = pos + Vector3(h_offset, v_offset, 0); + } + + set_transform(t); +} + +void PathFollow3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + Node *parent = get_parent(); + if (parent) { + path = Object::cast_to(parent); + if (path) { + _update_transform(); + } + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + path = NULL; + } break; + } +} + +void PathFollow3D::set_cubic_interpolation(bool p_enable) { + + cubic = p_enable; +} + +bool PathFollow3D::get_cubic_interpolation() const { + + return cubic; +} + +void PathFollow3D::_validate_property(PropertyInfo &property) const { + + if (property.name == "offset") { + + float max = 10000; + if (path && path->get_curve().is_valid()) + max = path->get_curve()->get_baked_length(); + + property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater"; + } +} + +String PathFollow3D::get_configuration_warning() const { + + if (!is_visible_in_tree() || !is_inside_tree()) + return String(); + + if (!Object::cast_to(get_parent())) { + return TTR("PathFollow only works when set as a child of a Path node."); + } else { + Path3D *path = Object::cast_to(get_parent()); + if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { + return TTR("PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path's Curve resource."); + } + } + + return String(); +} + +void PathFollow3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow3D::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow3D::get_offset); + + ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow3D::set_h_offset); + ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow3D::get_h_offset); + + ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow3D::set_v_offset); + ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow3D::get_v_offset); + + ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow3D::set_unit_offset); + ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow3D::get_unit_offset); + + ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow3D::set_rotation_mode); + ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow3D::get_rotation_mode); + + ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &PathFollow3D::set_cubic_interpolation); + ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow3D::get_cubic_interpolation); + + ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop); + ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); + + BIND_ENUM_CONSTANT(ROTATION_NONE); + BIND_ENUM_CONSTANT(ROTATION_Y); + BIND_ENUM_CONSTANT(ROTATION_XY); + BIND_ENUM_CONSTANT(ROTATION_XYZ); + BIND_ENUM_CONSTANT(ROTATION_ORIENTED); +} + +void PathFollow3D::set_offset(float p_offset) { + delta_offset = p_offset - offset; + offset = p_offset; + + if (path) { + if (path->get_curve().is_valid() && path->get_curve()->get_baked_length()) { + float path_length = path->get_curve()->get_baked_length(); + + if (loop) { + while (offset > path_length) + offset -= path_length; + + while (offset < 0) + offset += path_length; + + } else { + offset = CLAMP(offset, 0, path_length); + } + } + + _update_transform(); + } + _change_notify("offset"); + _change_notify("unit_offset"); +} + +void PathFollow3D::set_h_offset(float p_h_offset) { + + h_offset = p_h_offset; + if (path) + _update_transform(); +} + +float PathFollow3D::get_h_offset() const { + + return h_offset; +} + +void PathFollow3D::set_v_offset(float p_v_offset) { + + v_offset = p_v_offset; + if (path) + _update_transform(); +} + +float PathFollow3D::get_v_offset() const { + + return v_offset; +} + +float PathFollow3D::get_offset() const { + + return offset; +} + +void PathFollow3D::set_unit_offset(float p_unit_offset) { + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + set_offset(p_unit_offset * path->get_curve()->get_baked_length()); +} + +float PathFollow3D::get_unit_offset() const { + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + return get_offset() / path->get_curve()->get_baked_length(); + else + return 0; +} + +void PathFollow3D::set_rotation_mode(RotationMode p_rotation_mode) { + + rotation_mode = p_rotation_mode; + + update_configuration_warning(); + _update_transform(); +} + +PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const { + + return rotation_mode; +} + +void PathFollow3D::set_loop(bool p_loop) { + + loop = p_loop; +} + +bool PathFollow3D::has_loop() const { + + return loop; +} + +PathFollow3D::PathFollow3D() { + + offset = 0; + delta_offset = 0; + h_offset = 0; + v_offset = 0; + path = NULL; + rotation_mode = ROTATION_XYZ; + cubic = true; + loop = true; +} diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h new file mode 100644 index 0000000000..6f0db8c5c2 --- /dev/null +++ b/scene/3d/path_3d.h @@ -0,0 +1,117 @@ +/*************************************************************************/ +/* path_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PATH_H +#define PATH_H + +#include "scene/3d/node_3d.h" +#include "scene/resources/curve.h" + +class Path3D : public Node3D { + + GDCLASS(Path3D, Node3D); + + Ref curve; + + void _curve_changed(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_curve(const Ref &p_curve); + Ref get_curve() const; + + Path3D(); +}; + +class PathFollow3D : public Node3D { + + GDCLASS(PathFollow3D, Node3D); + +public: + enum RotationMode { + + ROTATION_NONE, + ROTATION_Y, + ROTATION_XY, + ROTATION_XYZ, + ROTATION_ORIENTED + }; + +private: + Path3D *path; + real_t delta_offset; // change in offset since last _update_transform + real_t offset; + real_t h_offset; + real_t v_offset; + bool cubic; + bool loop; + RotationMode rotation_mode; + + void _update_transform(); + +protected: + virtual void _validate_property(PropertyInfo &property) const; + + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_offset(float p_offset); + float get_offset() const; + + void set_h_offset(float p_h_offset); + float get_h_offset() const; + + void set_v_offset(float p_v_offset); + float get_v_offset() const; + + void set_unit_offset(float p_unit_offset); + float get_unit_offset() const; + + void set_loop(bool p_loop); + bool has_loop() const; + + void set_rotation_mode(RotationMode p_rotation_mode); + RotationMode get_rotation_mode() const; + + void set_cubic_interpolation(bool p_enable); + bool get_cubic_interpolation() const; + + String get_configuration_warning() const; + + PathFollow3D(); +}; + +VARIANT_ENUM_CAST(PathFollow3D::RotationMode); + +#endif // PATH_H diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp deleted file mode 100644 index 2f8dc31cb6..0000000000 --- a/scene/3d/physics_body.cpp +++ /dev/null @@ -1,2596 +0,0 @@ -/*************************************************************************/ -/* physics_body.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_body.h" - -#include "core/core_string_names.h" -#include "core/engine.h" -#include "core/list.h" -#include "core/method_bind_ext.gen.inc" -#include "core/object.h" -#include "core/rid.h" -#include "scene/3d/collision_shape.h" -#include "scene/scene_string_names.h" -#include "servers/navigation_server.h" - -#ifdef TOOLS_ENABLED -#include "editor/plugins/spatial_editor_plugin.h" -#endif - -Vector3 PhysicsBody::get_linear_velocity() const { - - return Vector3(); -} -Vector3 PhysicsBody::get_angular_velocity() const { - - return Vector3(); -} - -float PhysicsBody::get_inverse_mass() const { - - return 0; -} - -void PhysicsBody::set_collision_layer(uint32_t p_layer) { - - collision_layer = p_layer; - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); -} - -uint32_t PhysicsBody::get_collision_layer() const { - - return collision_layer; -} - -void PhysicsBody::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), p_mask); -} - -uint32_t PhysicsBody::get_collision_mask() const { - - return collision_mask; -} - -void PhysicsBody::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool PhysicsBody::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -void PhysicsBody::set_collision_layer_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_layer(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_layer(mask); -} - -bool PhysicsBody::get_collision_layer_bit(int p_bit) const { - - return get_collision_layer() & (1 << p_bit); -} - -Array PhysicsBody::get_collision_exceptions() { - List exceptions; - PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); - Array ret; - for (List::Element *E = exceptions.front(); E; E = E->next()) { - RID body = E->get(); - ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); - Object *obj = ObjectDB::get_instance(instance_id); - PhysicsBody *physics_body = Object::cast_to(obj); - ret.append(physics_body); - } - return ret; -} - -void PhysicsBody::add_collision_exception_with(Node *p_node) { - - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); -} - -void PhysicsBody::remove_collision_exception_with(Node *p_node) { - - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); -} - -void PhysicsBody::_set_layers(uint32_t p_mask) { - set_collision_layer(p_mask); - set_collision_mask(p_mask); -} - -uint32_t PhysicsBody::_get_layers() const { - - return get_collision_layer(); -} - -void PhysicsBody::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody::get_collision_layer); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &PhysicsBody::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsBody::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &PhysicsBody::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &PhysicsBody::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &PhysicsBody::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &PhysicsBody::get_collision_layer_bit); - - ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody::_set_layers); - ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody::_get_layers); - - ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); -} - -PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : - CollisionObject(PhysicsServer::get_singleton()->body_create(p_mode), false) { - - collision_layer = 1; - collision_mask = 1; -} - -void StaticBody::set_physics_material_override(const Ref &p_physics_material_override) { - if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics)); - } - } - - physics_material_override = p_physics_material_override; - - if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody::_reload_physics_characteristics)); - } - _reload_physics_characteristics(); -} - -Ref StaticBody::get_physics_material_override() const { - return physics_material_override; -} - -void StaticBody::set_constant_linear_velocity(const Vector3 &p_vel) { - - constant_linear_velocity = p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); -} - -void StaticBody::set_constant_angular_velocity(const Vector3 &p_vel) { - - constant_angular_velocity = p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); -} - -Vector3 StaticBody::get_constant_linear_velocity() const { - - return constant_linear_velocity; -} -Vector3 StaticBody::get_constant_angular_velocity() const { - - return constant_angular_velocity; -} - -void StaticBody::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody::set_constant_linear_velocity); - ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody::set_constant_angular_velocity); - ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody::get_constant_linear_velocity); - ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody::get_constant_angular_velocity); - - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody::get_physics_material_override); - - ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody::get_collision_exceptions); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with); - - 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"), "set_constant_linear_velocity", "get_constant_linear_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); -} - -StaticBody::StaticBody() : - PhysicsBody(PhysicsServer::BODY_MODE_STATIC) { -} - -StaticBody::~StaticBody() {} - -void StaticBody::_reload_physics_characteristics() { - if (physics_material_override.is_null()) { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); - } else { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); - } -} - -void RigidBody::_body_enter_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - - ERR_FAIL_COND(!contact_monitor); - Map::Element *E = contact_monitor->body_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_tree); - - E->get().in_tree = true; - - contact_monitor->locked = true; - - emit_signal(SceneStringNames::get_singleton()->body_entered, node); - - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); - } - - contact_monitor->locked = false; -} - -void RigidBody::_body_exit_tree(ObjectID p_id) { - - Object *obj = ObjectDB::get_instance(p_id); - Node *node = Object::cast_to(obj); - ERR_FAIL_COND(!node); - ERR_FAIL_COND(!contact_monitor); - Map::Element *E = contact_monitor->body_map.find(p_id); - ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_tree); - E->get().in_tree = false; - - contact_monitor->locked = true; - - emit_signal(SceneStringNames::get_singleton()->body_exited, node); - - for (int i = 0; i < E->get().shapes.size(); i++) { - - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); - } - - contact_monitor->locked = false; -} - -void RigidBody::_body_inout(int p_status, 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(obj); - - ERR_FAIL_COND(!contact_monitor); - Map::Element *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->get().rc=0; - E->get().in_tree = node && node->is_inside_tree(); - if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree), make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree), make_binds(objid)); - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_entered, node); - } - } - } - //E->get().rc++; - if (node) - E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape)); - - if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape); - } - - } else { - - //E->get().rc--; - - if (node) - E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape)); - - bool in_tree = E->get().in_tree; - - if (E->get().shapes.empty()) { - - if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree)); - if (in_tree) - emit_signal(SceneStringNames::get_singleton()->body_exited, node); - } - - contact_monitor->body_map.erase(E); - } - if (node && in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape); - } - } -} - -struct _RigidBodyInOut { - - ObjectID id; - int shape; - int local_shape; -}; - -void RigidBody::_direct_state_changed(Object *p_state) { - -#ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); -#else - state = (PhysicsDirectBodyState *)p_state; //trust it -#endif - - set_ignore_transform_notification(true); - set_global_transform(state->get_transform()); - linear_velocity = state->get_linear_velocity(); - angular_velocity = state->get_angular_velocity(); - if (sleeping != state->is_sleeping()) { - sleeping = state->is_sleeping(); - emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed); - } - if (get_script_instance()) - get_script_instance()->call("_integrate_forces", state); - set_ignore_transform_notification(false); - - if (contact_monitor) { - - contact_monitor->locked = true; - - //untag all - int rc = 0; - for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { - - for (int i = 0; i < E->get().shapes.size(); i++) { - - E->get().shapes[i].tagged = false; - rc++; - } - } - - _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(state->get_contact_count() * sizeof(_RigidBodyInOut)); - int toadd_count = 0; //state->get_contact_count(); - RigidBody_RemoveAction *toremove = (RigidBody_RemoveAction *)alloca(rc * sizeof(RigidBody_RemoveAction)); - int toremove_count = 0; - - //put the ones to add - - for (int i = 0; i < state->get_contact_count(); i++) { - - ObjectID obj = state->get_contact_collider_id(i); - int local_shape = state->get_contact_local_shape(i); - int shape = state->get_contact_collider_shape(i); - - //bool found=false; - - Map::Element *E = contact_monitor->body_map.find(obj); - if (!E) { - toadd[toadd_count].local_shape = local_shape; - toadd[toadd_count].id = obj; - toadd[toadd_count].shape = shape; - toadd_count++; - continue; - } - - ShapePair sp(shape, local_shape); - int idx = E->get().shapes.find(sp); - if (idx == -1) { - - toadd[toadd_count].local_shape = local_shape; - toadd[toadd_count].id = obj; - toadd[toadd_count].shape = shape; - toadd_count++; - continue; - } - - E->get().shapes[idx].tagged = true; - } - - //put the ones to remove - - for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { - - for (int i = 0; i < E->get().shapes.size(); i++) { - - if (!E->get().shapes[i].tagged) { - - toremove[toremove_count].body_id = E->key(); - toremove[toremove_count].pair = E->get().shapes[i]; - toremove_count++; - } - } - } - - //process remotions - - for (int i = 0; i < toremove_count; i++) { - - _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); - } - - //process aditions - - for (int i = 0; i < toadd_count; i++) { - - _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); - } - - contact_monitor->locked = false; - } - - state = NULL; -} - -void RigidBody::_notification(int p_what) { - -#ifdef TOOLS_ENABLED - if (p_what == NOTIFICATION_ENTER_TREE) { - if (Engine::get_singleton()->is_editor_hint()) { - set_notify_local_transform(true); //used for warnings and only in editor - } - } - - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warning(); - } - } - -#endif -} - -void RigidBody::set_mode(Mode p_mode) { - - mode = p_mode; - switch (p_mode) { - - case MODE_RIGID: { - - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); - } break; - case MODE_STATIC: { - - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - - } break; - case MODE_CHARACTER: { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_CHARACTER); - - } break; - case MODE_KINEMATIC: { - - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); - } break; - } - update_configuration_warning(); -} - -RigidBody::Mode RigidBody::get_mode() const { - - return mode; -} - -void RigidBody::set_mass(real_t p_mass) { - - ERR_FAIL_COND(p_mass <= 0); - mass = p_mass; - _change_notify("mass"); - _change_notify("weight"); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); -} -real_t RigidBody::get_mass() const { - - return mass; -} - -void RigidBody::set_weight(real_t p_weight) { - - set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); -} -real_t RigidBody::get_weight() const { - - return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); -} - -void RigidBody::set_physics_material_override(const Ref &p_physics_material_override) { - if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics)); - } - } - - physics_material_override = p_physics_material_override; - - if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody::_reload_physics_characteristics)); - } - _reload_physics_characteristics(); -} - -Ref RigidBody::get_physics_material_override() const { - return physics_material_override; -} - -void RigidBody::set_gravity_scale(real_t p_gravity_scale) { - - gravity_scale = p_gravity_scale; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); -} -real_t RigidBody::get_gravity_scale() const { - - return gravity_scale; -} - -void RigidBody::set_linear_damp(real_t p_linear_damp) { - - ERR_FAIL_COND(p_linear_damp < -1); - linear_damp = p_linear_damp; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_LINEAR_DAMP, linear_damp); -} -real_t RigidBody::get_linear_damp() const { - - return linear_damp; -} - -void RigidBody::set_angular_damp(real_t p_angular_damp) { - - ERR_FAIL_COND(p_angular_damp < -1); - angular_damp = p_angular_damp; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_ANGULAR_DAMP, angular_damp); -} -real_t RigidBody::get_angular_damp() const { - - return angular_damp; -} - -void RigidBody::set_axis_velocity(const Vector3 &p_axis) { - - Vector3 v = state ? state->get_linear_velocity() : linear_velocity; - Vector3 axis = p_axis.normalized(); - v -= axis * axis.dot(v); - v += p_axis; - if (state) { - set_linear_velocity(v); - } else { - PhysicsServer::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); - linear_velocity = v; - } -} - -void RigidBody::set_linear_velocity(const Vector3 &p_velocity) { - - linear_velocity = p_velocity; - if (state) - state->set_linear_velocity(linear_velocity); - else - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_LINEAR_VELOCITY, linear_velocity); -} - -Vector3 RigidBody::get_linear_velocity() const { - - return linear_velocity; -} - -void RigidBody::set_angular_velocity(const Vector3 &p_velocity) { - - angular_velocity = p_velocity; - if (state) - state->set_angular_velocity(angular_velocity); - else - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); -} -Vector3 RigidBody::get_angular_velocity() const { - - return angular_velocity; -} - -void RigidBody::set_use_custom_integrator(bool p_enable) { - - if (custom_integrator == p_enable) - return; - - custom_integrator = p_enable; - PhysicsServer::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); -} -bool RigidBody::is_using_custom_integrator() { - - return custom_integrator; -} - -void RigidBody::set_sleeping(bool p_sleeping) { - - sleeping = p_sleeping; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_SLEEPING, sleeping); -} - -void RigidBody::set_can_sleep(bool p_active) { - - can_sleep = p_active; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_CAN_SLEEP, p_active); -} - -bool RigidBody::is_able_to_sleep() const { - - return can_sleep; -} - -bool RigidBody::is_sleeping() const { - - return sleeping; -} - -void RigidBody::set_max_contacts_reported(int p_amount) { - - max_contacts_reported = p_amount; - PhysicsServer::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); -} - -int RigidBody::get_max_contacts_reported() const { - - return max_contacts_reported; -} - -void RigidBody::add_central_force(const Vector3 &p_force) { - PhysicsServer::get_singleton()->body_add_central_force(get_rid(), p_force); -} - -void RigidBody::add_force(const Vector3 &p_force, const Vector3 &p_pos) { - PhysicsServer::get_singleton()->body_add_force(get_rid(), p_force, p_pos); -} - -void RigidBody::add_torque(const Vector3 &p_torque) { - PhysicsServer::get_singleton()->body_add_torque(get_rid(), p_torque); -} - -void RigidBody::apply_central_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); -} - -void RigidBody::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - - PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); -} - -void RigidBody::apply_torque_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); -} - -void RigidBody::set_use_continuous_collision_detection(bool p_enable) { - - ccd = p_enable; - PhysicsServer::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable); -} - -bool RigidBody::is_using_continuous_collision_detection() const { - - return ccd; -} - -void RigidBody::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 (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { - - //clean up mess - Object *obj = ObjectDB::get_instance(E->key()); - Node *node = Object::cast_to(obj); - - if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody::_body_exit_tree)); - } - } - - memdelete(contact_monitor); - contact_monitor = NULL; - } else { - - contact_monitor = memnew(ContactMonitor); - contact_monitor->locked = false; - } -} - -bool RigidBody::is_contact_monitor_enabled() const { - - return contact_monitor != NULL; -} - -void RigidBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { - PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); -} - -bool RigidBody::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { - return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); -} - -Array RigidBody::get_colliding_bodies() const { - - ERR_FAIL_COND_V(!contact_monitor, Array()); - - Array ret; - ret.resize(contact_monitor->body_map.size()); - int idx = 0; - for (const Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { - Object *obj = ObjectDB::get_instance(E->key()); - if (!obj) { - ret.resize(ret.size() - 1); //ops - } else { - ret[idx++] = obj; - } - } - - return ret; -} - -String RigidBody::get_configuration_warning() const { - - Transform t = get_transform(); - - String warning = CollisionObject::get_configuration_warning(); - - if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { - if (warning != String()) { - warning += "\n\n"; - } - warning += TTR("Size changes to RigidBody (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); - } - - return warning; -} - -void RigidBody::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &RigidBody::get_mode); - - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody::get_mass); - - ClassDB::bind_method(D_METHOD("set_weight", "weight"), &RigidBody::set_weight); - ClassDB::bind_method(D_METHOD("get_weight"), &RigidBody::get_weight); - - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody::get_physics_material_override); - - ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody::get_linear_velocity); - - ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody::get_angular_velocity); - - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody::get_gravity_scale); - - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody::get_linear_damp); - - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody::get_angular_damp); - - ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody::set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody::get_max_contacts_reported); - - ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody::set_use_custom_integrator); - ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody::is_using_custom_integrator); - - ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody::set_contact_monitor); - ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody::is_contact_monitor_enabled); - - ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidBody::set_use_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody::is_using_continuous_collision_detection); - - ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody::set_axis_velocity); - - ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody::add_force); - ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody::add_torque); - - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody::apply_impulse); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody::apply_torque_impulse); - - ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody::set_sleeping); - ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody::is_sleeping); - - ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody::set_can_sleep); - ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody::is_able_to_sleep); - - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody::_direct_state_changed); - - ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody::set_axis_lock); - ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody::get_axis_lock); - - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody::get_colliding_bodies); - - BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState"))); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight"); - 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, "-128,128,0.01"), "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::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "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_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); - ADD_GROUP("Axis Lock", "axis_lock_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z); - ADD_GROUP("Linear", "linear_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); - 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::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); - - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("sleeping_state_changed")); - - BIND_ENUM_CONSTANT(MODE_RIGID); - BIND_ENUM_CONSTANT(MODE_STATIC); - BIND_ENUM_CONSTANT(MODE_CHARACTER); - BIND_ENUM_CONSTANT(MODE_KINEMATIC); -} - -RigidBody::RigidBody() : - PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { - - mode = MODE_RIGID; - - mass = 1; - max_contacts_reported = 0; - state = NULL; - - gravity_scale = 1; - linear_damp = -1; - angular_damp = -1; - - //angular_velocity=0; - sleeping = false; - ccd = false; - - custom_integrator = false; - contact_monitor = NULL; - can_sleep = true; - - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); -} - -RigidBody::~RigidBody() { - - if (contact_monitor) - memdelete(contact_monitor); -} - -void RigidBody::_reload_physics_characteristics() { - if (physics_material_override.is_null()) { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); - } else { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); - } -} - -////////////////////////////////////////////////////// -////////////////////////// - -Ref KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) { - - Collision col; - if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) { - if (motion_cache.is_null()) { - motion_cache.instance(); - motion_cache->owner = this; - } - - motion_cache->collision = col; - - return motion_cache; - } - - return Ref(); -} - -Vector3 KinematicBody::get_linear_velocity() const { - return linear_velocity; -} - -Vector3 KinematicBody::get_angular_velocity() const { - return angular_velocity; -} - -bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) { - - Transform gt = get_global_transform(); - PhysicsServer::MotionResult result; - bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes); - - if (colliding) { - r_collision.collider_metadata = result.collider_metadata; - r_collision.collider_shape = result.collider_shape; - r_collision.collider_vel = result.collider_velocity; - r_collision.collision = result.collision_point; - r_collision.normal = result.collision_normal; - r_collision.collider = result.collider_id; - r_collision.collider_rid = result.collider; - r_collision.travel = result.motion; - r_collision.remainder = result.remainder; - r_collision.local_shape = result.collision_local_shape; - } - - for (int i = 0; i < 3; i++) { - if (locked_axis & (1 << i)) { - result.motion[i] = 0; - } - } - - if (!p_test_only) { - gt.origin += result.motion; - set_global_transform(gt); - } - - return colliding; -} - -//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. -#define FLOOR_ANGLE_THRESHOLD 0.01 - -Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - - Vector3 body_velocity = p_linear_velocity; - Vector3 body_velocity_normal = body_velocity.normalized(); - - for (int i = 0; i < 3; i++) { - if (locked_axis & (1 << i)) { - body_velocity[i] = 0; - } - } - - // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky - Vector3 motion = (floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); - - on_floor = false; - on_floor_body = RID(); - on_ceiling = false; - on_wall = false; - colliders.clear(); - floor_normal = Vector3(); - floor_velocity = Vector3(); - - while (p_max_slides) { - - Collision collision; - bool found_collision = false; - - for (int i = 0; i < 2; ++i) { - bool collided; - if (i == 0) { //collide - collided = move_and_collide(motion, p_infinite_inertia, collision); - if (!collided) { - motion = Vector3(); //clear because no collision happened and motion completed - } - } else { //separate raycasts (if any) - collided = separate_raycast_shapes(p_infinite_inertia, collision); - if (collided) { - collision.remainder = motion; //keep - collision.travel = Vector3(); - } - } - - if (collided) { - found_collision = true; - - colliders.push_back(collision); - motion = collision.remainder; - - if (p_up_direction == Vector3()) { - //all is a wall - on_wall = true; - } else { - if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor - - on_floor = true; - floor_normal = collision.normal; - on_floor_body = collision.collider_rid; - floor_velocity = collision.collider_vel; - - if (p_stop_on_slope) { - if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { - Transform gt = get_global_transform(); - gt.origin -= collision.travel.slide(p_up_direction); - set_global_transform(gt); - return Vector3(); - } - } - } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling - on_ceiling = true; - } else { - on_wall = true; - } - } - - motion = motion.slide(collision.normal); - body_velocity = body_velocity.slide(collision.normal); - - for (int j = 0; j < 3; j++) { - if (locked_axis & (1 << j)) { - body_velocity[j] = 0; - } - } - } - } - - if (!found_collision || motion == Vector3()) - break; - - --p_max_slides; - } - - return body_velocity; -} - -Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { - - bool was_on_floor = on_floor; - - Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); - if (!was_on_floor || p_snap == Vector3()) { - return ret; - } - - Collision col; - Transform gt = get_global_transform(); - - if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { - - bool apply = true; - if (p_up_direction != Vector3()) { - if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { - on_floor = true; - floor_normal = col.normal; - on_floor_body = col.collider_rid; - floor_velocity = col.collider_vel; - if (p_stop_on_slope) { - // move and collide may stray the object a bit because of pre un-stucking, - // so only ensure that motion happens on floor direction in this case. - col.travel = col.travel.project(p_up_direction); - } - } else { - apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. - } - } - if (apply) { - gt.origin += col.travel; - set_global_transform(gt); - } - } - - return ret; -} - -bool KinematicBody::is_on_floor() const { - - return on_floor; -} - -bool KinematicBody::is_on_wall() const { - - return on_wall; -} -bool KinematicBody::is_on_ceiling() const { - - return on_ceiling; -} - -Vector3 KinematicBody::get_floor_normal() const { - - return floor_normal; -} - -Vector3 KinematicBody::get_floor_velocity() const { - - return floor_velocity; -} - -bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) { - - ERR_FAIL_COND_V(!is_inside_tree(), false); - - return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); -} - -bool KinematicBody::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) { - - PhysicsServer::SeparationResult sep_res[8]; //max 8 rays - - Transform gt = get_global_transform(); - - Vector3 recover; - int hits = PhysicsServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); - int deepest = -1; - float deepest_depth; - for (int i = 0; i < hits; i++) { - if (deepest == -1 || sep_res[i].collision_depth > deepest_depth) { - deepest = i; - deepest_depth = sep_res[i].collision_depth; - } - } - - gt.origin += recover; - set_global_transform(gt); - - if (deepest != -1) { - r_collision.collider = sep_res[deepest].collider_id; - r_collision.collider_metadata = sep_res[deepest].collider_metadata; - r_collision.collider_shape = sep_res[deepest].collider_shape; - r_collision.collider_vel = sep_res[deepest].collider_velocity; - r_collision.collision = sep_res[deepest].collision_point; - r_collision.normal = sep_res[deepest].collision_normal; - r_collision.local_shape = sep_res[deepest].collision_local_shape; - r_collision.travel = recover; - r_collision.remainder = Vector3(); - - return true; - } else { - return false; - } -} - -void KinematicBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { - PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); -} - -bool KinematicBody::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { - return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); -} - -void KinematicBody::set_safe_margin(float p_margin) { - - margin = p_margin; - PhysicsServer::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin); -} - -float KinematicBody::get_safe_margin() const { - - return margin; -} -int KinematicBody::get_slide_count() const { - - return colliders.size(); -} - -KinematicBody::Collision KinematicBody::get_slide_collision(int p_bounce) const { - ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Collision()); - return colliders[p_bounce]; -} - -Ref KinematicBody::_get_slide_collision(int p_bounce) { - - ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref()); - if (p_bounce >= slide_colliders.size()) { - slide_colliders.resize(p_bounce + 1); - } - - if (slide_colliders[p_bounce].is_null()) { - slide_colliders.write[p_bounce].instance(); - slide_colliders.write[p_bounce]->owner = this; - } - - slide_colliders.write[p_bounce]->collision = colliders[p_bounce]; - return slide_colliders[p_bounce]; -} - -void KinematicBody::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - // Reset move_and_slide() data. - on_floor = false; - on_floor_body = RID(); - on_ceiling = false; - on_wall = false; - colliders.clear(); - floor_velocity = Vector3(); - } -} - -void KinematicBody::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody::_direct_state_changed); - - ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true)); - - ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); - ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); - ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); - ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody::get_floor_normal); - ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); - - ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock); - ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &KinematicBody::get_axis_lock); - - ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody::set_safe_margin); - ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody::get_safe_margin); - - ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count); - ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); -} - -void KinematicBody::_direct_state_changed(Object *p_state) { -#ifdef DEBUG_ENABLED - PhysicsDirectBodyState *state = Object::cast_to(p_state); -#else - PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it -#endif - - linear_velocity = state->get_linear_velocity(); - angular_velocity = state->get_angular_velocity(); -} - -KinematicBody::KinematicBody() : - PhysicsBody(PhysicsServer::BODY_MODE_KINEMATIC) { - - margin = 0.001; - locked_axis = 0; - on_floor = false; - on_ceiling = false; - on_wall = false; - - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); -} -KinematicBody::~KinematicBody() { - - if (motion_cache.is_valid()) { - motion_cache->owner = NULL; - } - - for (int i = 0; i < slide_colliders.size(); i++) { - if (slide_colliders[i].is_valid()) { - slide_colliders.write[i]->owner = NULL; - } - } -} -/////////////////////////////////////// - -Vector3 KinematicCollision::get_position() const { - - return collision.collision; -} -Vector3 KinematicCollision::get_normal() const { - return collision.normal; -} -Vector3 KinematicCollision::get_travel() const { - return collision.travel; -} -Vector3 KinematicCollision::get_remainder() const { - return collision.remainder; -} -Object *KinematicCollision::get_local_shape() const { - if (!owner) return NULL; - uint32_t ownerid = owner->shape_find_owner(collision.local_shape); - return owner->shape_owner_get_owner(ownerid); -} - -Object *KinematicCollision::get_collider() const { - - if (collision.collider.is_valid()) { - return ObjectDB::get_instance(collision.collider); - } - - return NULL; -} -ObjectID KinematicCollision::get_collider_id() const { - - return collision.collider; -} -Object *KinematicCollision::get_collider_shape() const { - - Object *collider = get_collider(); - if (collider) { - CollisionObject *obj2d = Object::cast_to(collider); - if (obj2d) { - uint32_t ownerid = obj2d->shape_find_owner(collision.collider_shape); - return obj2d->shape_owner_get_owner(ownerid); - } - } - - return NULL; -} -int KinematicCollision::get_collider_shape_index() const { - - return collision.collider_shape; -} -Vector3 KinematicCollision::get_collider_velocity() const { - - return collision.collider_vel; -} -Variant KinematicCollision::get_collider_metadata() const { - - return Variant(); -} - -void KinematicCollision::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision::get_position); - ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision::get_normal); - ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision::get_travel); - ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision::get_remainder); - ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision::get_local_shape); - ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision::get_collider); - ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision::get_collider_id); - ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision::get_collider_shape); - ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision::get_collider_shape_index); - ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision::get_collider_velocity); - ClassDB::bind_method(D_METHOD("get_collider_metadata"), &KinematicCollision::get_collider_metadata); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "", "get_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "normal"), "", "get_normal"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "local_shape"), "", "get_local_shape"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id"), "", "get_collider_id"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider_shape"), "", "get_collider_shape"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape_index"), "", "get_collider_shape_index"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::NIL, "collider_metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "", "get_collider_metadata"); -} - -KinematicCollision::KinematicCollision() { - - collision.collider_shape = 0; - collision.local_shape = 0; - owner = NULL; -} - -/////////////////////////////////////// - -bool PhysicalBone::JointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - return false; -} - -bool PhysicalBone::JointData::_get(const StringName &p_name, Variant &r_ret) const { - return false; -} - -void PhysicalBone::JointData::_get_property_list(List *p_list) const { -} - -void PhysicalBone::apply_central_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); -} - -void PhysicalBone::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); -} - -void PhysicalBone::reset_physics_simulation_state() { - if (simulate_physics) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); - } -} - -void PhysicalBone::reset_to_rest_position() { - if (parent_skeleton) { - if (-1 == bone_id) { - set_global_transform(parent_skeleton->get_global_transform() * body_offset); - } else { - set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); - } - } -} - -bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { - return true; - } - - if ("joint_constraints/bias" == p_name) { - bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_BIAS, bias); - - } else if ("joint_constraints/damping" == p_name) { - damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_DAMPING, damping); - - } else if ("joint_constraints/impulse_clamp" == p_name) { - impulse_clamp = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp); - - } else { - return false; - } - - return true; -} - -bool PhysicalBone::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 PhysicalBone::PinJointData::_get_property_list(List *p_list) const { - JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01")); -} - -bool PhysicalBone::ConeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { - return true; - } - - if ("joint_constraints/swing_span" == p_name) { - swing_span = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, swing_span); - - } else if ("joint_constraints/twist_span" == p_name) { - twist_span = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); - - } else if ("joint_constraints/bias" == p_name) { - bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_BIAS, bias); - - } else if ("joint_constraints/softness" == p_name) { - softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, softness); - - } else if ("joint_constraints/relaxation" == p_name) { - relaxation = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, relaxation); - - } else { - return false; - } - - return true; -} - -bool PhysicalBone::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::rad2deg(swing_span); - } else if ("joint_constraints/twist_span" == p_name) { - r_ret = Math::rad2deg(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 PhysicalBone::ConeJointData::_get_property_list(List *p_list) const { - JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/swing_span", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_lesser,or_greater")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); -} - -bool PhysicalBone::HingeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { - return true; - } - - if ("joint_constraints/angular_limit_enabled" == p_name) { - angular_limit_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled); - - } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); - - } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); - - } else if ("joint_constraints/angular_limit_bias" == p_name) { - angular_limit_bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias); - - } else if ("joint_constraints/angular_limit_softness" == p_name) { - angular_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_relaxation" == p_name) { - angular_limit_relaxation = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation); - - } else { - return false; - } - - return true; -} - -bool PhysicalBone::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::rad2deg(angular_limit_upper); - } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(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 PhysicalBone::HingeJointData::_get_property_list(List *p_list) const { - JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/angular_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01")); -} - -bool PhysicalBone::SliderJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { - return true; - } - - if ("joint_constraints/linear_limit_upper" == p_name) { - linear_limit_upper = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper); - - } else if ("joint_constraints/linear_limit_lower" == p_name) { - linear_limit_lower = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower); - - } else if ("joint_constraints/linear_limit_softness" == p_name) { - linear_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness); - - } else if ("joint_constraints/linear_limit_restitution" == p_name) { - linear_limit_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution); - - } else if ("joint_constraints/linear_limit_damping" == p_name) { - linear_limit_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution); - - } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); - - } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); - - } else if ("joint_constraints/angular_limit_softness" == p_name) { - angular_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_restitution" == p_name) { - angular_limit_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_damping" == p_name) { - angular_limit_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping); - - } else { - return false; - } - - return true; -} - -bool PhysicalBone::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::rad2deg(angular_limit_upper); - } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(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 PhysicalBone::SliderJointData::_get_property_list(List *p_list) const { - JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_upper")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_lower")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01")); - - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01")); -} - -bool PhysicalBone::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; - - 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); - - if ("linear_limit_enabled" == var_name) { - axis_data[axis].linear_limit_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution); - - } else if ("linear_damping" == var_name) { - axis_data[axis].linear_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution); - - } else if ("angular_damping" == var_name) { - axis_data[axis].angular_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping); - - } else if ("erp" == var_name) { - axis_data[axis].erp = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp); - - } else if ("angular_spring_enabled" == var_name) { - axis_data[axis].angular_spring_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point); - - } else { - return false; - } - - return true; -} - -bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_ret) const { - if (JointData::_get(p_name, r_ret)) { - return true; - } - - String path = p_name; - - 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::rad2deg(axis_data[axis].angular_limit_upper); - } else if ("angular_limit_lower" == var_name) { - r_ret = Math::rad2deg(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 PhysicalBone::SixDOFJointData::_get_property_list(List *p_list) const { - const StringName axis_names[] = { "x", "y", "z" }; - for (int i = 0; i < 3; ++i) { - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_upper")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_lower")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_damping")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/erp")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_damping")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point")); - } -} - -bool PhysicalBone::_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)) { -#ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif - return true; - } - } - - return false; -} - -bool PhysicalBone::_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 PhysicalBone::_get_property_list(List *p_list) const { - - Skeleton *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, "bone_name", PROPERTY_HINT_ENUM, names)); - } else { - - p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bone_name")); - } - - if (joint_data) { - joint_data->_get_property_list(p_list); - } -} - -void PhysicalBone::_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.is_valid() && 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); - } - } - parent_skeleton = NULL; - if (joint.is_valid()) { - PhysicsServer::get_singleton()->free(joint); - joint = RID(); - } - break; - case NOTIFICATION_TRANSFORM_CHANGED: - if (Engine::get_singleton()->is_editor_hint()) { - - update_offset(); - } - break; - } -} - -void PhysicalBone::_direct_state_changed(Object *p_state) { - - if (!simulate_physics || !_internal_simulate_physics) { - return; - } - - /// Update bone transform - - PhysicsDirectBodyState *state; - -#ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); -#else - state = (PhysicsDirectBodyState *)p_state; //trust it -#endif - - Transform global_transform(state->get_transform()); - - set_ignore_transform_notification(true); - set_global_transform(global_transform); - set_ignore_transform_notification(false); - - // 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 PhysicalBone::_bind_methods() { - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &PhysicalBone::apply_impulse); - - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone::_direct_state_changed); - - ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone::set_joint_type); - ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone::get_joint_type); - - ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone::set_joint_offset); - ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone::get_joint_offset); - - ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); - ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); - - ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); - - ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); - - ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id); - - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone::get_mass); - - ClassDB::bind_method(D_METHOD("set_weight", "weight"), &PhysicalBone::set_weight); - ClassDB::bind_method(D_METHOD("get_weight"), &PhysicalBone::get_weight); - - ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone::set_friction); - ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone::get_friction); - - ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &PhysicalBone::set_bounce); - ClassDB::bind_method(D_METHOD("get_bounce"), &PhysicalBone::get_bounce); - - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone::get_gravity_scale); - - 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::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); - - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); - 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, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); - - 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); -} - -Skeleton *PhysicalBone::find_skeleton_parent(Node *p_parent) { - if (!p_parent) { - return NULL; - } - Skeleton *s = Object::cast_to(p_parent); - return s ? s : find_skeleton_parent(p_parent->get_parent()); -} - -void PhysicalBone::_fix_joint_offset() { - // Clamp joint origin to bone origin - if (parent_skeleton) { - joint_offset.origin = body_offset.affine_inverse().origin; - } -} - -void PhysicalBone::_reload_joint() { - - if (joint.is_valid()) { - PhysicsServer::get_singleton()->free(joint); - joint = RID(); - } - - if (!parent_skeleton) { - return; - } - - PhysicalBone *body_a = parent_skeleton->get_physical_bone_parent(bone_id); - if (!body_a) { - return; - } - - Transform joint_transf = get_global_transform() * joint_offset; - Transform local_a = body_a->get_global_transform().affine_inverse() * joint_transf; - local_a.orthonormalize(); - - switch (get_joint_type()) { - case JOINT_TYPE_PIN: { - - joint = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin); - const PinJointData *pjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_BIAS, pjd->bias); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_DAMPING, pjd->damping); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); - - } break; - case JOINT_TYPE_CONE: { - - joint = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset); - const ConeJointData *cjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_BIAS, cjd->bias); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); - - } break; - case JOINT_TYPE_HINGE: { - - joint = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset); - const HingeJointData *hjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); - - } break; - case JOINT_TYPE_SLIDER: { - - joint = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset); - const SliderJointData *sjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); - - } break; - case JOINT_TYPE_6DOF: { - - joint = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset); - const SixDOFJointData *g6dofjd(static_cast(joint_data)); - for (int axis = 0; axis < 3; ++axis) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point); - } - - } break; - case JOINT_TYPE_NONE: { - } break; - } -} - -void PhysicalBone::_on_bone_parent_changed() { - _reload_joint(); -} - -void PhysicalBone::_set_gizmo_move_joint(bool p_move_joint) { -#ifdef TOOLS_ENABLED - gizmo_move_joint = p_move_joint; - SpatialEditor::get_singleton()->update_transform_gizmo(); -#endif -} - -#ifdef TOOLS_ENABLED -Transform PhysicalBone::get_global_gizmo_transform() const { - return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform(); -} - -Transform PhysicalBone::get_local_gizmo_transform() const { - return gizmo_move_joint ? get_transform() * joint_offset : get_transform(); -} -#endif - -const PhysicalBone::JointData *PhysicalBone::get_joint_data() const { - return joint_data; -} - -Skeleton *PhysicalBone::find_skeleton_parent() { - return find_skeleton_parent(this); -} - -void PhysicalBone::set_joint_type(JointType p_joint_type) { - - if (p_joint_type == get_joint_type()) - return; - - if (joint_data) - memdelete(joint_data); - joint_data = NULL; - 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 - _change_notify(); - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif -} - -PhysicalBone::JointType PhysicalBone::get_joint_type() const { - return joint_data ? joint_data->get_joint_type() : JOINT_TYPE_NONE; -} - -void PhysicalBone::set_joint_offset(const Transform &p_offset) { - joint_offset = p_offset; - - _fix_joint_offset(); - - set_ignore_transform_notification(true); - reset_to_rest_position(); - set_ignore_transform_notification(false); - -#ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif -} - -const Transform &PhysicalBone::get_body_offset() const { - return body_offset; -} - -void PhysicalBone::set_body_offset(const Transform &p_offset) { - body_offset = p_offset; - body_offset_inverse = body_offset.affine_inverse(); - - _fix_joint_offset(); - - set_ignore_transform_notification(true); - reset_to_rest_position(); - set_ignore_transform_notification(false); - -#ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) - get_gizmo()->redraw(); -#endif -} - -const Transform &PhysicalBone::get_joint_offset() const { - return joint_offset; -} - -void PhysicalBone::set_simulate_physics(bool p_simulate) { - if (simulate_physics == p_simulate) { - return; - } - - simulate_physics = p_simulate; - reset_physics_simulation_state(); -} - -bool PhysicalBone::get_simulate_physics() { - return simulate_physics; -} - -bool PhysicalBone::is_simulating_physics() { - return _internal_simulate_physics; -} - -void PhysicalBone::set_bone_name(const String &p_name) { - - bone_name = p_name; - bone_id = -1; - - update_bone_id(); - reset_to_rest_position(); -} - -const String &PhysicalBone::get_bone_name() const { - - return bone_name; -} - -void PhysicalBone::set_mass(real_t p_mass) { - - ERR_FAIL_COND(p_mass <= 0); - mass = p_mass; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); -} - -real_t PhysicalBone::get_mass() const { - - return mass; -} - -void PhysicalBone::set_weight(real_t p_weight) { - - set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); -} - -real_t PhysicalBone::get_weight() const { - - return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); -} - -void PhysicalBone::set_friction(real_t p_friction) { - - ERR_FAIL_COND(p_friction < 0 || p_friction > 1); - - friction = p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); -} - -real_t PhysicalBone::get_friction() const { - - return friction; -} - -void PhysicalBone::set_bounce(real_t p_bounce) { - - ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); - - bounce = p_bounce; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); -} - -real_t PhysicalBone::get_bounce() const { - - return bounce; -} - -void PhysicalBone::set_gravity_scale(real_t p_gravity_scale) { - - gravity_scale = p_gravity_scale; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); -} - -real_t PhysicalBone::get_gravity_scale() const { - - return gravity_scale; -} - -PhysicalBone::PhysicalBone() : - PhysicsBody(PhysicsServer::BODY_MODE_STATIC), -#ifdef TOOLS_ENABLED - gizmo_move_joint(false), -#endif - joint_data(NULL), - parent_skeleton(NULL), - simulate_physics(false), - _internal_simulate_physics(false), - bone_id(-1), - bone_name(""), - bounce(0), - mass(1), - friction(1), - gravity_scale(1) { - - reset_physics_simulation_state(); -} - -PhysicalBone::~PhysicalBone() { - if (joint_data) - memdelete(joint_data); -} - -void PhysicalBone::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); - parent_skeleton->unbind_child_node_from_bone(bone_id, this); - } - - bone_id = new_bone_id; - - parent_skeleton->bind_physical_bone_to_bone(bone_id, this); - - _fix_joint_offset(); - reset_physics_simulation_state(); - } -} - -void PhysicalBone::update_offset() { -#ifdef TOOLS_ENABLED - if (parent_skeleton) { - - Transform 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 PhysicalBone::_start_physics_simulation() { - if (_internal_simulate_physics || !parent_skeleton) { - return; - } - reset_to_rest_position(); - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); - set_as_toplevel(true); - _internal_simulate_physics = true; -} - -void PhysicalBone::_stop_physics_simulation() { - if (!parent_skeleton) { - return; - } - if (parent_skeleton->get_animate_physical_bones()) { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - } else { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); - } - if (_internal_simulate_physics) { - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); - parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); - set_as_toplevel(false); - _internal_simulate_physics = false; - } -} diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h deleted file mode 100644 index 90de1ffce6..0000000000 --- a/scene/3d/physics_body.h +++ /dev/null @@ -1,646 +0,0 @@ -/*************************************************************************/ -/* physics_body.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_BODY__H -#define PHYSICS_BODY__H - -#include "core/vset.h" -#include "scene/3d/collision_object.h" -#include "scene/resources/physics_material.h" -#include "servers/physics_server.h" -#include "skeleton.h" - -class PhysicsBody : public CollisionObject { - - GDCLASS(PhysicsBody, CollisionObject); - - uint32_t collision_layer; - uint32_t collision_mask; - - void _set_layers(uint32_t p_mask); - uint32_t _get_layers() const; - -protected: - static void _bind_methods(); - PhysicsBody(PhysicsServer::BodyMode p_mode); - -public: - virtual Vector3 get_linear_velocity() const; - virtual Vector3 get_angular_velocity() const; - virtual float get_inverse_mass() const; - - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - Array get_collision_exceptions(); - void add_collision_exception_with(Node *p_node); //must be physicsbody - void remove_collision_exception_with(Node *p_node); - - PhysicsBody(); -}; - -class StaticBody : public PhysicsBody { - - GDCLASS(StaticBody, PhysicsBody); - - Vector3 constant_linear_velocity; - Vector3 constant_angular_velocity; - - Ref physics_material_override; - -protected: - static void _bind_methods(); - -public: - void set_physics_material_override(const Ref &p_physics_material_override); - Ref 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; - - StaticBody(); - ~StaticBody(); - -private: - void _reload_physics_characteristics(); -}; - -class RigidBody : public PhysicsBody { - - GDCLASS(RigidBody, PhysicsBody); - -public: - enum Mode { - MODE_RIGID, - MODE_STATIC, - MODE_CHARACTER, - MODE_KINEMATIC, - }; - -protected: - bool can_sleep; - PhysicsDirectBodyState *state; - Mode mode; - - real_t mass; - Ref physics_material_override; - - Vector3 linear_velocity; - Vector3 angular_velocity; - real_t gravity_scale; - real_t linear_damp; - real_t angular_damp; - - bool sleeping; - bool ccd; - - int max_contacts_reported; - - bool custom_integrator; - - struct ShapePair { - - int body_shape; - int local_shape; - bool tagged; - 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 RigidBody_RemoveAction { - - ObjectID body_id; - ShapePair pair; - }; - struct BodyState { - - //int rc; - bool in_tree; - VSet shapes; - }; - - struct ContactMonitor { - - bool locked; - Map body_map; - }; - - ContactMonitor *contact_monitor; - void _body_enter_tree(ObjectID p_id); - void _body_exit_tree(ObjectID p_id); - - void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); - virtual void _direct_state_changed(Object *p_state); - - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_mode(Mode p_mode); - Mode get_mode() const; - - void set_mass(real_t p_mass); - real_t get_mass() const; - - virtual float get_inverse_mass() const { return 1.0 / mass; } - - void set_weight(real_t p_weight); - real_t get_weight() const; - - void set_physics_material_override(const Ref &p_physics_material_override); - Ref get_physics_material_override() const; - - void set_linear_velocity(const Vector3 &p_velocity); - Vector3 get_linear_velocity() const; - - void set_axis_velocity(const Vector3 &p_axis); - - void set_angular_velocity(const Vector3 &p_velocity); - Vector3 get_angular_velocity() const; - - void set_gravity_scale(real_t p_gravity_scale); - real_t get_gravity_scale() 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; - - void set_use_continuous_collision_detection(bool p_enable); - bool is_using_continuous_collision_detection() const; - - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); - bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; - - Array get_colliding_bodies() const; - - void add_central_force(const Vector3 &p_force); - void add_force(const Vector3 &p_force, const Vector3 &p_pos); - void add_torque(const Vector3 &p_torque); - - void apply_central_impulse(const Vector3 &p_impulse); - void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); - void apply_torque_impulse(const Vector3 &p_impulse); - - virtual String get_configuration_warning() const; - - RigidBody(); - ~RigidBody(); - -private: - void _reload_physics_characteristics(); -}; - -VARIANT_ENUM_CAST(RigidBody::Mode); - -class KinematicCollision; - -class KinematicBody : public PhysicsBody { - - GDCLASS(KinematicBody, PhysicsBody); - -public: - struct Collision { - Vector3 collision; - Vector3 normal; - Vector3 collider_vel; - ObjectID collider; - RID collider_rid; - int collider_shape; - Variant collider_metadata; - Vector3 remainder; - Vector3 travel; - int local_shape; - }; - -private: - Vector3 linear_velocity; - Vector3 angular_velocity; - - uint16_t locked_axis; - - float margin; - - Vector3 floor_normal; - Vector3 floor_velocity; - RID on_floor_body; - bool on_floor; - bool on_ceiling; - bool on_wall; - Vector colliders; - Vector> slide_colliders; - Ref motion_cache; - - _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; - - Ref _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); - Ref _get_slide_collision(int p_bounce); - -protected: - void _notification(int p_what); - static void _bind_methods(); - - virtual void _direct_state_changed(Object *p_state); - -public: - virtual Vector3 get_linear_velocity() const; - virtual Vector3 get_angular_velocity() const; - - bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false); - bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia); - - bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision); - - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); - bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; - - void set_safe_margin(float p_margin); - float get_safe_margin() const; - - Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - bool is_on_floor() const; - bool is_on_wall() const; - bool is_on_ceiling() const; - Vector3 get_floor_normal() const; - Vector3 get_floor_velocity() const; - - int get_slide_count() const; - Collision get_slide_collision(int p_bounce) const; - - KinematicBody(); - ~KinematicBody(); -}; - -class KinematicCollision : public Reference { - - GDCLASS(KinematicCollision, Reference); - - KinematicBody *owner; - friend class KinematicBody; - KinematicBody::Collision collision; - -protected: - static void _bind_methods(); - -public: - Vector3 get_position() const; - Vector3 get_normal() const; - Vector3 get_travel() const; - Vector3 get_remainder() const; - Object *get_local_shape() const; - Object *get_collider() const; - ObjectID get_collider_id() const; - Object *get_collider_shape() const; - int get_collider_shape_index() const; - Vector3 get_collider_velocity() const; - Variant get_collider_metadata() const; - - KinematicCollision(); -}; - -class PhysicalBone : public PhysicsBody { - - GDCLASS(PhysicalBone, PhysicsBody); - -public: - 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 PhysicsServer - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *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 = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *p_list) const; - - real_t bias; - real_t damping; - real_t impulse_clamp; - - PinJointData() : - bias(0.3), - damping(1.), - impulse_clamp(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 = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *p_list) const; - - real_t swing_span; - real_t twist_span; - real_t bias; - real_t softness; - real_t relaxation; - - ConeJointData() : - swing_span(Math_PI * 0.25), - twist_span(Math_PI), - bias(0.3), - softness(0.8), - 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 = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *p_list) const; - - bool angular_limit_enabled; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_bias; - real_t angular_limit_softness; - real_t angular_limit_relaxation; - - HingeJointData() : - angular_limit_enabled(false), - angular_limit_upper(Math_PI * 0.5), - angular_limit_lower(-Math_PI * 0.5), - angular_limit_bias(0.3), - angular_limit_softness(0.9), - 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 = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *p_list) const; - - real_t linear_limit_upper; - real_t linear_limit_lower; - real_t linear_limit_softness; - real_t linear_limit_restitution; - real_t linear_limit_damping; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_softness; - real_t angular_limit_restitution; - real_t angular_limit_damping; - - SliderJointData() : - linear_limit_upper(1.), - linear_limit_lower(-1.), - linear_limit_softness(1.), - linear_limit_restitution(0.7), - linear_limit_damping(1.), - angular_limit_upper(0), - angular_limit_lower(0), - angular_limit_softness(1.), - angular_limit_restitution(0.7), - angular_limit_damping(1.) {} - }; - - struct SixDOFJointData : public JointData { - struct SixDOFAxisData { - bool linear_limit_enabled; - real_t linear_limit_upper; - real_t linear_limit_lower; - real_t linear_limit_softness; - real_t linear_restitution; - real_t linear_damping; - bool linear_spring_enabled; - real_t linear_spring_stiffness; - real_t linear_spring_damping; - real_t linear_equilibrium_point; - bool angular_limit_enabled; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_softness; - real_t angular_restitution; - real_t angular_damping; - real_t erp; - bool angular_spring_enabled; - real_t angular_spring_stiffness; - real_t angular_spring_damping; - real_t angular_equilibrium_point; - - SixDOFAxisData() : - linear_limit_enabled(true), - linear_limit_upper(0), - linear_limit_lower(0), - linear_limit_softness(0.7), - linear_restitution(0.5), - linear_damping(1.), - linear_spring_enabled(false), - linear_spring_stiffness(0), - linear_spring_damping(0), - linear_equilibrium_point(0), - angular_limit_enabled(true), - angular_limit_upper(0), - angular_limit_lower(0), - angular_limit_softness(0.5), - angular_restitution(0), - angular_damping(1.), - erp(0.5), - angular_spring_enabled(false), - angular_spring_stiffness(0), - angular_spring_damping(0.), - angular_equilibrium_point(0) {} - }; - - virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; } - - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); - virtual bool _get(const StringName &p_name, Variant &r_ret) const; - virtual void _get_property_list(List *p_list) const; - - SixDOFAxisData axis_data[3]; - - SixDOFJointData() {} - }; - -private: -#ifdef TOOLS_ENABLED - // if false gizmo move body - bool gizmo_move_joint; -#endif - - JointData *joint_data; - Transform joint_offset; - RID joint; - - Skeleton *parent_skeleton; - Transform body_offset; - Transform body_offset_inverse; - bool simulate_physics; - bool _internal_simulate_physics; - int bone_id; - - String bone_name; - real_t bounce; - real_t mass; - real_t friction; - real_t gravity_scale; - -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 *p_list) const; - void _notification(int p_what); - void _direct_state_changed(Object *p_state); - - static void _bind_methods(); - -private: - static Skeleton *find_skeleton_parent(Node *p_parent); - - void _fix_joint_offset(); - void _reload_joint(); - -public: - void _on_bone_parent_changed(); - void _set_gizmo_move_joint(bool p_move_joint); - -public: -#ifdef TOOLS_ENABLED - virtual Transform get_global_gizmo_transform() const; - virtual Transform get_local_gizmo_transform() const; -#endif - - const JointData *get_joint_data() const; - Skeleton *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 Transform &p_offset); - const Transform &get_joint_offset() const; - - void set_body_offset(const Transform &p_offset); - const Transform &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_weight(real_t p_weight); - real_t get_weight() 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 apply_central_impulse(const Vector3 &p_impulse); - void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); - - void reset_physics_simulation_state(); - void reset_to_rest_position(); - - PhysicalBone(); - ~PhysicalBone(); - -private: - void update_bone_id(); - void update_offset(); - - void _start_physics_simulation(); - void _stop_physics_simulation(); -}; - -VARIANT_ENUM_CAST(PhysicalBone::JointType); - -#endif // PHYSICS_BODY__H diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp new file mode 100644 index 0000000000..aae9e38988 --- /dev/null +++ b/scene/3d/physics_body_3d.cpp @@ -0,0 +1,2596 @@ +/*************************************************************************/ +/* physics_body_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_body_3d.h" + +#include "core/core_string_names.h" +#include "core/engine.h" +#include "core/list.h" +#include "core/method_bind_ext.gen.inc" +#include "core/object.h" +#include "core/rid.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/scene_string_names.h" +#include "servers/navigation_server.h" + +#ifdef TOOLS_ENABLED +#include "editor/plugins/spatial_editor_plugin.h" +#endif + +Vector3 PhysicsBody3D::get_linear_velocity() const { + + return Vector3(); +} +Vector3 PhysicsBody3D::get_angular_velocity() const { + + return Vector3(); +} + +float PhysicsBody3D::get_inverse_mass() const { + + return 0; +} + +void PhysicsBody3D::set_collision_layer(uint32_t p_layer) { + + collision_layer = p_layer; + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); +} + +uint32_t PhysicsBody3D::get_collision_layer() const { + + return collision_layer; +} + +void PhysicsBody3D::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), p_mask); +} + +uint32_t PhysicsBody3D::get_collision_mask() const { + + return collision_mask; +} + +void PhysicsBody3D::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool PhysicsBody3D::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void PhysicsBody3D::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_layer(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_layer(mask); +} + +bool PhysicsBody3D::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +Array PhysicsBody3D::get_collision_exceptions() { + List exceptions; + PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + Array ret; + for (List::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + PhysicsBody3D *physics_body = Object::cast_to(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(p_node); + ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); + PhysicsServer::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(p_node); + ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); + PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); +} + +void PhysicsBody3D::_set_layers(uint32_t p_mask) { + set_collision_layer(p_mask); + set_collision_mask(p_mask); +} + +uint32_t PhysicsBody3D::_get_layers() const { + + return get_collision_layer(); +} + +void PhysicsBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody3D::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &PhysicsBody3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsBody3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &PhysicsBody3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &PhysicsBody3D::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &PhysicsBody3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &PhysicsBody3D::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody3D::_set_layers); + ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody3D::_get_layers); + + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); +} + +PhysicsBody3D::PhysicsBody3D(PhysicsServer::BodyMode p_mode) : + CollisionObject3D(PhysicsServer::get_singleton()->body_create(p_mode), false) { + + collision_layer = 1; + collision_mask = 1; +} + +void StaticBody3D::set_physics_material_override(const Ref &p_physics_material_override) { + if (physics_material_override.is_valid()) { + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody3D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->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(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody3D::_reload_physics_characteristics)); + } + _reload_physics_characteristics(); +} + +Ref 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; + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); +} + +void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) { + + constant_angular_velocity = p_vel; + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::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); + + 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_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"), "set_constant_linear_velocity", "get_constant_linear_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity"); +} + +StaticBody3D::StaticBody3D() : + PhysicsBody3D(PhysicsServer::BODY_MODE_STATIC) { +} + +StaticBody3D::~StaticBody3D() {} + +void StaticBody3D::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + } else { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + } +} + +void RigidBody3D::_body_enter_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + + ERR_FAIL_COND(!contact_monitor); + Map::Element *E = contact_monitor->body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree = true; + + contact_monitor->locked = true; + + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().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(obj); + ERR_FAIL_COND(!node); + ERR_FAIL_COND(!contact_monitor); + Map::Element *E = contact_monitor->body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree = false; + + contact_monitor->locked = true; + + emit_signal(SceneStringNames::get_singleton()->body_exited, node); + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + } + + contact_monitor->locked = false; +} + +void RigidBody3D::_body_inout(int p_status, 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(obj); + + ERR_FAIL_COND(!contact_monitor); + Map::Element *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->get().rc=0; + E->get().in_tree = node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree), make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree), make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + } + } + } + //E->get().rc++; + if (node) + E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape)); + + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape); + } + + } else { + + //E->get().rc--; + + if (node) + E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape)); + + bool in_tree = E->get().in_tree; + + if (E->get().shapes.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.erase(E); + } + if (node && in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape); + } + } +} + +struct _RigidBodyInOut { + + ObjectID id; + int shape; + int local_shape; +}; + +void RigidBody3D::_direct_state_changed(Object *p_state) { + +#ifdef DEBUG_ENABLED + state = Object::cast_to(p_state); +#else + state = (PhysicsDirectBodyState *)p_state; //trust it +#endif + + set_ignore_transform_notification(true); + set_global_transform(state->get_transform()); + linear_velocity = state->get_linear_velocity(); + angular_velocity = state->get_angular_velocity(); + if (sleeping != state->is_sleeping()) { + sleeping = state->is_sleeping(); + emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed); + } + if (get_script_instance()) + get_script_instance()->call("_integrate_forces", state); + set_ignore_transform_notification(false); + + if (contact_monitor) { + + contact_monitor->locked = true; + + //untag all + int rc = 0; + for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + + for (int i = 0; i < E->get().shapes.size(); i++) { + + E->get().shapes[i].tagged = false; + rc++; + } + } + + _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(state->get_contact_count() * sizeof(_RigidBodyInOut)); + int toadd_count = 0; //state->get_contact_count(); + RigidBody_RemoveAction *toremove = (RigidBody_RemoveAction *)alloca(rc * sizeof(RigidBody_RemoveAction)); + int toremove_count = 0; + + //put the ones to add + + for (int i = 0; i < state->get_contact_count(); i++) { + + ObjectID obj = state->get_contact_collider_id(i); + int local_shape = state->get_contact_local_shape(i); + int shape = state->get_contact_collider_shape(i); + + //bool found=false; + + Map::Element *E = contact_monitor->body_map.find(obj); + if (!E) { + toadd[toadd_count].local_shape = local_shape; + toadd[toadd_count].id = obj; + toadd[toadd_count].shape = shape; + toadd_count++; + continue; + } + + ShapePair sp(shape, local_shape); + int idx = E->get().shapes.find(sp); + if (idx == -1) { + + toadd[toadd_count].local_shape = local_shape; + toadd[toadd_count].id = obj; + toadd[toadd_count].shape = shape; + toadd_count++; + continue; + } + + E->get().shapes[idx].tagged = true; + } + + //put the ones to remove + + for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + + for (int i = 0; i < E->get().shapes.size(); i++) { + + if (!E->get().shapes[i].tagged) { + + toremove[toremove_count].body_id = E->key(); + toremove[toremove_count].pair = E->get().shapes[i]; + toremove_count++; + } + } + } + + //process remotions + + for (int i = 0; i < toremove_count; i++) { + + _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); + } + + //process aditions + + for (int i = 0; i < toadd_count; i++) { + + _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); + } + + contact_monitor->locked = false; + } + + state = NULL; +} + +void RigidBody3D::_notification(int p_what) { + +#ifdef TOOLS_ENABLED + if (p_what == NOTIFICATION_ENTER_TREE) { + if (Engine::get_singleton()->is_editor_hint()) { + set_notify_local_transform(true); //used for warnings and only in editor + } + } + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warning(); + } + } + +#endif +} + +void RigidBody3D::set_mode(Mode p_mode) { + + mode = p_mode; + switch (p_mode) { + + case MODE_RIGID: { + + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); + } break; + case MODE_STATIC: { + + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + + } break; + case MODE_CHARACTER: { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_CHARACTER); + + } break; + case MODE_KINEMATIC: { + + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + } break; + } + update_configuration_warning(); +} + +RigidBody3D::Mode RigidBody3D::get_mode() const { + + return mode; +} + +void RigidBody3D::set_mass(real_t p_mass) { + + ERR_FAIL_COND(p_mass <= 0); + mass = p_mass; + _change_notify("mass"); + _change_notify("weight"); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); +} +real_t RigidBody3D::get_mass() const { + + return mass; +} + +void RigidBody3D::set_weight(real_t p_weight) { + + set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); +} +real_t RigidBody3D::get_weight() const { + + return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); +} + +void RigidBody3D::set_physics_material_override(const Ref &p_physics_material_override) { + if (physics_material_override.is_valid()) { + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->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(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics)); + } + _reload_physics_characteristics(); +} + +Ref 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; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); +} +real_t RigidBody3D::get_gravity_scale() const { + + return gravity_scale; +} + +void RigidBody3D::set_linear_damp(real_t p_linear_damp) { + + ERR_FAIL_COND(p_linear_damp < -1); + linear_damp = p_linear_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::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 < -1); + angular_damp = p_angular_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::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 v = state ? state->get_linear_velocity() : linear_velocity; + Vector3 axis = p_axis.normalized(); + v -= axis * axis.dot(v); + v += p_axis; + if (state) { + set_linear_velocity(v); + } else { + PhysicsServer::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); + linear_velocity = v; + } +} + +void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) { + + linear_velocity = p_velocity; + if (state) + state->set_linear_velocity(linear_velocity); + else + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::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; + if (state) + state->set_angular_velocity(angular_velocity); + else + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); +} +Vector3 RigidBody3D::get_angular_velocity() const { + + return angular_velocity; +} + +void RigidBody3D::set_use_custom_integrator(bool p_enable) { + + if (custom_integrator == p_enable) + return; + + custom_integrator = p_enable; + PhysicsServer::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; + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_SLEEPING, sleeping); +} + +void RigidBody3D::set_can_sleep(bool p_active) { + + can_sleep = p_active; + PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::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; + PhysicsServer::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); +} + +int RigidBody3D::get_max_contacts_reported() const { + + return max_contacts_reported; +} + +void RigidBody3D::add_central_force(const Vector3 &p_force) { + PhysicsServer::get_singleton()->body_add_central_force(get_rid(), p_force); +} + +void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) { + PhysicsServer::get_singleton()->body_add_force(get_rid(), p_force, p_pos); +} + +void RigidBody3D::add_torque(const Vector3 &p_torque) { + PhysicsServer::get_singleton()->body_add_torque(get_rid(), p_torque); +} + +void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); +} + +void RigidBody3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { + + PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); +} + +void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); +} + +void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) { + + ccd = p_enable; + PhysicsServer::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 (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + + //clean up mess + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = Object::cast_to(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 = NULL; + } else { + + contact_monitor = memnew(ContactMonitor); + contact_monitor->locked = false; + } +} + +bool RigidBody3D::is_contact_monitor_enabled() const { + + return contact_monitor != NULL; +} + +void RigidBody3D::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); +} + +bool RigidBody3D::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { + return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); +} + +Array RigidBody3D::get_colliding_bodies() const { + + ERR_FAIL_COND_V(!contact_monitor, Array()); + + Array ret; + ret.resize(contact_monitor->body_map.size()); + int idx = 0; + for (const Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize(ret.size() - 1); //ops + } else { + ret[idx++] = obj; + } + } + + return ret; +} + +String RigidBody3D::get_configuration_warning() const { + + Transform t = get_transform(); + + String warning = CollisionObject3D::get_configuration_warning(); + + if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { + if (warning != String()) { + warning += "\n\n"; + } + warning += TTR("Size changes to RigidBody (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); + } + + return warning; +} + +void RigidBody3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody3D::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &RigidBody3D::get_mode); + + 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_weight", "weight"), &RigidBody3D::set_weight); + ClassDB::bind_method(D_METHOD("get_weight"), &RigidBody3D::get_weight); + + 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("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", "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("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("add_central_force", "force"), &RigidBody3D::add_central_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody3D::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody3D::add_torque); + + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody3D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse); + + 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("_direct_state_changed"), &RigidBody3D::_direct_state_changed); + + ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody3D::set_axis_lock); + ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody3D::get_axis_lock); + + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies); + + BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState"))); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight"); + 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, "-128,128,0.01"), "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::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "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_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); + ADD_GROUP("Axis Lock", "axis_lock_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z); + ADD_GROUP("Linear", "linear_"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); + 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::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); + + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("sleeping_state_changed")); + + BIND_ENUM_CONSTANT(MODE_RIGID); + BIND_ENUM_CONSTANT(MODE_STATIC); + BIND_ENUM_CONSTANT(MODE_CHARACTER); + BIND_ENUM_CONSTANT(MODE_KINEMATIC); +} + +RigidBody3D::RigidBody3D() : + PhysicsBody3D(PhysicsServer::BODY_MODE_RIGID) { + + mode = MODE_RIGID; + + mass = 1; + max_contacts_reported = 0; + state = NULL; + + gravity_scale = 1; + linear_damp = -1; + angular_damp = -1; + + //angular_velocity=0; + sleeping = false; + ccd = false; + + custom_integrator = false; + contact_monitor = NULL; + can_sleep = true; + + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); +} + +RigidBody3D::~RigidBody3D() { + + if (contact_monitor) + memdelete(contact_monitor); +} + +void RigidBody3D::_reload_physics_characteristics() { + if (physics_material_override.is_null()) { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + } else { + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + } +} + +////////////////////////////////////////////////////// +////////////////////////// + +Ref KinematicBody3D::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) { + + Collision col; + if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) { + if (motion_cache.is_null()) { + motion_cache.instance(); + motion_cache->owner = this; + } + + motion_cache->collision = col; + + return motion_cache; + } + + return Ref(); +} + +Vector3 KinematicBody3D::get_linear_velocity() const { + return linear_velocity; +} + +Vector3 KinematicBody3D::get_angular_velocity() const { + return angular_velocity; +} + +bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) { + + Transform gt = get_global_transform(); + PhysicsServer::MotionResult result; + bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes); + + if (colliding) { + r_collision.collider_metadata = result.collider_metadata; + r_collision.collider_shape = result.collider_shape; + r_collision.collider_vel = result.collider_velocity; + r_collision.collision = result.collision_point; + r_collision.normal = result.collision_normal; + r_collision.collider = result.collider_id; + r_collision.collider_rid = result.collider; + r_collision.travel = result.motion; + r_collision.remainder = result.remainder; + r_collision.local_shape = result.collision_local_shape; + } + + for (int i = 0; i < 3; i++) { + if (locked_axis & (1 << i)) { + result.motion[i] = 0; + } + } + + if (!p_test_only) { + gt.origin += result.motion; + set_global_transform(gt); + } + + return colliding; +} + +//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. +#define FLOOR_ANGLE_THRESHOLD 0.01 + +Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + + Vector3 body_velocity = p_linear_velocity; + Vector3 body_velocity_normal = body_velocity.normalized(); + + for (int i = 0; i < 3; i++) { + if (locked_axis & (1 << i)) { + body_velocity[i] = 0; + } + } + + // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky + Vector3 motion = (floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); + + on_floor = false; + on_floor_body = RID(); + on_ceiling = false; + on_wall = false; + colliders.clear(); + floor_normal = Vector3(); + floor_velocity = Vector3(); + + while (p_max_slides) { + + Collision collision; + bool found_collision = false; + + for (int i = 0; i < 2; ++i) { + bool collided; + if (i == 0) { //collide + collided = move_and_collide(motion, p_infinite_inertia, collision); + if (!collided) { + motion = Vector3(); //clear because no collision happened and motion completed + } + } else { //separate raycasts (if any) + collided = separate_raycast_shapes(p_infinite_inertia, collision); + if (collided) { + collision.remainder = motion; //keep + collision.travel = Vector3(); + } + } + + if (collided) { + found_collision = true; + + colliders.push_back(collision); + motion = collision.remainder; + + if (p_up_direction == Vector3()) { + //all is a wall + on_wall = true; + } else { + if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + + on_floor = true; + floor_normal = collision.normal; + on_floor_body = collision.collider_rid; + floor_velocity = collision.collider_vel; + + if (p_stop_on_slope) { + if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { + Transform gt = get_global_transform(); + gt.origin -= collision.travel.slide(p_up_direction); + set_global_transform(gt); + return Vector3(); + } + } + } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + on_ceiling = true; + } else { + on_wall = true; + } + } + + motion = motion.slide(collision.normal); + body_velocity = body_velocity.slide(collision.normal); + + for (int j = 0; j < 3; j++) { + if (locked_axis & (1 << j)) { + body_velocity[j] = 0; + } + } + } + } + + if (!found_collision || motion == Vector3()) + break; + + --p_max_slides; + } + + return body_velocity; +} + +Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + + bool was_on_floor = on_floor; + + Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + if (!was_on_floor || p_snap == Vector3()) { + return ret; + } + + Collision col; + Transform gt = get_global_transform(); + + if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { + + bool apply = true; + if (p_up_direction != Vector3()) { + if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + on_floor = true; + floor_normal = col.normal; + on_floor_body = col.collider_rid; + floor_velocity = col.collider_vel; + if (p_stop_on_slope) { + // move and collide may stray the object a bit because of pre un-stucking, + // so only ensure that motion happens on floor direction in this case. + col.travel = col.travel.project(p_up_direction); + } + } else { + apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. + } + } + if (apply) { + gt.origin += col.travel; + set_global_transform(gt); + } + } + + return ret; +} + +bool KinematicBody3D::is_on_floor() const { + + return on_floor; +} + +bool KinematicBody3D::is_on_wall() const { + + return on_wall; +} +bool KinematicBody3D::is_on_ceiling() const { + + return on_ceiling; +} + +Vector3 KinematicBody3D::get_floor_normal() const { + + return floor_normal; +} + +Vector3 KinematicBody3D::get_floor_velocity() const { + + return floor_velocity; +} + +bool KinematicBody3D::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) { + + ERR_FAIL_COND_V(!is_inside_tree(), false); + + return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); +} + +bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) { + + PhysicsServer::SeparationResult sep_res[8]; //max 8 rays + + Transform gt = get_global_transform(); + + Vector3 recover; + int hits = PhysicsServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); + int deepest = -1; + float deepest_depth; + for (int i = 0; i < hits; i++) { + if (deepest == -1 || sep_res[i].collision_depth > deepest_depth) { + deepest = i; + deepest_depth = sep_res[i].collision_depth; + } + } + + gt.origin += recover; + set_global_transform(gt); + + if (deepest != -1) { + r_collision.collider = sep_res[deepest].collider_id; + r_collision.collider_metadata = sep_res[deepest].collider_metadata; + r_collision.collider_shape = sep_res[deepest].collider_shape; + r_collision.collider_vel = sep_res[deepest].collider_velocity; + r_collision.collision = sep_res[deepest].collision_point; + r_collision.normal = sep_res[deepest].collision_normal; + r_collision.local_shape = sep_res[deepest].collision_local_shape; + r_collision.travel = recover; + r_collision.remainder = Vector3(); + + return true; + } else { + return false; + } +} + +void KinematicBody3D::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { + PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); +} + +bool KinematicBody3D::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { + return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); +} + +void KinematicBody3D::set_safe_margin(float p_margin) { + + margin = p_margin; + PhysicsServer::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin); +} + +float KinematicBody3D::get_safe_margin() const { + + return margin; +} +int KinematicBody3D::get_slide_count() const { + + return colliders.size(); +} + +KinematicBody3D::Collision KinematicBody3D::get_slide_collision(int p_bounce) const { + ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Collision()); + return colliders[p_bounce]; +} + +Ref KinematicBody3D::_get_slide_collision(int p_bounce) { + + ERR_FAIL_INDEX_V(p_bounce, colliders.size(), Ref()); + if (p_bounce >= slide_colliders.size()) { + slide_colliders.resize(p_bounce + 1); + } + + if (slide_colliders[p_bounce].is_null()) { + slide_colliders.write[p_bounce].instance(); + slide_colliders.write[p_bounce]->owner = this; + } + + slide_colliders.write[p_bounce]->collision = colliders[p_bounce]; + return slide_colliders[p_bounce]; +} + +void KinematicBody3D::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE) { + // Reset move_and_slide() data. + on_floor = false; + on_floor_body = RID(); + on_ceiling = false; + on_wall = false; + colliders.clear(); + floor_velocity = Vector3(); + } +} + +void KinematicBody3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody3D::_direct_state_changed); + + ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody3D::test_move, DEFVAL(true)); + + ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody3D::is_on_floor); + ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody3D::is_on_ceiling); + ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody3D::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody3D::get_floor_normal); + ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody3D::get_floor_velocity); + + ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody3D::set_axis_lock); + ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &KinematicBody3D::get_axis_lock); + + ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody3D::set_safe_margin); + ClassDB::bind_method(D_METHOD("get_safe_margin"), &KinematicBody3D::get_safe_margin); + + ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody3D::get_slide_count); + ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody3D::_get_slide_collision); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); +} + +void KinematicBody3D::_direct_state_changed(Object *p_state) { +#ifdef DEBUG_ENABLED + PhysicsDirectBodyState *state = Object::cast_to(p_state); +#else + PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it +#endif + + linear_velocity = state->get_linear_velocity(); + angular_velocity = state->get_angular_velocity(); +} + +KinematicBody3D::KinematicBody3D() : + PhysicsBody3D(PhysicsServer::BODY_MODE_KINEMATIC) { + + margin = 0.001; + locked_axis = 0; + on_floor = false; + on_ceiling = false; + on_wall = false; + + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); +} +KinematicBody3D::~KinematicBody3D() { + + if (motion_cache.is_valid()) { + motion_cache->owner = NULL; + } + + for (int i = 0; i < slide_colliders.size(); i++) { + if (slide_colliders[i].is_valid()) { + slide_colliders.write[i]->owner = NULL; + } + } +} +/////////////////////////////////////// + +Vector3 KinematicCollision3D::get_position() const { + + return collision.collision; +} +Vector3 KinematicCollision3D::get_normal() const { + return collision.normal; +} +Vector3 KinematicCollision3D::get_travel() const { + return collision.travel; +} +Vector3 KinematicCollision3D::get_remainder() const { + return collision.remainder; +} +Object *KinematicCollision3D::get_local_shape() const { + if (!owner) return NULL; + uint32_t ownerid = owner->shape_find_owner(collision.local_shape); + return owner->shape_owner_get_owner(ownerid); +} + +Object *KinematicCollision3D::get_collider() const { + + if (collision.collider.is_valid()) { + return ObjectDB::get_instance(collision.collider); + } + + return NULL; +} +ObjectID KinematicCollision3D::get_collider_id() const { + + return collision.collider; +} +Object *KinematicCollision3D::get_collider_shape() const { + + Object *collider = get_collider(); + if (collider) { + CollisionObject3D *obj2d = Object::cast_to(collider); + if (obj2d) { + uint32_t ownerid = obj2d->shape_find_owner(collision.collider_shape); + return obj2d->shape_owner_get_owner(ownerid); + } + } + + return NULL; +} +int KinematicCollision3D::get_collider_shape_index() const { + + return collision.collider_shape; +} +Vector3 KinematicCollision3D::get_collider_velocity() const { + + return collision.collider_vel; +} +Variant KinematicCollision3D::get_collider_metadata() const { + + return Variant(); +} + +void KinematicCollision3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision3D::get_position); + ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision3D::get_normal); + 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_local_shape"), &KinematicCollision3D::get_local_shape); + ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision3D::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision3D::get_collider_id); + ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision3D::get_collider_shape); + ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision3D::get_collider_shape_index); + ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision3D::get_collider_velocity); + ClassDB::bind_method(D_METHOD("get_collider_metadata"), &KinematicCollision3D::get_collider_metadata); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "normal"), "", "get_normal"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "local_shape"), "", "get_local_shape"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id"), "", "get_collider_id"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider_shape"), "", "get_collider_shape"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape_index"), "", "get_collider_shape_index"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_collider_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::NIL, "collider_metadata", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "", "get_collider_metadata"); +} + +KinematicCollision3D::KinematicCollision3D() { + + collision.collider_shape = 0; + collision.local_shape = 0; + owner = NULL; +} + +/////////////////////////////////////// + +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 *p_list) const { +} + +void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); +} + +void PhysicalBone3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); +} + +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) { + if (-1 == bone_id) { + set_global_transform(parent_skeleton->get_global_transform() * body_offset); + } else { + set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); + } + } +} + +bool PhysicalBone3D::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { + if (JointData::_set(p_name, p_value, j)) { + return true; + } + + if ("joint_constraints/bias" == p_name) { + bias = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_BIAS, bias); + + } else if ("joint_constraints/damping" == p_name) { + damping = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_DAMPING, damping); + + } else if ("joint_constraints/impulse_clamp" == p_name) { + impulse_clamp = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::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 *p_list) const { + JointData::_get_property_list(p_list); + + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "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; + } + + if ("joint_constraints/swing_span" == p_name) { + swing_span = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, swing_span); + + } else if ("joint_constraints/twist_span" == p_name) { + twist_span = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); + + } else if ("joint_constraints/bias" == p_name) { + bias = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_BIAS, bias); + + } else if ("joint_constraints/softness" == p_name) { + softness = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, softness); + + } else if ("joint_constraints/relaxation" == p_name) { + relaxation = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::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::rad2deg(swing_span); + } else if ("joint_constraints/twist_span" == p_name) { + r_ret = Math::rad2deg(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 *p_list) const { + JointData::_get_property_list(p_list); + + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/swing_span", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_lesser,or_greater")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "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; + } + + if ("joint_constraints/angular_limit_enabled" == p_name) { + angular_limit_enabled = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled); + + } else if ("joint_constraints/angular_limit_upper" == p_name) { + angular_limit_upper = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); + + } else if ("joint_constraints/angular_limit_lower" == p_name) { + angular_limit_lower = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); + + } else if ("joint_constraints/angular_limit_bias" == p_name) { + angular_limit_bias = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias); + + } else if ("joint_constraints/angular_limit_softness" == p_name) { + angular_limit_softness = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness); + + } else if ("joint_constraints/angular_limit_relaxation" == p_name) { + angular_limit_relaxation = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::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::rad2deg(angular_limit_upper); + } else if ("joint_constraints/angular_limit_lower" == p_name) { + r_ret = Math::rad2deg(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 *p_list) const { + JointData::_get_property_list(p_list); + + p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/angular_limit_enabled")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "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; + } + + if ("joint_constraints/linear_limit_upper" == p_name) { + linear_limit_upper = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper); + + } else if ("joint_constraints/linear_limit_lower" == p_name) { + linear_limit_lower = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower); + + } else if ("joint_constraints/linear_limit_softness" == p_name) { + linear_limit_softness = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness); + + } else if ("joint_constraints/linear_limit_restitution" == p_name) { + linear_limit_restitution = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution); + + } else if ("joint_constraints/linear_limit_damping" == p_name) { + linear_limit_damping = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution); + + } else if ("joint_constraints/angular_limit_upper" == p_name) { + angular_limit_upper = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); + + } else if ("joint_constraints/angular_limit_lower" == p_name) { + angular_limit_lower = Math::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); + + } else if ("joint_constraints/angular_limit_softness" == p_name) { + angular_limit_softness = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); + + } else if ("joint_constraints/angular_limit_restitution" == p_name) { + angular_limit_restitution = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); + + } else if ("joint_constraints/angular_limit_damping" == p_name) { + angular_limit_damping = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::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::rad2deg(angular_limit_upper); + } else if ("joint_constraints/angular_limit_lower" == p_name) { + r_ret = Math::rad2deg(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 *p_list) const { + JointData::_get_property_list(p_list); + + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_upper")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_lower")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/linear_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01")); + + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/angular_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "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; + + 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); + + if ("linear_limit_enabled" == var_name) { + axis_data[axis].linear_limit_enabled = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution); + + } else if ("linear_damping" == var_name) { + axis_data[axis].linear_damping = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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::deg2rad(real_t(p_value)); + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution); + + } else if ("angular_damping" == var_name) { + axis_data[axis].angular_damping = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping); + + } else if ("erp" == var_name) { + axis_data[axis].erp = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp); + + } else if ("angular_spring_enabled" == var_name) { + axis_data[axis].angular_spring_enabled = p_value; + if (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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 (j.is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::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; + + 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::rad2deg(axis_data[axis].angular_limit_upper); + } else if ("angular_limit_lower" == var_name) { + r_ret = Math::rad2deg(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 *p_list) const { + const StringName axis_names[] = { "x", "y", "z" }; + for (int i = 0; i < 3; ++i) { + p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_limit_enabled")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_upper")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_lower")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_spring_damping")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/erp")); + p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/angular_spring_damping")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_constraints/" + axis_names[i] + "/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)) { +#ifdef TOOLS_ENABLED + if (get_gizmo().is_valid()) + get_gizmo()->redraw(); +#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 *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, "bone_name", PROPERTY_HINT_ENUM, names)); + } else { + + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "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.is_valid() && 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); + } + } + parent_skeleton = NULL; + if (joint.is_valid()) { + PhysicsServer::get_singleton()->free(joint); + joint = RID(); + } + break; + case NOTIFICATION_TRANSFORM_CHANGED: + if (Engine::get_singleton()->is_editor_hint()) { + + update_offset(); + } + break; + } +} + +void PhysicalBone3D::_direct_state_changed(Object *p_state) { + + if (!simulate_physics || !_internal_simulate_physics) { + return; + } + + /// Update bone transform + + PhysicsDirectBodyState *state; + +#ifdef DEBUG_ENABLED + state = Object::cast_to(p_state); +#else + state = (PhysicsDirectBodyState *)p_state; //trust it +#endif + + Transform global_transform(state->get_transform()); + + set_ignore_transform_notification(true); + set_global_transform(global_transform); + set_ignore_transform_notification(false); + + // 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", "position", "impulse"), &PhysicalBone3D::apply_impulse); + + ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone3D::_direct_state_changed); + + 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_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_weight", "weight"), &PhysicalBone3D::set_weight); + ClassDB::bind_method(D_METHOD("get_weight"), &PhysicalBone3D::get_weight); + + 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); + + 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::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); + + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); + 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, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); + + 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 NULL; + } + Skeleton3D *s = Object::cast_to(p_parent); + return s ? s : find_skeleton_parent(p_parent->get_parent()); +} + +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 (joint.is_valid()) { + PhysicsServer::get_singleton()->free(joint); + joint = RID(); + } + + if (!parent_skeleton) { + return; + } + + PhysicalBone3D *body_a = parent_skeleton->get_physical_bone_parent(bone_id); + if (!body_a) { + return; + } + + Transform joint_transf = get_global_transform() * joint_offset; + Transform local_a = body_a->get_global_transform().affine_inverse() * joint_transf; + local_a.orthonormalize(); + + switch (get_joint_type()) { + case JOINT_TYPE_PIN: { + + joint = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin); + const PinJointData *pjd(static_cast(joint_data)); + PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_BIAS, pjd->bias); + PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_DAMPING, pjd->damping); + PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); + + } break; + case JOINT_TYPE_CONE: { + + joint = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset); + const ConeJointData *cjd(static_cast(joint_data)); + PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span); + PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span); + PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_BIAS, cjd->bias); + PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); + PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); + + } break; + case JOINT_TYPE_HINGE: { + + joint = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset); + const HingeJointData *hjd(static_cast(joint_data)); + PhysicsServer::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled); + PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper); + PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower); + PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); + PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); + PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); + + } break; + case JOINT_TYPE_SLIDER: { + + joint = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset); + const SliderJointData *sjd(static_cast(joint_data)); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); + PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); + + } break; + case JOINT_TYPE_6DOF: { + + joint = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset); + const SixDOFJointData *g6dofjd(static_cast(joint_data)); + for (int axis = 0; axis < 3; ++axis) { + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::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(); +} + +void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) { +#ifdef TOOLS_ENABLED + gizmo_move_joint = p_move_joint; + Node3DEditor::get_singleton()->update_transform_gizmo(); +#endif +} + +#ifdef TOOLS_ENABLED +Transform PhysicalBone3D::get_global_gizmo_transform() const { + return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform(); +} + +Transform 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 = NULL; + 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 + _change_notify(); + if (get_gizmo().is_valid()) + get_gizmo()->redraw(); +#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 Transform &p_offset) { + joint_offset = p_offset; + + _fix_joint_offset(); + + set_ignore_transform_notification(true); + reset_to_rest_position(); + set_ignore_transform_notification(false); + +#ifdef TOOLS_ENABLED + if (get_gizmo().is_valid()) + get_gizmo()->redraw(); +#endif +} + +const Transform &PhysicalBone3D::get_body_offset() const { + return body_offset; +} + +void PhysicalBone3D::set_body_offset(const Transform &p_offset) { + body_offset = p_offset; + body_offset_inverse = body_offset.affine_inverse(); + + _fix_joint_offset(); + + set_ignore_transform_notification(true); + reset_to_rest_position(); + set_ignore_transform_notification(false); + +#ifdef TOOLS_ENABLED + if (get_gizmo().is_valid()) + get_gizmo()->redraw(); +#endif +} + +const Transform &PhysicalBone3D::get_joint_offset() const { + return 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; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); +} + +real_t PhysicalBone3D::get_mass() const { + + return mass; +} + +void PhysicalBone3D::set_weight(real_t p_weight) { + + set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); +} + +real_t PhysicalBone3D::get_weight() const { + + return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); +} + +void PhysicalBone3D::set_friction(real_t p_friction) { + + ERR_FAIL_COND(p_friction < 0 || p_friction > 1); + + friction = p_friction; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::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; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::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; + PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); +} + +real_t PhysicalBone3D::get_gravity_scale() const { + + return gravity_scale; +} + +PhysicalBone3D::PhysicalBone3D() : + PhysicsBody3D(PhysicsServer::BODY_MODE_STATIC), +#ifdef TOOLS_ENABLED + gizmo_move_joint(false), +#endif + joint_data(NULL), + parent_skeleton(NULL), + simulate_physics(false), + _internal_simulate_physics(false), + bone_id(-1), + bone_name(""), + bounce(0), + mass(1), + friction(1), + gravity_scale(1) { + + reset_physics_simulation_state(); +} + +PhysicalBone3D::~PhysicalBone3D() { + if (joint_data) + memdelete(joint_data); +} + +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); + parent_skeleton->unbind_child_node_from_bone(bone_id, this); + } + + 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) { + + Transform 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(); + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + set_as_toplevel(true); + _internal_simulate_physics = true; +} + +void PhysicalBone3D::_stop_physics_simulation() { + if (!parent_skeleton) { + return; + } + if (parent_skeleton->get_animate_physical_bones()) { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + } else { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); + } + if (_internal_simulate_physics) { + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); + set_as_toplevel(false); + _internal_simulate_physics = false; + } +} diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h new file mode 100644 index 0000000000..e7a403122b --- /dev/null +++ b/scene/3d/physics_body_3d.h @@ -0,0 +1,646 @@ +/*************************************************************************/ +/* physics_body_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_BODY_3D_H +#define PHYSICS_BODY_3D_H + +#include "core/vset.h" +#include "scene/3d/collision_object_3d.h" +#include "scene/resources/physics_material.h" +#include "servers/physics_server.h" +#include "skeleton_3d.h" + +class PhysicsBody3D : public CollisionObject3D { + + GDCLASS(PhysicsBody3D, CollisionObject3D); + + uint32_t collision_layer; + uint32_t collision_mask; + + void _set_layers(uint32_t p_mask); + uint32_t _get_layers() const; + +protected: + static void _bind_methods(); + PhysicsBody3D(PhysicsServer::BodyMode p_mode); + +public: + virtual Vector3 get_linear_velocity() const; + virtual Vector3 get_angular_velocity() const; + virtual float get_inverse_mass() const; + + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + Array get_collision_exceptions(); + void add_collision_exception_with(Node *p_node); //must be physicsbody + void remove_collision_exception_with(Node *p_node); + + PhysicsBody3D(); +}; + +class StaticBody3D : public PhysicsBody3D { + + GDCLASS(StaticBody3D, PhysicsBody3D); + + Vector3 constant_linear_velocity; + Vector3 constant_angular_velocity; + + Ref physics_material_override; + +protected: + static void _bind_methods(); + +public: + void set_physics_material_override(const Ref &p_physics_material_override); + Ref 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(); + ~StaticBody3D(); + +private: + void _reload_physics_characteristics(); +}; + +class RigidBody3D : public PhysicsBody3D { + + GDCLASS(RigidBody3D, PhysicsBody3D); + +public: + enum Mode { + MODE_RIGID, + MODE_STATIC, + MODE_CHARACTER, + MODE_KINEMATIC, + }; + +protected: + bool can_sleep; + PhysicsDirectBodyState *state; + Mode mode; + + real_t mass; + Ref physics_material_override; + + Vector3 linear_velocity; + Vector3 angular_velocity; + real_t gravity_scale; + real_t linear_damp; + real_t angular_damp; + + bool sleeping; + bool ccd; + + int max_contacts_reported; + + bool custom_integrator; + + struct ShapePair { + + int body_shape; + int local_shape; + bool tagged; + 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 RigidBody_RemoveAction { + + ObjectID body_id; + ShapePair pair; + }; + struct BodyState { + + //int rc; + bool in_tree; + VSet shapes; + }; + + struct ContactMonitor { + + bool locked; + Map body_map; + }; + + ContactMonitor *contact_monitor; + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); + + void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); + virtual void _direct_state_changed(Object *p_state); + + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_mode(Mode p_mode); + Mode get_mode() const; + + void set_mass(real_t p_mass); + real_t get_mass() const; + + virtual float get_inverse_mass() const { return 1.0 / mass; } + + void set_weight(real_t p_weight); + real_t get_weight() const; + + void set_physics_material_override(const Ref &p_physics_material_override); + Ref get_physics_material_override() const; + + void set_linear_velocity(const Vector3 &p_velocity); + Vector3 get_linear_velocity() const; + + void set_axis_velocity(const Vector3 &p_axis); + + void set_angular_velocity(const Vector3 &p_velocity); + Vector3 get_angular_velocity() const; + + void set_gravity_scale(real_t p_gravity_scale); + real_t get_gravity_scale() 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; + + void set_use_continuous_collision_detection(bool p_enable); + bool is_using_continuous_collision_detection() const; + + void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); + bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; + + Array get_colliding_bodies() const; + + void add_central_force(const Vector3 &p_force); + void add_force(const Vector3 &p_force, const Vector3 &p_pos); + void add_torque(const Vector3 &p_torque); + + void apply_central_impulse(const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void apply_torque_impulse(const Vector3 &p_impulse); + + virtual String get_configuration_warning() const; + + RigidBody3D(); + ~RigidBody3D(); + +private: + void _reload_physics_characteristics(); +}; + +VARIANT_ENUM_CAST(RigidBody3D::Mode); + +class KinematicCollision3D; + +class KinematicBody3D : public PhysicsBody3D { + + GDCLASS(KinematicBody3D, PhysicsBody3D); + +public: + struct Collision { + Vector3 collision; + Vector3 normal; + Vector3 collider_vel; + ObjectID collider; + RID collider_rid; + int collider_shape; + Variant collider_metadata; + Vector3 remainder; + Vector3 travel; + int local_shape; + }; + +private: + Vector3 linear_velocity; + Vector3 angular_velocity; + + uint16_t locked_axis; + + float margin; + + Vector3 floor_normal; + Vector3 floor_velocity; + RID on_floor_body; + bool on_floor; + bool on_ceiling; + bool on_wall; + Vector colliders; + Vector> slide_colliders; + Ref motion_cache; + + _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; + + Ref _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); + Ref _get_slide_collision(int p_bounce); + +protected: + void _notification(int p_what); + static void _bind_methods(); + + virtual void _direct_state_changed(Object *p_state); + +public: + virtual Vector3 get_linear_velocity() const; + virtual Vector3 get_angular_velocity() const; + + bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false); + bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia); + + bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision); + + void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); + bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; + + void set_safe_margin(float p_margin); + float get_safe_margin() const; + + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + bool is_on_floor() const; + bool is_on_wall() const; + bool is_on_ceiling() const; + Vector3 get_floor_normal() const; + Vector3 get_floor_velocity() const; + + int get_slide_count() const; + Collision get_slide_collision(int p_bounce) const; + + KinematicBody3D(); + ~KinematicBody3D(); +}; + +class KinematicCollision3D : public Reference { + + GDCLASS(KinematicCollision3D, Reference); + + KinematicBody3D *owner; + friend class KinematicBody3D; + KinematicBody3D::Collision collision; + +protected: + static void _bind_methods(); + +public: + Vector3 get_position() const; + Vector3 get_normal() const; + Vector3 get_travel() const; + Vector3 get_remainder() const; + Object *get_local_shape() const; + Object *get_collider() const; + ObjectID get_collider_id() const; + Object *get_collider_shape() const; + int get_collider_shape_index() const; + Vector3 get_collider_velocity() const; + Variant get_collider_metadata() const; + + KinematicCollision3D(); +}; + +class PhysicalBone3D : public PhysicsBody3D { + + GDCLASS(PhysicalBone3D, PhysicsBody3D); + +public: + 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 PhysicsServer + virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *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 = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *p_list) const; + + real_t bias; + real_t damping; + real_t impulse_clamp; + + PinJointData() : + bias(0.3), + damping(1.), + impulse_clamp(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 = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *p_list) const; + + real_t swing_span; + real_t twist_span; + real_t bias; + real_t softness; + real_t relaxation; + + ConeJointData() : + swing_span(Math_PI * 0.25), + twist_span(Math_PI), + bias(0.3), + softness(0.8), + 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 = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *p_list) const; + + bool angular_limit_enabled; + real_t angular_limit_upper; + real_t angular_limit_lower; + real_t angular_limit_bias; + real_t angular_limit_softness; + real_t angular_limit_relaxation; + + HingeJointData() : + angular_limit_enabled(false), + angular_limit_upper(Math_PI * 0.5), + angular_limit_lower(-Math_PI * 0.5), + angular_limit_bias(0.3), + angular_limit_softness(0.9), + 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 = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *p_list) const; + + real_t linear_limit_upper; + real_t linear_limit_lower; + real_t linear_limit_softness; + real_t linear_limit_restitution; + real_t linear_limit_damping; + real_t angular_limit_upper; + real_t angular_limit_lower; + real_t angular_limit_softness; + real_t angular_limit_restitution; + real_t angular_limit_damping; + + SliderJointData() : + linear_limit_upper(1.), + linear_limit_lower(-1.), + linear_limit_softness(1.), + linear_limit_restitution(0.7), + linear_limit_damping(1.), + angular_limit_upper(0), + angular_limit_lower(0), + angular_limit_softness(1.), + angular_limit_restitution(0.7), + angular_limit_damping(1.) {} + }; + + struct SixDOFJointData : public JointData { + struct SixDOFAxisData { + bool linear_limit_enabled; + real_t linear_limit_upper; + real_t linear_limit_lower; + real_t linear_limit_softness; + real_t linear_restitution; + real_t linear_damping; + bool linear_spring_enabled; + real_t linear_spring_stiffness; + real_t linear_spring_damping; + real_t linear_equilibrium_point; + bool angular_limit_enabled; + real_t angular_limit_upper; + real_t angular_limit_lower; + real_t angular_limit_softness; + real_t angular_restitution; + real_t angular_damping; + real_t erp; + bool angular_spring_enabled; + real_t angular_spring_stiffness; + real_t angular_spring_damping; + real_t angular_equilibrium_point; + + SixDOFAxisData() : + linear_limit_enabled(true), + linear_limit_upper(0), + linear_limit_lower(0), + linear_limit_softness(0.7), + linear_restitution(0.5), + linear_damping(1.), + linear_spring_enabled(false), + linear_spring_stiffness(0), + linear_spring_damping(0), + linear_equilibrium_point(0), + angular_limit_enabled(true), + angular_limit_upper(0), + angular_limit_lower(0), + angular_limit_softness(0.5), + angular_restitution(0), + angular_damping(1.), + erp(0.5), + angular_spring_enabled(false), + angular_spring_stiffness(0), + angular_spring_damping(0.), + angular_equilibrium_point(0) {} + }; + + virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; } + + virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _get(const StringName &p_name, Variant &r_ret) const; + virtual void _get_property_list(List *p_list) const; + + SixDOFAxisData axis_data[3]; + + SixDOFJointData() {} + }; + +private: +#ifdef TOOLS_ENABLED + // if false gizmo move body + bool gizmo_move_joint; +#endif + + JointData *joint_data; + Transform joint_offset; + RID joint; + + Skeleton3D *parent_skeleton; + Transform body_offset; + Transform body_offset_inverse; + bool simulate_physics; + bool _internal_simulate_physics; + int bone_id; + + String bone_name; + real_t bounce; + real_t mass; + real_t friction; + real_t gravity_scale; + +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 *p_list) const; + void _notification(int p_what); + void _direct_state_changed(Object *p_state); + + static void _bind_methods(); + +private: + static Skeleton3D *find_skeleton_parent(Node *p_parent); + + void _fix_joint_offset(); + void _reload_joint(); + +public: + void _on_bone_parent_changed(); + void _set_gizmo_move_joint(bool p_move_joint); + +public: +#ifdef TOOLS_ENABLED + virtual Transform get_global_gizmo_transform() const; + virtual Transform get_local_gizmo_transform() const; +#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 Transform &p_offset); + const Transform &get_joint_offset() const; + + void set_body_offset(const Transform &p_offset); + const Transform &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_weight(real_t p_weight); + real_t get_weight() 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 apply_central_impulse(const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + + 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); + +#endif // PHYSICS_BODY__H diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp deleted file mode 100644 index 0699e366e0..0000000000 --- a/scene/3d/physics_joint.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -/*************************************************************************/ -/* physics_joint.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_joint.h" - -void Joint::_update_joint(bool p_only_free) { - - if (joint.is_valid()) { - if (ba.is_valid() && bb.is_valid()) - PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb); - - PhysicsServer::get_singleton()->free(joint); - joint = RID(); - ba = RID(); - bb = RID(); - } - - if (p_only_free || !is_inside_tree()) - return; - - Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; - Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - - PhysicsBody *body_a = Object::cast_to(node_a); - PhysicsBody *body_b = Object::cast_to(node_b); - - if (!body_a && body_b) - SWAP(body_a, body_b); - - if (!body_a) - return; - - joint = _configure_joint(body_a, body_b); - - if (!joint.is_valid()) - return; - - PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); - - ba = body_a->get_rid(); - if (body_b) - bb = body_b->get_rid(); - - PhysicsServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); -} - -void Joint::set_node_a(const NodePath &p_node_a) { - - if (a == p_node_a) - return; - - a = p_node_a; - _update_joint(); -} - -NodePath Joint::get_node_a() const { - - return a; -} - -void Joint::set_node_b(const NodePath &p_node_b) { - - if (b == p_node_b) - return; - b = p_node_b; - _update_joint(); -} -NodePath Joint::get_node_b() const { - - return b; -} - -void Joint::set_solver_priority(int p_priority) { - - solver_priority = p_priority; - if (joint.is_valid()) - PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); -} - -int Joint::get_solver_priority() const { - - return solver_priority; -} - -void Joint::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_READY: { - _update_joint(); - } break; - case NOTIFICATION_EXIT_TREE: { - if (joint.is_valid()) { - _update_joint(true); - } - } break; - } -} - -void Joint::set_exclude_nodes_from_collision(bool p_enable) { - - if (exclude_from_collision == p_enable) - return; - exclude_from_collision = p_enable; - _update_joint(); -} - -bool Joint::get_exclude_nodes_from_collision() const { - - return exclude_from_collision; -} - -void Joint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint::set_node_a); - ClassDB::bind_method(D_METHOD("get_node_a"), &Joint::get_node_a); - - ClassDB::bind_method(D_METHOD("set_node_b", "node"), &Joint::set_node_b); - ClassDB::bind_method(D_METHOD("get_node_b"), &Joint::get_node_b); - - ClassDB::bind_method(D_METHOD("set_solver_priority", "priority"), &Joint::set_solver_priority); - ClassDB::bind_method(D_METHOD("get_solver_priority"), &Joint::get_solver_priority); - - ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint::set_exclude_nodes_from_collision); - ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint::get_exclude_nodes_from_collision); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject"), "set_node_a", "get_node_a"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject"), "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, "collision/exclude_nodes"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision"); -} - -Joint::Joint() { - - exclude_from_collision = true; - solver_priority = 1; - set_notify_transform(true); -} - -/////////////////////////////////// - -void PinJoint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &PinJoint::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &PinJoint::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 PinJoint::set_param(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, 3); - params[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer::PinJointParam(p_param), p_value); -} -float PinJoint::get_param(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, 3, 0); - return params[p_param]; -} - -RID PinJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { - - Vector3 pinpos = get_global_transform().origin; - Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos); - Vector3 local_b; - - if (body_b) - local_b = body_b->get_global_transform().affine_inverse().xform(pinpos); - else - local_b = pinpos; - - RID j = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); - for (int i = 0; i < 3; i++) { - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PinJointParam(i), params[i]); - } - return j; -} - -PinJoint::PinJoint() { - - params[PARAM_BIAS] = 0.3; - params[PARAM_DAMPING] = 1; - params[PARAM_IMPULSE_CLAMP] = 0; -} - -///////////////////////////////////////////////// - -/////////////////////////////////// - -void HingeJoint::_set_upper_limit(float p_limit) { - - set_param(PARAM_LIMIT_UPPER, Math::deg2rad(p_limit)); -} - -float HingeJoint::_get_upper_limit() const { - - return Math::rad2deg(get_param(PARAM_LIMIT_UPPER)); -} - -void HingeJoint::_set_lower_limit(float p_limit) { - - set_param(PARAM_LIMIT_LOWER, Math::deg2rad(p_limit)); -} - -float HingeJoint::_get_lower_limit() const { - - return Math::rad2deg(get_param(PARAM_LIMIT_LOWER)); -} - -void HingeJoint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &HingeJoint::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &HingeJoint::get_param); - - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &HingeJoint::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &HingeJoint::get_flag); - - ClassDB::bind_method(D_METHOD("_set_upper_limit", "upper_limit"), &HingeJoint::_set_upper_limit); - ClassDB::bind_method(D_METHOD("_get_upper_limit"), &HingeJoint::_get_upper_limit); - - ClassDB::bind_method(D_METHOD("_set_lower_limit", "lower_limit"), &HingeJoint::_set_lower_limit); - ClassDB::bind_method(D_METHOD("_get_lower_limit"), &HingeJoint::_get_lower_limit); - - 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_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit", "_get_upper_limit"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit", "_get_lower_limit"); - 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, "-200,200,0.01,or_greater,or_lesser"), "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 HingeJoint::set_param(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer::HingeJointParam(p_param), p_value); - - update_gizmo(); -} -float HingeJoint::get_param(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params[p_param]; -} - -void HingeJoint::set_flag(Flag p_flag, bool p_value) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags[p_flag] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer::HingeJointFlag(p_flag), p_value); - - update_gizmo(); -} -bool HingeJoint::get_flag(Flag p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags[p_flag]; -} - -RID HingeJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { - - Transform gt = get_global_transform(); - Transform ainv = body_a->get_global_transform().affine_inverse(); - - Transform local_a = ainv * gt; - local_a.orthonormalize(); - Transform local_b = gt; - - if (body_b) { - Transform binv = body_b->get_global_transform().affine_inverse(); - local_b = binv * gt; - } - - local_b.orthonormalize(); - - RID j = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); - for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HingeJointParam(i), params[i]); - } - for (int i = 0; i < FLAG_MAX; i++) { - set_flag(Flag(i), flags[i]); - PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HingeJointFlag(i), flags[i]); - } - return j; -} - -HingeJoint::HingeJoint() { - - 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 SliderJoint::_set_upper_limit_angular(float p_limit_angular) { - - set_param(PARAM_ANGULAR_LIMIT_UPPER, Math::deg2rad(p_limit_angular)); -} - -float SliderJoint::_get_upper_limit_angular() const { - - return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_UPPER)); -} - -void SliderJoint::_set_lower_limit_angular(float p_limit_angular) { - - set_param(PARAM_ANGULAR_LIMIT_LOWER, Math::deg2rad(p_limit_angular)); -} - -float SliderJoint::_get_lower_limit_angular() const { - - return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_LOWER)); -} - -void SliderJoint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &SliderJoint::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &SliderJoint::get_param); - - ClassDB::bind_method(D_METHOD("_set_upper_limit_angular", "upper_limit_angular"), &SliderJoint::_set_upper_limit_angular); - ClassDB::bind_method(D_METHOD("_get_upper_limit_angular"), &SliderJoint::_get_upper_limit_angular); - - ClassDB::bind_method(D_METHOD("_set_lower_limit_angular", "lower_limit_angular"), &SliderJoint::_set_lower_limit_angular); - ClassDB::bind_method(D_METHOD("_get_lower_limit_angular"), &SliderJoint::_get_lower_limit_angular); - - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "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_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit_angular", "_get_upper_limit_angular"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit_angular", "_get_lower_limit_angular"); - 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 SliderJoint::set_param(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer::SliderJointParam(p_param), p_value); - update_gizmo(); -} -float SliderJoint::get_param(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params[p_param]; -} - -RID SliderJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { - - Transform gt = get_global_transform(); - Transform ainv = body_a->get_global_transform().affine_inverse(); - - Transform local_a = ainv * gt; - local_a.orthonormalize(); - Transform local_b = gt; - - if (body_b) { - Transform binv = body_b->get_global_transform().affine_inverse(); - local_b = binv * gt; - } - - local_b.orthonormalize(); - - RID j = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); - for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SliderJointParam(i), params[i]); - } - - return j; -} - -SliderJoint::SliderJoint() { - - 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 ConeTwistJoint::_set_swing_span(float p_limit_angular) { - - set_param(PARAM_SWING_SPAN, Math::deg2rad(p_limit_angular)); -} - -float ConeTwistJoint::_get_swing_span() const { - - return Math::rad2deg(get_param(PARAM_SWING_SPAN)); -} - -void ConeTwistJoint::_set_twist_span(float p_limit_angular) { - - set_param(PARAM_TWIST_SPAN, Math::deg2rad(p_limit_angular)); -} - -float ConeTwistJoint::_get_twist_span() const { - - return Math::rad2deg(get_param(PARAM_TWIST_SPAN)); -} - -void ConeTwistJoint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ConeTwistJoint::set_param); - ClassDB::bind_method(D_METHOD("get_param", "param"), &ConeTwistJoint::get_param); - - ClassDB::bind_method(D_METHOD("_set_swing_span", "swing_span"), &ConeTwistJoint::_set_swing_span); - ClassDB::bind_method(D_METHOD("_get_swing_span"), &ConeTwistJoint::_get_swing_span); - - ClassDB::bind_method(D_METHOD("_set_twist_span", "twist_span"), &ConeTwistJoint::_set_twist_span); - ClassDB::bind_method(D_METHOD("_get_twist_span"), &ConeTwistJoint::_get_twist_span); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_swing_span", "_get_swing_span"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1"), "_set_twist_span", "_get_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 ConeTwistJoint::set_param(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer::ConeTwistJointParam(p_param), p_value); - - update_gizmo(); -} -float ConeTwistJoint::get_param(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params[p_param]; -} - -RID ConeTwistJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { - - Transform gt = get_global_transform(); - //Vector3 cone_twistpos = gt.origin; - //Vector3 cone_twistdir = gt.basis.get_axis(2); - - Transform ainv = body_a->get_global_transform().affine_inverse(); - - Transform local_a = ainv * gt; - local_a.orthonormalize(); - Transform local_b = gt; - - if (body_b) { - Transform binv = body_b->get_global_transform().affine_inverse(); - local_b = binv * gt; - } - - local_b.orthonormalize(); - - RID j = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); - for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::ConeTwistJointParam(i), params[i]); - } - - return j; -} - -ConeTwistJoint::ConeTwistJoint() { - - 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; -} - -///////////////////////////////////////////////////////////////////// - -void Generic6DOFJoint::_set_angular_hi_limit_x(float p_limit_angular) { - - set_param_x(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_hi_limit_x() const { - - return Math::rad2deg(get_param_x(PARAM_ANGULAR_UPPER_LIMIT)); -} - -void Generic6DOFJoint::_set_angular_lo_limit_x(float p_limit_angular) { - - set_param_x(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_lo_limit_x() const { - - return Math::rad2deg(get_param_x(PARAM_ANGULAR_LOWER_LIMIT)); -} - -void Generic6DOFJoint::_set_angular_hi_limit_y(float p_limit_angular) { - - set_param_y(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_hi_limit_y() const { - - return Math::rad2deg(get_param_y(PARAM_ANGULAR_UPPER_LIMIT)); -} - -void Generic6DOFJoint::_set_angular_lo_limit_y(float p_limit_angular) { - - set_param_y(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_lo_limit_y() const { - - return Math::rad2deg(get_param_y(PARAM_ANGULAR_LOWER_LIMIT)); -} - -void Generic6DOFJoint::_set_angular_hi_limit_z(float p_limit_angular) { - - set_param_z(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_hi_limit_z() const { - - return Math::rad2deg(get_param_z(PARAM_ANGULAR_UPPER_LIMIT)); -} - -void Generic6DOFJoint::_set_angular_lo_limit_z(float p_limit_angular) { - - set_param_z(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); -} - -float Generic6DOFJoint::_get_angular_lo_limit_z() const { - - return Math::rad2deg(get_param_z(PARAM_ANGULAR_LOWER_LIMIT)); -} - -void Generic6DOFJoint::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_x", "angle"), &Generic6DOFJoint::_set_angular_hi_limit_x); - ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_x"), &Generic6DOFJoint::_get_angular_hi_limit_x); - - ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_x", "angle"), &Generic6DOFJoint::_set_angular_lo_limit_x); - ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_x"), &Generic6DOFJoint::_get_angular_lo_limit_x); - - ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_y", "angle"), &Generic6DOFJoint::_set_angular_hi_limit_y); - ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_y"), &Generic6DOFJoint::_get_angular_hi_limit_y); - - ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_y", "angle"), &Generic6DOFJoint::_set_angular_lo_limit_y); - ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_y"), &Generic6DOFJoint::_get_angular_lo_limit_y); - - ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_z", "angle"), &Generic6DOFJoint::_set_angular_hi_limit_z); - ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_z"), &Generic6DOFJoint::_get_angular_hi_limit_z); - - ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_z", "angle"), &Generic6DOFJoint::_set_angular_lo_limit_z); - ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_z"), &Generic6DOFJoint::_get_angular_lo_limit_z); - - ClassDB::bind_method(D_METHOD("set_param_x", "param", "value"), &Generic6DOFJoint::set_param_x); - ClassDB::bind_method(D_METHOD("get_param_x", "param"), &Generic6DOFJoint::get_param_x); - - ClassDB::bind_method(D_METHOD("set_param_y", "param", "value"), &Generic6DOFJoint::set_param_y); - ClassDB::bind_method(D_METHOD("get_param_y", "param"), &Generic6DOFJoint::get_param_y); - - ClassDB::bind_method(D_METHOD("set_param_z", "param", "value"), &Generic6DOFJoint::set_param_z); - ClassDB::bind_method(D_METHOD("get_param_z", "param"), &Generic6DOFJoint::get_param_z); - - ClassDB::bind_method(D_METHOD("set_flag_x", "flag", "value"), &Generic6DOFJoint::set_flag_x); - ClassDB::bind_method(D_METHOD("get_flag_x", "flag"), &Generic6DOFJoint::get_flag_x); - - ClassDB::bind_method(D_METHOD("set_flag_y", "flag", "value"), &Generic6DOFJoint::set_flag_y); - ClassDB::bind_method(D_METHOD("get_flag_y", "flag"), &Generic6DOFJoint::get_flag_y); - - ClassDB::bind_method(D_METHOD("set_flag_z", "flag", "value"), &Generic6DOFJoint::set_flag_z); - ClassDB::bind_method(D_METHOD("get_flag_z", "flag"), &Generic6DOFJoint::get_flag_z); - - ClassDB::bind_method(D_METHOD("set_precision", "precision"), &Generic6DOFJoint::set_precision); - ClassDB::bind_method(D_METHOD("get_precision"), &Generic6DOFJoint::get_precision); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_LIMIT_SOFTNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_RESTITUTION); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "precision", PROPERTY_HINT_RANGE, "1,99999,1"), "set_precision", "get_precision"); - - BIND_ENUM_CONSTANT(PARAM_LINEAR_LOWER_LIMIT); - BIND_ENUM_CONSTANT(PARAM_LINEAR_UPPER_LIMIT); - BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(PARAM_LINEAR_RESTITUTION); - BIND_ENUM_CONSTANT(PARAM_LINEAR_DAMPING); - BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_TARGET_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_FORCE_LIMIT); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_LOWER_LIMIT); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_UPPER_LIMIT); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_DAMPING); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_RESTITUTION); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_FORCE_LIMIT); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_ERP); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); - BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_FORCE_LIMIT); - BIND_ENUM_CONSTANT(PARAM_MAX); - - BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT); - BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_LIMIT); - BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_SPRING); - BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_SPRING); - BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR); - BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_MOTOR); - BIND_ENUM_CONSTANT(FLAG_MAX); -} - -void Generic6DOFJoint::set_param_x(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params_x[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); - - update_gizmo(); -} -float Generic6DOFJoint::get_param_x(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params_x[p_param]; -} - -void Generic6DOFJoint::set_param_y(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params_y[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); - update_gizmo(); -} -float Generic6DOFJoint::get_param_y(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params_y[p_param]; -} - -void Generic6DOFJoint::set_param_z(Param p_param, float p_value) { - - ERR_FAIL_INDEX(p_param, PARAM_MAX); - params_z[p_param] = p_value; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); - update_gizmo(); -} -float Generic6DOFJoint::get_param_z(Param p_param) const { - - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - return params_z[p_param]; -} - -void Generic6DOFJoint::set_flag_x(Flag p_flag, bool p_enabled) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags_x[p_flag] = p_enabled; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); - update_gizmo(); -} -bool Generic6DOFJoint::get_flag_x(Flag p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags_x[p_flag]; -} - -void Generic6DOFJoint::set_flag_y(Flag p_flag, bool p_enabled) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags_y[p_flag] = p_enabled; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); - update_gizmo(); -} -bool Generic6DOFJoint::get_flag_y(Flag p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags_y[p_flag]; -} - -void Generic6DOFJoint::set_flag_z(Flag p_flag, bool p_enabled) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags_z[p_flag] = p_enabled; - if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); - update_gizmo(); -} -bool Generic6DOFJoint::get_flag_z(Flag p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags_z[p_flag]; -} - -void Generic6DOFJoint::set_precision(int p_precision) { - precision = p_precision; - - PhysicsServer::get_singleton()->generic_6dof_joint_set_precision( - get_joint(), - precision); -} - -RID Generic6DOFJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { - - Transform gt = get_global_transform(); - //Vector3 cone_twistpos = gt.origin; - //Vector3 cone_twistdir = gt.basis.get_axis(2); - - Transform ainv = body_a->get_global_transform().affine_inverse(); - - Transform local_a = ainv * gt; - local_a.orthonormalize(); - Transform local_b = gt; - - if (body_b) { - Transform binv = body_b->get_global_transform().affine_inverse(); - local_b = binv * gt; - } - - local_b.orthonormalize(); - - RID j = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); - for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(i), params_x[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(i), params_y[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(i), params_z[i]); - } - for (int i = 0; i < FLAG_MAX; i++) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(i), flags_x[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(i), flags_y[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(i), flags_z[i]); - } - - return j; -} - -Generic6DOFJoint::Generic6DOFJoint() : - precision(1) { - - set_param_x(PARAM_LINEAR_LOWER_LIMIT, 0); - set_param_x(PARAM_LINEAR_UPPER_LIMIT, 0); - set_param_x(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); - set_param_x(PARAM_LINEAR_RESTITUTION, 0.5); - set_param_x(PARAM_LINEAR_DAMPING, 1.0); - set_param_x(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); - set_param_x(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); - set_param_x(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); - set_param_x(PARAM_LINEAR_SPRING_DAMPING, 0.01); - set_param_x(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); - set_param_x(PARAM_ANGULAR_LOWER_LIMIT, 0); - set_param_x(PARAM_ANGULAR_UPPER_LIMIT, 0); - set_param_x(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); - set_param_x(PARAM_ANGULAR_DAMPING, 1.0f); - set_param_x(PARAM_ANGULAR_RESTITUTION, 0); - set_param_x(PARAM_ANGULAR_FORCE_LIMIT, 0); - set_param_x(PARAM_ANGULAR_ERP, 0.5); - set_param_x(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); - set_param_x(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); - set_param_x(PARAM_ANGULAR_SPRING_STIFFNESS, 0); - set_param_x(PARAM_ANGULAR_SPRING_DAMPING, 0); - set_param_x(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); - - set_flag_x(FLAG_ENABLE_ANGULAR_LIMIT, true); - set_flag_x(FLAG_ENABLE_LINEAR_LIMIT, true); - set_flag_x(FLAG_ENABLE_ANGULAR_SPRING, false); - set_flag_x(FLAG_ENABLE_LINEAR_SPRING, false); - set_flag_x(FLAG_ENABLE_MOTOR, false); - set_flag_x(FLAG_ENABLE_LINEAR_MOTOR, false); - - set_param_y(PARAM_LINEAR_LOWER_LIMIT, 0); - set_param_y(PARAM_LINEAR_UPPER_LIMIT, 0); - set_param_y(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); - set_param_y(PARAM_LINEAR_RESTITUTION, 0.5); - set_param_y(PARAM_LINEAR_DAMPING, 1.0); - set_param_y(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); - set_param_y(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); - set_param_y(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); - set_param_y(PARAM_LINEAR_SPRING_DAMPING, 0.01); - set_param_y(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); - set_param_y(PARAM_ANGULAR_LOWER_LIMIT, 0); - set_param_y(PARAM_ANGULAR_UPPER_LIMIT, 0); - set_param_y(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); - set_param_y(PARAM_ANGULAR_DAMPING, 1.0f); - set_param_y(PARAM_ANGULAR_RESTITUTION, 0); - set_param_y(PARAM_ANGULAR_FORCE_LIMIT, 0); - set_param_y(PARAM_ANGULAR_ERP, 0.5); - set_param_y(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); - set_param_y(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); - set_param_y(PARAM_ANGULAR_SPRING_STIFFNESS, 0); - set_param_y(PARAM_ANGULAR_SPRING_DAMPING, 0); - set_param_y(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); - - set_flag_y(FLAG_ENABLE_ANGULAR_LIMIT, true); - set_flag_y(FLAG_ENABLE_LINEAR_LIMIT, true); - set_flag_y(FLAG_ENABLE_ANGULAR_SPRING, false); - set_flag_y(FLAG_ENABLE_LINEAR_SPRING, false); - set_flag_y(FLAG_ENABLE_MOTOR, false); - set_flag_y(FLAG_ENABLE_LINEAR_MOTOR, false); - - set_param_z(PARAM_LINEAR_LOWER_LIMIT, 0); - set_param_z(PARAM_LINEAR_UPPER_LIMIT, 0); - set_param_z(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); - set_param_z(PARAM_LINEAR_RESTITUTION, 0.5); - set_param_z(PARAM_LINEAR_DAMPING, 1.0); - set_param_z(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); - set_param_z(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); - set_param_z(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); - set_param_z(PARAM_LINEAR_SPRING_DAMPING, 0.01); - set_param_z(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); - set_param_z(PARAM_ANGULAR_LOWER_LIMIT, 0); - set_param_z(PARAM_ANGULAR_UPPER_LIMIT, 0); - set_param_z(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); - set_param_z(PARAM_ANGULAR_DAMPING, 1.0f); - set_param_z(PARAM_ANGULAR_RESTITUTION, 0); - set_param_z(PARAM_ANGULAR_FORCE_LIMIT, 0); - set_param_z(PARAM_ANGULAR_ERP, 0.5); - set_param_z(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); - set_param_z(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); - set_param_z(PARAM_ANGULAR_SPRING_STIFFNESS, 0); - set_param_z(PARAM_ANGULAR_SPRING_DAMPING, 0); - set_param_z(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); - - set_flag_z(FLAG_ENABLE_ANGULAR_LIMIT, true); - set_flag_z(FLAG_ENABLE_LINEAR_LIMIT, true); - set_flag_z(FLAG_ENABLE_ANGULAR_SPRING, false); - set_flag_z(FLAG_ENABLE_LINEAR_SPRING, false); - set_flag_z(FLAG_ENABLE_MOTOR, false); - set_flag_z(FLAG_ENABLE_LINEAR_MOTOR, false); -} diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h deleted file mode 100644 index d03dbac392..0000000000 --- a/scene/3d/physics_joint.h +++ /dev/null @@ -1,343 +0,0 @@ -/*************************************************************************/ -/* physics_joint.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_JOINT_H -#define PHYSICS_JOINT_H - -#include "scene/3d/physics_body.h" -#include "scene/3d/spatial.h" - -class Joint : public Spatial { - - GDCLASS(Joint, Spatial); - - RID ba, bb; - - RID joint; - - NodePath a; - NodePath b; - - int solver_priority; - bool exclude_from_collision; - -protected: - void _update_joint(bool p_only_free = false); - - void _notification(int p_what); - - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) = 0; - - static void _bind_methods(); - -public: - 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_joint() const { return joint; } - Joint(); -}; - -/////////////////////////////////////////// - -class PinJoint : public Joint { - - GDCLASS(PinJoint, Joint); - -public: - enum Param { - PARAM_BIAS = PhysicsServer::PIN_JOINT_BIAS, - PARAM_DAMPING = PhysicsServer::PIN_JOINT_DAMPING, - PARAM_IMPULSE_CLAMP = PhysicsServer::PIN_JOINT_IMPULSE_CLAMP - }; - -protected: - float params[3]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); - static void _bind_methods(); - -public: - void set_param(Param p_param, float p_value); - float get_param(Param p_param) const; - - PinJoint(); -}; - -VARIANT_ENUM_CAST(PinJoint::Param); - -class HingeJoint : public Joint { - - GDCLASS(HingeJoint, Joint); - -public: - enum Param { - PARAM_BIAS = PhysicsServer::HINGE_JOINT_BIAS, - PARAM_LIMIT_UPPER = PhysicsServer::HINGE_JOINT_LIMIT_UPPER, - PARAM_LIMIT_LOWER = PhysicsServer::HINGE_JOINT_LIMIT_LOWER, - PARAM_LIMIT_BIAS = PhysicsServer::HINGE_JOINT_LIMIT_BIAS, - PARAM_LIMIT_SOFTNESS = PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, - PARAM_LIMIT_RELAXATION = PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, - PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY, - PARAM_MOTOR_MAX_IMPULSE = PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE, - PARAM_MAX = PhysicsServer::HINGE_JOINT_MAX - }; - - enum Flag { - FLAG_USE_LIMIT = PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, - FLAG_ENABLE_MOTOR = PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR, - FLAG_MAX = PhysicsServer::HINGE_JOINT_FLAG_MAX - }; - -protected: - float params[PARAM_MAX]; - bool flags[FLAG_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); - static void _bind_methods(); - - void _set_upper_limit(float p_limit); - float _get_upper_limit() const; - - void _set_lower_limit(float p_limit); - float _get_lower_limit() const; - -public: - void set_param(Param p_param, float p_value); - float get_param(Param p_param) const; - - void set_flag(Flag p_flag, bool p_value); - bool get_flag(Flag p_flag) const; - - HingeJoint(); -}; - -VARIANT_ENUM_CAST(HingeJoint::Param); -VARIANT_ENUM_CAST(HingeJoint::Flag); - -class SliderJoint : public Joint { - - GDCLASS(SliderJoint, Joint); - -public: - enum Param { - PARAM_LINEAR_LIMIT_UPPER = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, - PARAM_LINEAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, - PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, - PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, - PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, - PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, - PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, - PARAM_LINEAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING, - PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, - PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, - PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, - - PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, - PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, - PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, - PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, - PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, - PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, - PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, - PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING, - PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, - PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, - PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, - PARAM_MAX = PhysicsServer::SLIDER_JOINT_MAX - - }; - -protected: - void _set_upper_limit_angular(float p_limit_angular); - float _get_upper_limit_angular() const; - - void _set_lower_limit_angular(float p_limit_angular); - float _get_lower_limit_angular() const; - - float params[PARAM_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); - static void _bind_methods(); - -public: - void set_param(Param p_param, float p_value); - float get_param(Param p_param) const; - - SliderJoint(); -}; - -VARIANT_ENUM_CAST(SliderJoint::Param); - -class ConeTwistJoint : public Joint { - - GDCLASS(ConeTwistJoint, Joint); - -public: - enum Param { - - PARAM_SWING_SPAN, - PARAM_TWIST_SPAN, - PARAM_BIAS, - PARAM_SOFTNESS, - PARAM_RELAXATION, - PARAM_MAX - }; - -protected: - void _set_swing_span(float p_limit_angular); - float _get_swing_span() const; - - void _set_twist_span(float p_limit_angular); - float _get_twist_span() const; - - float params[PARAM_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); - static void _bind_methods(); - -public: - void set_param(Param p_param, float p_value); - float get_param(Param p_param) const; - - ConeTwistJoint(); -}; - -VARIANT_ENUM_CAST(ConeTwistJoint::Param); - -class Generic6DOFJoint : public Joint { - - GDCLASS(Generic6DOFJoint, Joint); - -public: - enum Param { - - PARAM_LINEAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, - PARAM_LINEAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, - PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, - PARAM_LINEAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, - PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, - PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, - PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, - PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, - PARAM_LINEAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, - PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, - PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, - PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, - PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, - PARAM_ANGULAR_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, - PARAM_ANGULAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, - PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT, - PARAM_ANGULAR_ERP = PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, - PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, - PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, - PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, - PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, - PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, - PARAM_MAX = PhysicsServer::G6DOF_JOINT_MAX, - }; - - enum Flag { - FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, - FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, - FLAG_ENABLE_LINEAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, - FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, - FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR, - FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, - FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX - }; - -protected: - void _set_angular_hi_limit_x(float p_limit_angular); - float _get_angular_hi_limit_x() const; - - void _set_angular_hi_limit_y(float p_limit_angular); - float _get_angular_hi_limit_y() const; - - void _set_angular_hi_limit_z(float p_limit_angular); - float _get_angular_hi_limit_z() const; - - void _set_angular_lo_limit_x(float p_limit_angular); - float _get_angular_lo_limit_x() const; - - void _set_angular_lo_limit_y(float p_limit_angular); - float _get_angular_lo_limit_y() const; - - void _set_angular_lo_limit_z(float p_limit_angular); - float _get_angular_lo_limit_z() const; - - float params_x[PARAM_MAX]; - bool flags_x[FLAG_MAX]; - float params_y[PARAM_MAX]; - bool flags_y[FLAG_MAX]; - float params_z[PARAM_MAX]; - bool flags_z[FLAG_MAX]; - - int precision; - - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); - static void _bind_methods(); - -public: - void set_param_x(Param p_param, float p_value); - float get_param_x(Param p_param) const; - - void set_param_y(Param p_param, float p_value); - float get_param_y(Param p_param) const; - - void set_param_z(Param p_param, float p_value); - float 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; - - void set_precision(int p_precision); - int get_precision() const { - return precision; - } - - Generic6DOFJoint(); -}; - -VARIANT_ENUM_CAST(Generic6DOFJoint::Param); -VARIANT_ENUM_CAST(Generic6DOFJoint::Flag); - -#endif // PHYSICS_JOINT_H diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp new file mode 100644 index 0000000000..dd7868cb38 --- /dev/null +++ b/scene/3d/physics_joint_3d.cpp @@ -0,0 +1,1049 @@ +/*************************************************************************/ +/* physics_joint_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_joint_3d.h" + +void Joint3D::_update_joint(bool p_only_free) { + + if (joint.is_valid()) { + if (ba.is_valid() && bb.is_valid()) + PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb); + + PhysicsServer::get_singleton()->free(joint); + joint = RID(); + ba = RID(); + bb = RID(); + } + + if (p_only_free || !is_inside_tree()) + return; + + Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; + Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; + + PhysicsBody3D *body_a = Object::cast_to(node_a); + PhysicsBody3D *body_b = Object::cast_to(node_b); + + if (!body_a && body_b) + SWAP(body_a, body_b); + + if (!body_a) + return; + + joint = _configure_joint(body_a, body_b); + + if (!joint.is_valid()) + return; + + PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); + + ba = body_a->get_rid(); + if (body_b) + bb = body_b->get_rid(); + + PhysicsServer::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; + + 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; + 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()) + PhysicsServer::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_READY: { + _update_joint(); + } break; + case NOTIFICATION_EXIT_TREE: { + if (joint.is_valid()) { + _update_joint(true); + } + } break; + } +} + +void Joint3D::set_exclude_nodes_from_collision(bool p_enable) { + + if (exclude_from_collision == p_enable) + return; + exclude_from_collision = p_enable; + _update_joint(); +} + +bool Joint3D::get_exclude_nodes_from_collision() const { + + return exclude_from_collision; +} + +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); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "set_node_a", "get_node_a"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "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, "collision/exclude_nodes"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision"); +} + +Joint3D::Joint3D() { + + exclude_from_collision = true; + solver_priority = 1; + set_notify_transform(true); +} + +/////////////////////////////////// + +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, float p_value) { + + ERR_FAIL_INDEX(p_param, 3); + params[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer::PinJointParam(p_param), p_value); +} +float PinJoint3D::get_param(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, 3, 0); + return params[p_param]; +} + +RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { + + Vector3 pinpos = get_global_transform().origin; + Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos); + Vector3 local_b; + + if (body_b) + local_b = body_b->get_global_transform().affine_inverse().xform(pinpos); + else + local_b = pinpos; + + RID j = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + for (int i = 0; i < 3; i++) { + PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PinJointParam(i), params[i]); + } + return j; +} + +PinJoint3D::PinJoint3D() { + + params[PARAM_BIAS] = 0.3; + params[PARAM_DAMPING] = 1; + params[PARAM_IMPULSE_CLAMP] = 0; +} + +///////////////////////////////////////////////// + +/////////////////////////////////// + +void HingeJoint3D::_set_upper_limit(float p_limit) { + + set_param(PARAM_LIMIT_UPPER, Math::deg2rad(p_limit)); +} + +float HingeJoint3D::_get_upper_limit() const { + + return Math::rad2deg(get_param(PARAM_LIMIT_UPPER)); +} + +void HingeJoint3D::_set_lower_limit(float p_limit) { + + set_param(PARAM_LIMIT_LOWER, Math::deg2rad(p_limit)); +} + +float HingeJoint3D::_get_lower_limit() const { + + return Math::rad2deg(get_param(PARAM_LIMIT_LOWER)); +} + +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); + + ClassDB::bind_method(D_METHOD("_set_upper_limit", "upper_limit"), &HingeJoint3D::_set_upper_limit); + ClassDB::bind_method(D_METHOD("_get_upper_limit"), &HingeJoint3D::_get_upper_limit); + + ClassDB::bind_method(D_METHOD("_set_lower_limit", "lower_limit"), &HingeJoint3D::_set_lower_limit); + ClassDB::bind_method(D_METHOD("_get_lower_limit"), &HingeJoint3D::_get_lower_limit); + + 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_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit", "_get_upper_limit"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit", "_get_lower_limit"); + 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, "-200,200,0.01,or_greater,or_lesser"), "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, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer::HingeJointParam(p_param), p_value); + + update_gizmo(); +} +float 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 (get_joint().is_valid()) + PhysicsServer::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer::HingeJointFlag(p_flag), p_value); + + update_gizmo(); +} +bool HingeJoint3D::get_flag(Flag p_flag) const { + + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { + + Transform gt = get_global_transform(); + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + for (int i = 0; i < PARAM_MAX; i++) { + PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HingeJointParam(i), params[i]); + } + for (int i = 0; i < FLAG_MAX; i++) { + set_flag(Flag(i), flags[i]); + PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HingeJointFlag(i), flags[i]); + } + return j; +} + +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::_set_upper_limit_angular(float p_limit_angular) { + + set_param(PARAM_ANGULAR_LIMIT_UPPER, Math::deg2rad(p_limit_angular)); +} + +float SliderJoint3D::_get_upper_limit_angular() const { + + return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_UPPER)); +} + +void SliderJoint3D::_set_lower_limit_angular(float p_limit_angular) { + + set_param(PARAM_ANGULAR_LIMIT_LOWER, Math::deg2rad(p_limit_angular)); +} + +float SliderJoint3D::_get_lower_limit_angular() const { + + return Math::rad2deg(get_param(PARAM_ANGULAR_LIMIT_LOWER)); +} + +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); + + ClassDB::bind_method(D_METHOD("_set_upper_limit_angular", "upper_limit_angular"), &SliderJoint3D::_set_upper_limit_angular); + ClassDB::bind_method(D_METHOD("_get_upper_limit_angular"), &SliderJoint3D::_get_upper_limit_angular); + + ClassDB::bind_method(D_METHOD("_set_lower_limit_angular", "lower_limit_angular"), &SliderJoint3D::_set_lower_limit_angular); + ClassDB::bind_method(D_METHOD("_get_lower_limit_angular"), &SliderJoint3D::_get_lower_limit_angular); + + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/upper_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_param", "get_param", PARAM_LINEAR_LIMIT_UPPER); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit/lower_distance", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "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_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit_angular", "_get_upper_limit_angular"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_lower_limit_angular", "_get_lower_limit_angular"); + 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, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer::SliderJointParam(p_param), p_value); + update_gizmo(); +} +float SliderJoint3D::get_param(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return params[p_param]; +} + +RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { + + Transform gt = get_global_transform(); + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + for (int i = 0; i < PARAM_MAX; i++) { + PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SliderJointParam(i), params[i]); + } + + return j; +} + +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::_set_swing_span(float p_limit_angular) { + + set_param(PARAM_SWING_SPAN, Math::deg2rad(p_limit_angular)); +} + +float ConeTwistJoint3D::_get_swing_span() const { + + return Math::rad2deg(get_param(PARAM_SWING_SPAN)); +} + +void ConeTwistJoint3D::_set_twist_span(float p_limit_angular) { + + set_param(PARAM_TWIST_SPAN, Math::deg2rad(p_limit_angular)); +} + +float ConeTwistJoint3D::_get_twist_span() const { + + return Math::rad2deg(get_param(PARAM_TWIST_SPAN)); +} + +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); + + ClassDB::bind_method(D_METHOD("_set_swing_span", "swing_span"), &ConeTwistJoint3D::_set_swing_span); + ClassDB::bind_method(D_METHOD("_get_swing_span"), &ConeTwistJoint3D::_get_swing_span); + + ClassDB::bind_method(D_METHOD("_set_twist_span", "twist_span"), &ConeTwistJoint3D::_set_twist_span); + ClassDB::bind_method(D_METHOD("_get_twist_span"), &ConeTwistJoint3D::_get_twist_span); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "swing_span", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_swing_span", "_get_swing_span"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1"), "_set_twist_span", "_get_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, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer::ConeTwistJointParam(p_param), p_value); + + update_gizmo(); +} +float ConeTwistJoint3D::get_param(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return params[p_param]; +} + +RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { + + Transform gt = get_global_transform(); + //Vector3 cone_twistpos = gt.origin; + //Vector3 cone_twistdir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + for (int i = 0; i < PARAM_MAX; i++) { + PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::ConeTwistJointParam(i), params[i]); + } + + return j; +} + +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; +} + +///////////////////////////////////////////////////////////////////// + +void Generic6DOFJoint3D::_set_angular_hi_limit_x(float p_limit_angular) { + + set_param_x(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_hi_limit_x() const { + + return Math::rad2deg(get_param_x(PARAM_ANGULAR_UPPER_LIMIT)); +} + +void Generic6DOFJoint3D::_set_angular_lo_limit_x(float p_limit_angular) { + + set_param_x(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_lo_limit_x() const { + + return Math::rad2deg(get_param_x(PARAM_ANGULAR_LOWER_LIMIT)); +} + +void Generic6DOFJoint3D::_set_angular_hi_limit_y(float p_limit_angular) { + + set_param_y(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_hi_limit_y() const { + + return Math::rad2deg(get_param_y(PARAM_ANGULAR_UPPER_LIMIT)); +} + +void Generic6DOFJoint3D::_set_angular_lo_limit_y(float p_limit_angular) { + + set_param_y(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_lo_limit_y() const { + + return Math::rad2deg(get_param_y(PARAM_ANGULAR_LOWER_LIMIT)); +} + +void Generic6DOFJoint3D::_set_angular_hi_limit_z(float p_limit_angular) { + + set_param_z(PARAM_ANGULAR_UPPER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_hi_limit_z() const { + + return Math::rad2deg(get_param_z(PARAM_ANGULAR_UPPER_LIMIT)); +} + +void Generic6DOFJoint3D::_set_angular_lo_limit_z(float p_limit_angular) { + + set_param_z(PARAM_ANGULAR_LOWER_LIMIT, Math::deg2rad(p_limit_angular)); +} + +float Generic6DOFJoint3D::_get_angular_lo_limit_z() const { + + return Math::rad2deg(get_param_z(PARAM_ANGULAR_LOWER_LIMIT)); +} + +void Generic6DOFJoint3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_x", "angle"), &Generic6DOFJoint3D::_set_angular_hi_limit_x); + ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_x"), &Generic6DOFJoint3D::_get_angular_hi_limit_x); + + ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_x", "angle"), &Generic6DOFJoint3D::_set_angular_lo_limit_x); + ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_x"), &Generic6DOFJoint3D::_get_angular_lo_limit_x); + + ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_y", "angle"), &Generic6DOFJoint3D::_set_angular_hi_limit_y); + ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_y"), &Generic6DOFJoint3D::_get_angular_hi_limit_y); + + ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_y", "angle"), &Generic6DOFJoint3D::_set_angular_lo_limit_y); + ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_y"), &Generic6DOFJoint3D::_get_angular_lo_limit_y); + + ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_z", "angle"), &Generic6DOFJoint3D::_set_angular_hi_limit_z); + ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_z"), &Generic6DOFJoint3D::_get_angular_hi_limit_z); + + ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_z", "angle"), &Generic6DOFJoint3D::_set_angular_lo_limit_z); + ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_z"), &Generic6DOFJoint3D::_get_angular_lo_limit_z); + + ClassDB::bind_method(D_METHOD("set_param_x", "param", "value"), &Generic6DOFJoint3D::set_param_x); + ClassDB::bind_method(D_METHOD("get_param_x", "param"), &Generic6DOFJoint3D::get_param_x); + + ClassDB::bind_method(D_METHOD("set_param_y", "param", "value"), &Generic6DOFJoint3D::set_param_y); + ClassDB::bind_method(D_METHOD("get_param_y", "param"), &Generic6DOFJoint3D::get_param_y); + + ClassDB::bind_method(D_METHOD("set_param_z", "param", "value"), &Generic6DOFJoint3D::set_param_z); + ClassDB::bind_method(D_METHOD("get_param_z", "param"), &Generic6DOFJoint3D::get_param_z); + + ClassDB::bind_method(D_METHOD("set_flag_x", "flag", "value"), &Generic6DOFJoint3D::set_flag_x); + ClassDB::bind_method(D_METHOD("get_flag_x", "flag"), &Generic6DOFJoint3D::get_flag_x); + + ClassDB::bind_method(D_METHOD("set_flag_y", "flag", "value"), &Generic6DOFJoint3D::set_flag_y); + ClassDB::bind_method(D_METHOD("get_flag_y", "flag"), &Generic6DOFJoint3D::get_flag_y); + + ClassDB::bind_method(D_METHOD("set_flag_z", "flag", "value"), &Generic6DOFJoint3D::set_flag_z); + ClassDB::bind_method(D_METHOD("get_flag_z", "flag"), &Generic6DOFJoint3D::get_flag_z); + + ClassDB::bind_method(D_METHOD("set_precision", "precision"), &Generic6DOFJoint3D::set_precision); + ClassDB::bind_method(D_METHOD("get_precision"), &Generic6DOFJoint3D::get_precision); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/upper_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/lower_distance"), "set_param_x", "get_param_x", PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_x/erp"), "set_param_x", "get_param_x", PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/lower_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_y/erp"), "set_param_y", "get_param_y", PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/lower_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_LOWER_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_LIMIT_SOFTNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_RESTITUTION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_ANGULAR_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_limit_z/erp"), "set_param_z", "get_param_z", PARAM_ANGULAR_ERP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "precision", PROPERTY_HINT_RANGE, "1,99999,1"), "set_precision", "get_precision"); + + BIND_ENUM_CONSTANT(PARAM_LINEAR_LOWER_LIMIT); + BIND_ENUM_CONSTANT(PARAM_LINEAR_UPPER_LIMIT); + BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(PARAM_LINEAR_RESTITUTION); + BIND_ENUM_CONSTANT(PARAM_LINEAR_DAMPING); + BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_TARGET_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_FORCE_LIMIT); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_LOWER_LIMIT); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_UPPER_LIMIT); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_DAMPING); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_RESTITUTION); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_FORCE_LIMIT); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_ERP); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); + BIND_ENUM_CONSTANT(PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + BIND_ENUM_CONSTANT(PARAM_MAX); + + BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT); + BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_LIMIT); + BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_SPRING); + BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_SPRING); + BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR); + BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_MOTOR); + BIND_ENUM_CONSTANT(FLAG_MAX); +} + +void Generic6DOFJoint3D::set_param_x(Param p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params_x[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + + update_gizmo(); +} +float Generic6DOFJoint3D::get_param_x(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return params_x[p_param]; +} + +void Generic6DOFJoint3D::set_param_y(Param p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params_y[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + update_gizmo(); +} +float Generic6DOFJoint3D::get_param_y(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return params_y[p_param]; +} + +void Generic6DOFJoint3D::set_param_z(Param p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + params_z[p_param] = p_value; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + update_gizmo(); +} +float Generic6DOFJoint3D::get_param_z(Param p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return params_z[p_param]; +} + +void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) { + + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags_x[p_flag] = p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + update_gizmo(); +} +bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const { + + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags_x[p_flag]; +} + +void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) { + + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags_y[p_flag] = p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + update_gizmo(); +} +bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const { + + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags_y[p_flag]; +} + +void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) { + + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags_z[p_flag] = p_enabled; + if (get_joint().is_valid()) + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + update_gizmo(); +} +bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const { + + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags_z[p_flag]; +} + +void Generic6DOFJoint3D::set_precision(int p_precision) { + precision = p_precision; + + PhysicsServer::get_singleton()->generic_6dof_joint_set_precision( + get_joint(), + precision); +} + +RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { + + Transform gt = get_global_transform(); + //Vector3 cone_twistpos = gt.origin; + //Vector3 cone_twistdir = gt.basis.get_axis(2); + + Transform ainv = body_a->get_global_transform().affine_inverse(); + + Transform local_a = ainv * gt; + local_a.orthonormalize(); + Transform local_b = gt; + + if (body_b) { + Transform binv = body_b->get_global_transform().affine_inverse(); + local_b = binv * gt; + } + + local_b.orthonormalize(); + + RID j = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + for (int i = 0; i < PARAM_MAX; i++) { + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(i), params_x[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(i), params_y[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(i), params_z[i]); + } + for (int i = 0; i < FLAG_MAX; i++) { + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(i), flags_x[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(i), flags_y[i]); + PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(i), flags_z[i]); + } + + return j; +} + +Generic6DOFJoint3D::Generic6DOFJoint3D() : + precision(1) { + + set_param_x(PARAM_LINEAR_LOWER_LIMIT, 0); + set_param_x(PARAM_LINEAR_UPPER_LIMIT, 0); + set_param_x(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); + set_param_x(PARAM_LINEAR_RESTITUTION, 0.5); + set_param_x(PARAM_LINEAR_DAMPING, 1.0); + set_param_x(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); + set_param_x(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_x(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_x(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_x(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); + set_param_x(PARAM_ANGULAR_LOWER_LIMIT, 0); + set_param_x(PARAM_ANGULAR_UPPER_LIMIT, 0); + set_param_x(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); + set_param_x(PARAM_ANGULAR_DAMPING, 1.0f); + set_param_x(PARAM_ANGULAR_RESTITUTION, 0); + set_param_x(PARAM_ANGULAR_FORCE_LIMIT, 0); + set_param_x(PARAM_ANGULAR_ERP, 0.5); + set_param_x(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); + set_param_x(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_x(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_x(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_x(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); + + set_flag_x(FLAG_ENABLE_ANGULAR_LIMIT, true); + set_flag_x(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_x(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_x(FLAG_ENABLE_LINEAR_SPRING, false); + set_flag_x(FLAG_ENABLE_MOTOR, false); + set_flag_x(FLAG_ENABLE_LINEAR_MOTOR, false); + + set_param_y(PARAM_LINEAR_LOWER_LIMIT, 0); + set_param_y(PARAM_LINEAR_UPPER_LIMIT, 0); + set_param_y(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); + set_param_y(PARAM_LINEAR_RESTITUTION, 0.5); + set_param_y(PARAM_LINEAR_DAMPING, 1.0); + set_param_y(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); + set_param_y(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_y(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_y(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_y(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); + set_param_y(PARAM_ANGULAR_LOWER_LIMIT, 0); + set_param_y(PARAM_ANGULAR_UPPER_LIMIT, 0); + set_param_y(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); + set_param_y(PARAM_ANGULAR_DAMPING, 1.0f); + set_param_y(PARAM_ANGULAR_RESTITUTION, 0); + set_param_y(PARAM_ANGULAR_FORCE_LIMIT, 0); + set_param_y(PARAM_ANGULAR_ERP, 0.5); + set_param_y(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); + set_param_y(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_y(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_y(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_y(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); + + set_flag_y(FLAG_ENABLE_ANGULAR_LIMIT, true); + set_flag_y(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_y(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_y(FLAG_ENABLE_LINEAR_SPRING, false); + set_flag_y(FLAG_ENABLE_MOTOR, false); + set_flag_y(FLAG_ENABLE_LINEAR_MOTOR, false); + + set_param_z(PARAM_LINEAR_LOWER_LIMIT, 0); + set_param_z(PARAM_LINEAR_UPPER_LIMIT, 0); + set_param_z(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7); + set_param_z(PARAM_LINEAR_RESTITUTION, 0.5); + set_param_z(PARAM_LINEAR_DAMPING, 1.0); + set_param_z(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); + set_param_z(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_z(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_z(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_z(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); + set_param_z(PARAM_ANGULAR_LOWER_LIMIT, 0); + set_param_z(PARAM_ANGULAR_UPPER_LIMIT, 0); + set_param_z(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); + set_param_z(PARAM_ANGULAR_DAMPING, 1.0f); + set_param_z(PARAM_ANGULAR_RESTITUTION, 0); + set_param_z(PARAM_ANGULAR_FORCE_LIMIT, 0); + set_param_z(PARAM_ANGULAR_ERP, 0.5); + set_param_z(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); + set_param_z(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_z(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_z(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_z(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); + + set_flag_z(FLAG_ENABLE_ANGULAR_LIMIT, true); + set_flag_z(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_z(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_z(FLAG_ENABLE_LINEAR_SPRING, false); + set_flag_z(FLAG_ENABLE_MOTOR, false); + set_flag_z(FLAG_ENABLE_LINEAR_MOTOR, false); +} diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h new file mode 100644 index 0000000000..b7c131c666 --- /dev/null +++ b/scene/3d/physics_joint_3d.h @@ -0,0 +1,343 @@ +/*************************************************************************/ +/* physics_joint_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_JOINT_H +#define PHYSICS_JOINT_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; + bool exclude_from_collision; + +protected: + void _update_joint(bool p_only_free = false); + + void _notification(int p_what); + + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) = 0; + + static void _bind_methods(); + +public: + 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_joint() const { return joint; } + Joint3D(); +}; + +/////////////////////////////////////////// + +class PinJoint3D : public Joint3D { + + GDCLASS(PinJoint3D, Joint3D); + +public: + enum Param { + PARAM_BIAS = PhysicsServer::PIN_JOINT_BIAS, + PARAM_DAMPING = PhysicsServer::PIN_JOINT_DAMPING, + PARAM_IMPULSE_CLAMP = PhysicsServer::PIN_JOINT_IMPULSE_CLAMP + }; + +protected: + float params[3]; + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b); + static void _bind_methods(); + +public: + void set_param(Param p_param, float p_value); + float get_param(Param p_param) const; + + PinJoint3D(); +}; + +VARIANT_ENUM_CAST(PinJoint3D::Param); + +class HingeJoint3D : public Joint3D { + + GDCLASS(HingeJoint3D, Joint3D); + +public: + enum Param { + PARAM_BIAS = PhysicsServer::HINGE_JOINT_BIAS, + PARAM_LIMIT_UPPER = PhysicsServer::HINGE_JOINT_LIMIT_UPPER, + PARAM_LIMIT_LOWER = PhysicsServer::HINGE_JOINT_LIMIT_LOWER, + PARAM_LIMIT_BIAS = PhysicsServer::HINGE_JOINT_LIMIT_BIAS, + PARAM_LIMIT_SOFTNESS = PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, + PARAM_LIMIT_RELAXATION = PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, + PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY, + PARAM_MOTOR_MAX_IMPULSE = PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE, + PARAM_MAX = PhysicsServer::HINGE_JOINT_MAX + }; + + enum Flag { + FLAG_USE_LIMIT = PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, + FLAG_ENABLE_MOTOR = PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR, + FLAG_MAX = PhysicsServer::HINGE_JOINT_FLAG_MAX + }; + +protected: + float params[PARAM_MAX]; + bool flags[FLAG_MAX]; + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b); + static void _bind_methods(); + + void _set_upper_limit(float p_limit); + float _get_upper_limit() const; + + void _set_lower_limit(float p_limit); + float _get_lower_limit() const; + +public: + void set_param(Param p_param, float p_value); + float 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 = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, + PARAM_LINEAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, + PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, + PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, + PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, + PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, + PARAM_LINEAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING, + PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, + PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, + PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, + + PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, + PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, + PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, + PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, + PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, + PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, + PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING, + PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, + PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, + PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, + PARAM_MAX = PhysicsServer::SLIDER_JOINT_MAX + + }; + +protected: + void _set_upper_limit_angular(float p_limit_angular); + float _get_upper_limit_angular() const; + + void _set_lower_limit_angular(float p_limit_angular); + float _get_lower_limit_angular() const; + + float params[PARAM_MAX]; + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b); + static void _bind_methods(); + +public: + void set_param(Param p_param, float p_value); + float 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: + void _set_swing_span(float p_limit_angular); + float _get_swing_span() const; + + void _set_twist_span(float p_limit_angular); + float _get_twist_span() const; + + float params[PARAM_MAX]; + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b); + static void _bind_methods(); + +public: + void set_param(Param p_param, float p_value); + float 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 = PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, + PARAM_LINEAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, + PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, + PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, + PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, + PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, + PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, + PARAM_LINEAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, + PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, + PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, + PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, + PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, + PARAM_ANGULAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, + PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT, + PARAM_ANGULAR_ERP = PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, + PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, + PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, + PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, + PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, + PARAM_MAX = PhysicsServer::G6DOF_JOINT_MAX, + }; + + enum Flag { + FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, + FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + FLAG_ENABLE_LINEAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, + FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, + FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR, + FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, + FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX + }; + +protected: + void _set_angular_hi_limit_x(float p_limit_angular); + float _get_angular_hi_limit_x() const; + + void _set_angular_hi_limit_y(float p_limit_angular); + float _get_angular_hi_limit_y() const; + + void _set_angular_hi_limit_z(float p_limit_angular); + float _get_angular_hi_limit_z() const; + + void _set_angular_lo_limit_x(float p_limit_angular); + float _get_angular_lo_limit_x() const; + + void _set_angular_lo_limit_y(float p_limit_angular); + float _get_angular_lo_limit_y() const; + + void _set_angular_lo_limit_z(float p_limit_angular); + float _get_angular_lo_limit_z() const; + + float params_x[PARAM_MAX]; + bool flags_x[FLAG_MAX]; + float params_y[PARAM_MAX]; + bool flags_y[FLAG_MAX]; + float params_z[PARAM_MAX]; + bool flags_z[FLAG_MAX]; + + int precision; + + virtual RID _configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b); + static void _bind_methods(); + +public: + void set_param_x(Param p_param, float p_value); + float get_param_x(Param p_param) const; + + void set_param_y(Param p_param, float p_value); + float get_param_y(Param p_param) const; + + void set_param_z(Param p_param, float p_value); + float 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; + + void set_precision(int p_precision); + int get_precision() const { + return precision; + } + + Generic6DOFJoint3D(); +}; + +VARIANT_ENUM_CAST(Generic6DOFJoint3D::Param); +VARIANT_ENUM_CAST(Generic6DOFJoint3D::Flag); + +#endif // PHYSICS_JOINT_H diff --git a/scene/3d/position_3d.h b/scene/3d/position_3d.h index cd5080c95a..9c806723fb 100644 --- a/scene/3d/position_3d.h +++ b/scene/3d/position_3d.h @@ -31,11 +31,11 @@ #ifndef POSITION_3D_H #define POSITION_3D_H -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" -class Position3D : public Spatial { +class Position3D : public Node3D { - GDCLASS(Position3D, Spatial); + GDCLASS(Position3D, Node3D); public: Position3D(); diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp deleted file mode 100644 index 2e1478b1cf..0000000000 --- a/scene/3d/proximity_group.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/*************************************************************************/ -/* proximity_group.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "proximity_group.h" - -#include "core/math/math_funcs.h" - -void ProximityGroup::clear_groups() { - - Map::Element *E; - - { - const int size = 16; - StringName remove_list[size]; - E = groups.front(); - int num = 0; - while (E && num < size) { - - if (E->get() != group_version) { - remove_list[num++] = E->key(); - }; - - E = E->next(); - }; - for (int i = 0; i < num; i++) { - - groups.erase(remove_list[i]); - }; - }; - - if (E) { - clear_groups(); // call until we go through the whole list - }; -}; - -void ProximityGroup::update_groups() { - - if (grid_radius == Vector3(0, 0, 0)) - return; - - ++group_version; - - Vector3 pos = get_global_transform().get_origin(); - Vector3 vcell = pos / cell_size; - int cell[3] = { Math::fast_ftoi(vcell.x), Math::fast_ftoi(vcell.y), Math::fast_ftoi(vcell.z) }; - - add_groups(cell, group_name, 0); - - clear_groups(); -}; - -void ProximityGroup::add_groups(int *p_cell, String p_base, int p_depth) { - - p_base = p_base + "|"; - if (grid_radius[p_depth] == 0) { - - if (p_depth == 2) { - _new_group(p_base); - } else { - add_groups(p_cell, p_base, p_depth + 1); - }; - }; - - int start = p_cell[p_depth] - grid_radius[p_depth]; - int end = p_cell[p_depth] + grid_radius[p_depth]; - - for (int i = start; i <= end; i++) { - - String gname = p_base + itos(i); - if (p_depth == 2) { - _new_group(gname); - } else { - add_groups(p_cell, gname, p_depth + 1); - }; - }; -}; - -void ProximityGroup::_new_group(StringName p_name) { - - const Map::Element *E = groups.find(p_name); - if (!E) { - add_to_group(p_name); - }; - - groups[p_name] = group_version; -}; - -void ProximityGroup::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_EXIT_TREE: - ++group_version; - clear_groups(); - break; - case NOTIFICATION_TRANSFORM_CHANGED: - update_groups(); - break; - }; -}; - -void ProximityGroup::broadcast(String p_name, Variant p_params) { - - Map::Element *E; - E = groups.front(); - while (E) { - - get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params); - E = E->next(); - }; -}; - -void ProximityGroup::_proximity_group_broadcast(String p_name, Variant p_params) { - - if (dispatch_mode == MODE_PROXY) { - - get_parent()->call(p_name, p_params); - } else { - - emit_signal("broadcast", p_name, p_params); - }; -}; - -void ProximityGroup::set_group_name(const String &p_group_name) { - - group_name = p_group_name; -}; - -String ProximityGroup::get_group_name() const { - - return group_name; -}; - -void ProximityGroup::set_dispatch_mode(DispatchMode p_mode) { - - dispatch_mode = p_mode; -}; - -ProximityGroup::DispatchMode ProximityGroup::get_dispatch_mode() const { - - return dispatch_mode; -}; - -void ProximityGroup::set_grid_radius(const Vector3 &p_radius) { - - grid_radius = p_radius; -}; - -Vector3 ProximityGroup::get_grid_radius() const { - - return grid_radius; -}; - -void ProximityGroup::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_group_name", "name"), &ProximityGroup::set_group_name); - ClassDB::bind_method(D_METHOD("get_group_name"), &ProximityGroup::get_group_name); - ClassDB::bind_method(D_METHOD("set_dispatch_mode", "mode"), &ProximityGroup::set_dispatch_mode); - ClassDB::bind_method(D_METHOD("get_dispatch_mode"), &ProximityGroup::get_dispatch_mode); - ClassDB::bind_method(D_METHOD("set_grid_radius", "radius"), &ProximityGroup::set_grid_radius); - ClassDB::bind_method(D_METHOD("get_grid_radius"), &ProximityGroup::get_grid_radius); - ClassDB::bind_method(D_METHOD("broadcast", "name", "parameters"), &ProximityGroup::broadcast); - ClassDB::bind_method(D_METHOD("_proximity_group_broadcast", "name", "params"), &ProximityGroup::_proximity_group_broadcast); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "group_name"), "set_group_name", "get_group_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dispatch_mode", PROPERTY_HINT_ENUM, "Proxy,Signal"), "set_dispatch_mode", "get_dispatch_mode"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "grid_radius"), "set_grid_radius", "get_grid_radius"); - - ADD_SIGNAL(MethodInfo("broadcast", PropertyInfo(Variant::STRING, "group_name"), PropertyInfo(Variant::ARRAY, "parameters"))); - - BIND_ENUM_CONSTANT(MODE_PROXY); - BIND_ENUM_CONSTANT(MODE_SIGNAL); -}; - -ProximityGroup::ProximityGroup() { - - group_version = 0; - dispatch_mode = MODE_PROXY; - - cell_size = 1.0; - grid_radius = Vector3(1, 1, 1); - set_notify_transform(true); -}; - -ProximityGroup::~ProximityGroup(){ - -}; diff --git a/scene/3d/proximity_group.h b/scene/3d/proximity_group.h deleted file mode 100644 index 9ff8853178..0000000000 --- a/scene/3d/proximity_group.h +++ /dev/null @@ -1,87 +0,0 @@ -/*************************************************************************/ -/* proximity_group.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PROXIMITY_GROUP_H -#define PROXIMITY_GROUP_H - -#include "spatial.h" - -class ProximityGroup : public Spatial { - - GDCLASS(ProximityGroup, Spatial); - OBJ_CATEGORY("3D"); - -public: - enum DispatchMode { - MODE_PROXY, - MODE_SIGNAL, - }; - -public: - void clear_groups(); - void update_groups(); - - void _notification(int p_what); - - DispatchMode dispatch_mode; - - Map groups; - String group_name; - - float cell_size; - Vector3 grid_radius; - uint32_t group_version; - - void add_groups(int *p_cell, String p_base, int p_depth); - void _new_group(StringName p_name); - - void _proximity_group_broadcast(String p_name, Variant p_params); - - static void _bind_methods(); - -public: - void set_group_name(const String &p_group_name); - String get_group_name() const; - - void set_dispatch_mode(DispatchMode p_mode); - DispatchMode get_dispatch_mode() const; - - void set_grid_radius(const Vector3 &p_radius); - Vector3 get_grid_radius() const; - - void broadcast(String p_name, Variant p_params); - - ProximityGroup(); - ~ProximityGroup(); -}; - -VARIANT_ENUM_CAST(ProximityGroup::DispatchMode); - -#endif diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp new file mode 100644 index 0000000000..44ffabb655 --- /dev/null +++ b/scene/3d/proximity_group_3d.cpp @@ -0,0 +1,214 @@ +/*************************************************************************/ +/* proximity_group_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "proximity_group_3d.h" + +#include "core/math/math_funcs.h" + +void ProximityGroup3D::clear_groups() { + + Map::Element *E; + + { + const int size = 16; + StringName remove_list[size]; + E = groups.front(); + int num = 0; + while (E && num < size) { + + if (E->get() != group_version) { + remove_list[num++] = E->key(); + }; + + E = E->next(); + }; + for (int i = 0; i < num; i++) { + + groups.erase(remove_list[i]); + }; + }; + + if (E) { + clear_groups(); // call until we go through the whole list + }; +}; + +void ProximityGroup3D::update_groups() { + + if (grid_radius == Vector3(0, 0, 0)) + return; + + ++group_version; + + Vector3 pos = get_global_transform().get_origin(); + Vector3 vcell = pos / cell_size; + int cell[3] = { Math::fast_ftoi(vcell.x), Math::fast_ftoi(vcell.y), Math::fast_ftoi(vcell.z) }; + + add_groups(cell, group_name, 0); + + clear_groups(); +}; + +void ProximityGroup3D::add_groups(int *p_cell, String p_base, int p_depth) { + + p_base = p_base + "|"; + if (grid_radius[p_depth] == 0) { + + if (p_depth == 2) { + _new_group(p_base); + } else { + add_groups(p_cell, p_base, p_depth + 1); + }; + }; + + int start = p_cell[p_depth] - grid_radius[p_depth]; + int end = p_cell[p_depth] + grid_radius[p_depth]; + + for (int i = start; i <= end; i++) { + + String gname = p_base + itos(i); + if (p_depth == 2) { + _new_group(gname); + } else { + add_groups(p_cell, gname, p_depth + 1); + }; + }; +}; + +void ProximityGroup3D::_new_group(StringName p_name) { + + const Map::Element *E = groups.find(p_name); + if (!E) { + add_to_group(p_name); + }; + + groups[p_name] = group_version; +}; + +void ProximityGroup3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_EXIT_TREE: + ++group_version; + clear_groups(); + break; + case NOTIFICATION_TRANSFORM_CHANGED: + update_groups(); + break; + }; +}; + +void ProximityGroup3D::broadcast(String p_name, Variant p_params) { + + Map::Element *E; + E = groups.front(); + while (E) { + + get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params); + E = E->next(); + }; +}; + +void ProximityGroup3D::_proximity_group_broadcast(String p_name, Variant p_params) { + + if (dispatch_mode == MODE_PROXY) { + + get_parent()->call(p_name, p_params); + } else { + + emit_signal("broadcast", p_name, p_params); + }; +}; + +void ProximityGroup3D::set_group_name(const String &p_group_name) { + + group_name = p_group_name; +}; + +String ProximityGroup3D::get_group_name() const { + + return group_name; +}; + +void ProximityGroup3D::set_dispatch_mode(DispatchMode p_mode) { + + dispatch_mode = p_mode; +}; + +ProximityGroup3D::DispatchMode ProximityGroup3D::get_dispatch_mode() const { + + return dispatch_mode; +}; + +void ProximityGroup3D::set_grid_radius(const Vector3 &p_radius) { + + grid_radius = p_radius; +}; + +Vector3 ProximityGroup3D::get_grid_radius() const { + + return grid_radius; +}; + +void ProximityGroup3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_group_name", "name"), &ProximityGroup3D::set_group_name); + ClassDB::bind_method(D_METHOD("get_group_name"), &ProximityGroup3D::get_group_name); + ClassDB::bind_method(D_METHOD("set_dispatch_mode", "mode"), &ProximityGroup3D::set_dispatch_mode); + ClassDB::bind_method(D_METHOD("get_dispatch_mode"), &ProximityGroup3D::get_dispatch_mode); + ClassDB::bind_method(D_METHOD("set_grid_radius", "radius"), &ProximityGroup3D::set_grid_radius); + ClassDB::bind_method(D_METHOD("get_grid_radius"), &ProximityGroup3D::get_grid_radius); + ClassDB::bind_method(D_METHOD("broadcast", "name", "parameters"), &ProximityGroup3D::broadcast); + ClassDB::bind_method(D_METHOD("_proximity_group_broadcast", "name", "params"), &ProximityGroup3D::_proximity_group_broadcast); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "group_name"), "set_group_name", "get_group_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "dispatch_mode", PROPERTY_HINT_ENUM, "Proxy,Signal"), "set_dispatch_mode", "get_dispatch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "grid_radius"), "set_grid_radius", "get_grid_radius"); + + ADD_SIGNAL(MethodInfo("broadcast", PropertyInfo(Variant::STRING, "group_name"), PropertyInfo(Variant::ARRAY, "parameters"))); + + BIND_ENUM_CONSTANT(MODE_PROXY); + BIND_ENUM_CONSTANT(MODE_SIGNAL); +}; + +ProximityGroup3D::ProximityGroup3D() { + + group_version = 0; + dispatch_mode = MODE_PROXY; + + cell_size = 1.0; + grid_radius = Vector3(1, 1, 1); + set_notify_transform(true); +}; + +ProximityGroup3D::~ProximityGroup3D(){ + +}; diff --git a/scene/3d/proximity_group_3d.h b/scene/3d/proximity_group_3d.h new file mode 100644 index 0000000000..751bfbdb52 --- /dev/null +++ b/scene/3d/proximity_group_3d.h @@ -0,0 +1,87 @@ +/*************************************************************************/ +/* proximity_group_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PROXIMITY_GROUP_H +#define PROXIMITY_GROUP_H + +#include "node_3d.h" + +class ProximityGroup3D : public Node3D { + + GDCLASS(ProximityGroup3D, Node3D); + OBJ_CATEGORY("3D"); + +public: + enum DispatchMode { + MODE_PROXY, + MODE_SIGNAL, + }; + +public: + void clear_groups(); + void update_groups(); + + void _notification(int p_what); + + DispatchMode dispatch_mode; + + Map groups; + String group_name; + + float cell_size; + Vector3 grid_radius; + uint32_t group_version; + + void add_groups(int *p_cell, String p_base, int p_depth); + void _new_group(StringName p_name); + + void _proximity_group_broadcast(String p_name, Variant p_params); + + static void _bind_methods(); + +public: + void set_group_name(const String &p_group_name); + String get_group_name() const; + + void set_dispatch_mode(DispatchMode p_mode); + DispatchMode get_dispatch_mode() const; + + void set_grid_radius(const Vector3 &p_radius); + Vector3 get_grid_radius() const; + + void broadcast(String p_name, Variant p_params); + + ProximityGroup3D(); + ~ProximityGroup3D(); +}; + +VARIANT_ENUM_CAST(ProximityGroup3D::DispatchMode); + +#endif diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp deleted file mode 100644 index f6eb3d954a..0000000000 --- a/scene/3d/ray_cast.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/*************************************************************************/ -/* ray_cast.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "ray_cast.h" - -#include "collision_object.h" -#include "core/engine.h" -#include "mesh_instance.h" -#include "servers/physics_server.h" - -void RayCast::set_cast_to(const Vector3 &p_point) { - - cast_to = p_point; - if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) - update_gizmo(); - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) - _update_debug_shape(); -} - -Vector3 RayCast::get_cast_to() const { - - return cast_to; -} - -void RayCast::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; -} - -uint32_t RayCast::get_collision_mask() const { - - return collision_mask; -} - -void RayCast::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool RayCast::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -bool RayCast::is_colliding() const { - - return collided; -} -Object *RayCast::get_collider() const { - - if (against.is_null()) - return NULL; - - return ObjectDB::get_instance(against); -} - -int RayCast::get_collider_shape() const { - - return against_shape; -} -Vector3 RayCast::get_collision_point() const { - - return collision_point; -} -Vector3 RayCast::get_collision_normal() const { - - return collision_normal; -} - -void RayCast::set_enabled(bool p_enabled) { - - enabled = p_enabled; - update_gizmo(); - - if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) - set_physics_process_internal(p_enabled); - if (!p_enabled) - collided = false; - - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { - if (p_enabled) - _update_debug_shape(); - else - _clear_debug_shape(); - } -} - -bool RayCast::is_enabled() const { - - return enabled; -} - -void RayCast::set_exclude_parent_body(bool p_exclude_parent_body) { - - if (exclude_parent_body == p_exclude_parent_body) - return; - - exclude_parent_body = p_exclude_parent_body; - - if (!is_inside_tree()) - return; - - if (Object::cast_to(get_parent())) { - if (exclude_parent_body) - exclude.insert(Object::cast_to(get_parent())->get_rid()); - else - exclude.erase(Object::cast_to(get_parent())->get_rid()); - } -} - -bool RayCast::get_exclude_parent_body() const { - - return exclude_parent_body; -} - -void RayCast::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - if (enabled && !Engine::get_singleton()->is_editor_hint()) { - set_physics_process_internal(true); - - if (get_tree()->is_debugging_collisions_hint()) - _update_debug_shape(); - } else - set_physics_process_internal(false); - - if (Object::cast_to(get_parent())) { - if (exclude_parent_body) - exclude.insert(Object::cast_to(get_parent())->get_rid()); - else - exclude.erase(Object::cast_to(get_parent())->get_rid()); - } - - } break; - case NOTIFICATION_EXIT_TREE: { - - if (enabled) { - set_physics_process_internal(false); - } - - if (debug_shape) - _clear_debug_shape(); - - } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - - if (!enabled) - break; - - bool prev_collision_state = collided; - _update_raycast_state(); - if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) { - if (debug_material.is_valid()) { - Ref line_material = static_cast>(debug_material); - line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6)); - } - } - - } break; - } -} - -void RayCast::_update_raycast_state() { - Ref w3d = get_world(); - ERR_FAIL_COND(w3d.is_null()); - - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); - ERR_FAIL_COND(!dss); - - Transform gt = get_global_transform(); - - Vector3 to = cast_to; - if (to == Vector3()) - to = Vector3(0, 0.01, 0); - - PhysicsDirectSpaceState::RayResult rr; - - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { - - collided = true; - against = rr.collider_id; - collision_point = rr.position; - collision_normal = rr.normal; - against_shape = rr.shape; - } else { - collided = false; - against = ObjectID(); - against_shape = 0; - } -} - -void RayCast::force_raycast_update() { - _update_raycast_state(); -} - -void RayCast::add_exception_rid(const RID &p_rid) { - - exclude.insert(p_rid); -} - -void RayCast::add_exception(const Object *p_object) { - - ERR_FAIL_NULL(p_object); - const CollisionObject *co = Object::cast_to(p_object); - if (!co) - return; - add_exception_rid(co->get_rid()); -} - -void RayCast::remove_exception_rid(const RID &p_rid) { - - exclude.erase(p_rid); -} - -void RayCast::remove_exception(const Object *p_object) { - - ERR_FAIL_NULL(p_object); - const CollisionObject *co = Object::cast_to(p_object); - if (!co) - return; - remove_exception_rid(co->get_rid()); -} - -void RayCast::clear_exceptions() { - - exclude.clear(); -} - -void RayCast::set_collide_with_areas(bool p_clip) { - - collide_with_areas = p_clip; -} - -bool RayCast::is_collide_with_areas_enabled() const { - - return collide_with_areas; -} - -void RayCast::set_collide_with_bodies(bool p_clip) { - - collide_with_bodies = p_clip; -} - -bool RayCast::is_collide_with_bodies_enabled() const { - - return collide_with_bodies; -} - -void RayCast::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast::set_enabled); - ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast::is_enabled); - - ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast::set_cast_to); - ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast::get_cast_to); - - ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast::is_colliding); - ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast::force_raycast_update); - - ClassDB::bind_method(D_METHOD("get_collider"), &RayCast::get_collider); - ClassDB::bind_method(D_METHOD("get_collider_shape"), &RayCast::get_collider_shape); - ClassDB::bind_method(D_METHOD("get_collision_point"), &RayCast::get_collision_point); - ClassDB::bind_method(D_METHOD("get_collision_normal"), &RayCast::get_collision_normal); - - ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &RayCast::add_exception_rid); - ClassDB::bind_method(D_METHOD("add_exception", "node"), &RayCast::add_exception); - - ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &RayCast::remove_exception_rid); - ClassDB::bind_method(D_METHOD("remove_exception", "node"), &RayCast::remove_exception); - - ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast::clear_exceptions); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &RayCast::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &RayCast::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &RayCast::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &RayCast::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &RayCast::set_exclude_parent_body); - ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &RayCast::get_exclude_parent_body); - - ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &RayCast::set_collide_with_areas); - ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &RayCast::is_collide_with_areas_enabled); - - ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast::set_collide_with_bodies); - ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast::is_collide_with_bodies_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - - ADD_GROUP("Collide With", "collide_with"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); -} - -void RayCast::_create_debug_shape() { - - if (!debug_material.is_valid()) { - debug_material = Ref(memnew(StandardMaterial3D)); - - Ref line_material = static_cast>(debug_material); - line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - line_material->set_albedo(Color(1.0, 0.8, 0.6)); - } - - Ref mesh = memnew(ArrayMesh); - - MeshInstance *mi = memnew(MeshInstance); - mi->set_mesh(mesh); - - add_child(mi); - debug_shape = mi; -} - -void RayCast::_update_debug_shape() { - - if (!enabled) - return; - - if (!debug_shape) - _create_debug_shape(); - - MeshInstance *mi = static_cast(debug_shape); - if (!mi->get_mesh().is_valid()) - return; - - Ref mesh = mi->get_mesh(); - mesh->clear_surfaces(); - - Array a; - a.resize(Mesh::ARRAY_MAX); - - Vector verts; - verts.push_back(Vector3()); - verts.push_back(cast_to); - a[Mesh::ARRAY_VERTEX] = verts; - - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); - mesh->surface_set_material(0, debug_material); -} - -void RayCast::_clear_debug_shape() { - - if (!debug_shape) - return; - - MeshInstance *mi = static_cast(debug_shape); - if (mi->is_inside_tree()) - mi->queue_delete(); - else - memdelete(mi); - - debug_shape = NULL; -} - -RayCast::RayCast() { - - enabled = false; - - collided = false; - against_shape = 0; - collision_mask = 1; - cast_to = Vector3(0, -1, 0); - debug_shape = NULL; - exclude_parent_body = true; - collide_with_areas = false; - collide_with_bodies = true; -} diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h deleted file mode 100644 index 5cebfe3ac2..0000000000 --- a/scene/3d/ray_cast.h +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************/ -/* ray_cast.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RAY_CAST_H -#define RAY_CAST_H - -#include "scene/3d/spatial.h" - -class RayCast : public Spatial { - - GDCLASS(RayCast, Spatial); - - bool enabled; - bool collided; - ObjectID against; - int against_shape; - Vector3 collision_point; - Vector3 collision_normal; - - Vector3 cast_to; - Set exclude; - - uint32_t collision_mask; - bool exclude_parent_body; - - Node *debug_shape; - Ref debug_material; - - void _create_debug_shape(); - void _update_debug_shape(); - void _clear_debug_shape(); - - bool collide_with_areas; - bool collide_with_bodies; - -protected: - void _notification(int p_what); - void _update_raycast_state(); - static void _bind_methods(); - -public: - void set_collide_with_areas(bool p_clip); - bool is_collide_with_areas_enabled() const; - - void set_collide_with_bodies(bool p_clip); - bool is_collide_with_bodies_enabled() const; - - void set_enabled(bool p_enabled); - bool is_enabled() const; - - void set_cast_to(const Vector3 &p_point); - Vector3 get_cast_to() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - void set_exclude_parent_body(bool p_exclude_parent_body); - bool get_exclude_parent_body() const; - - void force_raycast_update(); - bool is_colliding() const; - Object *get_collider() const; - int get_collider_shape() const; - Vector3 get_collision_point() const; - Vector3 get_collision_normal() const; - - void add_exception_rid(const RID &p_rid); - void add_exception(const Object *p_object); - void remove_exception_rid(const RID &p_rid); - void remove_exception(const Object *p_object); - void clear_exceptions(); - - RayCast(); -}; - -#endif // RAY_CAST_H diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp new file mode 100644 index 0000000000..578b9c0170 --- /dev/null +++ b/scene/3d/ray_cast_3d.cpp @@ -0,0 +1,405 @@ +/*************************************************************************/ +/* ray_cast_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ray_cast_3d.h" + +#include "collision_object_3d.h" +#include "core/engine.h" +#include "mesh_instance_3d.h" +#include "servers/physics_server.h" + +void RayCast3D::set_cast_to(const Vector3 &p_point) { + + cast_to = p_point; + if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) + update_gizmo(); + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) + _update_debug_shape(); +} + +Vector3 RayCast3D::get_cast_to() const { + + return cast_to; +} + +void RayCast3D::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; +} + +uint32_t RayCast3D::get_collision_mask() const { + + return collision_mask; +} + +void RayCast3D::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool RayCast3D::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +bool RayCast3D::is_colliding() const { + + return collided; +} +Object *RayCast3D::get_collider() const { + + if (against.is_null()) + return NULL; + + return ObjectDB::get_instance(against); +} + +int RayCast3D::get_collider_shape() const { + + return against_shape; +} +Vector3 RayCast3D::get_collision_point() const { + + return collision_point; +} +Vector3 RayCast3D::get_collision_normal() const { + + return collision_normal; +} + +void RayCast3D::set_enabled(bool p_enabled) { + + enabled = p_enabled; + update_gizmo(); + + if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) + set_physics_process_internal(p_enabled); + if (!p_enabled) + collided = false; + + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { + if (p_enabled) + _update_debug_shape(); + else + _clear_debug_shape(); + } +} + +bool RayCast3D::is_enabled() const { + + return enabled; +} + +void RayCast3D::set_exclude_parent_body(bool p_exclude_parent_body) { + + if (exclude_parent_body == p_exclude_parent_body) + return; + + exclude_parent_body = p_exclude_parent_body; + + if (!is_inside_tree()) + return; + + if (Object::cast_to(get_parent())) { + if (exclude_parent_body) + exclude.insert(Object::cast_to(get_parent())->get_rid()); + else + exclude.erase(Object::cast_to(get_parent())->get_rid()); + } +} + +bool RayCast3D::get_exclude_parent_body() const { + + return exclude_parent_body; +} + +void RayCast3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + if (enabled && !Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + + if (get_tree()->is_debugging_collisions_hint()) + _update_debug_shape(); + } else + set_physics_process_internal(false); + + if (Object::cast_to(get_parent())) { + if (exclude_parent_body) + exclude.insert(Object::cast_to(get_parent())->get_rid()); + else + exclude.erase(Object::cast_to(get_parent())->get_rid()); + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + if (enabled) { + set_physics_process_internal(false); + } + + if (debug_shape) + _clear_debug_shape(); + + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + + if (!enabled) + break; + + bool prev_collision_state = collided; + _update_raycast_state(); + if (prev_collision_state != collided && get_tree()->is_debugging_collisions_hint()) { + if (debug_material.is_valid()) { + Ref line_material = static_cast>(debug_material); + line_material->set_albedo(collided ? Color(1.0, 0, 0) : Color(1.0, 0.8, 0.6)); + } + } + + } break; + } +} + +void RayCast3D::_update_raycast_state() { + Ref w3d = get_world(); + ERR_FAIL_COND(w3d.is_null()); + + PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); + ERR_FAIL_COND(!dss); + + Transform gt = get_global_transform(); + + Vector3 to = cast_to; + if (to == Vector3()) + to = Vector3(0, 0.01, 0); + + PhysicsDirectSpaceState::RayResult rr; + + if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { + + collided = true; + against = rr.collider_id; + collision_point = rr.position; + collision_normal = rr.normal; + against_shape = rr.shape; + } else { + collided = false; + against = ObjectID(); + against_shape = 0; + } +} + +void RayCast3D::force_raycast_update() { + _update_raycast_state(); +} + +void RayCast3D::add_exception_rid(const RID &p_rid) { + + exclude.insert(p_rid); +} + +void RayCast3D::add_exception(const Object *p_object) { + + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to(p_object); + if (!co) + return; + add_exception_rid(co->get_rid()); +} + +void RayCast3D::remove_exception_rid(const RID &p_rid) { + + exclude.erase(p_rid); +} + +void RayCast3D::remove_exception(const Object *p_object) { + + ERR_FAIL_NULL(p_object); + const CollisionObject3D *co = Object::cast_to(p_object); + if (!co) + return; + remove_exception_rid(co->get_rid()); +} + +void RayCast3D::clear_exceptions() { + + exclude.clear(); +} + +void RayCast3D::set_collide_with_areas(bool p_clip) { + + collide_with_areas = p_clip; +} + +bool RayCast3D::is_collide_with_areas_enabled() const { + + return collide_with_areas; +} + +void RayCast3D::set_collide_with_bodies(bool p_clip) { + + collide_with_bodies = p_clip; +} + +bool RayCast3D::is_collide_with_bodies_enabled() const { + + return collide_with_bodies; +} + +void RayCast3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled); + + ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast3D::set_cast_to); + ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast3D::get_cast_to); + + ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast3D::is_colliding); + ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast3D::force_raycast_update); + + ClassDB::bind_method(D_METHOD("get_collider"), &RayCast3D::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_shape"), &RayCast3D::get_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_point"), &RayCast3D::get_collision_point); + ClassDB::bind_method(D_METHOD("get_collision_normal"), &RayCast3D::get_collision_normal); + + ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &RayCast3D::add_exception_rid); + ClassDB::bind_method(D_METHOD("add_exception", "node"), &RayCast3D::add_exception); + + ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &RayCast3D::remove_exception_rid); + ClassDB::bind_method(D_METHOD("remove_exception", "node"), &RayCast3D::remove_exception); + + ClassDB::bind_method(D_METHOD("clear_exceptions"), &RayCast3D::clear_exceptions); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &RayCast3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &RayCast3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &RayCast3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &RayCast3D::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &RayCast3D::set_exclude_parent_body); + ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &RayCast3D::get_exclude_parent_body); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &RayCast3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &RayCast3D::is_collide_with_areas_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast3D::is_collide_with_bodies_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Collide With", "collide_with"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); +} + +void RayCast3D::_create_debug_shape() { + + if (!debug_material.is_valid()) { + debug_material = Ref(memnew(StandardMaterial3D)); + + Ref line_material = static_cast>(debug_material); + line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + line_material->set_albedo(Color(1.0, 0.8, 0.6)); + } + + Ref mesh = memnew(ArrayMesh); + + MeshInstance3D *mi = memnew(MeshInstance3D); + mi->set_mesh(mesh); + + add_child(mi); + debug_shape = mi; +} + +void RayCast3D::_update_debug_shape() { + + if (!enabled) + return; + + if (!debug_shape) + _create_debug_shape(); + + MeshInstance3D *mi = static_cast(debug_shape); + if (!mi->get_mesh().is_valid()) + return; + + Ref mesh = mi->get_mesh(); + mesh->clear_surfaces(); + + Array a; + a.resize(Mesh::ARRAY_MAX); + + Vector verts; + verts.push_back(Vector3()); + verts.push_back(cast_to); + a[Mesh::ARRAY_VERTEX] = verts; + + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); + mesh->surface_set_material(0, debug_material); +} + +void RayCast3D::_clear_debug_shape() { + + if (!debug_shape) + return; + + MeshInstance3D *mi = static_cast(debug_shape); + if (mi->is_inside_tree()) + mi->queue_delete(); + else + memdelete(mi); + + debug_shape = NULL; +} + +RayCast3D::RayCast3D() { + + enabled = false; + + collided = false; + against_shape = 0; + collision_mask = 1; + cast_to = Vector3(0, -1, 0); + debug_shape = NULL; + exclude_parent_body = true; + collide_with_areas = false; + collide_with_bodies = true; +} diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h new file mode 100644 index 0000000000..f8bfb7846a --- /dev/null +++ b/scene/3d/ray_cast_3d.h @@ -0,0 +1,106 @@ +/*************************************************************************/ +/* ray_cast_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RAY_CAST_3D_H +#define RAY_CAST_3D_H + +#include "scene/3d/node_3d.h" + +class RayCast3D : public Node3D { + + GDCLASS(RayCast3D, Node3D); + + bool enabled; + bool collided; + ObjectID against; + int against_shape; + Vector3 collision_point; + Vector3 collision_normal; + + Vector3 cast_to; + Set exclude; + + uint32_t collision_mask; + bool exclude_parent_body; + + Node *debug_shape; + Ref debug_material; + + void _create_debug_shape(); + void _update_debug_shape(); + void _clear_debug_shape(); + + bool collide_with_areas; + bool collide_with_bodies; + +protected: + void _notification(int p_what); + void _update_raycast_state(); + static void _bind_methods(); + +public: + void set_collide_with_areas(bool p_clip); + bool is_collide_with_areas_enabled() const; + + void set_collide_with_bodies(bool p_clip); + bool is_collide_with_bodies_enabled() const; + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_cast_to(const Vector3 &p_point); + Vector3 get_cast_to() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_exclude_parent_body(bool p_exclude_parent_body); + bool get_exclude_parent_body() const; + + void force_raycast_update(); + bool is_colliding() const; + Object *get_collider() const; + int get_collider_shape() const; + Vector3 get_collision_point() const; + Vector3 get_collision_normal() const; + + void add_exception_rid(const RID &p_rid); + void add_exception(const Object *p_object); + void remove_exception_rid(const RID &p_rid); + void remove_exception(const Object *p_object); + void clear_exceptions(); + + RayCast3D(); +}; + +#endif // RAY_CAST_H diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 57c1b0a320..9cc0c3e8c7 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -31,13 +31,13 @@ #ifndef REFLECTIONPROBE_H #define REFLECTIONPROBE_H -#include "scene/3d/visual_instance.h" +#include "scene/3d/visual_instance_3d.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" #include "servers/visual_server.h" -class ReflectionProbe : public VisualInstance { - GDCLASS(ReflectionProbe, VisualInstance); +class ReflectionProbe : public VisualInstance3D { + GDCLASS(ReflectionProbe, VisualInstance3D); public: enum UpdateMode { diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp deleted file mode 100644 index 9ef43647ba..0000000000 --- a/scene/3d/remote_transform.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/*************************************************************************/ -/* remote_transform.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "remote_transform.h" - -void RemoteTransform::_update_cache() { - cache = ObjectID(); - if (has_node(remote_node)) { - Node *node = get_node(remote_node); - if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) { - return; - } - - cache = node->get_instance_id(); - } -} - -void RemoteTransform::_update_remote() { - - if (!is_inside_tree()) - return; - - if (cache.is_null()) - return; - - Spatial *n = Object::cast_to(ObjectDB::get_instance(cache)); - if (!n) - return; - - if (!n->is_inside_tree()) - return; - - //todo make faster - if (use_global_coordinates) { - - if (update_remote_position && update_remote_rotation && update_remote_scale) { - n->set_global_transform(get_global_transform()); - } else { - Transform our_trans = get_global_transform(); - - if (update_remote_rotation) - n->set_rotation(our_trans.basis.get_rotation()); - - if (update_remote_scale) - n->set_scale(our_trans.basis.get_scale()); - - if (update_remote_position) { - Transform n_trans = n->get_global_transform(); - - n_trans.set_origin(our_trans.get_origin()); - n->set_global_transform(n_trans); - } - } - - } else { - if (update_remote_position && update_remote_rotation && update_remote_scale) { - n->set_transform(get_transform()); - } else { - Transform our_trans = get_transform(); - - if (update_remote_rotation) - n->set_rotation(our_trans.basis.get_rotation()); - - if (update_remote_scale) - n->set_scale(our_trans.basis.get_scale()); - - if (update_remote_position) { - Transform n_trans = n->get_transform(); - - n_trans.set_origin(our_trans.get_origin()); - n->set_transform(n_trans); - } - } - } -} - -void RemoteTransform::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_TREE: { - - _update_cache(); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - if (!is_inside_tree()) - break; - - if (cache.is_valid()) { - - _update_remote(); - } - - } break; - } -} - -void RemoteTransform::set_remote_node(const NodePath &p_remote_node) { - - remote_node = p_remote_node; - if (is_inside_tree()) { - _update_cache(); - _update_remote(); - } - - update_configuration_warning(); -} - -NodePath RemoteTransform::get_remote_node() const { - - return remote_node; -} - -void RemoteTransform::set_use_global_coordinates(const bool p_enable) { - use_global_coordinates = p_enable; -} - -bool RemoteTransform::get_use_global_coordinates() const { - return use_global_coordinates; -} - -void RemoteTransform::set_update_position(const bool p_update) { - update_remote_position = p_update; - _update_remote(); -} - -bool RemoteTransform::get_update_position() const { - return update_remote_position; -} - -void RemoteTransform::set_update_rotation(const bool p_update) { - update_remote_rotation = p_update; - _update_remote(); -} - -bool RemoteTransform::get_update_rotation() const { - return update_remote_rotation; -} - -void RemoteTransform::set_update_scale(const bool p_update) { - update_remote_scale = p_update; - _update_remote(); -} - -bool RemoteTransform::get_update_scale() const { - return update_remote_scale; -} - -void RemoteTransform::force_update_cache() { - _update_cache(); -} - -String RemoteTransform::get_configuration_warning() const { - - if (!has_node(remote_node) || !Object::cast_to(get_node(remote_node))) { - return TTR("The \"Remote Path\" property must point to a valid Spatial or Spatial-derived node to work."); - } - - return String(); -} - -void RemoteTransform::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node); - ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node); - ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform::force_update_cache); - - ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates); - ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates); - - ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform::set_update_position); - ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform::get_update_position); - ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform::set_update_rotation); - ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform::get_update_rotation); - ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform::set_update_scale); - ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform::get_update_scale); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_remote_node", "get_remote_node"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates"); - - ADD_GROUP("Update", "update_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale"); -} - -RemoteTransform::RemoteTransform() { - - use_global_coordinates = true; - update_remote_position = true; - update_remote_rotation = true; - update_remote_scale = true; - - set_notify_transform(true); -} diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h deleted file mode 100644 index 02e448832f..0000000000 --- a/scene/3d/remote_transform.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************/ -/* remote_transform.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef REMOTETRANSFORM_H -#define REMOTETRANSFORM_H - -#include "scene/3d/spatial.h" - -class RemoteTransform : public Spatial { - GDCLASS(RemoteTransform, Spatial); - - NodePath remote_node; - - ObjectID cache; - - bool use_global_coordinates; - bool update_remote_position; - bool update_remote_rotation; - bool update_remote_scale; - - void _update_remote(); - void _update_cache(); - -protected: - static void _bind_methods(); - void _notification(int p_what); - -public: - void set_remote_node(const NodePath &p_remote_node); - NodePath get_remote_node() const; - - void set_use_global_coordinates(const bool p_enable); - bool get_use_global_coordinates() const; - - void set_update_position(const bool p_update); - bool get_update_position() const; - - void set_update_rotation(const bool p_update); - bool get_update_rotation() const; - - void set_update_scale(const bool p_update); - bool get_update_scale() const; - - void force_update_cache(); - - virtual String get_configuration_warning() const; - - RemoteTransform(); -}; - -#endif // REMOTETRANSFORM_H diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp new file mode 100644 index 0000000000..38792bbb58 --- /dev/null +++ b/scene/3d/remote_transform_3d.cpp @@ -0,0 +1,223 @@ +/*************************************************************************/ +/* remote_transform_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "remote_transform_3d.h" + +void RemoteTransform3D::_update_cache() { + cache = ObjectID(); + if (has_node(remote_node)) { + Node *node = get_node(remote_node); + if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) { + return; + } + + cache = node->get_instance_id(); + } +} + +void RemoteTransform3D::_update_remote() { + + if (!is_inside_tree()) + return; + + if (cache.is_null()) + return; + + Node3D *n = Object::cast_to(ObjectDB::get_instance(cache)); + if (!n) + return; + + if (!n->is_inside_tree()) + return; + + //todo make faster + if (use_global_coordinates) { + + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_global_transform(get_global_transform()); + } else { + Transform our_trans = get_global_transform(); + + if (update_remote_rotation) + n->set_rotation(our_trans.basis.get_rotation()); + + if (update_remote_scale) + n->set_scale(our_trans.basis.get_scale()); + + if (update_remote_position) { + Transform n_trans = n->get_global_transform(); + + n_trans.set_origin(our_trans.get_origin()); + n->set_global_transform(n_trans); + } + } + + } else { + if (update_remote_position && update_remote_rotation && update_remote_scale) { + n->set_transform(get_transform()); + } else { + Transform our_trans = get_transform(); + + if (update_remote_rotation) + n->set_rotation(our_trans.basis.get_rotation()); + + if (update_remote_scale) + n->set_scale(our_trans.basis.get_scale()); + + if (update_remote_position) { + Transform n_trans = n->get_transform(); + + n_trans.set_origin(our_trans.get_origin()); + n->set_transform(n_trans); + } + } + } +} + +void RemoteTransform3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + _update_cache(); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + if (!is_inside_tree()) + break; + + if (cache.is_valid()) { + + _update_remote(); + } + + } break; + } +} + +void RemoteTransform3D::set_remote_node(const NodePath &p_remote_node) { + + remote_node = p_remote_node; + if (is_inside_tree()) { + _update_cache(); + _update_remote(); + } + + update_configuration_warning(); +} + +NodePath RemoteTransform3D::get_remote_node() const { + + return remote_node; +} + +void RemoteTransform3D::set_use_global_coordinates(const bool p_enable) { + use_global_coordinates = p_enable; +} + +bool RemoteTransform3D::get_use_global_coordinates() const { + return use_global_coordinates; +} + +void RemoteTransform3D::set_update_position(const bool p_update) { + update_remote_position = p_update; + _update_remote(); +} + +bool RemoteTransform3D::get_update_position() const { + return update_remote_position; +} + +void RemoteTransform3D::set_update_rotation(const bool p_update) { + update_remote_rotation = p_update; + _update_remote(); +} + +bool RemoteTransform3D::get_update_rotation() const { + return update_remote_rotation; +} + +void RemoteTransform3D::set_update_scale(const bool p_update) { + update_remote_scale = p_update; + _update_remote(); +} + +bool RemoteTransform3D::get_update_scale() const { + return update_remote_scale; +} + +void RemoteTransform3D::force_update_cache() { + _update_cache(); +} + +String RemoteTransform3D::get_configuration_warning() const { + + if (!has_node(remote_node) || !Object::cast_to(get_node(remote_node))) { + return TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work."); + } + + return String(); +} + +void RemoteTransform3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform3D::set_remote_node); + ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform3D::get_remote_node); + ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform3D::force_update_cache); + + ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform3D::set_use_global_coordinates); + ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform3D::get_use_global_coordinates); + + ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform3D::set_update_position); + ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform3D::get_update_position); + ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform3D::set_update_rotation); + ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform3D::get_update_rotation); + ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform3D::set_update_scale); + ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform3D::get_update_scale); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_remote_node", "get_remote_node"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates"); + + ADD_GROUP("Update", "update_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale"); +} + +RemoteTransform3D::RemoteTransform3D() { + + use_global_coordinates = true; + update_remote_position = true; + update_remote_rotation = true; + update_remote_scale = true; + + set_notify_transform(true); +} diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h new file mode 100644 index 0000000000..50d7c5a9b2 --- /dev/null +++ b/scene/3d/remote_transform_3d.h @@ -0,0 +1,78 @@ +/*************************************************************************/ +/* remote_transform_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef REMOTETRANSFORM_H +#define REMOTETRANSFORM_H + +#include "scene/3d/node_3d.h" + +class RemoteTransform3D : public Node3D { + GDCLASS(RemoteTransform3D, Node3D); + + NodePath remote_node; + + ObjectID cache; + + bool use_global_coordinates; + bool update_remote_position; + bool update_remote_rotation; + bool update_remote_scale; + + void _update_remote(); + void _update_cache(); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + void set_remote_node(const NodePath &p_remote_node); + NodePath get_remote_node() const; + + void set_use_global_coordinates(const bool p_enable); + bool get_use_global_coordinates() const; + + void set_update_position(const bool p_update); + bool get_update_position() const; + + void set_update_rotation(const bool p_update); + bool get_update_rotation() const; + + void set_update_scale(const bool p_update); + bool get_update_scale() const; + + void force_update_cache(); + + virtual String get_configuration_warning() const; + + RemoteTransform3D(); +}; + +#endif // REMOTETRANSFORM_H diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp deleted file mode 100644 index 8e954ddc80..0000000000 --- a/scene/3d/skeleton.cpp +++ /dev/null @@ -1,956 +0,0 @@ -/*************************************************************************/ -/* skeleton.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "skeleton.h" - -#include "core/engine.h" -#include "core/message_queue.h" -#include "core/project_settings.h" -#include "scene/3d/physics_body.h" -#include "scene/resources/surface_tool.h" - -void SkinReference::_skin_changed() { - if (skeleton_node) { - skeleton_node->_make_dirty(); - } - skeleton_version = 0; -} - -void SkinReference::_bind_methods() { - ClassDB::bind_method(D_METHOD("_skin_changed"), &SkinReference::_skin_changed); - ClassDB::bind_method(D_METHOD("get_skeleton"), &SkinReference::get_skeleton); - ClassDB::bind_method(D_METHOD("get_skin"), &SkinReference::get_skin); -} - -RID SkinReference::get_skeleton() const { - return skeleton; -} - -Ref SkinReference::get_skin() const { - return skin; -} - -SkinReference::~SkinReference() { - if (skeleton_node) { - skeleton_node->skin_bindings.erase(this); - } - - VS::get_singleton()->free(skeleton); -} - -bool Skeleton::_set(const StringName &p_path, const Variant &p_value) { - - String path = p_path; - - if (!path.begins_with("bones/")) - return false; - - int which = path.get_slicec('/', 1).to_int(); - String what = path.get_slicec('/', 2); - - if (which == bones.size() && what == "name") { - - add_bone(p_value); - return true; - } - - ERR_FAIL_INDEX_V(which, bones.size(), false); - - if (what == "parent") - set_bone_parent(which, p_value); - else if (what == "rest") - set_bone_rest(which, p_value); - else if (what == "enabled") - set_bone_enabled(which, p_value); - else if (what == "pose") - set_bone_pose(which, p_value); - else if (what == "bound_children") { - Array children = p_value; - - if (is_inside_tree()) { - bones.write[which].nodes_bound.clear(); - - for (int i = 0; i < children.size(); i++) { - - NodePath npath = children[i]; - ERR_CONTINUE(npath.operator String() == ""); - Node *node = get_node(npath); - ERR_CONTINUE(!node); - bind_child_node_to_bone(which, node); - } - } - } else { - return false; - } - - return true; -} - -bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const { - - String path = p_path; - - if (!path.begins_with("bones/")) - return false; - - int which = path.get_slicec('/', 1).to_int(); - String what = path.get_slicec('/', 2); - - ERR_FAIL_INDEX_V(which, bones.size(), false); - - if (what == "name") - r_ret = get_bone_name(which); - else if (what == "parent") - r_ret = get_bone_parent(which); - else if (what == "rest") - r_ret = get_bone_rest(which); - else if (what == "enabled") - r_ret = is_bone_enabled(which); - else if (what == "pose") - r_ret = get_bone_pose(which); - else if (what == "bound_children") { - Array children; - - for (const List::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { - - Object *obj = ObjectDB::get_instance(E->get()); - ERR_CONTINUE(!obj); - Node *node = Object::cast_to(obj); - ERR_CONTINUE(!node); - NodePath npath = get_path_to(node); - children.push_back(npath); - } - - r_ret = children; - } else - return false; - - return true; -} -void Skeleton::_get_property_list(List *p_list) const { - - for (int i = 0; i < bones.size(); i++) { - - String prep = "bones/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, prep + "name")); - p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1")); - p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest")); - p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled")); - p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_children")); - } -} - -void Skeleton::_update_process_order() { - - if (!process_order_dirty) - return; - - Bone *bonesptr = bones.ptrw(); - int len = bones.size(); - - process_order.resize(len); - int *order = process_order.ptrw(); - for (int i = 0; i < len; i++) { - - if (bonesptr[i].parent >= len) { - //validate this just in case - ERR_PRINT("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); - bonesptr[i].parent = -1; - } - order[i] = i; - bonesptr[i].sort_index = i; - } - //now check process order - int pass_count = 0; - while (pass_count < len * len) { - //using bubblesort because of simplicity, it won't run every frame though. - //bublesort worst case is O(n^2), and this may be an infinite loop if cyclic - bool swapped = false; - for (int i = 0; i < len; i++) { - int parent_idx = bonesptr[order[i]].parent; - if (parent_idx < 0) - continue; //do nothing because it has no parent - //swap indices - int parent_order = bonesptr[parent_idx].sort_index; - if (parent_order > i) { - bonesptr[order[i]].sort_index = parent_order; - bonesptr[parent_idx].sort_index = i; - //swap order - SWAP(order[i], order[parent_order]); - swapped = true; - } - } - - if (!swapped) - break; - pass_count++; - } - - if (pass_count == len * len) { - ERR_PRINT("Skeleton parenthood graph is cyclic"); - } - - process_order_dirty = false; -} - -void Skeleton::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_UPDATE_SKELETON: { - - VisualServer *vs = VisualServer::get_singleton(); - Bone *bonesptr = bones.ptrw(); - int len = bones.size(); - - _update_process_order(); - - const int *order = process_order.ptr(); - - for (int i = 0; i < len; i++) { - - Bone &b = bonesptr[order[i]]; - - if (b.global_pose_override_amount >= 0.999) { - b.pose_global = b.global_pose_override; - } else { - if (b.disable_rest) { - if (b.enabled) { - - Transform pose = b.pose; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - - b.pose_global = bonesptr[b.parent].pose_global * pose; - } else { - - b.pose_global = pose; - } - } else { - - if (b.parent >= 0) { - - b.pose_global = bonesptr[b.parent].pose_global; - } else { - - b.pose_global = Transform(); - } - } - - } else { - if (b.enabled) { - - Transform pose = b.pose; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - - b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); - } else { - - b.pose_global = b.rest * pose; - } - } else { - - if (b.parent >= 0) { - - b.pose_global = bonesptr[b.parent].pose_global * b.rest; - } else { - - b.pose_global = b.rest; - } - } - } - - if (b.global_pose_override_amount >= CMP_EPSILON) { - b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); - } - } - - if (b.global_pose_override_reset) { - b.global_pose_override_amount = 0.0; - } - - for (List::Element *E = b.nodes_bound.front(); E; E = E->next()) { - - Object *obj = ObjectDB::get_instance(E->get()); - ERR_CONTINUE(!obj); - Spatial *sp = Object::cast_to(obj); - ERR_CONTINUE(!sp); - sp->set_transform(b.pose_global); - } - } - - //update skins - for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { - - const Skin *skin = E->get()->skin.operator->(); - RID skeleton = E->get()->skeleton; - uint32_t bind_count = skin->get_bind_count(); - - if (E->get()->bind_count != bind_count) { - VS::get_singleton()->skeleton_allocate(skeleton, bind_count); - E->get()->bind_count = bind_count; - E->get()->skin_bone_indices.resize(bind_count); - E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw(); - } - - if (E->get()->skeleton_version != version) { - - for (uint32_t i = 0; i < bind_count; i++) { - StringName bind_name = skin->get_bind_name(i); - - if (bind_name != StringName()) { - //bind name used, use this - bool found = false; - for (int j = 0; j < len; j++) { - if (bonesptr[j].name == bind_name) { - E->get()->skin_bone_indices_ptrs[i] = j; - found = true; - break; - } - } - - if (!found) { - ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name."); - E->get()->skin_bone_indices_ptrs[i] = 0; - } - } else if (skin->get_bind_bone(i) >= 0) { - int bind_index = skin->get_bind_bone(i); - if (bind_index >= len) { - ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + "."); - E->get()->skin_bone_indices_ptrs[i] = 0; - } else { - E->get()->skin_bone_indices_ptrs[i] = bind_index; - } - } else { - ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index."); - E->get()->skin_bone_indices_ptrs[i] = 0; - } - } - - E->get()->skeleton_version = version; - } - - for (uint32_t i = 0; i < bind_count; i++) { - uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i]; - ERR_CONTINUE(bone_index >= (uint32_t)len); - vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); - } - } - - dirty = false; - } break; - -#ifndef _3D_DISABLED - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - // This is active only if the skeleton animates the physical bones - // and the state of the bone is not active. - if (animate_physical_bones) { - for (int i = 0; i < bones.size(); i += 1) { - if (bones[i].physical_bone) { - if (bones[i].physical_bone->is_simulating_physics() == false) { - bones[i].physical_bone->reset_to_rest_position(); - } - } - } - } - } break; - case NOTIFICATION_READY: { - if (Engine::get_singleton()->is_editor_hint()) { - set_physics_process_internal(true); - } - } break; -#endif - } -} - -void Skeleton::clear_bones_global_pose_override() { - for (int i = 0; i < bones.size(); i += 1) { - bones.write[i].global_pose_override_amount = 0; - } - _make_dirty(); -} - -void Skeleton::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].global_pose_override_amount = p_amount; - bones.write[p_bone].global_pose_override = p_pose; - bones.write[p_bone].global_pose_override_reset = !p_persistent; - _make_dirty(); -} - -Transform Skeleton::get_bone_global_pose(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - if (dirty) - const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); - return bones[p_bone].pose_global; -} - -// skeleton creation api -void Skeleton::add_bone(const String &p_name) { - - ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1); - - for (int i = 0; i < bones.size(); i++) { - - ERR_FAIL_COND(bones[i].name == p_name); - } - - Bone b; - b.name = p_name; - bones.push_back(b); - process_order_dirty = true; - version++; - _make_dirty(); - update_gizmo(); -} -int Skeleton::find_bone(const String &p_name) const { - - for (int i = 0; i < bones.size(); i++) { - - if (bones[i].name == p_name) - return i; - } - - return -1; -} -String Skeleton::get_bone_name(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), ""); - - return bones[p_bone].name; -} - -bool Skeleton::is_bone_parent_of(int p_bone, int p_parent_bone_id) const { - - int parent_of_bone = get_bone_parent(p_bone); - - if (-1 == parent_of_bone) - return false; - - if (parent_of_bone == p_parent_bone_id) - return true; - - return is_bone_parent_of(parent_of_bone, p_parent_bone_id); -} - -int Skeleton::get_bone_count() const { - - return bones.size(); -} - -void Skeleton::set_bone_parent(int p_bone, int p_parent) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - ERR_FAIL_COND(p_parent != -1 && (p_parent < 0)); - - bones.write[p_bone].parent = p_parent; - process_order_dirty = true; - _make_dirty(); -} - -void Skeleton::unparent_bone_and_rest(int p_bone) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - - _update_process_order(); - - int parent = bones[p_bone].parent; - while (parent >= 0) { - bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; - parent = bones[parent].parent; - } - - bones.write[p_bone].parent = -1; - process_order_dirty = true; - - _make_dirty(); -} - -void Skeleton::set_bone_disable_rest(int p_bone, bool p_disable) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].disable_rest = p_disable; -} - -bool Skeleton::is_bone_rest_disabled(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), false); - return bones[p_bone].disable_rest; -} - -int Skeleton::get_bone_parent(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), -1); - - return bones[p_bone].parent; -} - -void Skeleton::set_bone_rest(int p_bone, const Transform &p_rest) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - - bones.write[p_bone].rest = p_rest; - _make_dirty(); -} -Transform Skeleton::get_bone_rest(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - - return bones[p_bone].rest; -} - -void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - - bones.write[p_bone].enabled = p_enabled; - _make_dirty(); -} -bool Skeleton::is_bone_enabled(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), false); - return bones[p_bone].enabled; -} - -void Skeleton::bind_child_node_to_bone(int p_bone, Node *p_node) { - - ERR_FAIL_NULL(p_node); - ERR_FAIL_INDEX(p_bone, bones.size()); - - ObjectID id = p_node->get_instance_id(); - - for (const List::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { - - if (E->get() == id) - return; // already here - } - - bones.write[p_bone].nodes_bound.push_back(id); -} -void Skeleton::unbind_child_node_from_bone(int p_bone, Node *p_node) { - - ERR_FAIL_NULL(p_node); - ERR_FAIL_INDEX(p_bone, bones.size()); - - ObjectID id = p_node->get_instance_id(); - bones.write[p_bone].nodes_bound.erase(id); -} -void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List *p_bound) const { - - ERR_FAIL_INDEX(p_bone, bones.size()); - - for (const List::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { - - Object *obj = ObjectDB::get_instance(E->get()); - ERR_CONTINUE(!obj); - p_bound->push_back(Object::cast_to(obj)); - } -} - -void Skeleton::clear_bones() { - - bones.clear(); - process_order_dirty = true; - version++; - _make_dirty(); -} - -// posing api - -void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - - bones.write[p_bone].pose = p_pose; - if (is_inside_tree()) { - _make_dirty(); - } -} -Transform Skeleton::get_bone_pose(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - return bones[p_bone].pose; -} - -void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) { - - ERR_FAIL_INDEX(p_bone, bones.size()); - //ERR_FAIL_COND( !is_inside_scene() ); - - bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform()); - bones.write[p_bone].custom_pose = p_custom_pose; - - _make_dirty(); -} - -Transform Skeleton::get_bone_custom_pose(int p_bone) const { - - ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); - return bones[p_bone].custom_pose; -} - -void Skeleton::_make_dirty() { - - if (dirty) - return; - - MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON); - dirty = true; -} - -int Skeleton::get_process_order(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, bones.size(), -1); - _update_process_order(); - return process_order[p_idx]; -} - -void Skeleton::localize_rests() { - - _update_process_order(); - - for (int i = bones.size() - 1; i >= 0; i--) { - int idx = process_order[i]; - if (bones[idx].parent >= 0) { - set_bone_rest(idx, bones[bones[idx].parent].rest.affine_inverse() * bones[idx].rest); - } - } -} - -#ifndef _3D_DISABLED - -void Skeleton::set_animate_physical_bones(bool p_animate) { - animate_physical_bones = p_animate; - - if (Engine::get_singleton()->is_editor_hint() == false) { - bool sim = false; - for (int i = 0; i < bones.size(); i += 1) { - if (bones[i].physical_bone) { - bones[i].physical_bone->reset_physics_simulation_state(); - if (bones[i].physical_bone->is_simulating_physics()) { - sim = true; - } - } - } - set_physics_process_internal(sim == false && p_animate); - } -} - -bool Skeleton::get_animate_physical_bones() const { - return animate_physical_bones; -} - -void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { - ERR_FAIL_INDEX(p_bone, bones.size()); - ERR_FAIL_COND(bones[p_bone].physical_bone); - ERR_FAIL_COND(!p_physical_bone); - bones.write[p_bone].physical_bone = p_physical_bone; - - _rebuild_physical_bones_cache(); -} - -void Skeleton::unbind_physical_bone_from_bone(int p_bone) { - ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].physical_bone = NULL; - - _rebuild_physical_bones_cache(); -} - -PhysicalBone *Skeleton::get_physical_bone(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); - - return bones[p_bone].physical_bone; -} - -PhysicalBone *Skeleton::get_physical_bone_parent(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); - - if (bones[p_bone].cache_parent_physical_bone) { - return bones[p_bone].cache_parent_physical_bone; - } - - return _get_physical_bone_parent(p_bone); -} - -PhysicalBone *Skeleton::_get_physical_bone_parent(int p_bone) { - ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); - - const int parent_bone = bones[p_bone].parent; - if (0 > parent_bone) { - return NULL; - } - - PhysicalBone *pb = bones[parent_bone].physical_bone; - if (pb) { - return pb; - } else { - return get_physical_bone_parent(parent_bone); - } -} - -void Skeleton::_rebuild_physical_bones_cache() { - const int b_size = bones.size(); - for (int i = 0; i < b_size; ++i) { - PhysicalBone *parent_pb = _get_physical_bone_parent(i); - if (parent_pb != bones[i].physical_bone) { - bones.write[i].cache_parent_physical_bone = parent_pb; - if (bones[i].physical_bone) - bones[i].physical_bone->_on_bone_parent_changed(); - } - } -} - -void _pb_stop_simulation(Node *p_node) { - - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _pb_stop_simulation(p_node->get_child(i)); - } - - PhysicalBone *pb = Object::cast_to(p_node); - if (pb) { - pb->set_simulate_physics(false); - } -} - -void Skeleton::physical_bones_stop_simulation() { - _pb_stop_simulation(this); - if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { - set_physics_process_internal(true); - } -} - -void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector &p_sim_bones) { - - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones); - } - - PhysicalBone *pb = Object::cast_to(p_node); - if (pb) { - for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { - if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { - pb->set_simulate_physics(true); - break; - } - } - } -} - -void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { - set_physics_process_internal(false); - - Vector sim_bones; - if (p_bones.size() <= 0) { - sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body - } else { - sim_bones.resize(p_bones.size()); - int c = 0; - for (int i = sim_bones.size() - 1; 0 <= i; --i) { - Variant::Type type = p_bones.get(i).get_type(); - if (Variant::STRING == type || Variant::STRING_NAME == type) { - int bone_id = find_bone(p_bones.get(i)); - if (bone_id != -1) - sim_bones.write[c++] = bone_id; - } - } - sim_bones.resize(c); - } - - _pb_start_simulation(this, this, sim_bones); -} - -void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { - - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception); - } - - CollisionObject *co = Object::cast_to(p_node); - if (co) { - if (p_add) { - PhysicsServer::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); - } else { - PhysicsServer::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); - } - } -} - -void Skeleton::physical_bones_add_collision_exception(RID p_exception) { - _physical_bones_add_remove_collision_exception(true, this, p_exception); -} - -void Skeleton::physical_bones_remove_collision_exception(RID p_exception) { - _physical_bones_add_remove_collision_exception(false, this, p_exception); -} - -#endif // _3D_DISABLED - -void Skeleton::_skin_changed() { - _make_dirty(); -} - -Ref Skeleton::register_skin(const Ref &p_skin) { - - for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { - if (E->get()->skin == p_skin) { - return Ref(E->get()); - } - } - - Ref skin = p_skin; - - if (skin.is_null()) { - //need to create one from existing code, this is for compatibility only - //when skeletons did not support skins. It is also used by gizmo - //to display the skeleton. - - skin.instance(); - skin->set_bind_count(bones.size()); - _update_process_order(); //just in case - - // pose changed, rebuild cache of inverses - const Bone *bonesptr = bones.ptr(); - int len = bones.size(); - const int *order = process_order.ptr(); - - // calculate global rests and invert them - for (int i = 0; i < len; i++) { - const Bone &b = bonesptr[order[i]]; - if (b.parent >= 0) { - skin->set_bind_pose(order[i], skin->get_bind_pose(b.parent) * b.rest); - } else { - skin->set_bind_pose(order[i], b.rest); - } - } - - for (int i = 0; i < len; i++) { - //the inverse is what is actually required - skin->set_bind_bone(i, i); - skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); - } - } - - ERR_FAIL_COND_V(skin.is_null(), Ref()); - - Ref skin_ref; - skin_ref.instance(); - - skin_ref->skeleton_node = this; - skin_ref->bind_count = 0; - skin_ref->skeleton = VisualServer::get_singleton()->skeleton_create(); - skin_ref->skeleton_node = this; - skin_ref->skin = skin; - - skin_bindings.insert(skin_ref.operator->()); - - skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed"); - - _make_dirty(); //skin needs to be updated, so update skeleton - - return skin_ref; -} - -void Skeleton::_bind_methods() { - - ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton::add_bone); - ClassDB::bind_method(D_METHOD("find_bone", "name"), &Skeleton::find_bone); - ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton::get_bone_name); - - ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &Skeleton::get_bone_parent); - ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "parent_idx"), &Skeleton::set_bone_parent); - - ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton::get_bone_count); - - ClassDB::bind_method(D_METHOD("unparent_bone_and_rest", "bone_idx"), &Skeleton::unparent_bone_and_rest); - - ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton::get_bone_rest); - ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton::set_bone_rest); - - ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton::register_skin); - - ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton::localize_rests); - - ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest); - ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton::is_bone_rest_disabled); - - ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node"), &Skeleton::bind_child_node_to_bone); - ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node"), &Skeleton::unbind_child_node_from_bone); - ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone", "bone_idx"), &Skeleton::_get_bound_child_nodes_to_bone); - - ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones); - - ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton::get_bone_pose); - ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose); - - ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton::clear_bones_global_pose_override); - ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton::set_bone_global_pose_override, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton::get_bone_global_pose); - - ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton::get_bone_custom_pose); - ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton::set_bone_custom_pose); - -#ifndef _3D_DISABLED - - ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones); - ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones); - - ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); - ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); - ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); - ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); -#endif // _3D_DISABLED - - BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); -} - -Skeleton::Skeleton() { - - animate_physical_bones = true; - dirty = false; - version = 1; - process_order_dirty = true; -} - -Skeleton::~Skeleton() { - - //some skins may remain bound - for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { - E->get()->skeleton_node = nullptr; - } -} diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h deleted file mode 100644 index 11fc9fff2e..0000000000 --- a/scene/3d/skeleton.h +++ /dev/null @@ -1,235 +0,0 @@ -/*************************************************************************/ -/* skeleton.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SKELETON_H -#define SKELETON_H - -#include "core/rid.h" -#include "scene/3d/spatial.h" -#include "scene/resources/skin.h" - -#ifndef _3D_DISABLED -typedef int BoneId; - -class PhysicalBone; -#endif // _3D_DISABLED - -class Skeleton; - -class SkinReference : public Reference { - GDCLASS(SkinReference, Reference) - friend class Skeleton; - - Skeleton *skeleton_node; - RID skeleton; - Ref skin; - uint32_t bind_count = 0; - uint64_t skeleton_version = 0; - Vector skin_bone_indices; - uint32_t *skin_bone_indices_ptrs; - void _skin_changed(); - -protected: - static void _bind_methods(); - -public: - RID get_skeleton() const; - Ref get_skin() const; - ~SkinReference(); -}; - -class Skeleton : public Spatial { - - GDCLASS(Skeleton, Spatial); - -private: - friend class SkinReference; - - Set skin_bindings; - - void _skin_changed(); - - struct Bone { - - String name; - - bool enabled; - int parent; - int sort_index; //used for re-sorting process order - - bool disable_rest; - Transform rest; - - Transform pose; - Transform pose_global; - - bool custom_pose_enable; - Transform custom_pose; - - float global_pose_override_amount; - bool global_pose_override_reset; - Transform global_pose_override; - -#ifndef _3D_DISABLED - PhysicalBone *physical_bone; - PhysicalBone *cache_parent_physical_bone; -#endif // _3D_DISABLED - - List nodes_bound; - - Bone() { - parent = -1; - enabled = true; - disable_rest = false; - custom_pose_enable = false; - global_pose_override_amount = 0; - global_pose_override_reset = false; -#ifndef _3D_DISABLED - physical_bone = NULL; - cache_parent_physical_bone = NULL; -#endif // _3D_DISABLED - } - }; - - bool animate_physical_bones; - Vector bones; - Vector process_order; - bool process_order_dirty; - - void _make_dirty(); - bool dirty; - - uint64_t version; - - // bind helpers - Array _get_bound_child_nodes_to_bone(int p_bone) const { - - Array bound; - List children; - get_bound_child_nodes_to_bone(p_bone, &children); - - for (int i = 0; i < children.size(); i++) { - - bound.push_back(children[i]); - } - return bound; - } - - void _update_process_order(); - -protected: - bool _get(const StringName &p_path, Variant &r_ret) const; - bool _set(const StringName &p_path, const Variant &p_value); - void _get_property_list(List *p_list) const; - void _notification(int p_what); - static void _bind_methods(); - -public: - enum { - - NOTIFICATION_UPDATE_SKELETON = 50 - }; - - // skeleton creation api - void add_bone(const String &p_name); - int find_bone(const String &p_name) const; - String get_bone_name(int p_bone) const; - - bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const; - - void set_bone_parent(int p_bone, int p_parent); - int get_bone_parent(int p_bone) const; - - void unparent_bone_and_rest(int p_bone); - - void set_bone_disable_rest(int p_bone, bool p_disable); - bool is_bone_rest_disabled(int p_bone) const; - - int get_bone_count() const; - - void set_bone_rest(int p_bone, const Transform &p_rest); - Transform get_bone_rest(int p_bone) const; - Transform get_bone_global_pose(int p_bone) const; - - void clear_bones_global_pose_override(); - void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false); - - void set_bone_enabled(int p_bone, bool p_enabled); - bool is_bone_enabled(int p_bone) const; - - void bind_child_node_to_bone(int p_bone, Node *p_node); - void unbind_child_node_from_bone(int p_bone, Node *p_node); - void get_bound_child_nodes_to_bone(int p_bone, List *p_bound) const; - - void clear_bones(); - - // posing api - - void set_bone_pose(int p_bone, const Transform &p_pose); - Transform get_bone_pose(int p_bone) const; - - void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose); - Transform get_bone_custom_pose(int p_bone) const; - - void localize_rests(); // used for loaders and tools - int get_process_order(int p_idx); - - Ref register_skin(const Ref &p_skin); - -#ifndef _3D_DISABLED - // Physical bone API - - void set_animate_physical_bones(bool p_animate); - bool get_animate_physical_bones() const; - - void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); - void unbind_physical_bone_from_bone(int p_bone); - - PhysicalBone *get_physical_bone(int p_bone); - PhysicalBone *get_physical_bone_parent(int p_bone); - -private: - /// This is a slow API os it's cached - PhysicalBone *_get_physical_bone_parent(int p_bone); - void _rebuild_physical_bones_cache(); - -public: - void physical_bones_stop_simulation(); - void physical_bones_start_simulation_on(const Array &p_bones); - void physical_bones_add_collision_exception(RID p_exception); - void physical_bones_remove_collision_exception(RID p_exception); -#endif // _3D_DISABLED - -public: - Skeleton(); - ~Skeleton(); -}; - -#endif diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp new file mode 100644 index 0000000000..1ea6647d61 --- /dev/null +++ b/scene/3d/skeleton_3d.cpp @@ -0,0 +1,956 @@ +/*************************************************************************/ +/* skeleton_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "skeleton_3d.h" + +#include "core/engine.h" +#include "core/message_queue.h" +#include "core/project_settings.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/resources/surface_tool.h" + +void SkinReference::_skin_changed() { + if (skeleton_node) { + skeleton_node->_make_dirty(); + } + skeleton_version = 0; +} + +void SkinReference::_bind_methods() { + ClassDB::bind_method(D_METHOD("_skin_changed"), &SkinReference::_skin_changed); + ClassDB::bind_method(D_METHOD("get_skeleton"), &SkinReference::get_skeleton); + ClassDB::bind_method(D_METHOD("get_skin"), &SkinReference::get_skin); +} + +RID SkinReference::get_skeleton() const { + return skeleton; +} + +Ref SkinReference::get_skin() const { + return skin; +} + +SkinReference::~SkinReference() { + if (skeleton_node) { + skeleton_node->skin_bindings.erase(this); + } + + VS::get_singleton()->free(skeleton); +} + +bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { + + String path = p_path; + + if (!path.begins_with("bones/")) + return false; + + int which = path.get_slicec('/', 1).to_int(); + String what = path.get_slicec('/', 2); + + if (which == bones.size() && what == "name") { + + add_bone(p_value); + return true; + } + + ERR_FAIL_INDEX_V(which, bones.size(), false); + + if (what == "parent") + set_bone_parent(which, p_value); + else if (what == "rest") + set_bone_rest(which, p_value); + else if (what == "enabled") + set_bone_enabled(which, p_value); + else if (what == "pose") + set_bone_pose(which, p_value); + else if (what == "bound_children") { + Array children = p_value; + + if (is_inside_tree()) { + bones.write[which].nodes_bound.clear(); + + for (int i = 0; i < children.size(); i++) { + + NodePath npath = children[i]; + ERR_CONTINUE(npath.operator String() == ""); + Node *node = get_node(npath); + ERR_CONTINUE(!node); + bind_child_node_to_bone(which, node); + } + } + } else { + return false; + } + + return true; +} + +bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { + + String path = p_path; + + if (!path.begins_with("bones/")) + return false; + + int which = path.get_slicec('/', 1).to_int(); + String what = path.get_slicec('/', 2); + + ERR_FAIL_INDEX_V(which, bones.size(), false); + + if (what == "name") + r_ret = get_bone_name(which); + else if (what == "parent") + r_ret = get_bone_parent(which); + else if (what == "rest") + r_ret = get_bone_rest(which); + else if (what == "enabled") + r_ret = is_bone_enabled(which); + else if (what == "pose") + r_ret = get_bone_pose(which); + else if (what == "bound_children") { + Array children; + + for (const List::Element *E = bones[which].nodes_bound.front(); E; E = E->next()) { + + Object *obj = ObjectDB::get_instance(E->get()); + ERR_CONTINUE(!obj); + Node *node = Object::cast_to(obj); + ERR_CONTINUE(!node); + NodePath npath = get_path_to(node); + children.push_back(npath); + } + + r_ret = children; + } else + return false; + + return true; +} +void Skeleton3D::_get_property_list(List *p_list) const { + + for (int i = 0; i < bones.size(); i++) { + + String prep = "bones/" + itos(i) + "/"; + p_list->push_back(PropertyInfo(Variant::STRING, prep + "name")); + p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest")); + p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, prep + "bound_children")); + } +} + +void Skeleton3D::_update_process_order() { + + if (!process_order_dirty) + return; + + Bone *bonesptr = bones.ptrw(); + int len = bones.size(); + + process_order.resize(len); + int *order = process_order.ptrw(); + for (int i = 0; i < len; i++) { + + if (bonesptr[i].parent >= len) { + //validate this just in case + ERR_PRINT("Bone " + itos(i) + " has invalid parent: " + itos(bonesptr[i].parent)); + bonesptr[i].parent = -1; + } + order[i] = i; + bonesptr[i].sort_index = i; + } + //now check process order + int pass_count = 0; + while (pass_count < len * len) { + //using bubblesort because of simplicity, it won't run every frame though. + //bublesort worst case is O(n^2), and this may be an infinite loop if cyclic + bool swapped = false; + for (int i = 0; i < len; i++) { + int parent_idx = bonesptr[order[i]].parent; + if (parent_idx < 0) + continue; //do nothing because it has no parent + //swap indices + int parent_order = bonesptr[parent_idx].sort_index; + if (parent_order > i) { + bonesptr[order[i]].sort_index = parent_order; + bonesptr[parent_idx].sort_index = i; + //swap order + SWAP(order[i], order[parent_order]); + swapped = true; + } + } + + if (!swapped) + break; + pass_count++; + } + + if (pass_count == len * len) { + ERR_PRINT("Skeleton parenthood graph is cyclic"); + } + + process_order_dirty = false; +} + +void Skeleton3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_UPDATE_SKELETON: { + + VisualServer *vs = VisualServer::get_singleton(); + Bone *bonesptr = bones.ptrw(); + int len = bones.size(); + + _update_process_order(); + + const int *order = process_order.ptr(); + + for (int i = 0; i < len; i++) { + + Bone &b = bonesptr[order[i]]; + + if (b.global_pose_override_amount >= 0.999) { + b.pose_global = b.global_pose_override; + } else { + if (b.disable_rest) { + if (b.enabled) { + + Transform pose = b.pose; + if (b.custom_pose_enable) { + pose = b.custom_pose * pose; + } + if (b.parent >= 0) { + + b.pose_global = bonesptr[b.parent].pose_global * pose; + } else { + + b.pose_global = pose; + } + } else { + + if (b.parent >= 0) { + + b.pose_global = bonesptr[b.parent].pose_global; + } else { + + b.pose_global = Transform(); + } + } + + } else { + if (b.enabled) { + + Transform pose = b.pose; + if (b.custom_pose_enable) { + pose = b.custom_pose * pose; + } + if (b.parent >= 0) { + + b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); + } else { + + b.pose_global = b.rest * pose; + } + } else { + + if (b.parent >= 0) { + + b.pose_global = bonesptr[b.parent].pose_global * b.rest; + } else { + + b.pose_global = b.rest; + } + } + } + + if (b.global_pose_override_amount >= CMP_EPSILON) { + b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); + } + } + + if (b.global_pose_override_reset) { + b.global_pose_override_amount = 0.0; + } + + for (List::Element *E = b.nodes_bound.front(); E; E = E->next()) { + + Object *obj = ObjectDB::get_instance(E->get()); + ERR_CONTINUE(!obj); + Node3D *sp = Object::cast_to(obj); + ERR_CONTINUE(!sp); + sp->set_transform(b.pose_global); + } + } + + //update skins + for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { + + const Skin *skin = E->get()->skin.operator->(); + RID skeleton = E->get()->skeleton; + uint32_t bind_count = skin->get_bind_count(); + + if (E->get()->bind_count != bind_count) { + VS::get_singleton()->skeleton_allocate(skeleton, bind_count); + E->get()->bind_count = bind_count; + E->get()->skin_bone_indices.resize(bind_count); + E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw(); + } + + if (E->get()->skeleton_version != version) { + + for (uint32_t i = 0; i < bind_count; i++) { + StringName bind_name = skin->get_bind_name(i); + + if (bind_name != StringName()) { + //bind name used, use this + bool found = false; + for (int j = 0; j < len; j++) { + if (bonesptr[j].name == bind_name) { + E->get()->skin_bone_indices_ptrs[i] = j; + found = true; + break; + } + } + + if (!found) { + ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } + } else if (skin->get_bind_bone(i) >= 0) { + int bind_index = skin->get_bind_bone(i); + if (bind_index >= len) { + ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + "."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } else { + E->get()->skin_bone_indices_ptrs[i] = bind_index; + } + } else { + ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index."); + E->get()->skin_bone_indices_ptrs[i] = 0; + } + } + + E->get()->skeleton_version = version; + } + + for (uint32_t i = 0; i < bind_count; i++) { + uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i]; + ERR_CONTINUE(bone_index >= (uint32_t)len); + vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); + } + } + + dirty = false; + } break; + +#ifndef _3D_DISABLED + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // This is active only if the skeleton animates the physical bones + // and the state of the bone is not active. + if (animate_physical_bones) { + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + if (bones[i].physical_bone->is_simulating_physics() == false) { + bones[i].physical_bone->reset_to_rest_position(); + } + } + } + } + } break; + case NOTIFICATION_READY: { + if (Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } + } break; +#endif + } +} + +void Skeleton3D::clear_bones_global_pose_override() { + for (int i = 0; i < bones.size(); i += 1) { + bones.write[i].global_pose_override_amount = 0; + } + _make_dirty(); +} + +void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + bones.write[p_bone].global_pose_override_amount = p_amount; + bones.write[p_bone].global_pose_override = p_pose; + bones.write[p_bone].global_pose_override_reset = !p_persistent; + _make_dirty(); +} + +Transform Skeleton3D::get_bone_global_pose(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); + if (dirty) + const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); + return bones[p_bone].pose_global; +} + +// skeleton creation api +void Skeleton3D::add_bone(const String &p_name) { + + ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1); + + for (int i = 0; i < bones.size(); i++) { + + ERR_FAIL_COND(bones[i].name == p_name); + } + + Bone b; + b.name = p_name; + bones.push_back(b); + process_order_dirty = true; + version++; + _make_dirty(); + update_gizmo(); +} +int Skeleton3D::find_bone(const String &p_name) const { + + for (int i = 0; i < bones.size(); i++) { + + if (bones[i].name == p_name) + return i; + } + + return -1; +} +String Skeleton3D::get_bone_name(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), ""); + + return bones[p_bone].name; +} + +bool Skeleton3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const { + + int parent_of_bone = get_bone_parent(p_bone); + + if (-1 == parent_of_bone) + return false; + + if (parent_of_bone == p_parent_bone_id) + return true; + + return is_bone_parent_of(parent_of_bone, p_parent_bone_id); +} + +int Skeleton3D::get_bone_count() const { + + return bones.size(); +} + +void Skeleton3D::set_bone_parent(int p_bone, int p_parent) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + ERR_FAIL_COND(p_parent != -1 && (p_parent < 0)); + + bones.write[p_bone].parent = p_parent; + process_order_dirty = true; + _make_dirty(); +} + +void Skeleton3D::unparent_bone_and_rest(int p_bone) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + + _update_process_order(); + + int parent = bones[p_bone].parent; + while (parent >= 0) { + bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest; + parent = bones[parent].parent; + } + + bones.write[p_bone].parent = -1; + process_order_dirty = true; + + _make_dirty(); +} + +void Skeleton3D::set_bone_disable_rest(int p_bone, bool p_disable) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + bones.write[p_bone].disable_rest = p_disable; +} + +bool Skeleton3D::is_bone_rest_disabled(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), false); + return bones[p_bone].disable_rest; +} + +int Skeleton3D::get_bone_parent(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), -1); + + return bones[p_bone].parent; +} + +void Skeleton3D::set_bone_rest(int p_bone, const Transform &p_rest) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + + bones.write[p_bone].rest = p_rest; + _make_dirty(); +} +Transform Skeleton3D::get_bone_rest(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); + + return bones[p_bone].rest; +} + +void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + + bones.write[p_bone].enabled = p_enabled; + _make_dirty(); +} +bool Skeleton3D::is_bone_enabled(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), false); + return bones[p_bone].enabled; +} + +void Skeleton3D::bind_child_node_to_bone(int p_bone, Node *p_node) { + + ERR_FAIL_NULL(p_node); + ERR_FAIL_INDEX(p_bone, bones.size()); + + ObjectID id = p_node->get_instance_id(); + + for (const List::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + + if (E->get() == id) + return; // already here + } + + bones.write[p_bone].nodes_bound.push_back(id); +} +void Skeleton3D::unbind_child_node_from_bone(int p_bone, Node *p_node) { + + ERR_FAIL_NULL(p_node); + ERR_FAIL_INDEX(p_bone, bones.size()); + + ObjectID id = p_node->get_instance_id(); + bones.write[p_bone].nodes_bound.erase(id); +} +void Skeleton3D::get_bound_child_nodes_to_bone(int p_bone, List *p_bound) const { + + ERR_FAIL_INDEX(p_bone, bones.size()); + + for (const List::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) { + + Object *obj = ObjectDB::get_instance(E->get()); + ERR_CONTINUE(!obj); + p_bound->push_back(Object::cast_to(obj)); + } +} + +void Skeleton3D::clear_bones() { + + bones.clear(); + process_order_dirty = true; + version++; + _make_dirty(); +} + +// posing api + +void Skeleton3D::set_bone_pose(int p_bone, const Transform &p_pose) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + + bones.write[p_bone].pose = p_pose; + if (is_inside_tree()) { + _make_dirty(); + } +} +Transform Skeleton3D::get_bone_pose(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); + return bones[p_bone].pose; +} + +void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) { + + ERR_FAIL_INDEX(p_bone, bones.size()); + //ERR_FAIL_COND( !is_inside_scene() ); + + bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform()); + bones.write[p_bone].custom_pose = p_custom_pose; + + _make_dirty(); +} + +Transform Skeleton3D::get_bone_custom_pose(int p_bone) const { + + ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); + return bones[p_bone].custom_pose; +} + +void Skeleton3D::_make_dirty() { + + if (dirty) + return; + + MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON); + dirty = true; +} + +int Skeleton3D::get_process_order(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, bones.size(), -1); + _update_process_order(); + return process_order[p_idx]; +} + +void Skeleton3D::localize_rests() { + + _update_process_order(); + + for (int i = bones.size() - 1; i >= 0; i--) { + int idx = process_order[i]; + if (bones[idx].parent >= 0) { + set_bone_rest(idx, bones[bones[idx].parent].rest.affine_inverse() * bones[idx].rest); + } + } +} + +#ifndef _3D_DISABLED + +void Skeleton3D::set_animate_physical_bones(bool p_animate) { + animate_physical_bones = p_animate; + + if (Engine::get_singleton()->is_editor_hint() == false) { + bool sim = false; + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + bones[i].physical_bone->reset_physics_simulation_state(); + if (bones[i].physical_bone->is_simulating_physics()) { + sim = true; + } + } + } + set_physics_process_internal(sim == false && p_animate); + } +} + +bool Skeleton3D::get_animate_physical_bones() const { + return animate_physical_bones; +} + +void Skeleton3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone) { + ERR_FAIL_INDEX(p_bone, bones.size()); + ERR_FAIL_COND(bones[p_bone].physical_bone); + ERR_FAIL_COND(!p_physical_bone); + bones.write[p_bone].physical_bone = p_physical_bone; + + _rebuild_physical_bones_cache(); +} + +void Skeleton3D::unbind_physical_bone_from_bone(int p_bone) { + ERR_FAIL_INDEX(p_bone, bones.size()); + bones.write[p_bone].physical_bone = NULL; + + _rebuild_physical_bones_cache(); +} + +PhysicalBone3D *Skeleton3D::get_physical_bone(int p_bone) { + ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + + return bones[p_bone].physical_bone; +} + +PhysicalBone3D *Skeleton3D::get_physical_bone_parent(int p_bone) { + ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + + if (bones[p_bone].cache_parent_physical_bone) { + return bones[p_bone].cache_parent_physical_bone; + } + + return _get_physical_bone_parent(p_bone); +} + +PhysicalBone3D *Skeleton3D::_get_physical_bone_parent(int p_bone) { + ERR_FAIL_INDEX_V(p_bone, bones.size(), NULL); + + const int parent_bone = bones[p_bone].parent; + if (0 > parent_bone) { + return NULL; + } + + PhysicalBone3D *pb = bones[parent_bone].physical_bone; + if (pb) { + return pb; + } else { + return get_physical_bone_parent(parent_bone); + } +} + +void Skeleton3D::_rebuild_physical_bones_cache() { + const int b_size = bones.size(); + for (int i = 0; i < b_size; ++i) { + PhysicalBone3D *parent_pb = _get_physical_bone_parent(i); + if (parent_pb != bones[i].physical_bone) { + bones.write[i].cache_parent_physical_bone = parent_pb; + if (bones[i].physical_bone) + bones[i].physical_bone->_on_bone_parent_changed(); + } + } +} + +void _pb_stop_simulation(Node *p_node) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _pb_stop_simulation(p_node->get_child(i)); + } + + PhysicalBone3D *pb = Object::cast_to(p_node); + if (pb) { + pb->set_simulate_physics(false); + } +} + +void Skeleton3D::physical_bones_stop_simulation() { + _pb_stop_simulation(this); + if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { + set_physics_process_internal(true); + } +} + +void _pb_start_simulation(const Skeleton3D *p_skeleton, Node *p_node, const Vector &p_sim_bones) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones); + } + + PhysicalBone3D *pb = Object::cast_to(p_node); + if (pb) { + for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { + if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { + pb->set_simulate_physics(true); + break; + } + } + } +} + +void Skeleton3D::physical_bones_start_simulation_on(const Array &p_bones) { + set_physics_process_internal(false); + + Vector sim_bones; + if (p_bones.size() <= 0) { + sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body + } else { + sim_bones.resize(p_bones.size()); + int c = 0; + for (int i = sim_bones.size() - 1; 0 <= i; --i) { + Variant::Type type = p_bones.get(i).get_type(); + if (Variant::STRING == type || Variant::STRING_NAME == type) { + int bone_id = find_bone(p_bones.get(i)); + if (bone_id != -1) + sim_bones.write[c++] = bone_id; + } + } + sim_bones.resize(c); + } + + _pb_start_simulation(this, this, sim_bones); +} + +void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception); + } + + CollisionObject3D *co = Object::cast_to(p_node); + if (co) { + if (p_add) { + PhysicsServer::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); + } else { + PhysicsServer::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); + } + } +} + +void Skeleton3D::physical_bones_add_collision_exception(RID p_exception) { + _physical_bones_add_remove_collision_exception(true, this, p_exception); +} + +void Skeleton3D::physical_bones_remove_collision_exception(RID p_exception) { + _physical_bones_add_remove_collision_exception(false, this, p_exception); +} + +#endif // _3D_DISABLED + +void Skeleton3D::_skin_changed() { + _make_dirty(); +} + +Ref Skeleton3D::register_skin(const Ref &p_skin) { + + for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { + if (E->get()->skin == p_skin) { + return Ref(E->get()); + } + } + + Ref skin = p_skin; + + if (skin.is_null()) { + //need to create one from existing code, this is for compatibility only + //when skeletons did not support skins. It is also used by gizmo + //to display the skeleton. + + skin.instance(); + skin->set_bind_count(bones.size()); + _update_process_order(); //just in case + + // pose changed, rebuild cache of inverses + const Bone *bonesptr = bones.ptr(); + int len = bones.size(); + const int *order = process_order.ptr(); + + // calculate global rests and invert them + for (int i = 0; i < len; i++) { + const Bone &b = bonesptr[order[i]]; + if (b.parent >= 0) { + skin->set_bind_pose(order[i], skin->get_bind_pose(b.parent) * b.rest); + } else { + skin->set_bind_pose(order[i], b.rest); + } + } + + for (int i = 0; i < len; i++) { + //the inverse is what is actually required + skin->set_bind_bone(i, i); + skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); + } + } + + ERR_FAIL_COND_V(skin.is_null(), Ref()); + + Ref skin_ref; + skin_ref.instance(); + + skin_ref->skeleton_node = this; + skin_ref->bind_count = 0; + skin_ref->skeleton = VisualServer::get_singleton()->skeleton_create(); + skin_ref->skeleton_node = this; + skin_ref->skin = skin; + + skin_bindings.insert(skin_ref.operator->()); + + skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed"); + + _make_dirty(); //skin needs to be updated, so update skeleton + + return skin_ref; +} + +void Skeleton3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton3D::add_bone); + ClassDB::bind_method(D_METHOD("find_bone", "name"), &Skeleton3D::find_bone); + ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton3D::get_bone_name); + + ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &Skeleton3D::get_bone_parent); + ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "parent_idx"), &Skeleton3D::set_bone_parent); + + ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton3D::get_bone_count); + + ClassDB::bind_method(D_METHOD("unparent_bone_and_rest", "bone_idx"), &Skeleton3D::unparent_bone_and_rest); + + ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton3D::get_bone_rest); + ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton3D::set_bone_rest); + + ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton3D::register_skin); + + ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton3D::localize_rests); + + ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton3D::set_bone_disable_rest); + ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton3D::is_bone_rest_disabled); + + ClassDB::bind_method(D_METHOD("bind_child_node_to_bone", "bone_idx", "node"), &Skeleton3D::bind_child_node_to_bone); + ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone", "bone_idx", "node"), &Skeleton3D::unbind_child_node_from_bone); + ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone", "bone_idx"), &Skeleton3D::_get_bound_child_nodes_to_bone); + + ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton3D::clear_bones); + + ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose); + ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton3D::set_bone_pose); + + ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override); + ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose); + + ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose); + ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose); + +#ifndef _3D_DISABLED + + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones); + ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton3D::get_animate_physical_bones); + + ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton3D::physical_bones_stop_simulation); + ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton3D::physical_bones_start_simulation_on, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton3D::physical_bones_add_collision_exception); + ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton3D::physical_bones_remove_collision_exception); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); +#endif // _3D_DISABLED + + BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); +} + +Skeleton3D::Skeleton3D() { + + animate_physical_bones = true; + dirty = false; + version = 1; + process_order_dirty = true; +} + +Skeleton3D::~Skeleton3D() { + + //some skins may remain bound + for (Set::Element *E = skin_bindings.front(); E; E = E->next()) { + E->get()->skeleton_node = nullptr; + } +} diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h new file mode 100644 index 0000000000..2ae04aa575 --- /dev/null +++ b/scene/3d/skeleton_3d.h @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* skeleton_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SKELETON_3D_H +#define SKELETON_3D_H + +#include "core/rid.h" +#include "scene/3d/node_3d.h" +#include "scene/resources/skin.h" + +#ifndef _3D_DISABLED +typedef int BoneId; + +class PhysicalBone3D; +#endif // _3D_DISABLED + +class Skeleton3D; + +class SkinReference : public Reference { + GDCLASS(SkinReference, Reference) + friend class Skeleton3D; + + Skeleton3D *skeleton_node; + RID skeleton; + Ref skin; + uint32_t bind_count = 0; + uint64_t skeleton_version = 0; + Vector skin_bone_indices; + uint32_t *skin_bone_indices_ptrs; + void _skin_changed(); + +protected: + static void _bind_methods(); + +public: + RID get_skeleton() const; + Ref get_skin() const; + ~SkinReference(); +}; + +class Skeleton3D : public Node3D { + + GDCLASS(Skeleton3D, Node3D); + +private: + friend class SkinReference; + + Set skin_bindings; + + void _skin_changed(); + + struct Bone { + + String name; + + bool enabled; + int parent; + int sort_index; //used for re-sorting process order + + bool disable_rest; + Transform rest; + + Transform pose; + Transform pose_global; + + bool custom_pose_enable; + Transform custom_pose; + + float global_pose_override_amount; + bool global_pose_override_reset; + Transform global_pose_override; + +#ifndef _3D_DISABLED + PhysicalBone3D *physical_bone; + PhysicalBone3D *cache_parent_physical_bone; +#endif // _3D_DISABLED + + List nodes_bound; + + Bone() { + parent = -1; + enabled = true; + disable_rest = false; + custom_pose_enable = false; + global_pose_override_amount = 0; + global_pose_override_reset = false; +#ifndef _3D_DISABLED + physical_bone = NULL; + cache_parent_physical_bone = NULL; +#endif // _3D_DISABLED + } + }; + + bool animate_physical_bones; + Vector bones; + Vector process_order; + bool process_order_dirty; + + void _make_dirty(); + bool dirty; + + uint64_t version; + + // bind helpers + Array _get_bound_child_nodes_to_bone(int p_bone) const { + + Array bound; + List children; + get_bound_child_nodes_to_bone(p_bone, &children); + + for (int i = 0; i < children.size(); i++) { + + bound.push_back(children[i]); + } + return bound; + } + + void _update_process_order(); + +protected: + bool _get(const StringName &p_path, Variant &r_ret) const; + bool _set(const StringName &p_path, const Variant &p_value); + void _get_property_list(List *p_list) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + enum { + + NOTIFICATION_UPDATE_SKELETON = 50 + }; + + // skeleton creation api + void add_bone(const String &p_name); + int find_bone(const String &p_name) const; + String get_bone_name(int p_bone) const; + + bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const; + + void set_bone_parent(int p_bone, int p_parent); + int get_bone_parent(int p_bone) const; + + void unparent_bone_and_rest(int p_bone); + + void set_bone_disable_rest(int p_bone, bool p_disable); + bool is_bone_rest_disabled(int p_bone) const; + + int get_bone_count() const; + + void set_bone_rest(int p_bone, const Transform &p_rest); + Transform get_bone_rest(int p_bone) const; + Transform get_bone_global_pose(int p_bone) const; + + void clear_bones_global_pose_override(); + void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false); + + void set_bone_enabled(int p_bone, bool p_enabled); + bool is_bone_enabled(int p_bone) const; + + void bind_child_node_to_bone(int p_bone, Node *p_node); + void unbind_child_node_from_bone(int p_bone, Node *p_node); + void get_bound_child_nodes_to_bone(int p_bone, List *p_bound) const; + + void clear_bones(); + + // posing api + + void set_bone_pose(int p_bone, const Transform &p_pose); + Transform get_bone_pose(int p_bone) const; + + void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose); + Transform get_bone_custom_pose(int p_bone) const; + + void localize_rests(); // used for loaders and tools + int get_process_order(int p_idx); + + Ref register_skin(const Ref &p_skin); + +#ifndef _3D_DISABLED + // Physical bone API + + void set_animate_physical_bones(bool p_animate); + bool get_animate_physical_bones() const; + + void bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone); + void unbind_physical_bone_from_bone(int p_bone); + + PhysicalBone3D *get_physical_bone(int p_bone); + PhysicalBone3D *get_physical_bone_parent(int p_bone); + +private: + /// This is a slow API os it's cached + PhysicalBone3D *_get_physical_bone_parent(int p_bone); + void _rebuild_physical_bones_cache(); + +public: + void physical_bones_stop_simulation(); + void physical_bones_start_simulation_on(const Array &p_bones); + void physical_bones_add_collision_exception(RID p_exception); + void physical_bones_remove_collision_exception(RID p_exception); +#endif // _3D_DISABLED + +public: + Skeleton3D(); + ~Skeleton3D(); +}; + +#endif diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp deleted file mode 100644 index 65f868aed4..0000000000 --- a/scene/3d/soft_body.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/*************************************************************************/ -/* soft_body.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "soft_body.h" -#include "core/list.h" -#include "core/object.h" -#include "core/os/os.h" -#include "core/rid.h" -#include "scene/3d/collision_object.h" -#include "scene/3d/physics_body.h" -#include "scene/3d/skeleton.h" -#include "servers/physics_server.h" - -SoftBodyVisualServerHandler::SoftBodyVisualServerHandler() {} - -void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) { - clear(); - - ERR_FAIL_COND(!p_mesh.is_valid()); - - mesh = p_mesh; - surface = p_surface; -#ifndef _MSC_VER -#warning Softbody is not working, needs to be redone considering that these functions no longer exist -#endif -#if 0 - const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface); - const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); - const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); - uint32_t surface_offsets[VS::ARRAY_MAX]; - - buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface); - stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); - offset_vertices = surface_offsets[VS::ARRAY_VERTEX]; - offset_normal = surface_offsets[VS::ARRAY_NORMAL]; -#endif -} - -void SoftBodyVisualServerHandler::clear() { - - if (mesh.is_valid()) { - buffer.resize(0); - } - - mesh = RID(); -} - -void SoftBodyVisualServerHandler::open() { - write_buffer = buffer.ptrw(); -} - -void SoftBodyVisualServerHandler::close() { - //write_buffer.release(); -} - -void SoftBodyVisualServerHandler::commit_changes() { - VS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); -} - -void SoftBodyVisualServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { - copymem(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); -} - -void SoftBodyVisualServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { - copymem(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3); -} - -void SoftBodyVisualServerHandler::set_aabb(const AABB &p_aabb) { - VS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); -} - -SoftBody::PinnedPoint::PinnedPoint() : - point_index(-1), - spatial_attachment(NULL) { -} - -SoftBody::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { - point_index = obj_tocopy.point_index; - spatial_attachment_path = obj_tocopy.spatial_attachment_path; - spatial_attachment = obj_tocopy.spatial_attachment; - offset = obj_tocopy.offset; -} - -SoftBody::PinnedPoint SoftBody::PinnedPoint::operator=(const PinnedPoint &obj) { - point_index = obj.point_index; - spatial_attachment_path = obj.spatial_attachment_path; - spatial_attachment = obj.spatial_attachment; - offset = obj.offset; - return *this; -} - -void SoftBody::_update_pickable() { - if (!is_inside_tree()) - return; - bool pickable = ray_pickable && is_visible_in_tree(); - PhysicsServer::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); -} - -bool SoftBody::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; - String which = name.get_slicec('/', 0); - - if ("pinned_points" == which) { - - return _set_property_pinned_points_indices(p_value); - - } else if ("attachments" == which) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - - return _set_property_pinned_points_attachment(idx, what, p_value); - } - - return false; -} - -bool SoftBody::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; - String which = name.get_slicec('/', 0); - - if ("pinned_points" == which) { - Array arr_ret; - const int pinned_points_indices_size = pinned_points.size(); - const PinnedPoint *r = pinned_points.ptr(); - arr_ret.resize(pinned_points_indices_size); - - for (int i = 0; i < pinned_points_indices_size; ++i) { - arr_ret[i] = r[i].point_index; - } - - r_ret = arr_ret; - return true; - - } else if ("attachments" == which) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - - return _get_property_pinned_points(idx, what, r_ret); - } - - return false; -} - -void SoftBody::_get_property_list(List *p_list) const { - - const int pinned_points_indices_size = pinned_points.size(); - - p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "pinned_points")); - - for (int i = 0; i < pinned_points_indices_size; ++i) { - p_list->push_back(PropertyInfo(Variant::INT, "attachments/" + itos(i) + "/point_index")); - p_list->push_back(PropertyInfo(Variant::NODE_PATH, "attachments/" + itos(i) + "/spatial_attachment_path")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "attachments/" + itos(i) + "/offset")); - } -} - -bool SoftBody::_set_property_pinned_points_indices(const Array &p_indices) { - - const int p_indices_size = p_indices.size(); - - { // Remove the pined points on physics server that will be removed by resize - const PinnedPoint *r = pinned_points.ptr(); - if (p_indices_size < pinned_points.size()) { - for (int i = pinned_points.size() - 1; i >= p_indices_size; --i) { - pin_point(r[i].point_index, false); - } - } - } - - pinned_points.resize(p_indices_size); - - PinnedPoint *w = pinned_points.ptrw(); - int point_index; - for (int i = 0; i < p_indices_size; ++i) { - point_index = p_indices.get(i); - if (w[i].point_index != point_index) { - if (-1 != w[i].point_index) - pin_point(w[i].point_index, false); - w[i].point_index = point_index; - pin_point(w[i].point_index, true); - } - } - return true; -} - -bool SoftBody::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { - if (pinned_points.size() <= p_item) { - return false; - } - - if ("spatial_attachment_path" == p_what) { - PinnedPoint *w = pinned_points.ptrw(); - pin_point(w[p_item].point_index, true, p_value); - _make_cache_dirty(); - } else if ("offset" == p_what) { - PinnedPoint *w = pinned_points.ptrw(); - w[p_item].offset = p_value; - } else { - return false; - } - - return true; -} - -bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { - if (pinned_points.size() <= p_item) { - return false; - } - const PinnedPoint *r = pinned_points.ptr(); - - if ("point_index" == p_what) { - r_ret = r[p_item].point_index; - } else if ("spatial_attachment_path" == p_what) { - r_ret = r[p_item].spatial_attachment_path; - } else if ("offset" == p_what) { - r_ret = r[p_item].offset; - } else { - return false; - } - - return true; -} - -void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) { - prepare_physics_server(); - _reset_points_offsets(); -#ifdef TOOLS_ENABLED - if (p_changed == this) { - update_configuration_warning(); - } -#endif -} - -void SoftBody::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_WORLD: { - - if (Engine::get_singleton()->is_editor_hint()) { - - add_change_receptor(this); - } - - RID space = get_world()->get_space(); - PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); - prepare_physics_server(); - } break; - case NOTIFICATION_READY: { - if (!parent_collision_ignore.is_empty()) - add_collision_exception_with(get_node(parent_collision_ignore)); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - if (Engine::get_singleton()->is_editor_hint()) { - _reset_points_offsets(); - return; - } - - PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); - - set_notify_transform(false); - // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform - set_as_toplevel(true); - set_transform(Transform()); - set_notify_transform(true); - - } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - - _update_pickable(); - - } break; - case NOTIFICATION_EXIT_WORLD: { - - PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, RID()); - - } break; - } - -#ifdef TOOLS_ENABLED - - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warning(); - } - } - -#endif -} - -void SoftBody::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody::get_collision_layer); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &SoftBody::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &SoftBody::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &SoftBody::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &SoftBody::get_collision_layer_bit); - - ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody::set_parent_collision_ignore); - ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody::get_parent_collision_ignore); - - ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody::get_collision_exceptions); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody::remove_collision_exception_with); - - ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody::set_simulation_precision); - ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody::get_simulation_precision); - - ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody::set_total_mass); - ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody::get_total_mass); - - ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody::set_linear_stiffness); - ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody::get_linear_stiffness); - - ClassDB::bind_method(D_METHOD("set_areaAngular_stiffness", "areaAngular_stiffness"), &SoftBody::set_areaAngular_stiffness); - ClassDB::bind_method(D_METHOD("get_areaAngular_stiffness"), &SoftBody::get_areaAngular_stiffness); - - ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody::set_volume_stiffness); - ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody::get_volume_stiffness); - - ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody::set_pressure_coefficient); - ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody::get_pressure_coefficient); - - ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody::set_pose_matching_coefficient); - ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody::get_pose_matching_coefficient); - - ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody::set_damping_coefficient); - ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody::get_damping_coefficient); - - ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody::set_drag_coefficient); - ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody::get_drag_coefficient); - - ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody::set_ray_pickable); - ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody::is_ray_pickable); - - ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "parent_collision_ignore", PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, "Parent collision object"), "set_parent_collision_ignore", "get_parent_collision_ignore"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient"); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); -} - -String SoftBody::get_configuration_warning() const { - - String warning = MeshInstance::get_configuration_warning(); - - if (get_mesh().is_null()) { - if (!warning.empty()) - warning += "\n\n"; - - warning += TTR("This body will be ignored until you set a mesh."); - } - - Transform t = get_transform(); - if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { - if (!warning.empty()) - warning += "\n\n"; - - warning += TTR("Size changes to SoftBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); - } - - return warning; -} - -void SoftBody::_update_physics_server() { - if (!simulation_started) - return; - - _update_cache_pin_points_datas(); - // Submit bone attachment - const int pinned_points_indices_size = pinned_points.size(); - const PinnedPoint *r = pinned_points.ptr(); - for (int i = 0; i < pinned_points_indices_size; ++i) { - if (r[i].spatial_attachment) { - PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); - } - } -} - -void SoftBody::_draw_soft_mesh() { - if (get_mesh().is_null()) - return; - - if (!visual_server_handler.is_ready()) { - - visual_server_handler.prepare(get_mesh()->get_rid(), 0); - - /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) - simulation_started = true; - call_deferred("set_as_toplevel", true); - call_deferred("set_transform", Transform()); - } - - _update_physics_server(); - - visual_server_handler.open(); - PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); - visual_server_handler.close(); - - visual_server_handler.commit_changes(); -} - -void SoftBody::prepare_physics_server() { - - if (Engine::get_singleton()->is_editor_hint()) { - - if (get_mesh().is_valid()) - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); - else - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); - - return; - } - - if (get_mesh().is_valid()) { - - become_mesh_owner(); - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); - VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh)); - } else { - - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); - if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh))) { - VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody::_draw_soft_mesh)); - } - } -} - -void SoftBody::become_mesh_owner() { - if (mesh.is_null()) - return; - - if (!mesh_owner) { - mesh_owner = true; - - Vector> copy_materials; - copy_materials.append_array(materials); - - ERR_FAIL_COND(!mesh->get_surface_count()); - - // Get current mesh array and create new mesh array with necessary flag for softbody - Array surface_arrays = mesh->surface_get_arrays(0); - Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); - Dictionary surface_lods = mesh->surface_get_lods(0); - uint32_t surface_format = mesh->surface_get_format(0); - - surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL); - surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; - - Ref soft_mesh; - soft_mesh.instance(); - soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format); - soft_mesh->surface_set_material(0, mesh->surface_get_material(0)); - - set_mesh(soft_mesh); - - for (int i = copy_materials.size() - 1; 0 <= i; --i) { - set_surface_material(i, copy_materials[i]); - } - } -} - -void SoftBody::set_collision_mask(uint32_t p_mask) { - collision_mask = p_mask; - PhysicsServer::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); -} - -uint32_t SoftBody::get_collision_mask() const { - return collision_mask; -} -void SoftBody::set_collision_layer(uint32_t p_layer) { - collision_layer = p_layer; - PhysicsServer::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); -} - -uint32_t SoftBody::get_collision_layer() const { - return collision_layer; -} - -void SoftBody::set_collision_mask_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool SoftBody::get_collision_mask_bit(int p_bit) const { - return get_collision_mask() & (1 << p_bit); -} - -void SoftBody::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t layer = get_collision_layer(); - if (p_value) - layer |= 1 << p_bit; - else - layer &= ~(1 << p_bit); - set_collision_layer(layer); -} - -bool SoftBody::get_collision_layer_bit(int p_bit) const { - return get_collision_layer() & (1 << p_bit); -} - -void SoftBody::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { - parent_collision_ignore = p_parent_collision_ignore; -} - -const NodePath &SoftBody::get_parent_collision_ignore() const { - return parent_collision_ignore; -} - -void SoftBody::set_pinned_points_indices(Vector p_pinned_points_indices) { - pinned_points = p_pinned_points_indices; - for (int i = pinned_points.size() - 1; 0 <= i; --i) { - pin_point(p_pinned_points_indices[i].point_index, true); - } -} - -Vector SoftBody::get_pinned_points_indices() { - return pinned_points; -} - -Array SoftBody::get_collision_exceptions() { - List exceptions; - PhysicsServer::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); - Array ret; - for (List::Element *E = exceptions.front(); E; E = E->next()) { - RID body = E->get(); - ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); - Object *obj = ObjectDB::get_instance(instance_id); - PhysicsBody *physics_body = Object::cast_to(obj); - ret.append(physics_body); - } - return ret; -} - -void SoftBody::add_collision_exception_with(Node *p_node) { - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); -} - -void SoftBody::remove_collision_exception_with(Node *p_node) { - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); -} - -int SoftBody::get_simulation_precision() { - return PhysicsServer::get_singleton()->soft_body_get_simulation_precision(physics_rid); -} - -void SoftBody::set_simulation_precision(int p_simulation_precision) { - PhysicsServer::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); -} - -real_t SoftBody::get_total_mass() { - return PhysicsServer::get_singleton()->soft_body_get_total_mass(physics_rid); -} - -void SoftBody::set_total_mass(real_t p_total_mass) { - PhysicsServer::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); -} - -void SoftBody::set_linear_stiffness(real_t p_linear_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); -} - -real_t SoftBody::get_linear_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_linear_stiffness(physics_rid); -} - -void SoftBody::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness); -} - -real_t SoftBody::get_areaAngular_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid); -} - -void SoftBody::set_volume_stiffness(real_t p_volume_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); -} - -real_t SoftBody::get_volume_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_volume_stiffness(physics_rid); -} - -real_t SoftBody::get_pressure_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); -} - -void SoftBody::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); -} - -real_t SoftBody::get_pose_matching_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); -} - -void SoftBody::set_pressure_coefficient(real_t p_pressure_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); -} - -real_t SoftBody::get_damping_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_damping_coefficient(physics_rid); -} - -void SoftBody::set_damping_coefficient(real_t p_damping_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); -} - -real_t SoftBody::get_drag_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_drag_coefficient(physics_rid); -} - -void SoftBody::set_drag_coefficient(real_t p_drag_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); -} - -Vector3 SoftBody::get_point_transform(int p_point_index) { - return PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); -} - -void SoftBody::pin_point_toggle(int p_point_index) { - pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index))); -} - -void SoftBody::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { - _pin_point_on_physics_server(p_point_index, pin); - if (pin) { - _add_pinned_point(p_point_index, p_spatial_attachment_path); - } else { - _remove_pinned_point(p_point_index); - } -} - -bool SoftBody::is_point_pinned(int p_point_index) const { - return -1 != _has_pinned_point(p_point_index); -} - -void SoftBody::set_ray_pickable(bool p_ray_pickable) { - - ray_pickable = p_ray_pickable; - _update_pickable(); -} - -bool SoftBody::is_ray_pickable() const { - - return ray_pickable; -} - -SoftBody::SoftBody() : - physics_rid(PhysicsServer::get_singleton()->soft_body_create()), - mesh_owner(false), - collision_mask(1), - collision_layer(1), - simulation_started(false), - pinned_points_cache_dirty(true), - ray_pickable(true) { - - PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); -} - -SoftBody::~SoftBody() { - PhysicsServer::get_singleton()->free(physics_rid); -} - -void SoftBody::reset_softbody_pin() { - PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid); - const PinnedPoint *pps = pinned_points.ptr(); - for (int i = pinned_points.size() - 1; 0 < i; --i) { - PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); - } -} - -void SoftBody::_make_cache_dirty() { - pinned_points_cache_dirty = true; -} - -void SoftBody::_update_cache_pin_points_datas() { - if (!pinned_points_cache_dirty) - return; - - pinned_points_cache_dirty = false; - - PinnedPoint *w = pinned_points.ptrw(); - for (int i = pinned_points.size() - 1; 0 <= i; --i) { - - if (!w[i].spatial_attachment_path.is_empty()) { - w[i].spatial_attachment = Object::cast_to(get_node(w[i].spatial_attachment_path)); - } - if (!w[i].spatial_attachment) { - ERR_PRINT("Spatial node not defined in the pinned point, Softbody undefined behaviour!"); - } - } -} - -void SoftBody::_pin_point_on_physics_server(int p_point_index, bool pin) { - PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); -} - -void SoftBody::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { - SoftBody::PinnedPoint *pinned_point; - if (-1 == _get_pinned_point(p_point_index, pinned_point)) { - - // Create new - PinnedPoint pp; - pp.point_index = p_point_index; - pp.spatial_attachment_path = p_spatial_attachment_path; - - if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { - pp.spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); - pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index)); - } - - pinned_points.push_back(pp); - - } else { - - pinned_point->point_index = p_point_index; - pinned_point->spatial_attachment_path = p_spatial_attachment_path; - - if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { - pinned_point->spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); - pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index)); - } - } -} - -void SoftBody::_reset_points_offsets() { - - if (!Engine::get_singleton()->is_editor_hint()) - return; - - const PinnedPoint *r = pinned_points.ptr(); - PinnedPoint *w = pinned_points.ptrw(); - for (int i = pinned_points.size() - 1; 0 <= i; --i) { - - if (!r[i].spatial_attachment) - w[i].spatial_attachment = Object::cast_to(get_node(r[i].spatial_attachment_path)); - - if (!r[i].spatial_attachment) - continue; - - w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index)); - } -} - -void SoftBody::_remove_pinned_point(int p_point_index) { - const int id(_has_pinned_point(p_point_index)); - if (-1 != id) { - pinned_points.remove(id); - } -} - -int SoftBody::_get_pinned_point(int p_point_index, SoftBody::PinnedPoint *&r_point) const { - const int id = _has_pinned_point(p_point_index); - if (-1 == id) { - r_point = NULL; - return -1; - } else { - r_point = const_cast(&pinned_points.ptr()[id]); - return id; - } -} - -int SoftBody::_has_pinned_point(int p_point_index) const { - const PinnedPoint *r = pinned_points.ptr(); - for (int i = pinned_points.size() - 1; 0 <= i; --i) { - if (p_point_index == r[i].point_index) { - return i; - } - } - return -1; -} diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h deleted file mode 100644 index d6c35a5989..0000000000 --- a/scene/3d/soft_body.h +++ /dev/null @@ -1,202 +0,0 @@ -/*************************************************************************/ -/* soft_body.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SOFT_PHYSICS_BODY_H -#define SOFT_PHYSICS_BODY_H - -#include "scene/3d/mesh_instance.h" - -class SoftBody; - -class SoftBodyVisualServerHandler { - - friend class SoftBody; - - RID mesh; - int surface; - Vector buffer; - uint32_t stride; - uint32_t offset_vertices; - uint32_t offset_normal; - - uint8_t *write_buffer; - -private: - SoftBodyVisualServerHandler(); - bool is_ready() { return mesh.is_valid(); } - void prepare(RID p_mesh_rid, int p_surface); - void clear(); - void open(); - void close(); - void commit_changes(); - -public: - void set_vertex(int p_vertex_id, const void *p_vector3); - void set_normal(int p_vertex_id, const void *p_vector3); - void set_aabb(const AABB &p_aabb); -}; - -class SoftBody : public MeshInstance { - GDCLASS(SoftBody, MeshInstance); - -public: - struct PinnedPoint { - int point_index; - NodePath spatial_attachment_path; - Spatial *spatial_attachment; // Cache - Vector3 offset; - - PinnedPoint(); - PinnedPoint(const PinnedPoint &obj_tocopy); - PinnedPoint operator=(const PinnedPoint &obj); - }; - -private: - SoftBodyVisualServerHandler visual_server_handler; - - RID physics_rid; - - bool mesh_owner; - uint32_t collision_mask; - uint32_t collision_layer; - NodePath parent_collision_ignore; - Vector pinned_points; - bool simulation_started; - bool pinned_points_cache_dirty; - - Ref debug_mesh_cache; - class MeshInstance *debug_mesh; - - bool capture_input_on_drag; - bool ray_pickable; - - void _update_pickable(); - -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 *p_list) const; - - bool _set_property_pinned_points_indices(const Array &p_indices); - bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value); - bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const; - - virtual void _changed_callback(Object *p_changed, const char *p_prop); - - void _notification(int p_what); - static void _bind_methods(); - - virtual String get_configuration_warning() const; - -protected: - void _update_physics_server(); - void _draw_soft_mesh(); - -public: - void prepare_physics_server(); - void become_mesh_owner(); - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; - - void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore); - const NodePath &get_parent_collision_ignore() const; - - void set_pinned_points_indices(Vector p_pinned_points_indices); - Vector get_pinned_points_indices(); - - void set_simulation_precision(int p_simulation_precision); - int get_simulation_precision(); - - void set_total_mass(real_t p_total_mass); - real_t get_total_mass(); - - void set_linear_stiffness(real_t p_linear_stiffness); - real_t get_linear_stiffness(); - - void set_areaAngular_stiffness(real_t p_areaAngular_stiffness); - real_t get_areaAngular_stiffness(); - - void set_volume_stiffness(real_t p_volume_stiffness); - real_t get_volume_stiffness(); - - void set_pressure_coefficient(real_t p_pressure_coefficient); - real_t get_pressure_coefficient(); - - void set_pose_matching_coefficient(real_t p_pose_matching_coefficient); - real_t get_pose_matching_coefficient(); - - void set_damping_coefficient(real_t p_damping_coefficient); - real_t get_damping_coefficient(); - - void set_drag_coefficient(real_t p_drag_coefficient); - real_t get_drag_coefficient(); - - Array get_collision_exceptions(); - void add_collision_exception_with(Node *p_node); - void remove_collision_exception_with(Node *p_node); - - Vector3 get_point_transform(int p_point_index); - - void pin_point_toggle(int p_point_index); - void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath()); - bool is_point_pinned(int p_point_index) const; - - void set_ray_pickable(bool p_ray_pickable); - bool is_ray_pickable() const; - - SoftBody(); - ~SoftBody(); - -private: - void reset_softbody_pin(); - - void _make_cache_dirty(); - void _update_cache_pin_points_datas(); - - void _pin_point_on_physics_server(int p_point_index, bool pin); - void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path); - void _reset_points_offsets(); - - void _remove_pinned_point(int p_point_index); - int _get_pinned_point(int p_point_index, PinnedPoint *&r_point) const; - int _has_pinned_point(int p_point_index) const; -}; - -#endif // SOFT_PHYSICS_BODY_H diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp new file mode 100644 index 0000000000..6c93c3c1c7 --- /dev/null +++ b/scene/3d/soft_body_3d.cpp @@ -0,0 +1,826 @@ +/*************************************************************************/ +/* soft_body_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "soft_body_3d.h" +#include "core/list.h" +#include "core/object.h" +#include "core/os/os.h" +#include "core/rid.h" +#include "scene/3d/collision_object_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/3d/skeleton_3d.h" +#include "servers/physics_server.h" + +SoftBodyVisualServerHandler::SoftBodyVisualServerHandler() {} + +void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) { + clear(); + + ERR_FAIL_COND(!p_mesh.is_valid()); + + mesh = p_mesh; + surface = p_surface; +#ifndef _MSC_VER +#warning Softbody is not working, needs to be redone considering that these functions no longer exist +#endif +#if 0 + const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface); + const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); + const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); + uint32_t surface_offsets[VS::ARRAY_MAX]; + + buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface); + stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); + offset_vertices = surface_offsets[VS::ARRAY_VERTEX]; + offset_normal = surface_offsets[VS::ARRAY_NORMAL]; +#endif +} + +void SoftBodyVisualServerHandler::clear() { + + if (mesh.is_valid()) { + buffer.resize(0); + } + + mesh = RID(); +} + +void SoftBodyVisualServerHandler::open() { + write_buffer = buffer.ptrw(); +} + +void SoftBodyVisualServerHandler::close() { + //write_buffer.release(); +} + +void SoftBodyVisualServerHandler::commit_changes() { + VS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); +} + +void SoftBodyVisualServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { + copymem(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); +} + +void SoftBodyVisualServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { + copymem(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3); +} + +void SoftBodyVisualServerHandler::set_aabb(const AABB &p_aabb) { + VS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); +} + +SoftBody3D::PinnedPoint::PinnedPoint() : + point_index(-1), + spatial_attachment(NULL) { +} + +SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { + point_index = obj_tocopy.point_index; + spatial_attachment_path = obj_tocopy.spatial_attachment_path; + spatial_attachment = obj_tocopy.spatial_attachment; + offset = obj_tocopy.offset; +} + +SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { + point_index = obj.point_index; + spatial_attachment_path = obj.spatial_attachment_path; + spatial_attachment = obj.spatial_attachment; + offset = obj.offset; + return *this; +} + +void SoftBody3D::_update_pickable() { + if (!is_inside_tree()) + return; + bool pickable = ray_pickable && is_visible_in_tree(); + PhysicsServer::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); +} + +bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + String which = name.get_slicec('/', 0); + + if ("pinned_points" == which) { + + return _set_property_pinned_points_indices(p_value); + + } else if ("attachments" == which) { + + int idx = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + + return _set_property_pinned_points_attachment(idx, what, p_value); + } + + return false; +} + +bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const { + String name = p_name; + String which = name.get_slicec('/', 0); + + if ("pinned_points" == which) { + Array arr_ret; + const int pinned_points_indices_size = pinned_points.size(); + const PinnedPoint *r = pinned_points.ptr(); + arr_ret.resize(pinned_points_indices_size); + + for (int i = 0; i < pinned_points_indices_size; ++i) { + arr_ret[i] = r[i].point_index; + } + + r_ret = arr_ret; + return true; + + } else if ("attachments" == which) { + + int idx = name.get_slicec('/', 1).to_int(); + String what = name.get_slicec('/', 2); + + return _get_property_pinned_points(idx, what, r_ret); + } + + return false; +} + +void SoftBody3D::_get_property_list(List *p_list) const { + + const int pinned_points_indices_size = pinned_points.size(); + + p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "pinned_points")); + + for (int i = 0; i < pinned_points_indices_size; ++i) { + p_list->push_back(PropertyInfo(Variant::INT, "attachments/" + itos(i) + "/point_index")); + p_list->push_back(PropertyInfo(Variant::NODE_PATH, "attachments/" + itos(i) + "/spatial_attachment_path")); + p_list->push_back(PropertyInfo(Variant::VECTOR3, "attachments/" + itos(i) + "/offset")); + } +} + +bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) { + + const int p_indices_size = p_indices.size(); + + { // Remove the pined points on physics server that will be removed by resize + const PinnedPoint *r = pinned_points.ptr(); + if (p_indices_size < pinned_points.size()) { + for (int i = pinned_points.size() - 1; i >= p_indices_size; --i) { + pin_point(r[i].point_index, false); + } + } + } + + pinned_points.resize(p_indices_size); + + PinnedPoint *w = pinned_points.ptrw(); + int point_index; + for (int i = 0; i < p_indices_size; ++i) { + point_index = p_indices.get(i); + if (w[i].point_index != point_index) { + if (-1 != w[i].point_index) + pin_point(w[i].point_index, false); + w[i].point_index = point_index; + pin_point(w[i].point_index, true); + } + } + return true; +} + +bool SoftBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { + if (pinned_points.size() <= p_item) { + return false; + } + + if ("spatial_attachment_path" == p_what) { + PinnedPoint *w = pinned_points.ptrw(); + pin_point(w[p_item].point_index, true, p_value); + _make_cache_dirty(); + } else if ("offset" == p_what) { + PinnedPoint *w = pinned_points.ptrw(); + w[p_item].offset = p_value; + } else { + return false; + } + + return true; +} + +bool SoftBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { + if (pinned_points.size() <= p_item) { + return false; + } + const PinnedPoint *r = pinned_points.ptr(); + + if ("point_index" == p_what) { + r_ret = r[p_item].point_index; + } else if ("spatial_attachment_path" == p_what) { + r_ret = r[p_item].spatial_attachment_path; + } else if ("offset" == p_what) { + r_ret = r[p_item].offset; + } else { + return false; + } + + return true; +} + +void SoftBody3D::_changed_callback(Object *p_changed, const char *p_prop) { + prepare_physics_server(); + _reset_points_offsets(); +#ifdef TOOLS_ENABLED + if (p_changed == this) { + update_configuration_warning(); + } +#endif +} + +void SoftBody3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_WORLD: { + + if (Engine::get_singleton()->is_editor_hint()) { + + add_change_receptor(this); + } + + RID space = get_world()->get_space(); + PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); + prepare_physics_server(); + } break; + case NOTIFICATION_READY: { + if (!parent_collision_ignore.is_empty()) + add_collision_exception_with(get_node(parent_collision_ignore)); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (Engine::get_singleton()->is_editor_hint()) { + _reset_points_offsets(); + return; + } + + PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); + + set_notify_transform(false); + // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform + set_as_toplevel(true); + set_transform(Transform()); + set_notify_transform(true); + + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + + } break; + case NOTIFICATION_EXIT_WORLD: { + + PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, RID()); + + } break; + } + +#ifdef TOOLS_ENABLED + + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (Engine::get_singleton()->is_editor_hint()) { + update_configuration_warning(); + } + } + +#endif +} + +void SoftBody3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody3D::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &SoftBody3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &SoftBody3D::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &SoftBody3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &SoftBody3D::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore); + + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with); + + ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody3D::set_simulation_precision); + ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody3D::get_simulation_precision); + + ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody3D::set_total_mass); + ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody3D::get_total_mass); + + ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness); + ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness); + + ClassDB::bind_method(D_METHOD("set_areaAngular_stiffness", "areaAngular_stiffness"), &SoftBody3D::set_areaAngular_stiffness); + ClassDB::bind_method(D_METHOD("get_areaAngular_stiffness"), &SoftBody3D::get_areaAngular_stiffness); + + ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody3D::set_volume_stiffness); + ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody3D::get_volume_stiffness); + + ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient); + ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient); + + ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody3D::set_pose_matching_coefficient); + ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody3D::get_pose_matching_coefficient); + + ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient); + ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient); + + ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody3D::set_drag_coefficient); + ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody3D::get_drag_coefficient); + + ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody3D::set_ray_pickable); + ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody3D::is_ray_pickable); + + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "parent_collision_ignore", PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, "Parent collision object"), "set_parent_collision_ignore", "get_parent_collision_ignore"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "areaAngular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_areaAngular_stiffness", "get_areaAngular_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); +} + +String SoftBody3D::get_configuration_warning() const { + + String warning = MeshInstance3D::get_configuration_warning(); + + if (get_mesh().is_null()) { + if (!warning.empty()) + warning += "\n\n"; + + warning += TTR("This body will be ignored until you set a mesh."); + } + + Transform t = get_transform(); + if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { + if (!warning.empty()) + warning += "\n\n"; + + warning += TTR("Size changes to SoftBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); + } + + return warning; +} + +void SoftBody3D::_update_physics_server() { + if (!simulation_started) + return; + + _update_cache_pin_points_datas(); + // Submit bone attachment + const int pinned_points_indices_size = pinned_points.size(); + const PinnedPoint *r = pinned_points.ptr(); + for (int i = 0; i < pinned_points_indices_size; ++i) { + if (r[i].spatial_attachment) { + PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); + } + } +} + +void SoftBody3D::_draw_soft_mesh() { + if (get_mesh().is_null()) + return; + + if (!visual_server_handler.is_ready()) { + + visual_server_handler.prepare(get_mesh()->get_rid(), 0); + + /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) + simulation_started = true; + call_deferred("set_as_toplevel", true); + call_deferred("set_transform", Transform()); + } + + _update_physics_server(); + + visual_server_handler.open(); + PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); + visual_server_handler.close(); + + visual_server_handler.commit_changes(); +} + +void SoftBody3D::prepare_physics_server() { + + if (Engine::get_singleton()->is_editor_hint()) { + + if (get_mesh().is_valid()) + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); + else + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + + return; + } + + if (get_mesh().is_valid()) { + + become_mesh_owner(); + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); + VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); + } else { + + PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) { + VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); + } + } +} + +void SoftBody3D::become_mesh_owner() { + if (mesh.is_null()) + return; + + if (!mesh_owner) { + mesh_owner = true; + + Vector> copy_materials; + copy_materials.append_array(materials); + + ERR_FAIL_COND(!mesh->get_surface_count()); + + // Get current mesh array and create new mesh array with necessary flag for softbody + Array surface_arrays = mesh->surface_get_arrays(0); + Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); + Dictionary surface_lods = mesh->surface_get_lods(0); + uint32_t surface_format = mesh->surface_get_format(0); + + surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL); + surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; + + Ref soft_mesh; + soft_mesh.instance(); + soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format); + soft_mesh->surface_set_material(0, mesh->surface_get_material(0)); + + set_mesh(soft_mesh); + + for (int i = copy_materials.size() - 1; 0 <= i; --i) { + set_surface_material(i, copy_materials[i]); + } + } +} + +void SoftBody3D::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; + PhysicsServer::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); +} + +uint32_t SoftBody3D::get_collision_mask() const { + return collision_mask; +} +void SoftBody3D::set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + PhysicsServer::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); +} + +uint32_t SoftBody3D::get_collision_layer() const { + return collision_layer; +} + +void SoftBody3D::set_collision_mask_bit(int p_bit, bool p_value) { + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool SoftBody3D::get_collision_mask_bit(int p_bit) const { + return get_collision_mask() & (1 << p_bit); +} + +void SoftBody3D::set_collision_layer_bit(int p_bit, bool p_value) { + uint32_t layer = get_collision_layer(); + if (p_value) + layer |= 1 << p_bit; + else + layer &= ~(1 << p_bit); + set_collision_layer(layer); +} + +bool SoftBody3D::get_collision_layer_bit(int p_bit) const { + return get_collision_layer() & (1 << p_bit); +} + +void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { + parent_collision_ignore = p_parent_collision_ignore; +} + +const NodePath &SoftBody3D::get_parent_collision_ignore() const { + return parent_collision_ignore; +} + +void SoftBody3D::set_pinned_points_indices(Vector p_pinned_points_indices) { + pinned_points = p_pinned_points_indices; + for (int i = pinned_points.size() - 1; 0 <= i; --i) { + pin_point(p_pinned_points_indices[i].point_index, true); + } +} + +Vector SoftBody3D::get_pinned_points_indices() { + return pinned_points; +} + +Array SoftBody3D::get_collision_exceptions() { + List exceptions; + PhysicsServer::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); + Array ret; + for (List::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + PhysicsBody3D *physics_body = Object::cast_to(obj); + ret.append(physics_body); + } + return ret; +} + +void SoftBody3D::add_collision_exception_with(Node *p_node) { + ERR_FAIL_NULL(p_node); + CollisionObject3D *collision_object = Object::cast_to(p_node); + ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); + PhysicsServer::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); +} + +void SoftBody3D::remove_collision_exception_with(Node *p_node) { + ERR_FAIL_NULL(p_node); + CollisionObject3D *collision_object = Object::cast_to(p_node); + ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); + PhysicsServer::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); +} + +int SoftBody3D::get_simulation_precision() { + return PhysicsServer::get_singleton()->soft_body_get_simulation_precision(physics_rid); +} + +void SoftBody3D::set_simulation_precision(int p_simulation_precision) { + PhysicsServer::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); +} + +real_t SoftBody3D::get_total_mass() { + return PhysicsServer::get_singleton()->soft_body_get_total_mass(physics_rid); +} + +void SoftBody3D::set_total_mass(real_t p_total_mass) { + PhysicsServer::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); +} + +void SoftBody3D::set_linear_stiffness(real_t p_linear_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); +} + +real_t SoftBody3D::get_linear_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_linear_stiffness(physics_rid); +} + +void SoftBody3D::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness); +} + +real_t SoftBody3D::get_areaAngular_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid); +} + +void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) { + PhysicsServer::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); +} + +real_t SoftBody3D::get_volume_stiffness() { + return PhysicsServer::get_singleton()->soft_body_get_volume_stiffness(physics_rid); +} + +real_t SoftBody3D::get_pressure_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); +} + +void SoftBody3D::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); +} + +real_t SoftBody3D::get_pose_matching_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); +} + +void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); +} + +real_t SoftBody3D::get_damping_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_damping_coefficient(physics_rid); +} + +void SoftBody3D::set_damping_coefficient(real_t p_damping_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); +} + +real_t SoftBody3D::get_drag_coefficient() { + return PhysicsServer::get_singleton()->soft_body_get_drag_coefficient(physics_rid); +} + +void SoftBody3D::set_drag_coefficient(real_t p_drag_coefficient) { + PhysicsServer::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); +} + +Vector3 SoftBody3D::get_point_transform(int p_point_index) { + return PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); +} + +void SoftBody3D::pin_point_toggle(int p_point_index) { + pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index))); +} + +void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { + _pin_point_on_physics_server(p_point_index, pin); + if (pin) { + _add_pinned_point(p_point_index, p_spatial_attachment_path); + } else { + _remove_pinned_point(p_point_index); + } +} + +bool SoftBody3D::is_point_pinned(int p_point_index) const { + return -1 != _has_pinned_point(p_point_index); +} + +void SoftBody3D::set_ray_pickable(bool p_ray_pickable) { + + ray_pickable = p_ray_pickable; + _update_pickable(); +} + +bool SoftBody3D::is_ray_pickable() const { + + return ray_pickable; +} + +SoftBody3D::SoftBody3D() : + physics_rid(PhysicsServer::get_singleton()->soft_body_create()), + mesh_owner(false), + collision_mask(1), + collision_layer(1), + simulation_started(false), + pinned_points_cache_dirty(true), + ray_pickable(true) { + + PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); +} + +SoftBody3D::~SoftBody3D() { + PhysicsServer::get_singleton()->free(physics_rid); +} + +void SoftBody3D::reset_softbody_pin() { + PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid); + const PinnedPoint *pps = pinned_points.ptr(); + for (int i = pinned_points.size() - 1; 0 < i; --i) { + PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); + } +} + +void SoftBody3D::_make_cache_dirty() { + pinned_points_cache_dirty = true; +} + +void SoftBody3D::_update_cache_pin_points_datas() { + if (!pinned_points_cache_dirty) + return; + + pinned_points_cache_dirty = false; + + PinnedPoint *w = pinned_points.ptrw(); + for (int i = pinned_points.size() - 1; 0 <= i; --i) { + + if (!w[i].spatial_attachment_path.is_empty()) { + w[i].spatial_attachment = Object::cast_to(get_node(w[i].spatial_attachment_path)); + } + if (!w[i].spatial_attachment) { + ERR_PRINT("Node3D node not defined in the pinned point, Softbody undefined behaviour!"); + } + } +} + +void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { + PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); +} + +void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { + SoftBody3D::PinnedPoint *pinned_point; + if (-1 == _get_pinned_point(p_point_index, pinned_point)) { + + // Create new + PinnedPoint pp; + pp.point_index = p_point_index; + pp.spatial_attachment_path = p_spatial_attachment_path; + + if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { + pp.spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); + pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index)); + } + + pinned_points.push_back(pp); + + } else { + + pinned_point->point_index = p_point_index; + pinned_point->spatial_attachment_path = p_spatial_attachment_path; + + if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { + pinned_point->spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); + pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index)); + } + } +} + +void SoftBody3D::_reset_points_offsets() { + + if (!Engine::get_singleton()->is_editor_hint()) + return; + + const PinnedPoint *r = pinned_points.ptr(); + PinnedPoint *w = pinned_points.ptrw(); + for (int i = pinned_points.size() - 1; 0 <= i; --i) { + + if (!r[i].spatial_attachment) + w[i].spatial_attachment = Object::cast_to(get_node(r[i].spatial_attachment_path)); + + if (!r[i].spatial_attachment) + continue; + + w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index)); + } +} + +void SoftBody3D::_remove_pinned_point(int p_point_index) { + const int id(_has_pinned_point(p_point_index)); + if (-1 != id) { + pinned_points.remove(id); + } +} + +int SoftBody3D::_get_pinned_point(int p_point_index, SoftBody3D::PinnedPoint *&r_point) const { + const int id = _has_pinned_point(p_point_index); + if (-1 == id) { + r_point = NULL; + return -1; + } else { + r_point = const_cast(&pinned_points.ptr()[id]); + return id; + } +} + +int SoftBody3D::_has_pinned_point(int p_point_index) const { + const PinnedPoint *r = pinned_points.ptr(); + for (int i = pinned_points.size() - 1; 0 <= i; --i) { + if (p_point_index == r[i].point_index) { + return i; + } + } + return -1; +} diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h new file mode 100644 index 0000000000..a1a4b4fa2f --- /dev/null +++ b/scene/3d/soft_body_3d.h @@ -0,0 +1,202 @@ +/*************************************************************************/ +/* soft_body_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SOFT_PHYSICS_BODY_H +#define SOFT_PHYSICS_BODY_H + +#include "scene/3d/mesh_instance_3d.h" + +class SoftBody3D; + +class SoftBodyVisualServerHandler { + + friend class SoftBody3D; + + RID mesh; + int surface; + Vector buffer; + uint32_t stride; + uint32_t offset_vertices; + uint32_t offset_normal; + + uint8_t *write_buffer; + +private: + SoftBodyVisualServerHandler(); + bool is_ready() { return mesh.is_valid(); } + void prepare(RID p_mesh_rid, int p_surface); + void clear(); + void open(); + void close(); + void commit_changes(); + +public: + void set_vertex(int p_vertex_id, const void *p_vector3); + void set_normal(int p_vertex_id, const void *p_vector3); + void set_aabb(const AABB &p_aabb); +}; + +class SoftBody3D : public MeshInstance3D { + GDCLASS(SoftBody3D, MeshInstance3D); + +public: + struct PinnedPoint { + int point_index; + NodePath spatial_attachment_path; + Node3D *spatial_attachment; // Cache + Vector3 offset; + + PinnedPoint(); + PinnedPoint(const PinnedPoint &obj_tocopy); + PinnedPoint operator=(const PinnedPoint &obj); + }; + +private: + SoftBodyVisualServerHandler visual_server_handler; + + RID physics_rid; + + bool mesh_owner; + uint32_t collision_mask; + uint32_t collision_layer; + NodePath parent_collision_ignore; + Vector pinned_points; + bool simulation_started; + bool pinned_points_cache_dirty; + + Ref debug_mesh_cache; + class MeshInstance3D *debug_mesh; + + bool capture_input_on_drag; + bool ray_pickable; + + void _update_pickable(); + +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 *p_list) const; + + bool _set_property_pinned_points_indices(const Array &p_indices); + bool _set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value); + bool _get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const; + + virtual void _changed_callback(Object *p_changed, const char *p_prop); + + void _notification(int p_what); + static void _bind_methods(); + + virtual String get_configuration_warning() const; + +protected: + void _update_physics_server(); + void _draw_soft_mesh(); + +public: + void prepare_physics_server(); + void become_mesh_owner(); + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore); + const NodePath &get_parent_collision_ignore() const; + + void set_pinned_points_indices(Vector p_pinned_points_indices); + Vector get_pinned_points_indices(); + + void set_simulation_precision(int p_simulation_precision); + int get_simulation_precision(); + + void set_total_mass(real_t p_total_mass); + real_t get_total_mass(); + + void set_linear_stiffness(real_t p_linear_stiffness); + real_t get_linear_stiffness(); + + void set_areaAngular_stiffness(real_t p_areaAngular_stiffness); + real_t get_areaAngular_stiffness(); + + void set_volume_stiffness(real_t p_volume_stiffness); + real_t get_volume_stiffness(); + + void set_pressure_coefficient(real_t p_pressure_coefficient); + real_t get_pressure_coefficient(); + + void set_pose_matching_coefficient(real_t p_pose_matching_coefficient); + real_t get_pose_matching_coefficient(); + + void set_damping_coefficient(real_t p_damping_coefficient); + real_t get_damping_coefficient(); + + void set_drag_coefficient(real_t p_drag_coefficient); + real_t get_drag_coefficient(); + + Array get_collision_exceptions(); + void add_collision_exception_with(Node *p_node); + void remove_collision_exception_with(Node *p_node); + + Vector3 get_point_transform(int p_point_index); + + void pin_point_toggle(int p_point_index); + void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath()); + bool is_point_pinned(int p_point_index) const; + + void set_ray_pickable(bool p_ray_pickable); + bool is_ray_pickable() const; + + SoftBody3D(); + ~SoftBody3D(); + +private: + void reset_softbody_pin(); + + void _make_cache_dirty(); + void _update_cache_pin_points_datas(); + + void _pin_point_on_physics_server(int p_point_index, bool pin); + void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path); + void _reset_points_offsets(); + + void _remove_pinned_point(int p_point_index); + int _get_pinned_point(int p_point_index, PinnedPoint *&r_point) const; + int _has_pinned_point(int p_point_index) const; +}; + +#endif // SOFT_PHYSICS_BODY_H diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp deleted file mode 100644 index c6225dd291..0000000000 --- a/scene/3d/spatial.cpp +++ /dev/null @@ -1,848 +0,0 @@ -/*************************************************************************/ -/* spatial.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "spatial.h" - -#include "core/engine.h" -#include "core/message_queue.h" -#include "scene/main/scene_tree.h" -#include "scene/main/window.h" -#include "scene/scene_string_names.h" - -/* - - possible algorithms: - - Algorithm 1: (current) - - definition of invalidation: global is invalid - - 1) If a node sets a LOCAL, it produces an invalidation of everything above - a) If above is invalid, don't keep invalidating upwards - 2) If a node sets a GLOBAL, it is converted to LOCAL (and forces validation of everything pending below) - - drawback: setting/reading globals is useful and used very very often, and using affine inverses is slow - ---- - - Algorithm 2: (no longer current) - - definition of invalidation: NONE dirty, LOCAL dirty, GLOBAL dirty - - 1) If a node sets a LOCAL, it must climb the tree and set it as GLOBAL dirty - a) marking GLOBALs as dirty up all the tree must be done always - 2) If a node sets a GLOBAL, it marks local as dirty, and that's all? - - //is clearing the dirty state correct in this case? - - drawback: setting a local down the tree forces many tree walks often - --- - -future: no idea - - */ - -SpatialGizmo::SpatialGizmo() { -} - -void Spatial::_notify_dirty() { - -#ifdef TOOLS_ENABLED - if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { -#else - if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { - -#endif - get_tree()->xform_change_list.add(&xform_change); - } -} - -void Spatial::_update_local_transform() const { - data.local_transform.basis.set_euler_scale(data.rotation, data.scale); - - data.dirty &= ~DIRTY_LOCAL; -} -void Spatial::_propagate_transform_changed(Spatial *p_origin) { - - if (!is_inside_tree()) { - return; - } - - /* - if (data.dirty&DIRTY_GLOBAL) - return; //already dirty - */ - - data.children_lock++; - - for (List::Element *E = data.children.front(); E; E = E->next()) { - - if (E->get()->data.toplevel_active) - continue; //don't propagate to a toplevel - E->get()->_propagate_transform_changed(p_origin); - } -#ifdef TOOLS_ENABLED - if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { -#else - if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { -#endif - get_tree()->xform_change_list.add(&xform_change); - } - data.dirty |= DIRTY_GLOBAL; - - data.children_lock--; -} - -void Spatial::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - ERR_FAIL_COND(!get_tree()); - - Node *p = get_parent(); - if (p) - data.parent = Object::cast_to(p); - - if (data.parent) - data.C = data.parent->data.children.push_back(this); - else - data.C = NULL; - - if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) { - - if (data.parent) { - data.local_transform = data.parent->get_global_transform() * get_transform(); - data.dirty = DIRTY_VECTORS; //global is always dirty upon entering a scene - } - data.toplevel_active = true; - } - - data.dirty |= DIRTY_GLOBAL; //global is always dirty upon entering a scene - _notify_dirty(); - - notification(NOTIFICATION_ENTER_WORLD); - - } break; - case NOTIFICATION_EXIT_TREE: { - - notification(NOTIFICATION_EXIT_WORLD, true); - if (xform_change.in_list()) - get_tree()->xform_change_list.remove(&xform_change); - if (data.C) - data.parent->data.children.erase(data.C); - data.parent = NULL; - data.C = NULL; - data.toplevel_active = false; - } break; - case NOTIFICATION_ENTER_WORLD: { - - data.inside_world = true; - data.viewport = NULL; - Node *parent = get_parent(); - while (parent && !data.viewport) { - data.viewport = Object::cast_to(parent); - parent = parent->get_parent(); - } - - ERR_FAIL_COND(!data.viewport); - - if (get_script_instance()) { - - get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world, NULL, 0); - } -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { - - //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); - get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); - if (!data.gizmo_disabled) { - - if (data.gizmo.is_valid()) { - data.gizmo->create(); - if (is_visible_in_tree()) { - data.gizmo->redraw(); - } - data.gizmo->transform(); - } - } - } -#endif - - } break; - case NOTIFICATION_EXIT_WORLD: { - -#ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) { - data.gizmo->free(); - data.gizmo.unref(); - } -#endif - - if (get_script_instance()) { - - get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_world, NULL, 0); - } - - data.viewport = NULL; - data.inside_world = false; - - } break; - - case NOTIFICATION_TRANSFORM_CHANGED: { - -#ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) { - data.gizmo->transform(); - } -#endif - } break; - - default: { - } - } -} - -void Spatial::set_transform(const Transform &p_transform) { - - data.local_transform = p_transform; - data.dirty |= DIRTY_VECTORS; - _change_notify("translation"); - _change_notify("rotation"); - _change_notify("rotation_degrees"); - _change_notify("scale"); - _propagate_transform_changed(this); - if (data.notify_local_transform) { - notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); - } -} - -void Spatial::set_global_transform(const Transform &p_transform) { - - Transform xform = - (data.parent && !data.toplevel_active) ? - data.parent->get_global_transform().affine_inverse() * p_transform : - p_transform; - - set_transform(xform); -} - -Transform Spatial::get_transform() const { - - if (data.dirty & DIRTY_LOCAL) { - - _update_local_transform(); - } - - return data.local_transform; -} -Transform Spatial::get_global_transform() const { - - ERR_FAIL_COND_V(!is_inside_tree(), Transform()); - - if (data.dirty & DIRTY_GLOBAL) { - - if (data.dirty & DIRTY_LOCAL) { - - _update_local_transform(); - } - - if (data.parent && !data.toplevel_active) { - - data.global_transform = data.parent->get_global_transform() * data.local_transform; - } else { - - data.global_transform = data.local_transform; - } - - if (data.disable_scale) { - data.global_transform.basis.orthonormalize(); - } - - data.dirty &= ~DIRTY_GLOBAL; - } - - return data.global_transform; -} - -#ifdef TOOLS_ENABLED -Transform Spatial::get_global_gizmo_transform() const { - return get_global_transform(); -} - -Transform Spatial::get_local_gizmo_transform() const { - return get_transform(); -} -#endif - -Spatial *Spatial::get_parent_spatial() const { - - return data.parent; -} - -Transform Spatial::get_relative_transform(const Node *p_parent) const { - - if (p_parent == this) - return Transform(); - - ERR_FAIL_COND_V(!data.parent, Transform()); - - if (p_parent == data.parent) - return get_transform(); - else - return data.parent->get_relative_transform(p_parent) * get_transform(); -} - -void Spatial::set_translation(const Vector3 &p_translation) { - - data.local_transform.origin = p_translation; - _change_notify("transform"); - _propagate_transform_changed(this); - if (data.notify_local_transform) { - notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); - } -} - -void Spatial::set_rotation(const Vector3 &p_euler_rad) { - - if (data.dirty & DIRTY_VECTORS) { - data.scale = data.local_transform.basis.get_scale(); - data.dirty &= ~DIRTY_VECTORS; - } - - data.rotation = p_euler_rad; - data.dirty |= DIRTY_LOCAL; - _change_notify("transform"); - _propagate_transform_changed(this); - if (data.notify_local_transform) { - notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); - } -} - -void Spatial::set_rotation_degrees(const Vector3 &p_euler_deg) { - - set_rotation(p_euler_deg * Math_PI / 180.0); -} - -void Spatial::set_scale(const Vector3 &p_scale) { - - if (data.dirty & DIRTY_VECTORS) { - data.rotation = data.local_transform.basis.get_rotation(); - data.dirty &= ~DIRTY_VECTORS; - } - - data.scale = p_scale; - data.dirty |= DIRTY_LOCAL; - _change_notify("transform"); - _propagate_transform_changed(this); - if (data.notify_local_transform) { - notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); - } -} - -Vector3 Spatial::get_translation() const { - - return data.local_transform.origin; -} - -Vector3 Spatial::get_rotation() const { - - if (data.dirty & DIRTY_VECTORS) { - data.scale = data.local_transform.basis.get_scale(); - data.rotation = data.local_transform.basis.get_rotation(); - - data.dirty &= ~DIRTY_VECTORS; - } - - return data.rotation; -} - -Vector3 Spatial::get_rotation_degrees() const { - - return get_rotation() * 180.0 / Math_PI; -} - -Vector3 Spatial::get_scale() const { - - if (data.dirty & DIRTY_VECTORS) { - data.scale = data.local_transform.basis.get_scale(); - data.rotation = data.local_transform.basis.get_rotation(); - - data.dirty &= ~DIRTY_VECTORS; - } - - return data.scale; -} - -void Spatial::update_gizmo() { - -#ifdef TOOLS_ENABLED - if (!is_inside_world()) - return; - if (!data.gizmo.is_valid()) - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); - if (!data.gizmo.is_valid()) - return; - if (data.gizmo_dirty) - return; - data.gizmo_dirty = true; - MessageQueue::get_singleton()->push_call(this, "_update_gizmo"); -#endif -} - -void Spatial::set_gizmo(const Ref &p_gizmo) { - -#ifdef TOOLS_ENABLED - - if (data.gizmo_disabled) - return; - if (data.gizmo.is_valid() && is_inside_world()) - data.gizmo->free(); - data.gizmo = p_gizmo; - if (data.gizmo.is_valid() && is_inside_world()) { - - data.gizmo->create(); - if (is_visible_in_tree()) { - data.gizmo->redraw(); - } - data.gizmo->transform(); - } - -#endif -} - -Ref Spatial::get_gizmo() const { - -#ifdef TOOLS_ENABLED - - return data.gizmo; -#else - - return Ref(); -#endif -} - -void Spatial::_update_gizmo() { - -#ifdef TOOLS_ENABLED - if (!is_inside_world()) - return; - data.gizmo_dirty = false; - if (data.gizmo.is_valid()) { - if (is_visible_in_tree()) - data.gizmo->redraw(); - else - data.gizmo->clear(); - } -#endif -} - -#ifdef TOOLS_ENABLED -void Spatial::set_disable_gizmo(bool p_enabled) { - - data.gizmo_disabled = p_enabled; - if (!p_enabled && data.gizmo.is_valid()) - data.gizmo = Ref(); -} - -#endif - -void Spatial::set_disable_scale(bool p_enabled) { - - data.disable_scale = p_enabled; -} - -bool Spatial::is_scale_disabled() const { - return data.disable_scale; -} - -void Spatial::set_as_toplevel(bool p_enabled) { - - if (data.toplevel == p_enabled) - return; - if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { - - if (p_enabled) - set_transform(get_global_transform()); - else if (data.parent) - set_transform(data.parent->get_global_transform().affine_inverse() * get_global_transform()); - - data.toplevel = p_enabled; - data.toplevel_active = p_enabled; - - } else { - data.toplevel = p_enabled; - } -} - -bool Spatial::is_set_as_toplevel() const { - - return data.toplevel; -} - -Ref Spatial::get_world() const { - - ERR_FAIL_COND_V(!is_inside_world(), Ref()); - ERR_FAIL_COND_V(!data.viewport, Ref()); - - return data.viewport->find_world(); -} - -void Spatial::_propagate_visibility_changed() { - - notification(NOTIFICATION_VISIBILITY_CHANGED); - emit_signal(SceneStringNames::get_singleton()->visibility_changed); - _change_notify("visible"); -#ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) - _update_gizmo(); -#endif - - for (List::Element *E = data.children.front(); E; E = E->next()) { - - Spatial *c = E->get(); - if (!c || !c->data.visible) - continue; - c->_propagate_visibility_changed(); - } -} - -void Spatial::show() { - - if (data.visible) - return; - - data.visible = true; - - if (!is_inside_tree()) - return; - - _propagate_visibility_changed(); -} - -void Spatial::hide() { - - if (!data.visible) - return; - - data.visible = false; - - if (!is_inside_tree()) - return; - - _propagate_visibility_changed(); -} - -bool Spatial::is_visible_in_tree() const { - - const Spatial *s = this; - - while (s) { - if (!s->data.visible) { - return false; - } - s = s->data.parent; - } - - return true; -} - -void Spatial::set_visible(bool p_visible) { - - if (p_visible) - show(); - else - hide(); -} - -bool Spatial::is_visible() const { - - return data.visible; -} - -void Spatial::rotate_object_local(const Vector3 &p_axis, float p_angle) { - Transform t = get_transform(); - t.basis.rotate_local(p_axis, p_angle); - set_transform(t); -} - -void Spatial::rotate(const Vector3 &p_axis, float p_angle) { - - Transform t = get_transform(); - t.basis.rotate(p_axis, p_angle); - set_transform(t); -} - -void Spatial::rotate_x(float p_angle) { - - Transform t = get_transform(); - t.basis.rotate(Vector3(1, 0, 0), p_angle); - set_transform(t); -} - -void Spatial::rotate_y(float p_angle) { - - Transform t = get_transform(); - t.basis.rotate(Vector3(0, 1, 0), p_angle); - set_transform(t); -} -void Spatial::rotate_z(float p_angle) { - - Transform t = get_transform(); - t.basis.rotate(Vector3(0, 0, 1), p_angle); - set_transform(t); -} - -void Spatial::translate(const Vector3 &p_offset) { - - Transform t = get_transform(); - t.translate(p_offset); - set_transform(t); -} - -void Spatial::translate_object_local(const Vector3 &p_offset) { - Transform t = get_transform(); - - Transform s; - s.translate(p_offset); - set_transform(t * s); -} - -void Spatial::scale(const Vector3 &p_ratio) { - - Transform t = get_transform(); - t.basis.scale(p_ratio); - set_transform(t); -} - -void Spatial::scale_object_local(const Vector3 &p_scale) { - Transform t = get_transform(); - t.basis.scale_local(p_scale); - set_transform(t); -} - -void Spatial::global_rotate(const Vector3 &p_axis, float p_angle) { - - Transform t = get_global_transform(); - t.basis.rotate(p_axis, p_angle); - set_global_transform(t); -} - -void Spatial::global_scale(const Vector3 &p_scale) { - - Transform t = get_global_transform(); - t.basis.scale(p_scale); - set_global_transform(t); -} - -void Spatial::global_translate(const Vector3 &p_offset) { - Transform t = get_global_transform(); - t.origin += p_offset; - set_global_transform(t); -} - -void Spatial::orthonormalize() { - - Transform t = get_transform(); - t.orthonormalize(); - set_transform(t); -} - -void Spatial::set_identity() { - - set_transform(Transform()); -} - -void Spatial::look_at(const Vector3 &p_target, const Vector3 &p_up) { - - Vector3 origin(get_global_transform().origin); - look_at_from_position(origin, p_target, p_up); -} - -void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) { - - ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed."); - ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed."); - - Transform lookat; - lookat.origin = p_pos; - - Vector3 original_scale(get_scale()); - lookat = lookat.looking_at(p_target, p_up); - set_global_transform(lookat); - set_scale(original_scale); -} - -Vector3 Spatial::to_local(Vector3 p_global) const { - - return get_global_transform().affine_inverse().xform(p_global); -} - -Vector3 Spatial::to_global(Vector3 p_local) const { - - return get_global_transform().xform(p_local); -} - -void Spatial::set_notify_transform(bool p_enable) { - data.notify_transform = p_enable; -} - -bool Spatial::is_transform_notification_enabled() const { - return data.notify_transform; -} - -void Spatial::set_notify_local_transform(bool p_enable) { - data.notify_local_transform = p_enable; -} - -bool Spatial::is_local_transform_notification_enabled() const { - return data.notify_local_transform; -} - -void Spatial::force_update_transform() { - ERR_FAIL_COND(!is_inside_tree()); - if (!xform_change.in_list()) { - return; //nothing to update - } - get_tree()->xform_change_list.remove(&xform_change); - - notification(NOTIFICATION_TRANSFORM_CHANGED); -} - -void Spatial::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_transform", "local"), &Spatial::set_transform); - ClassDB::bind_method(D_METHOD("get_transform"), &Spatial::get_transform); - ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Spatial::set_translation); - ClassDB::bind_method(D_METHOD("get_translation"), &Spatial::get_translation); - ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Spatial::set_rotation); - ClassDB::bind_method(D_METHOD("get_rotation"), &Spatial::get_rotation); - ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Spatial::set_rotation_degrees); - ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Spatial::get_rotation_degrees); - ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Spatial::set_scale); - ClassDB::bind_method(D_METHOD("get_scale"), &Spatial::get_scale); - ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Spatial::set_global_transform); - ClassDB::bind_method(D_METHOD("get_global_transform"), &Spatial::get_global_transform); - ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Spatial::get_parent_spatial); - ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Spatial::set_ignore_transform_notification); - ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Spatial::set_as_toplevel); - ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel); - ClassDB::bind_method(D_METHOD("set_disable_scale", "disable"), &Spatial::set_disable_scale); - ClassDB::bind_method(D_METHOD("is_scale_disabled"), &Spatial::is_scale_disabled); - ClassDB::bind_method(D_METHOD("get_world"), &Spatial::get_world); - - ClassDB::bind_method(D_METHOD("force_update_transform"), &Spatial::force_update_transform); - - ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); - - ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo); - ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Spatial::set_gizmo); - ClassDB::bind_method(D_METHOD("get_gizmo"), &Spatial::get_gizmo); - - ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Spatial::set_visible); - ClassDB::bind_method(D_METHOD("is_visible"), &Spatial::is_visible); - ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &Spatial::is_visible_in_tree); - ClassDB::bind_method(D_METHOD("show"), &Spatial::show); - ClassDB::bind_method(D_METHOD("hide"), &Spatial::hide); - - ClassDB::bind_method(D_METHOD("set_notify_local_transform", "enable"), &Spatial::set_notify_local_transform); - ClassDB::bind_method(D_METHOD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled); - - ClassDB::bind_method(D_METHOD("set_notify_transform", "enable"), &Spatial::set_notify_transform); - ClassDB::bind_method(D_METHOD("is_transform_notification_enabled"), &Spatial::is_transform_notification_enabled); - - ClassDB::bind_method(D_METHOD("rotate", "axis", "angle"), &Spatial::rotate); - ClassDB::bind_method(D_METHOD("global_rotate", "axis", "angle"), &Spatial::global_rotate); - ClassDB::bind_method(D_METHOD("global_scale", "scale"), &Spatial::global_scale); - ClassDB::bind_method(D_METHOD("global_translate", "offset"), &Spatial::global_translate); - ClassDB::bind_method(D_METHOD("rotate_object_local", "axis", "angle"), &Spatial::rotate_object_local); - ClassDB::bind_method(D_METHOD("scale_object_local", "scale"), &Spatial::scale_object_local); - ClassDB::bind_method(D_METHOD("translate_object_local", "offset"), &Spatial::translate_object_local); - ClassDB::bind_method(D_METHOD("rotate_x", "angle"), &Spatial::rotate_x); - ClassDB::bind_method(D_METHOD("rotate_y", "angle"), &Spatial::rotate_y); - ClassDB::bind_method(D_METHOD("rotate_z", "angle"), &Spatial::rotate_z); - ClassDB::bind_method(D_METHOD("translate", "offset"), &Spatial::translate); - ClassDB::bind_method(D_METHOD("orthonormalize"), &Spatial::orthonormalize); - ClassDB::bind_method(D_METHOD("set_identity"), &Spatial::set_identity); - - ClassDB::bind_method(D_METHOD("look_at", "target", "up"), &Spatial::look_at); - ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Spatial::look_at_from_position); - - ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Spatial::to_local); - ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Spatial::to_global); - - BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED); - BIND_CONSTANT(NOTIFICATION_ENTER_WORLD); - BIND_CONSTANT(NOTIFICATION_EXIT_WORLD); - BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); - - //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ; - ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); - ADD_GROUP("Matrix", ""); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); - ADD_GROUP("Visibility", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo"); - - ADD_SIGNAL(MethodInfo("visibility_changed")); -} - -Spatial::Spatial() : - xform_change(this) { - - data.dirty = DIRTY_NONE; - data.children_lock = 0; - - data.ignore_notification = false; - data.toplevel = false; - data.toplevel_active = false; - data.scale = Vector3(1, 1, 1); - data.viewport = NULL; - data.inside_world = false; - data.visible = true; - data.disable_scale = false; - -#ifdef TOOLS_ENABLED - data.gizmo_disabled = false; - data.gizmo_dirty = false; -#endif - data.notify_local_transform = false; - data.notify_transform = false; - data.parent = NULL; - data.C = NULL; -} - -Spatial::~Spatial() { -} diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h deleted file mode 100644 index 9d4705700b..0000000000 --- a/scene/3d/spatial.h +++ /dev/null @@ -1,207 +0,0 @@ -/*************************************************************************/ -/* spatial.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPATIAL_H -#define SPATIAL_H - -#include "scene/main/node.h" -#include "scene/main/scene_tree.h" - -class SpatialGizmo : public Reference { - - GDCLASS(SpatialGizmo, Reference); - -public: - virtual void create() = 0; - virtual void transform() = 0; - virtual void clear() = 0; - virtual void redraw() = 0; - virtual void free() = 0; - - SpatialGizmo(); - virtual ~SpatialGizmo() {} -}; - -class Spatial : public Node { - - GDCLASS(Spatial, Node); - OBJ_CATEGORY("3D"); - - enum TransformDirty { - DIRTY_NONE = 0, - DIRTY_VECTORS = 1, - DIRTY_LOCAL = 2, - DIRTY_GLOBAL = 4 - }; - - mutable SelfList xform_change; - - struct Data { - - mutable Transform global_transform; - mutable Transform local_transform; - mutable Vector3 rotation; - mutable Vector3 scale; - - mutable int dirty; - - Viewport *viewport; - - bool toplevel_active; - bool toplevel; - bool inside_world; - - int children_lock; - Spatial *parent; - List children; - List::Element *C; - - bool ignore_notification; - bool notify_local_transform; - bool notify_transform; - - bool visible; - bool disable_scale; - -#ifdef TOOLS_ENABLED - Ref gizmo; - bool gizmo_disabled; - bool gizmo_dirty; -#endif - - } data; - - void _update_gizmo(); - void _notify_dirty(); - void _propagate_transform_changed(Spatial *p_origin); - - void _propagate_visibility_changed(); - -protected: - _FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) { data.ignore_notification = p_ignore; } - - _FORCE_INLINE_ void _update_local_transform() const; - - void _notification(int p_what); - static void _bind_methods(); - -public: - enum { - - NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED, - NOTIFICATION_ENTER_WORLD = 41, - NOTIFICATION_EXIT_WORLD = 42, - NOTIFICATION_VISIBILITY_CHANGED = 43, - NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 44, - }; - - Spatial *get_parent_spatial() const; - - Ref get_world() const; - - void set_translation(const Vector3 &p_translation); - void set_rotation(const Vector3 &p_euler_rad); - void set_rotation_degrees(const Vector3 &p_euler_deg); - void set_scale(const Vector3 &p_scale); - - Vector3 get_translation() const; - Vector3 get_rotation() const; - Vector3 get_rotation_degrees() const; - Vector3 get_scale() const; - - void set_transform(const Transform &p_transform); - void set_global_transform(const Transform &p_transform); - - Transform get_transform() const; - Transform get_global_transform() const; - -#ifdef TOOLS_ENABLED - virtual Transform get_global_gizmo_transform() const; - virtual Transform get_local_gizmo_transform() const; -#endif - - void set_as_toplevel(bool p_enabled); - bool is_set_as_toplevel() const; - - void set_disable_scale(bool p_enabled); - bool is_scale_disabled() const; - - void set_disable_gizmo(bool p_enabled); - void update_gizmo(); - void set_gizmo(const Ref &p_gizmo); - Ref get_gizmo() const; - - _FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; } - - Transform get_relative_transform(const Node *p_parent) const; - - void rotate(const Vector3 &p_axis, float p_angle); - void rotate_x(float p_angle); - void rotate_y(float p_angle); - void rotate_z(float p_angle); - void translate(const Vector3 &p_offset); - void scale(const Vector3 &p_ratio); - - void rotate_object_local(const Vector3 &p_axis, float p_angle); - void scale_object_local(const Vector3 &p_scale); - void translate_object_local(const Vector3 &p_offset); - - void global_rotate(const Vector3 &p_axis, float p_angle); - void global_scale(const Vector3 &p_scale); - void global_translate(const Vector3 &p_offset); - - void look_at(const Vector3 &p_target, const Vector3 &p_up); - void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up); - - Vector3 to_local(Vector3 p_global) const; - Vector3 to_global(Vector3 p_local) const; - - void set_notify_transform(bool p_enable); - bool is_transform_notification_enabled() const; - - void set_notify_local_transform(bool p_enable); - bool is_local_transform_notification_enabled() const; - - void orthonormalize(); - void set_identity(); - - void set_visible(bool p_visible); - bool is_visible() const; - void show(); - void hide(); - bool is_visible_in_tree() const; - - void force_update_transform(); - - Spatial(); - ~Spatial(); -}; - -#endif diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp deleted file mode 100644 index ec1bb1f991..0000000000 --- a/scene/3d/spatial_velocity_tracker.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/*************************************************************************/ -/* spatial_velocity_tracker.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "spatial_velocity_tracker.h" -#include "core/engine.h" - -void SpatialVelocityTracker::set_track_physics_step(bool p_track_physics_step) { - - physics_step = p_track_physics_step; -} - -bool SpatialVelocityTracker::is_tracking_physics_step() const { - - return physics_step; -} -void SpatialVelocityTracker::update_position(const Vector3 &p_position) { - - PositionHistory ph; - ph.position = p_position; - if (physics_step) { - ph.frame = Engine::get_singleton()->get_physics_frames(); - } else { - ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); - } - - if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest - position_history_len = MIN(position_history.size(), position_history_len + 1); - for (int i = position_history_len - 1; i > 0; i--) { - position_history.write[i] = position_history[i - 1]; - } - } - - position_history.write[0] = ph; -} -Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const { - - Vector3 linear_velocity; - - float max_time = 1 / 5.0; //maximum time to interpolate a velocity - - Vector3 distance_accum; - float time_accum = 0.0; - float base_time = 0.0; - - if (position_history_len) { - if (physics_step) { - uint64_t base = Engine::get_singleton()->get_physics_frames(); - base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second(); - } else { - uint64_t base = Engine::get_singleton()->get_idle_frame_ticks(); - base_time = double(base - position_history[0].frame) / 1000000.0; - } - } - - for (int i = 0; i < position_history_len - 1; i++) { - float delta = 0.0; - uint64_t diff = position_history[i].frame - position_history[i + 1].frame; - Vector3 distance = position_history[i].position - position_history[i + 1].position; - - if (physics_step) { - delta = float(diff) / Engine::get_singleton()->get_iterations_per_second(); - } else { - delta = double(diff) / 1000000.0; - } - - if (base_time + time_accum + delta > max_time) - break; - - distance_accum += distance; - time_accum += delta; - } - - if (time_accum) { - linear_velocity = distance_accum / time_accum; - } - - return linear_velocity; -} - -void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) { - - PositionHistory ph; - ph.position = p_new_pos; - if (physics_step) { - ph.frame = Engine::get_singleton()->get_physics_frames(); - } else { - ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); - } - - position_history.write[0] = ph; - position_history_len = 1; -} - -void SpatialVelocityTracker::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_track_physics_step", "enable"), &SpatialVelocityTracker::set_track_physics_step); - ClassDB::bind_method(D_METHOD("is_tracking_physics_step"), &SpatialVelocityTracker::is_tracking_physics_step); - ClassDB::bind_method(D_METHOD("update_position", "position"), &SpatialVelocityTracker::update_position); - ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &SpatialVelocityTracker::get_tracked_linear_velocity); - ClassDB::bind_method(D_METHOD("reset", "position"), &SpatialVelocityTracker::reset); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "track_physics_step"), "set_track_physics_step", "is_tracking_physics_step"); -} - -SpatialVelocityTracker::SpatialVelocityTracker() { - position_history.resize(4); // should be configurable - position_history_len = 0; - physics_step = false; -} diff --git a/scene/3d/spatial_velocity_tracker.h b/scene/3d/spatial_velocity_tracker.h deleted file mode 100644 index 92b527b93c..0000000000 --- a/scene/3d/spatial_velocity_tracker.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************/ -/* spatial_velocity_tracker.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPATIAL_VELOCITY_TRACKER_H -#define SPATIAL_VELOCITY_TRACKER_H - -#include "scene/3d/spatial.h" - -class SpatialVelocityTracker : public Reference { - GDCLASS(SpatialVelocityTracker, Reference); - - struct PositionHistory { - uint64_t frame; - Vector3 position; - }; - - bool physics_step; - Vector position_history; - int position_history_len; - -protected: - static void _bind_methods(); - -public: - void reset(const Vector3 &p_new_pos); - void set_track_physics_step(bool p_track_physics_step); - bool is_tracking_physics_step() const; - void update_position(const Vector3 &p_position); - Vector3 get_tracked_linear_velocity() const; - - SpatialVelocityTracker(); -}; - -#endif // SPATIAL_VELOCITY_TRACKER_H diff --git a/scene/3d/spring_arm.cpp b/scene/3d/spring_arm.cpp deleted file mode 100644 index ce277dae5b..0000000000 --- a/scene/3d/spring_arm.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/*************************************************************************/ -/* spring_arm.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "spring_arm.h" -#include "core/engine.h" -#include "scene/3d/collision_object.h" -#include "scene/resources/sphere_shape.h" -#include "servers/physics_server.h" - -SpringArm::SpringArm() : - spring_length(1), - current_spring_length(0), - keep_child_basis(false), - mask(1), - margin(0.01) {} - -void SpringArm::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - if (!Engine::get_singleton()->is_editor_hint()) { - set_process_internal(true); - } - break; - case NOTIFICATION_EXIT_TREE: - if (!Engine::get_singleton()->is_editor_hint()) { - set_process_internal(false); - } - break; - case NOTIFICATION_INTERNAL_PROCESS: - process_spring(); - break; - } -} - -void SpringArm::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_hit_length"), &SpringArm::get_hit_length); - - ClassDB::bind_method(D_METHOD("set_length", "length"), &SpringArm::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &SpringArm::get_length); - - ClassDB::bind_method(D_METHOD("set_shape", "shape"), &SpringArm::set_shape); - ClassDB::bind_method(D_METHOD("get_shape"), &SpringArm::get_shape); - - ClassDB::bind_method(D_METHOD("add_excluded_object", "RID"), &SpringArm::add_excluded_object); - ClassDB::bind_method(D_METHOD("remove_excluded_object", "RID"), &SpringArm::remove_excluded_object); - ClassDB::bind_method(D_METHOD("clear_excluded_objects"), &SpringArm::clear_excluded_objects); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &SpringArm::set_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &SpringArm::get_mask); - - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &SpringArm::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &SpringArm::get_margin); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spring_length"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); -} - -float SpringArm::get_length() const { - return spring_length; -} - -void SpringArm::set_length(float p_length) { - if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) - update_gizmo(); - - spring_length = p_length; -} - -void SpringArm::set_shape(Ref p_shape) { - shape = p_shape; -} - -Ref SpringArm::get_shape() const { - return shape; -} - -void SpringArm::set_mask(uint32_t p_mask) { - mask = p_mask; -} - -uint32_t SpringArm::get_mask() { - return mask; -} - -float SpringArm::get_margin() { - return margin; -} - -void SpringArm::set_margin(float p_margin) { - margin = p_margin; -} - -void SpringArm::add_excluded_object(RID p_rid) { - excluded_objects.insert(p_rid); -} - -bool SpringArm::remove_excluded_object(RID p_rid) { - return excluded_objects.erase(p_rid); -} - -void SpringArm::clear_excluded_objects() { - excluded_objects.clear(); -} - -float SpringArm::get_hit_length() { - return current_spring_length; -} - -void SpringArm::process_spring() { - // From - real_t motion_delta(1); - real_t motion_delta_unsafe(1); - - Vector3 motion; - const Vector3 cast_direction(get_global_transform().basis.xform(Vector3(0, 0, 1))); - - if (shape.is_null()) { - motion = Vector3(cast_direction * (spring_length)); - PhysicsDirectSpaceState::RayResult r; - bool intersected = get_world()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask); - if (intersected) { - float dist = get_global_transform().origin.distance_to(r.position); - dist -= margin; - motion_delta = dist / (spring_length); - } - } else { - motion = Vector3(cast_direction * spring_length); - get_world()->get_direct_space_state()->cast_motion(shape->get_rid(), get_global_transform(), motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask); - } - - current_spring_length = spring_length * motion_delta; - Transform childs_transform; - childs_transform.origin = get_global_transform().origin + cast_direction * (spring_length * motion_delta); - - for (int i = get_child_count() - 1; 0 <= i; --i) { - - Spatial *child = Object::cast_to(get_child(i)); - if (child) { - childs_transform.basis = child->get_global_transform().basis; - child->set_global_transform(childs_transform); - } - } -} diff --git a/scene/3d/spring_arm.h b/scene/3d/spring_arm.h deleted file mode 100644 index 1a12370564..0000000000 --- a/scene/3d/spring_arm.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************/ -/* spring_arm.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPRING_ARM_H -#define SPRING_ARM_H - -#include "scene/3d/spatial.h" - -class SpringArm : public Spatial { - GDCLASS(SpringArm, Spatial); - - Ref shape; - Set excluded_objects; - float spring_length; - float current_spring_length; - bool keep_child_basis; - uint32_t mask; - float margin; - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_length(float p_length); - float get_length() const; - void set_shape(Ref p_shape); - Ref get_shape() const; - void set_mask(uint32_t p_mask); - uint32_t get_mask(); - void add_excluded_object(RID p_rid); - bool remove_excluded_object(RID p_rid); - void clear_excluded_objects(); - float get_hit_length(); - void set_margin(float p_margin); - float get_margin(); - - SpringArm(); - -private: - void process_spring(); -}; - -#endif diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp new file mode 100644 index 0000000000..1856171539 --- /dev/null +++ b/scene/3d/spring_arm_3d.cpp @@ -0,0 +1,173 @@ +/*************************************************************************/ +/* spring_arm_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "spring_arm_3d.h" +#include "core/engine.h" +#include "scene/3d/collision_object_3d.h" +#include "scene/resources/sphere_shape_3d.h" +#include "servers/physics_server.h" + +SpringArm3D::SpringArm3D() : + spring_length(1), + current_spring_length(0), + keep_child_basis(false), + mask(1), + margin(0.01) {} + +void SpringArm3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + if (!Engine::get_singleton()->is_editor_hint()) { + set_process_internal(true); + } + break; + case NOTIFICATION_EXIT_TREE: + if (!Engine::get_singleton()->is_editor_hint()) { + set_process_internal(false); + } + break; + case NOTIFICATION_INTERNAL_PROCESS: + process_spring(); + break; + } +} + +void SpringArm3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_hit_length"), &SpringArm3D::get_hit_length); + + ClassDB::bind_method(D_METHOD("set_length", "length"), &SpringArm3D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &SpringArm3D::get_length); + + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &SpringArm3D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &SpringArm3D::get_shape); + + ClassDB::bind_method(D_METHOD("add_excluded_object", "RID"), &SpringArm3D::add_excluded_object); + ClassDB::bind_method(D_METHOD("remove_excluded_object", "RID"), &SpringArm3D::remove_excluded_object); + ClassDB::bind_method(D_METHOD("clear_excluded_objects"), &SpringArm3D::clear_excluded_objects); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &SpringArm3D::set_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &SpringArm3D::get_mask); + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &SpringArm3D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &SpringArm3D::get_margin); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spring_length"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); +} + +float SpringArm3D::get_length() const { + return spring_length; +} + +void SpringArm3D::set_length(float p_length) { + if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) + update_gizmo(); + + spring_length = p_length; +} + +void SpringArm3D::set_shape(Ref p_shape) { + shape = p_shape; +} + +Ref SpringArm3D::get_shape() const { + return shape; +} + +void SpringArm3D::set_mask(uint32_t p_mask) { + mask = p_mask; +} + +uint32_t SpringArm3D::get_mask() { + return mask; +} + +float SpringArm3D::get_margin() { + return margin; +} + +void SpringArm3D::set_margin(float p_margin) { + margin = p_margin; +} + +void SpringArm3D::add_excluded_object(RID p_rid) { + excluded_objects.insert(p_rid); +} + +bool SpringArm3D::remove_excluded_object(RID p_rid) { + return excluded_objects.erase(p_rid); +} + +void SpringArm3D::clear_excluded_objects() { + excluded_objects.clear(); +} + +float SpringArm3D::get_hit_length() { + return current_spring_length; +} + +void SpringArm3D::process_spring() { + // From + real_t motion_delta(1); + real_t motion_delta_unsafe(1); + + Vector3 motion; + const Vector3 cast_direction(get_global_transform().basis.xform(Vector3(0, 0, 1))); + + if (shape.is_null()) { + motion = Vector3(cast_direction * (spring_length)); + PhysicsDirectSpaceState::RayResult r; + bool intersected = get_world()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask); + if (intersected) { + float dist = get_global_transform().origin.distance_to(r.position); + dist -= margin; + motion_delta = dist / (spring_length); + } + } else { + motion = Vector3(cast_direction * spring_length); + get_world()->get_direct_space_state()->cast_motion(shape->get_rid(), get_global_transform(), motion, 0, motion_delta, motion_delta_unsafe, excluded_objects, mask); + } + + current_spring_length = spring_length * motion_delta; + Transform childs_transform; + childs_transform.origin = get_global_transform().origin + cast_direction * (spring_length * motion_delta); + + for (int i = get_child_count() - 1; 0 <= i; --i) { + + Node3D *child = Object::cast_to(get_child(i)); + if (child) { + childs_transform.basis = child->get_global_transform().basis; + child->set_global_transform(childs_transform); + } + } +} diff --git a/scene/3d/spring_arm_3d.h b/scene/3d/spring_arm_3d.h new file mode 100644 index 0000000000..cb8a00ecf9 --- /dev/null +++ b/scene/3d/spring_arm_3d.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* spring_arm_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPRING_ARM_H +#define SPRING_ARM_H + +#include "scene/3d/node_3d.h" + +class SpringArm3D : public Node3D { + GDCLASS(SpringArm3D, Node3D); + + Ref shape; + Set excluded_objects; + float spring_length; + float current_spring_length; + bool keep_child_basis; + uint32_t mask; + float margin; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_length(float p_length); + float get_length() const; + void set_shape(Ref p_shape); + Ref get_shape() const; + void set_mask(uint32_t p_mask); + uint32_t get_mask(); + void add_excluded_object(RID p_rid); + bool remove_excluded_object(RID p_rid); + void clear_excluded_objects(); + float get_hit_length(); + void set_margin(float p_margin); + float get_margin(); + + SpringArm3D(); + +private: + void process_spring(); +}; + +#endif diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 082884c83b..64bef41fd8 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -31,12 +31,12 @@ #ifndef SPRITE_3D_H #define SPRITE_3D_H -#include "scene/2d/animated_sprite.h" -#include "scene/3d/visual_instance.h" +#include "scene/2d/animated_sprite_2d.h" +#include "scene/3d/visual_instance_3d.h" -class SpriteBase3D : public GeometryInstance { +class SpriteBase3D : public GeometryInstance3D { - GDCLASS(SpriteBase3D, GeometryInstance); + GDCLASS(SpriteBase3D, GeometryInstance3D); mutable Ref triangle_mesh; //cached diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index c249d844d1..5bef2a14f5 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -463,7 +463,7 @@ real_t VehicleBody::_ray_cast(int p_idx, PhysicsDirectBodyState *s) { wheel.m_raycastInfo.m_isInContact = true; if (rr.collider) - wheel.m_raycastInfo.m_groundObject = Object::cast_to(rr.collider); + wheel.m_raycastInfo.m_groundObject = Object::cast_to(rr.collider); real_t hitDistance = param * raylen; wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius; @@ -559,7 +559,7 @@ void VehicleBody::_update_suspension(PhysicsDirectBodyState *s) { //bilateral constraint between two dynamic objects void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, - PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) { + PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) { real_t normalLenSqr = normal.length_squared(); //ERR_FAIL_COND( normalLenSqr < real_t(1.1)); @@ -636,7 +636,7 @@ void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vec #endif } -VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) : +VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) : m_s(s), m_body1(body1), m_frictionPositionWorld(frictionPosWorld), @@ -825,7 +825,7 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { s->apply_impulse(rel_pos, m_forwardWS[wheel] * (m_forwardImpulse[wheel])); } if (m_sideImpulse[wheel] != real_t(0.)) { - PhysicsBody *groundObject = wheelInfo.m_raycastInfo.m_groundObject; + PhysicsBody3D *groundObject = wheelInfo.m_raycastInfo.m_groundObject; Vector3 rel_pos2; if (groundObject) { @@ -852,7 +852,7 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { void VehicleBody::_direct_state_changed(Object *p_state) { - RigidBody::_direct_state_changed(p_state); + RigidBody3D::_direct_state_changed(p_state); state = Object::cast_to(p_state); diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index c05ea30f94..b754311b7b 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -31,13 +31,13 @@ #ifndef VEHICLE_BODY_H #define VEHICLE_BODY_H -#include "scene/3d/physics_body.h" +#include "scene/3d/physics_body_3d.h" class VehicleBody; -class VehicleWheel : public Spatial { +class VehicleWheel : public Node3D { - GDCLASS(VehicleWheel, Spatial); + GDCLASS(VehicleWheel, Node3D); friend class VehicleBody; @@ -88,7 +88,7 @@ class VehicleWheel : public Spatial { Vector3 m_wheelDirectionWS; //direction in worldspace Vector3 m_wheelAxleWS; // axle in worldspace bool m_isInContact; - PhysicsBody *m_groundObject; //could be general void* ptr + PhysicsBody3D *m_groundObject; //could be general void* ptr } m_raycastInfo; void _update(PhysicsDirectBodyState *s); @@ -151,9 +151,9 @@ public: VehicleWheel(); }; -class VehicleBody : public RigidBody { +class VehicleBody : public RigidBody3D { - GDCLASS(VehicleBody, RigidBody); + GDCLASS(VehicleBody, RigidBody3D); float engine_force; float brake; @@ -171,16 +171,16 @@ class VehicleBody : public RigidBody { struct btVehicleWheelContactPoint { PhysicsDirectBodyState *m_s; - PhysicsBody *m_body1; + PhysicsBody3D *m_body1; Vector3 m_frictionPositionWorld; Vector3 m_frictionDirectionWorld; real_t m_jacDiagABInv; real_t m_maxImpulse; - btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse); + btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse); }; - void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence); + void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence); real_t _calc_rolling_friction(btVehicleWheelContactPoint &contactPoint); void _update_friction(PhysicsDirectBodyState *s); diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp new file mode 100644 index 0000000000..c9b95e6397 --- /dev/null +++ b/scene/3d/velocity_tracker_3d.cpp @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* velocity_tracker_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "velocity_tracker_3d.h" +#include "core/engine.h" + +void VelocityTracker3D::set_track_physics_step(bool p_track_physics_step) { + + physics_step = p_track_physics_step; +} + +bool VelocityTracker3D::is_tracking_physics_step() const { + + return physics_step; +} +void VelocityTracker3D::update_position(const Vector3 &p_position) { + + PositionHistory ph; + ph.position = p_position; + if (physics_step) { + ph.frame = Engine::get_singleton()->get_physics_frames(); + } else { + ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); + } + + if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest + position_history_len = MIN(position_history.size(), position_history_len + 1); + for (int i = position_history_len - 1; i > 0; i--) { + position_history.write[i] = position_history[i - 1]; + } + } + + position_history.write[0] = ph; +} +Vector3 VelocityTracker3D::get_tracked_linear_velocity() const { + + Vector3 linear_velocity; + + float max_time = 1 / 5.0; //maximum time to interpolate a velocity + + Vector3 distance_accum; + float time_accum = 0.0; + float base_time = 0.0; + + if (position_history_len) { + if (physics_step) { + uint64_t base = Engine::get_singleton()->get_physics_frames(); + base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second(); + } else { + uint64_t base = Engine::get_singleton()->get_idle_frame_ticks(); + base_time = double(base - position_history[0].frame) / 1000000.0; + } + } + + for (int i = 0; i < position_history_len - 1; i++) { + float delta = 0.0; + uint64_t diff = position_history[i].frame - position_history[i + 1].frame; + Vector3 distance = position_history[i].position - position_history[i + 1].position; + + if (physics_step) { + delta = float(diff) / Engine::get_singleton()->get_iterations_per_second(); + } else { + delta = double(diff) / 1000000.0; + } + + if (base_time + time_accum + delta > max_time) + break; + + distance_accum += distance; + time_accum += delta; + } + + if (time_accum) { + linear_velocity = distance_accum / time_accum; + } + + return linear_velocity; +} + +void VelocityTracker3D::reset(const Vector3 &p_new_pos) { + + PositionHistory ph; + ph.position = p_new_pos; + if (physics_step) { + ph.frame = Engine::get_singleton()->get_physics_frames(); + } else { + ph.frame = Engine::get_singleton()->get_idle_frame_ticks(); + } + + position_history.write[0] = ph; + position_history_len = 1; +} + +void VelocityTracker3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_track_physics_step", "enable"), &VelocityTracker3D::set_track_physics_step); + ClassDB::bind_method(D_METHOD("is_tracking_physics_step"), &VelocityTracker3D::is_tracking_physics_step); + ClassDB::bind_method(D_METHOD("update_position", "position"), &VelocityTracker3D::update_position); + ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &VelocityTracker3D::get_tracked_linear_velocity); + ClassDB::bind_method(D_METHOD("reset", "position"), &VelocityTracker3D::reset); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "track_physics_step"), "set_track_physics_step", "is_tracking_physics_step"); +} + +VelocityTracker3D::VelocityTracker3D() { + position_history.resize(4); // should be configurable + position_history_len = 0; + physics_step = false; +} diff --git a/scene/3d/velocity_tracker_3d.h b/scene/3d/velocity_tracker_3d.h new file mode 100644 index 0000000000..a7ab3dce4d --- /dev/null +++ b/scene/3d/velocity_tracker_3d.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* velocity_tracker_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPATIAL_VELOCITY_TRACKER_H +#define SPATIAL_VELOCITY_TRACKER_H + +#include "scene/3d/node_3d.h" + +class VelocityTracker3D : public Reference { + GDCLASS(VelocityTracker3D, Reference); + + struct PositionHistory { + uint64_t frame; + Vector3 position; + }; + + bool physics_step; + Vector position_history; + int position_history_len; + +protected: + static void _bind_methods(); + +public: + void reset(const Vector3 &p_new_pos); + void set_track_physics_step(bool p_track_physics_step); + bool is_tracking_physics_step() const; + void update_position(const Vector3 &p_position); + Vector3 get_tracked_linear_velocity() const; + + VelocityTracker3D(); +}; + +#endif // SPATIAL_VELOCITY_TRACKER_H diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp deleted file mode 100644 index 5bc568bd5d..0000000000 --- a/scene/3d/visibility_notifier.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/*************************************************************************/ -/* visibility_notifier.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visibility_notifier.h" - -#include "core/engine.h" -#include "scene/3d/camera.h" -#include "scene/3d/physics_body.h" -#include "scene/animation/animation_player.h" -#include "scene/scene_string_names.h" - -void VisibilityNotifier::_enter_camera(Camera *p_camera) { - - ERR_FAIL_COND(cameras.has(p_camera)); - cameras.insert(p_camera); - if (cameras.size() == 1) { - emit_signal(SceneStringNames::get_singleton()->screen_entered); - _screen_enter(); - } - - emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera); -} - -void VisibilityNotifier::_exit_camera(Camera *p_camera) { - - ERR_FAIL_COND(!cameras.has(p_camera)); - cameras.erase(p_camera); - - emit_signal(SceneStringNames::get_singleton()->camera_exited, p_camera); - if (cameras.size() == 0) { - emit_signal(SceneStringNames::get_singleton()->screen_exited); - - _screen_exit(); - } -} - -void VisibilityNotifier::set_aabb(const AABB &p_aabb) { - - if (aabb == p_aabb) - return; - aabb = p_aabb; - - if (is_inside_world()) { - get_world()->_update_notifier(this, get_global_transform().xform(aabb)); - } - - _change_notify("aabb"); - update_gizmo(); -} - -AABB VisibilityNotifier::get_aabb() const { - - return aabb; -} - -void VisibilityNotifier::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_ENTER_WORLD: { - - get_world()->_register_notifier(this, get_global_transform().xform(aabb)); - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - get_world()->_update_notifier(this, get_global_transform().xform(aabb)); - } break; - case NOTIFICATION_EXIT_WORLD: { - - get_world()->_remove_notifier(this); - } break; - } -} - -bool VisibilityNotifier::is_on_screen() const { - - return cameras.size() != 0; -} - -void VisibilityNotifier::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibilityNotifier::set_aabb); - ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier::get_aabb); - ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier::is_on_screen); - - ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb"); - - ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"))); - ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"))); - ADD_SIGNAL(MethodInfo("screen_entered")); - ADD_SIGNAL(MethodInfo("screen_exited")); -} - -VisibilityNotifier::VisibilityNotifier() { - - aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - set_notify_transform(true); -} - -////////////////////////////////////// - -void VisibilityEnabler::_screen_enter() { - - for (Map::Element *E = nodes.front(); E; E = E->next()) { - - _change_node_state(E->key(), true); - } - - visible = true; -} - -void VisibilityEnabler::_screen_exit() { - - for (Map::Element *E = nodes.front(); E; E = E->next()) { - - _change_node_state(E->key(), false); - } - - visible = false; -} - -void VisibilityEnabler::_find_nodes(Node *p_node) { - - bool add = false; - Variant meta; - - { - RigidBody *rb = Object::cast_to(p_node); - if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || rb->get_mode() == RigidBody::MODE_RIGID))) { - - add = true; - meta = rb->get_mode(); - } - } - - { - AnimationPlayer *ap = Object::cast_to(p_node); - if (ap) { - add = true; - } - } - - if (add) { - - p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler::_node_removed), varray(p_node), CONNECT_ONESHOT); - nodes[p_node] = meta; - _change_node_state(p_node, false); - } - - for (int i = 0; i < p_node->get_child_count(); i++) { - Node *c = p_node->get_child(i); - if (c->get_filename() != String()) - continue; //skip, instance - - _find_nodes(c); - } -} - -void VisibilityEnabler::_notification(int p_what) { - - if (p_what == NOTIFICATION_ENTER_TREE) { - - if (Engine::get_singleton()->is_editor_hint()) - return; - - Node *from = this; - //find where current scene starts - while (from->get_parent() && from->get_filename() == String()) - from = from->get_parent(); - - _find_nodes(from); - } - - if (p_what == NOTIFICATION_EXIT_TREE) { - - if (Engine::get_singleton()->is_editor_hint()) - return; - - for (Map::Element *E = nodes.front(); E; E = E->next()) { - - if (!visible) - _change_node_state(E->key(), true); - E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler::_node_removed)); - } - - nodes.clear(); - } -} - -void VisibilityEnabler::_change_node_state(Node *p_node, bool p_enabled) { - - ERR_FAIL_COND(!nodes.has(p_node)); - - if (enabler[ENABLER_FREEZE_BODIES]) { - RigidBody *rb = Object::cast_to(p_node); - if (rb) - - rb->set_sleeping(!p_enabled); - } - - if (enabler[ENABLER_PAUSE_ANIMATIONS]) { - AnimationPlayer *ap = Object::cast_to(p_node); - - if (ap) { - - ap->set_active(p_enabled); - } - } -} - -void VisibilityEnabler::_node_removed(Node *p_node) { - - if (!visible) - _change_node_state(p_node, true); - nodes.erase(p_node); -} - -void VisibilityEnabler::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler::set_enabler); - ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler::is_enabler_enabled); - - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES); - - BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS); - BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES); - BIND_ENUM_CONSTANT(ENABLER_MAX); -} - -void VisibilityEnabler::set_enabler(Enabler p_enabler, bool p_enable) { - - ERR_FAIL_INDEX(p_enabler, ENABLER_MAX); - enabler[p_enabler] = p_enable; -} -bool VisibilityEnabler::is_enabler_enabled(Enabler p_enabler) const { - - ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false); - return enabler[p_enabler]; -} - -VisibilityEnabler::VisibilityEnabler() { - - for (int i = 0; i < ENABLER_MAX; i++) - enabler[i] = true; - - visible = false; -} diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h deleted file mode 100644 index 71fdfdb78c..0000000000 --- a/scene/3d/visibility_notifier.h +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************/ -/* visibility_notifier.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISIBILITY_NOTIFIER_H -#define VISIBILITY_NOTIFIER_H - -#include "scene/3d/spatial.h" - -class Camera; -class VisibilityNotifier : public Spatial { - - GDCLASS(VisibilityNotifier, Spatial); - - Set cameras; - - AABB aabb; - -protected: - virtual void _screen_enter() {} - virtual void _screen_exit() {} - - void _notification(int p_what); - static void _bind_methods(); - friend struct SpatialIndexer; - - void _enter_camera(Camera *p_camera); - void _exit_camera(Camera *p_camera); - -public: - void set_aabb(const AABB &p_aabb); - AABB get_aabb() const; - bool is_on_screen() const; - - VisibilityNotifier(); -}; - -class VisibilityEnabler : public VisibilityNotifier { - - GDCLASS(VisibilityEnabler, VisibilityNotifier); - -public: - enum Enabler { - ENABLER_PAUSE_ANIMATIONS, - ENABLER_FREEZE_BODIES, - ENABLER_MAX - }; - -protected: - virtual void _screen_enter(); - virtual void _screen_exit(); - - bool visible; - - void _find_nodes(Node *p_node); - - Map nodes; - void _node_removed(Node *p_node); - bool enabler[ENABLER_MAX]; - - void _change_node_state(Node *p_node, bool p_enabled); - - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_enabler(Enabler p_enabler, bool p_enable); - bool is_enabler_enabled(Enabler p_enabler) const; - - VisibilityEnabler(); -}; - -VARIANT_ENUM_CAST(VisibilityEnabler::Enabler); - -#endif // VISIBILITY_NOTIFIER_H diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp new file mode 100644 index 0000000000..2f657fe7b1 --- /dev/null +++ b/scene/3d/visibility_notifier_3d.cpp @@ -0,0 +1,274 @@ +/*************************************************************************/ +/* visibility_notifier_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "visibility_notifier_3d.h" + +#include "core/engine.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/animation/animation_player.h" +#include "scene/scene_string_names.h" + +void VisibilityNotifier3D::_enter_camera(Camera3D *p_camera) { + + ERR_FAIL_COND(cameras.has(p_camera)); + cameras.insert(p_camera); + if (cameras.size() == 1) { + emit_signal(SceneStringNames::get_singleton()->screen_entered); + _screen_enter(); + } + + emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera); +} + +void VisibilityNotifier3D::_exit_camera(Camera3D *p_camera) { + + ERR_FAIL_COND(!cameras.has(p_camera)); + cameras.erase(p_camera); + + emit_signal(SceneStringNames::get_singleton()->camera_exited, p_camera); + if (cameras.size() == 0) { + emit_signal(SceneStringNames::get_singleton()->screen_exited); + + _screen_exit(); + } +} + +void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) { + + if (aabb == p_aabb) + return; + aabb = p_aabb; + + if (is_inside_world()) { + get_world()->_update_notifier(this, get_global_transform().xform(aabb)); + } + + _change_notify("aabb"); + update_gizmo(); +} + +AABB VisibilityNotifier3D::get_aabb() const { + + return aabb; +} + +void VisibilityNotifier3D::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_WORLD: { + + get_world()->_register_notifier(this, get_global_transform().xform(aabb)); + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + get_world()->_update_notifier(this, get_global_transform().xform(aabb)); + } break; + case NOTIFICATION_EXIT_WORLD: { + + get_world()->_remove_notifier(this); + } break; + } +} + +bool VisibilityNotifier3D::is_on_screen() const { + + return cameras.size() != 0; +} + +void VisibilityNotifier3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibilityNotifier3D::set_aabb); + ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier3D::get_aabb); + ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier3D::is_on_screen); + + ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb"); + + ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"))); + ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"))); + ADD_SIGNAL(MethodInfo("screen_entered")); + ADD_SIGNAL(MethodInfo("screen_exited")); +} + +VisibilityNotifier3D::VisibilityNotifier3D() { + + aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + set_notify_transform(true); +} + +////////////////////////////////////// + +void VisibilityEnabler3D::_screen_enter() { + + for (Map::Element *E = nodes.front(); E; E = E->next()) { + + _change_node_state(E->key(), true); + } + + visible = true; +} + +void VisibilityEnabler3D::_screen_exit() { + + for (Map::Element *E = nodes.front(); E; E = E->next()) { + + _change_node_state(E->key(), false); + } + + visible = false; +} + +void VisibilityEnabler3D::_find_nodes(Node *p_node) { + + bool add = false; + Variant meta; + + { + RigidBody3D *rb = Object::cast_to(p_node); + if (rb && ((rb->get_mode() == RigidBody3D::MODE_CHARACTER || rb->get_mode() == RigidBody3D::MODE_RIGID))) { + + add = true; + meta = rb->get_mode(); + } + } + + { + AnimationPlayer *ap = Object::cast_to(p_node); + if (ap) { + add = true; + } + } + + if (add) { + + p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed), varray(p_node), CONNECT_ONESHOT); + nodes[p_node] = meta; + _change_node_state(p_node, false); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *c = p_node->get_child(i); + if (c->get_filename() != String()) + continue; //skip, instance + + _find_nodes(c); + } +} + +void VisibilityEnabler3D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + + if (Engine::get_singleton()->is_editor_hint()) + return; + + Node *from = this; + //find where current scene starts + while (from->get_parent() && from->get_filename() == String()) + from = from->get_parent(); + + _find_nodes(from); + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + if (Engine::get_singleton()->is_editor_hint()) + return; + + for (Map::Element *E = nodes.front(); E; E = E->next()) { + + if (!visible) + _change_node_state(E->key(), true); + E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed)); + } + + nodes.clear(); + } +} + +void VisibilityEnabler3D::_change_node_state(Node *p_node, bool p_enabled) { + + ERR_FAIL_COND(!nodes.has(p_node)); + + if (enabler[ENABLER_FREEZE_BODIES]) { + RigidBody3D *rb = Object::cast_to(p_node); + if (rb) + + rb->set_sleeping(!p_enabled); + } + + if (enabler[ENABLER_PAUSE_ANIMATIONS]) { + AnimationPlayer *ap = Object::cast_to(p_node); + + if (ap) { + + ap->set_active(p_enabled); + } + } +} + +void VisibilityEnabler3D::_node_removed(Node *p_node) { + + if (!visible) + _change_node_state(p_node, true); + nodes.erase(p_node); +} + +void VisibilityEnabler3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler3D::set_enabler); + ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler3D::is_enabler_enabled); + + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES); + + BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS); + BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES); + BIND_ENUM_CONSTANT(ENABLER_MAX); +} + +void VisibilityEnabler3D::set_enabler(Enabler p_enabler, bool p_enable) { + + ERR_FAIL_INDEX(p_enabler, ENABLER_MAX); + enabler[p_enabler] = p_enable; +} +bool VisibilityEnabler3D::is_enabler_enabled(Enabler p_enabler) const { + + ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false); + return enabler[p_enabler]; +} + +VisibilityEnabler3D::VisibilityEnabler3D() { + + for (int i = 0; i < ENABLER_MAX; i++) + enabler[i] = true; + + visible = false; +} diff --git a/scene/3d/visibility_notifier_3d.h b/scene/3d/visibility_notifier_3d.h new file mode 100644 index 0000000000..19204a6a4e --- /dev/null +++ b/scene/3d/visibility_notifier_3d.h @@ -0,0 +1,101 @@ +/*************************************************************************/ +/* visibility_notifier_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VISIBILITY_NOTIFIER_H +#define VISIBILITY_NOTIFIER_H + +#include "scene/3d/node_3d.h" + +class Camera3D; +class VisibilityNotifier3D : public Node3D { + + GDCLASS(VisibilityNotifier3D, Node3D); + + Set cameras; + + AABB aabb; + +protected: + virtual void _screen_enter() {} + virtual void _screen_exit() {} + + void _notification(int p_what); + static void _bind_methods(); + friend struct SpatialIndexer; + + void _enter_camera(Camera3D *p_camera); + void _exit_camera(Camera3D *p_camera); + +public: + void set_aabb(const AABB &p_aabb); + AABB get_aabb() const; + bool is_on_screen() const; + + VisibilityNotifier3D(); +}; + +class VisibilityEnabler3D : public VisibilityNotifier3D { + + GDCLASS(VisibilityEnabler3D, VisibilityNotifier3D); + +public: + enum Enabler { + ENABLER_PAUSE_ANIMATIONS, + ENABLER_FREEZE_BODIES, + ENABLER_MAX + }; + +protected: + virtual void _screen_enter(); + virtual void _screen_exit(); + + bool visible; + + void _find_nodes(Node *p_node); + + Map nodes; + void _node_removed(Node *p_node); + bool enabler[ENABLER_MAX]; + + void _change_node_state(Node *p_node, bool p_enabled); + + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_enabler(Enabler p_enabler, bool p_enable); + bool is_enabler_enabled(Enabler p_enabler) const; + + VisibilityEnabler3D(); +}; + +VARIANT_ENUM_CAST(VisibilityEnabler3D::Enabler); + +#endif // VISIBILITY_NOTIFIER_H diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp deleted file mode 100644 index 105ce9ca74..0000000000 --- a/scene/3d/visual_instance.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/*************************************************************************/ -/* visual_instance.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_instance.h" - -#include "scene/scene_string_names.h" -#include "servers/visual_server.h" -#include "skeleton.h" - -AABB VisualInstance::get_transformed_aabb() const { - - return get_global_transform().xform(get_aabb()); -} - -void VisualInstance::_update_visibility() { - - if (!is_inside_tree()) - return; - - _change_notify("visible"); - VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree()); -} - -void VisualInstance::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_ENTER_WORLD: { - - // CHECK SKELETON => moving skeleton attaching logic to MeshInstance - /* - Skeleton *skeleton=Object::cast_to(get_parent()); - if (skeleton) - VisualServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() ); - */ - ERR_FAIL_COND(get_world().is_null()); - VisualServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); - _update_visibility(); - - } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - - Transform gt = get_global_transform(); - VisualServer::get_singleton()->instance_set_transform(instance, gt); - } break; - case NOTIFICATION_EXIT_WORLD: { - - VisualServer::get_singleton()->instance_set_scenario(instance, RID()); - VisualServer::get_singleton()->instance_attach_skeleton(instance, RID()); - //VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); - - } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - - _update_visibility(); - } break; - } -} - -RID VisualInstance::get_instance() const { - - return instance; -} - -RID VisualInstance::_get_visual_instance_rid() const { - - return instance; -} - -void VisualInstance::set_layer_mask(uint32_t p_mask) { - - layers = p_mask; - VisualServer::get_singleton()->instance_set_layer_mask(instance, p_mask); -} - -uint32_t VisualInstance::get_layer_mask() const { - - return layers; -} - -void VisualInstance::set_layer_mask_bit(int p_layer, bool p_enable) { - ERR_FAIL_INDEX(p_layer, 32); - if (p_enable) { - set_layer_mask(layers | (1 << p_layer)); - } else { - set_layer_mask(layers & (~(1 << p_layer))); - } -} - -bool VisualInstance::get_layer_mask_bit(int p_layer) const { - ERR_FAIL_INDEX_V(p_layer, 32, false); - return (layers & (1 << p_layer)); -} - -void VisualInstance::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance::_get_visual_instance_rid); - ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance::set_base); - ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance::get_base); - ClassDB::bind_method(D_METHOD("get_instance"), &VisualInstance::get_instance); - ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &VisualInstance::set_layer_mask); - ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance::get_layer_mask); - ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "layer", "enabled"), &VisualInstance::set_layer_mask_bit); - ClassDB::bind_method(D_METHOD("get_layer_mask_bit", "layer"), &VisualInstance::get_layer_mask_bit); - - ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask"); -} - -void VisualInstance::set_base(const RID &p_base) { - - VisualServer::get_singleton()->instance_set_base(instance, p_base); - base = p_base; -} - -RID VisualInstance::get_base() const { - - return base; -} - -VisualInstance::VisualInstance() { - - instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); - layers = 1; - set_notify_transform(true); -} - -VisualInstance::~VisualInstance() { - - VisualServer::get_singleton()->free(instance); -} - -void GeometryInstance::set_material_override(const Ref &p_material) { - - material_override = p_material; - VS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID()); -} - -Ref GeometryInstance::get_material_override() const { - - return material_override; -} - -void GeometryInstance::set_lod_min_distance(float p_dist) { - - lod_min_distance = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); -} - -float GeometryInstance::get_lod_min_distance() const { - - return lod_min_distance; -} - -void GeometryInstance::set_lod_max_distance(float p_dist) { - - lod_max_distance = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); -} - -float GeometryInstance::get_lod_max_distance() const { - - return lod_max_distance; -} - -void GeometryInstance::set_lod_min_hysteresis(float p_dist) { - - lod_min_hysteresis = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); -} - -float GeometryInstance::get_lod_min_hysteresis() const { - - return lod_min_hysteresis; -} - -void GeometryInstance::set_lod_max_hysteresis(float p_dist) { - - lod_max_hysteresis = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); -} - -float GeometryInstance::get_lod_max_hysteresis() const { - - return lod_max_hysteresis; -} - -void GeometryInstance::_notification(int p_what) { -} - -void GeometryInstance::set_flag(Flags p_flag, bool p_value) { - - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - if (flags[p_flag] == p_value) - return; - - flags[p_flag] = p_value; - VS::get_singleton()->instance_geometry_set_flag(get_instance(), (VS::InstanceFlags)p_flag, p_value); -} - -bool GeometryInstance::get_flag(Flags p_flag) const { - - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - - return flags[p_flag]; -} - -void GeometryInstance::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) { - - shadow_casting_setting = p_shadow_casting_setting; - - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (VS::ShadowCastingSetting)p_shadow_casting_setting); -} - -GeometryInstance::ShadowCastingSetting GeometryInstance::get_cast_shadows_setting() const { - - return shadow_casting_setting; -} - -void GeometryInstance::set_extra_cull_margin(float p_margin) { - - ERR_FAIL_COND(p_margin < 0); - extra_cull_margin = p_margin; - VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin); -} - -float GeometryInstance::get_extra_cull_margin() const { - - return extra_cull_margin; -} - -void GeometryInstance::set_custom_aabb(AABB aabb) { - - VS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb); -} - -void GeometryInstance::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance::set_material_override); - ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance::get_material_override); - - ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance::get_flag); - - ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting); - ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting); - - ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis", "mode"), &GeometryInstance::set_lod_max_hysteresis); - ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance::get_lod_max_hysteresis); - - ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance::set_lod_max_distance); - ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance::get_lod_max_distance); - - ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance::set_lod_min_hysteresis); - ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance::get_lod_min_hysteresis); - - ClassDB::bind_method(D_METHOD("set_lod_min_distance", "mode"), &GeometryInstance::set_lod_min_distance); - ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance::get_lod_min_distance); - - ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin); - ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin); - - ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance::set_custom_aabb); - - ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance::get_aabb); - - ADD_GROUP("Geometry", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_dynamic_gi"), "set_flag", "get_flag", FLAG_USE_DYNAMIC_GI); - - ADD_GROUP("LOD", "lod_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis"); - - //ADD_SIGNAL( MethodInfo("visibility_changed")); - - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); - - BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT); - BIND_ENUM_CONSTANT(FLAG_USE_DYNAMIC_GI); - BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE); - BIND_ENUM_CONSTANT(FLAG_MAX); -} - -GeometryInstance::GeometryInstance() { - lod_min_distance = 0; - lod_max_distance = 0; - lod_min_hysteresis = 0; - lod_max_hysteresis = 0; - - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; - } - - shadow_casting_setting = SHADOW_CASTING_SETTING_ON; - extra_cull_margin = 0; - //VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0); -} diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h deleted file mode 100644 index fee6787c87..0000000000 --- a/scene/3d/visual_instance.h +++ /dev/null @@ -1,150 +0,0 @@ -/*************************************************************************/ -/* visual_instance.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUAL_INSTANCE_H -#define VISUAL_INSTANCE_H - -#include "core/math/face3.h" -#include "core/rid.h" -#include "scene/3d/spatial.h" -#include "scene/resources/material.h" - -class VisualInstance : public Spatial { - - GDCLASS(VisualInstance, Spatial); - OBJ_CATEGORY("3D Visual Nodes"); - - RID base; - RID instance; - uint32_t layers; - - RID _get_visual_instance_rid() const; - -protected: - void _update_visibility(); - - void _notification(int p_what); - static void _bind_methods(); - -public: - enum GetFacesFlags { - FACES_SOLID = 1, // solid geometry - FACES_ENCLOSING = 2, - FACES_DYNAMIC = 4 // dynamic object geometry - - }; - - RID get_instance() const; - virtual AABB get_aabb() const = 0; - virtual Vector get_faces(uint32_t p_usage_flags) const = 0; - - virtual AABB get_transformed_aabb() const; // helper - - void set_base(const RID &p_base); - RID get_base() const; - - void set_layer_mask(uint32_t p_mask); - uint32_t get_layer_mask() const; - - void set_layer_mask_bit(int p_layer, bool p_enable); - bool get_layer_mask_bit(int p_layer) const; - - VisualInstance(); - ~VisualInstance(); -}; - -class GeometryInstance : public VisualInstance { - - GDCLASS(GeometryInstance, VisualInstance); - -public: - enum Flags { - FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT, - FLAG_USE_DYNAMIC_GI = VS::INSTANCE_FLAG_USE_DYNAMIC_GI, - FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, - FLAG_MAX = VS::INSTANCE_FLAG_MAX, - }; - - enum ShadowCastingSetting { - SHADOW_CASTING_SETTING_OFF = VS::SHADOW_CASTING_SETTING_OFF, - SHADOW_CASTING_SETTING_ON = VS::SHADOW_CASTING_SETTING_ON, - SHADOW_CASTING_SETTING_DOUBLE_SIDED = VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED, - SHADOW_CASTING_SETTING_SHADOWS_ONLY = VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY - }; - -private: - bool flags[FLAG_MAX]; - ShadowCastingSetting shadow_casting_setting; - Ref material_override; - float lod_min_distance; - float lod_max_distance; - float lod_min_hysteresis; - float lod_max_hysteresis; - - float extra_cull_margin; - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void set_flag(Flags p_flag, bool p_value); - bool get_flag(Flags p_flag) const; - - void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting); - ShadowCastingSetting get_cast_shadows_setting() const; - - void set_lod_min_distance(float p_dist); - float get_lod_min_distance() const; - - void set_lod_max_distance(float p_dist); - float get_lod_max_distance() const; - - void set_lod_min_hysteresis(float p_dist); - float get_lod_min_hysteresis() const; - - void set_lod_max_hysteresis(float p_dist); - float get_lod_max_hysteresis() const; - - void set_material_override(const Ref &p_material); - Ref get_material_override() const; - - void set_extra_cull_margin(float p_margin); - float get_extra_cull_margin() const; - - void set_custom_aabb(AABB aabb); - - GeometryInstance(); -}; - -VARIANT_ENUM_CAST(GeometryInstance::Flags); -VARIANT_ENUM_CAST(GeometryInstance::ShadowCastingSetting); - -#endif diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp new file mode 100644 index 0000000000..14a975c023 --- /dev/null +++ b/scene/3d/visual_instance_3d.cpp @@ -0,0 +1,335 @@ +/*************************************************************************/ +/* visual_instance_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "visual_instance_3d.h" + +#include "scene/scene_string_names.h" +#include "servers/visual_server.h" +#include "skeleton_3d.h" + +AABB VisualInstance3D::get_transformed_aabb() const { + + return get_global_transform().xform(get_aabb()); +} + +void VisualInstance3D::_update_visibility() { + + if (!is_inside_tree()) + return; + + _change_notify("visible"); + VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree()); +} + +void VisualInstance3D::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_WORLD: { + + // CHECK SKELETON => moving skeleton attaching logic to MeshInstance + /* + Skeleton *skeleton=Object::cast_to(get_parent()); + if (skeleton) + VisualServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() ); + */ + ERR_FAIL_COND(get_world().is_null()); + VisualServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); + _update_visibility(); + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + Transform gt = get_global_transform(); + VisualServer::get_singleton()->instance_set_transform(instance, gt); + } break; + case NOTIFICATION_EXIT_WORLD: { + + VisualServer::get_singleton()->instance_set_scenario(instance, RID()); + VisualServer::get_singleton()->instance_attach_skeleton(instance, RID()); + //VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); + + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_visibility(); + } break; + } +} + +RID VisualInstance3D::get_instance() const { + + return instance; +} + +RID VisualInstance3D::_get_visual_instance_rid() const { + + return instance; +} + +void VisualInstance3D::set_layer_mask(uint32_t p_mask) { + + layers = p_mask; + VisualServer::get_singleton()->instance_set_layer_mask(instance, p_mask); +} + +uint32_t VisualInstance3D::get_layer_mask() const { + + return layers; +} + +void VisualInstance3D::set_layer_mask_bit(int p_layer, bool p_enable) { + ERR_FAIL_INDEX(p_layer, 32); + if (p_enable) { + set_layer_mask(layers | (1 << p_layer)); + } else { + set_layer_mask(layers & (~(1 << p_layer))); + } +} + +bool VisualInstance3D::get_layer_mask_bit(int p_layer) const { + ERR_FAIL_INDEX_V(p_layer, 32, false); + return (layers & (1 << p_layer)); +} + +void VisualInstance3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance3D::_get_visual_instance_rid); + ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance3D::set_base); + ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance3D::get_base); + ClassDB::bind_method(D_METHOD("get_instance"), &VisualInstance3D::get_instance); + ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &VisualInstance3D::set_layer_mask); + ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance3D::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "layer", "enabled"), &VisualInstance3D::set_layer_mask_bit); + ClassDB::bind_method(D_METHOD("get_layer_mask_bit", "layer"), &VisualInstance3D::get_layer_mask_bit); + + ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance3D::get_transformed_aabb); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask"); +} + +void VisualInstance3D::set_base(const RID &p_base) { + + VisualServer::get_singleton()->instance_set_base(instance, p_base); + base = p_base; +} + +RID VisualInstance3D::get_base() const { + + return base; +} + +VisualInstance3D::VisualInstance3D() { + + instance = VisualServer::get_singleton()->instance_create(); + VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); + layers = 1; + set_notify_transform(true); +} + +VisualInstance3D::~VisualInstance3D() { + + VisualServer::get_singleton()->free(instance); +} + +void GeometryInstance3D::set_material_override(const Ref &p_material) { + + material_override = p_material; + VS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID()); +} + +Ref GeometryInstance3D::get_material_override() const { + + return material_override; +} + +void GeometryInstance3D::set_lod_min_distance(float p_dist) { + + lod_min_distance = p_dist; + VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); +} + +float GeometryInstance3D::get_lod_min_distance() const { + + return lod_min_distance; +} + +void GeometryInstance3D::set_lod_max_distance(float p_dist) { + + lod_max_distance = p_dist; + VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); +} + +float GeometryInstance3D::get_lod_max_distance() const { + + return lod_max_distance; +} + +void GeometryInstance3D::set_lod_min_hysteresis(float p_dist) { + + lod_min_hysteresis = p_dist; + VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); +} + +float GeometryInstance3D::get_lod_min_hysteresis() const { + + return lod_min_hysteresis; +} + +void GeometryInstance3D::set_lod_max_hysteresis(float p_dist) { + + lod_max_hysteresis = p_dist; + VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); +} + +float GeometryInstance3D::get_lod_max_hysteresis() const { + + return lod_max_hysteresis; +} + +void GeometryInstance3D::_notification(int p_what) { +} + +void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) { + + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + if (flags[p_flag] == p_value) + return; + + flags[p_flag] = p_value; + VS::get_singleton()->instance_geometry_set_flag(get_instance(), (VS::InstanceFlags)p_flag, p_value); +} + +bool GeometryInstance3D::get_flag(Flags p_flag) const { + + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + + return flags[p_flag]; +} + +void GeometryInstance3D::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) { + + shadow_casting_setting = p_shadow_casting_setting; + + VS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (VS::ShadowCastingSetting)p_shadow_casting_setting); +} + +GeometryInstance3D::ShadowCastingSetting GeometryInstance3D::get_cast_shadows_setting() const { + + return shadow_casting_setting; +} + +void GeometryInstance3D::set_extra_cull_margin(float p_margin) { + + ERR_FAIL_COND(p_margin < 0); + extra_cull_margin = p_margin; + VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin); +} + +float GeometryInstance3D::get_extra_cull_margin() const { + + return extra_cull_margin; +} + +void GeometryInstance3D::set_custom_aabb(AABB aabb) { + + VS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb); +} + +void GeometryInstance3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance3D::set_material_override); + ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance3D::get_material_override); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance3D::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance3D::get_flag); + + ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance3D::set_cast_shadows_setting); + ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance3D::get_cast_shadows_setting); + + ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis", "mode"), &GeometryInstance3D::set_lod_max_hysteresis); + ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance3D::get_lod_max_hysteresis); + + ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance); + ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance); + + ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis); + ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis); + + ClassDB::bind_method(D_METHOD("set_lod_min_distance", "mode"), &GeometryInstance3D::set_lod_min_distance); + ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance3D::get_lod_min_distance); + + ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin); + ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin); + + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb); + + ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb); + + ADD_GROUP("Geometry", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_dynamic_gi"), "set_flag", "get_flag", FLAG_USE_DYNAMIC_GI); + + ADD_GROUP("LOD", "lod_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis"); + + //ADD_SIGNAL( MethodInfo("visibility_changed")); + + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); + + BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT); + BIND_ENUM_CONSTANT(FLAG_USE_DYNAMIC_GI); + BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE); + BIND_ENUM_CONSTANT(FLAG_MAX); +} + +GeometryInstance3D::GeometryInstance3D() { + lod_min_distance = 0; + lod_max_distance = 0; + lod_min_hysteresis = 0; + lod_max_hysteresis = 0; + + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + + shadow_casting_setting = SHADOW_CASTING_SETTING_ON; + extra_cull_margin = 0; + //VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0); +} diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h new file mode 100644 index 0000000000..59a935fdee --- /dev/null +++ b/scene/3d/visual_instance_3d.h @@ -0,0 +1,150 @@ +/*************************************************************************/ +/* visual_instance_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VISUAL_INSTANCE_H +#define VISUAL_INSTANCE_H + +#include "core/math/face3.h" +#include "core/rid.h" +#include "scene/3d/node_3d.h" +#include "scene/resources/material.h" + +class VisualInstance3D : public Node3D { + + GDCLASS(VisualInstance3D, Node3D); + OBJ_CATEGORY("3D Visual Nodes"); + + RID base; + RID instance; + uint32_t layers; + + RID _get_visual_instance_rid() const; + +protected: + void _update_visibility(); + + void _notification(int p_what); + static void _bind_methods(); + +public: + enum GetFacesFlags { + FACES_SOLID = 1, // solid geometry + FACES_ENCLOSING = 2, + FACES_DYNAMIC = 4 // dynamic object geometry + + }; + + RID get_instance() const; + virtual AABB get_aabb() const = 0; + virtual Vector get_faces(uint32_t p_usage_flags) const = 0; + + virtual AABB get_transformed_aabb() const; // helper + + void set_base(const RID &p_base); + RID get_base() const; + + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + + void set_layer_mask_bit(int p_layer, bool p_enable); + bool get_layer_mask_bit(int p_layer) const; + + VisualInstance3D(); + ~VisualInstance3D(); +}; + +class GeometryInstance3D : public VisualInstance3D { + + GDCLASS(GeometryInstance3D, VisualInstance3D); + +public: + enum Flags { + FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT, + FLAG_USE_DYNAMIC_GI = VS::INSTANCE_FLAG_USE_DYNAMIC_GI, + FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, + FLAG_MAX = VS::INSTANCE_FLAG_MAX, + }; + + enum ShadowCastingSetting { + SHADOW_CASTING_SETTING_OFF = VS::SHADOW_CASTING_SETTING_OFF, + SHADOW_CASTING_SETTING_ON = VS::SHADOW_CASTING_SETTING_ON, + SHADOW_CASTING_SETTING_DOUBLE_SIDED = VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED, + SHADOW_CASTING_SETTING_SHADOWS_ONLY = VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY + }; + +private: + bool flags[FLAG_MAX]; + ShadowCastingSetting shadow_casting_setting; + Ref material_override; + float lod_min_distance; + float lod_max_distance; + float lod_min_hysteresis; + float lod_max_hysteresis; + + float extra_cull_margin; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_flag(Flags p_flag, bool p_value); + bool get_flag(Flags p_flag) const; + + void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting); + ShadowCastingSetting get_cast_shadows_setting() const; + + void set_lod_min_distance(float p_dist); + float get_lod_min_distance() const; + + void set_lod_max_distance(float p_dist); + float get_lod_max_distance() const; + + void set_lod_min_hysteresis(float p_dist); + float get_lod_min_hysteresis() const; + + void set_lod_max_hysteresis(float p_dist); + float get_lod_max_hysteresis() const; + + void set_material_override(const Ref &p_material); + Ref get_material_override() const; + + void set_extra_cull_margin(float p_margin); + float get_extra_cull_margin() const; + + void set_custom_aabb(AABB aabb); + + GeometryInstance3D(); +}; + +VARIANT_ENUM_CAST(GeometryInstance3D::Flags); +VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting); + +#endif diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index af9237ae7b..1fde6237a2 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -32,7 +32,7 @@ #define VOXEL_LIGHT_BAKER_H #include "core/math/vector3i.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/resources/multimesh.h" class Voxelizer { diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 9276432ba9..8cf4554653 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -33,7 +33,7 @@ void WorldEnvironment::_notification(int p_what) { - if (p_what == Spatial::NOTIFICATION_ENTER_WORLD || p_what == Spatial::NOTIFICATION_ENTER_TREE) { + if (p_what == Node3D::NOTIFICATION_ENTER_WORLD || p_what == Node3D::NOTIFICATION_ENTER_TREE) { if (environment.is_valid()) { if (get_viewport()->find_world()->get_environment().is_valid()) { @@ -51,7 +51,7 @@ void WorldEnvironment::_notification(int p_what) { add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } - } else if (p_what == Spatial::NOTIFICATION_EXIT_WORLD || p_what == Spatial::NOTIFICATION_EXIT_TREE) { + } else if (p_what == Node3D::NOTIFICATION_EXIT_WORLD || p_what == Node3D::NOTIFICATION_EXIT_TREE) { if (environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) { get_viewport()->find_world()->set_environment(Ref()); diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 0c590bfc07..e4c9fc071d 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -31,7 +31,7 @@ #ifndef SCENARIO_FX_H #define SCENARIO_FX_H -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" class WorldEnvironment : public Node { diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 9ed8155bdc..79a7c36e7f 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -94,19 +94,19 @@ void AnimationCache::_update_cache() { ERR_CONTINUE_MSG(animation->track_get_type(i) == Animation::TYPE_TRANSFORM, "Transform tracks can't have a subpath '" + np + "'."); } - Spatial *sp = Object::cast_to(node); + Node3D *sp = Object::cast_to(node); if (!sp) { path_cache.push_back(Path()); - ERR_CONTINUE_MSG(!sp, "Transform track not of type Spatial '" + np + "'."); + ERR_CONTINUE_MSG(!sp, "Transform track not of type Node3D '" + np + "'."); } if (np.get_subname_count() == 1) { StringName property = np.get_subname(0); String ps = property; - Skeleton *sk = Object::cast_to(node); + Skeleton3D *sk = Object::cast_to(node); if (!sk) { path_cache.push_back(Path()); diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index e73b9e2498..20147f060b 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -31,7 +31,7 @@ #ifndef ANIMATION_CACHE_H #define ANIMATION_CACHE_H -#include "scene/3d/skeleton.h" +#include "scene/3d/skeleton_3d.h" #include "scene/resources/animation.h" class AnimationCache : public Object { @@ -42,9 +42,9 @@ class AnimationCache : public Object { RES resource; Object *object; - Skeleton *skeleton; // haxor + Skeleton3D *skeleton; // haxor Node *node; - Spatial *spatial; + Node3D *spatial; int bone_idx; Vector subpath; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 587485669e..6c870682a6 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -44,7 +44,7 @@ void AnimatedValuesBackup::update_skeletons() { for (int i = 0; i < entries.size(); i++) { if (entries[i].bone_idx != -1) { // 3D bone - Object::cast_to(entries[i].object)->notification(Skeleton::NOTIFICATION_UPDATE_SKELETON); + Object::cast_to(entries[i].object)->notification(Skeleton3D::NOTIFICATION_UPDATE_SKELETON); } else { Bone2D *bone = Object::cast_to(entries[i].object); if (bone && bone->skeleton) { @@ -252,9 +252,9 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { ObjectID id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id(); int bone_idx = -1; - if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to(child)) { + if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to(child)) { - Skeleton *sk = Object::cast_to(child); + Skeleton3D *sk = Object::cast_to(child); bone_idx = sk->find_bone(a->track_get_path(i).get_subname(0)); if (bone_idx == -1) { @@ -283,9 +283,9 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) { // special cases and caches for transform tracks // cache spatial - p_anim->node_cache[i]->spatial = Object::cast_to(child); + p_anim->node_cache[i]->spatial = Object::cast_to(child); // cache skeleton - p_anim->node_cache[i]->skeleton = Object::cast_to(child); + p_anim->node_cache[i]->skeleton = Object::cast_to(child); if (p_anim->node_cache[i]->skeleton) { if (a->track_get_path(i).get_subname_count() == 1) { StringName bone_name = a->track_get_path(i).get_subname(0); @@ -1612,7 +1612,7 @@ void AnimationPlayer::restore_animated_values(const AnimatedValuesBackup &p_back if (entry->bone_idx == -1) { entry->object->set_indexed(entry->subpath, entry->value); } else { - Object::cast_to(entry->object)->set_bone_pose(entry->bone_idx, entry->value); + Object::cast_to(entry->object)->set_bone_pose(entry->bone_idx, entry->value); } } } diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 24f60363ed..32bed6f4d6 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -32,8 +32,8 @@ #define ANIMATION_PLAYER_H #include "scene/2d/node_2d.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/resources/animation.h" #ifdef TOOLS_ENABLED @@ -90,9 +90,9 @@ private: uint32_t id; RES resource; Node *node; - Spatial *spatial; + Node3D *spatial; Node2D *node_2d; - Skeleton *skeleton; + Skeleton3D *skeleton; int bone_idx; // accumulated transforms diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 95afd74ee5..0e1089cc6a 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -605,7 +605,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } break; case Animation::TYPE_TRANSFORM: { - Spatial *spatial = Object::cast_to(child); + Node3D *spatial = Object::cast_to(child); if (!spatial) { ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'"); @@ -618,9 +618,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_xform->skeleton = NULL; track_xform->bone_idx = -1; - if (path.get_subname_count() == 1 && Object::cast_to(spatial)) { + if (path.get_subname_count() == 1 && Object::cast_to(spatial)) { - Skeleton *sk = Object::cast_to(spatial); + Skeleton3D *sk = Object::cast_to(spatial); int bone_idx = sk->find_bone(path.get_subname(0)); if (bone_idx != -1) { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 742942fcda..faf4333f1d 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -32,8 +32,8 @@ #define ANIMATION_GRAPH_PLAYER_H #include "animation_player.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/resources/animation.h" class AnimationNodeBlendTree; @@ -192,8 +192,8 @@ private: }; struct TrackCacheTransform : public TrackCache { - Spatial *spatial; - Skeleton *skeleton; + Node3D *spatial; + Skeleton3D *skeleton; int bone_idx; Vector3 loc; Quat rot; diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h index 42950dde42..c8a755a854 100644 --- a/scene/animation/root_motion_view.h +++ b/scene/animation/root_motion_view.h @@ -31,10 +31,10 @@ #ifndef ROOT_MOTION_VIEW_H #define ROOT_MOTION_VIEW_H -#include "scene/3d/visual_instance.h" +#include "scene/3d/visual_instance_3d.h" -class RootMotionView : public VisualInstance { - GDCLASS(RootMotionView, VisualInstance); +class RootMotionView : public VisualInstance3D { + GDCLASS(RootMotionView, VisualInstance3D); public: RID immediate; diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp index 5800b41ae6..71aa5e13b3 100644 --- a/scene/animation/skeleton_ik.cpp +++ b/scene/animation/skeleton_ik.cpp @@ -136,7 +136,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain return true; } -void FabrikInverseKinematic::update_chain(const Skeleton *p_sk, ChainItem *p_chain_item) { +void FabrikInverseKinematic::update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item) { if (!p_chain_item) return; @@ -238,7 +238,7 @@ void FabrikInverseKinematic::solve_simple_forwards(Chain &r_chain, bool p_solve_ } } -FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleton *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform) { +FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform) { FabrikInverseKinematic::EndEffector ee; ee.tip_bone = tip_bone; @@ -332,7 +332,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove } } -void SkeletonIK::_validate_property(PropertyInfo &property) const { +void SkeletonIK3D::_validate_property(PropertyInfo &property) const { if (property.name == "root_bone" || property.name == "tip_bone") { @@ -355,43 +355,43 @@ void SkeletonIK::_validate_property(PropertyInfo &property) const { } } -void SkeletonIK::_bind_methods() { +void SkeletonIK3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_root_bone", "root_bone"), &SkeletonIK::set_root_bone); - ClassDB::bind_method(D_METHOD("get_root_bone"), &SkeletonIK::get_root_bone); + ClassDB::bind_method(D_METHOD("set_root_bone", "root_bone"), &SkeletonIK3D::set_root_bone); + ClassDB::bind_method(D_METHOD("get_root_bone"), &SkeletonIK3D::get_root_bone); - ClassDB::bind_method(D_METHOD("set_tip_bone", "tip_bone"), &SkeletonIK::set_tip_bone); - ClassDB::bind_method(D_METHOD("get_tip_bone"), &SkeletonIK::get_tip_bone); + ClassDB::bind_method(D_METHOD("set_tip_bone", "tip_bone"), &SkeletonIK3D::set_tip_bone); + ClassDB::bind_method(D_METHOD("get_tip_bone"), &SkeletonIK3D::get_tip_bone); - ClassDB::bind_method(D_METHOD("set_interpolation", "interpolation"), &SkeletonIK::set_interpolation); - ClassDB::bind_method(D_METHOD("get_interpolation"), &SkeletonIK::get_interpolation); + ClassDB::bind_method(D_METHOD("set_interpolation", "interpolation"), &SkeletonIK3D::set_interpolation); + ClassDB::bind_method(D_METHOD("get_interpolation"), &SkeletonIK3D::get_interpolation); - ClassDB::bind_method(D_METHOD("set_target_transform", "target"), &SkeletonIK::set_target_transform); - ClassDB::bind_method(D_METHOD("get_target_transform"), &SkeletonIK::get_target_transform); + ClassDB::bind_method(D_METHOD("set_target_transform", "target"), &SkeletonIK3D::set_target_transform); + ClassDB::bind_method(D_METHOD("get_target_transform"), &SkeletonIK3D::get_target_transform); - ClassDB::bind_method(D_METHOD("set_target_node", "node"), &SkeletonIK::set_target_node); - ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonIK::get_target_node); + ClassDB::bind_method(D_METHOD("set_target_node", "node"), &SkeletonIK3D::set_target_node); + ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonIK3D::get_target_node); - ClassDB::bind_method(D_METHOD("set_override_tip_basis", "override"), &SkeletonIK::set_override_tip_basis); - ClassDB::bind_method(D_METHOD("is_override_tip_basis"), &SkeletonIK::is_override_tip_basis); + ClassDB::bind_method(D_METHOD("set_override_tip_basis", "override"), &SkeletonIK3D::set_override_tip_basis); + ClassDB::bind_method(D_METHOD("is_override_tip_basis"), &SkeletonIK3D::is_override_tip_basis); - ClassDB::bind_method(D_METHOD("set_use_magnet", "use"), &SkeletonIK::set_use_magnet); - ClassDB::bind_method(D_METHOD("is_using_magnet"), &SkeletonIK::is_using_magnet); + ClassDB::bind_method(D_METHOD("set_use_magnet", "use"), &SkeletonIK3D::set_use_magnet); + ClassDB::bind_method(D_METHOD("is_using_magnet"), &SkeletonIK3D::is_using_magnet); - ClassDB::bind_method(D_METHOD("set_magnet_position", "local_position"), &SkeletonIK::set_magnet_position); - ClassDB::bind_method(D_METHOD("get_magnet_position"), &SkeletonIK::get_magnet_position); + ClassDB::bind_method(D_METHOD("set_magnet_position", "local_position"), &SkeletonIK3D::set_magnet_position); + ClassDB::bind_method(D_METHOD("get_magnet_position"), &SkeletonIK3D::get_magnet_position); - ClassDB::bind_method(D_METHOD("get_parent_skeleton"), &SkeletonIK::get_parent_skeleton); - ClassDB::bind_method(D_METHOD("is_running"), &SkeletonIK::is_running); + ClassDB::bind_method(D_METHOD("get_parent_skeleton"), &SkeletonIK3D::get_parent_skeleton); + ClassDB::bind_method(D_METHOD("is_running"), &SkeletonIK3D::is_running); - ClassDB::bind_method(D_METHOD("set_min_distance", "min_distance"), &SkeletonIK::set_min_distance); - ClassDB::bind_method(D_METHOD("get_min_distance"), &SkeletonIK::get_min_distance); + ClassDB::bind_method(D_METHOD("set_min_distance", "min_distance"), &SkeletonIK3D::set_min_distance); + ClassDB::bind_method(D_METHOD("get_min_distance"), &SkeletonIK3D::get_min_distance); - ClassDB::bind_method(D_METHOD("set_max_iterations", "iterations"), &SkeletonIK::set_max_iterations); - ClassDB::bind_method(D_METHOD("get_max_iterations"), &SkeletonIK::get_max_iterations); + ClassDB::bind_method(D_METHOD("set_max_iterations", "iterations"), &SkeletonIK3D::set_max_iterations); + ClassDB::bind_method(D_METHOD("get_max_iterations"), &SkeletonIK3D::get_max_iterations); - ClassDB::bind_method(D_METHOD("start", "one_time"), &SkeletonIK::start, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("stop"), &SkeletonIK::stop); + ClassDB::bind_method(D_METHOD("start", "one_time"), &SkeletonIK3D::start, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("stop"), &SkeletonIK3D::stop); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "root_bone"), "set_root_bone", "get_root_bone"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "tip_bone"), "set_tip_bone", "get_tip_bone"); @@ -405,10 +405,10 @@ void SkeletonIK::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "max_iterations"), "set_max_iterations", "get_max_iterations"); } -void SkeletonIK::_notification(int p_what) { +void SkeletonIK3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - skeleton = Object::cast_to(get_parent()); + skeleton = Object::cast_to(get_parent()); set_process_priority(1); reload_chain(); } break; @@ -426,7 +426,7 @@ void SkeletonIK::_notification(int p_what) { } } -SkeletonIK::SkeletonIK() : +SkeletonIK3D::SkeletonIK3D() : interpolation(1), override_tip_basis(true), use_magnet(false), @@ -437,93 +437,93 @@ SkeletonIK::SkeletonIK() : task(NULL) { } -SkeletonIK::~SkeletonIK() { +SkeletonIK3D::~SkeletonIK3D() { FabrikInverseKinematic::free_task(task); task = NULL; } -void SkeletonIK::set_root_bone(const StringName &p_root_bone) { +void SkeletonIK3D::set_root_bone(const StringName &p_root_bone) { root_bone = p_root_bone; reload_chain(); } -StringName SkeletonIK::get_root_bone() const { +StringName SkeletonIK3D::get_root_bone() const { return root_bone; } -void SkeletonIK::set_tip_bone(const StringName &p_tip_bone) { +void SkeletonIK3D::set_tip_bone(const StringName &p_tip_bone) { tip_bone = p_tip_bone; reload_chain(); } -StringName SkeletonIK::get_tip_bone() const { +StringName SkeletonIK3D::get_tip_bone() const { return tip_bone; } -void SkeletonIK::set_interpolation(real_t p_interpolation) { +void SkeletonIK3D::set_interpolation(real_t p_interpolation) { interpolation = p_interpolation; } -real_t SkeletonIK::get_interpolation() const { +real_t SkeletonIK3D::get_interpolation() const { return interpolation; } -void SkeletonIK::set_target_transform(const Transform &p_target) { +void SkeletonIK3D::set_target_transform(const Transform &p_target) { target = p_target; reload_goal(); } -const Transform &SkeletonIK::get_target_transform() const { +const Transform &SkeletonIK3D::get_target_transform() const { return target; } -void SkeletonIK::set_target_node(const NodePath &p_node) { +void SkeletonIK3D::set_target_node(const NodePath &p_node) { target_node_path_override = p_node; target_node_override = NULL; reload_goal(); } -NodePath SkeletonIK::get_target_node() { +NodePath SkeletonIK3D::get_target_node() { return target_node_path_override; } -void SkeletonIK::set_override_tip_basis(bool p_override) { +void SkeletonIK3D::set_override_tip_basis(bool p_override) { override_tip_basis = p_override; } -bool SkeletonIK::is_override_tip_basis() const { +bool SkeletonIK3D::is_override_tip_basis() const { return override_tip_basis; } -void SkeletonIK::set_use_magnet(bool p_use) { +void SkeletonIK3D::set_use_magnet(bool p_use) { use_magnet = p_use; } -bool SkeletonIK::is_using_magnet() const { +bool SkeletonIK3D::is_using_magnet() const { return use_magnet; } -void SkeletonIK::set_magnet_position(const Vector3 &p_local_position) { +void SkeletonIK3D::set_magnet_position(const Vector3 &p_local_position) { magnet_position = p_local_position; } -const Vector3 &SkeletonIK::get_magnet_position() const { +const Vector3 &SkeletonIK3D::get_magnet_position() const { return magnet_position; } -void SkeletonIK::set_min_distance(real_t p_min_distance) { +void SkeletonIK3D::set_min_distance(real_t p_min_distance) { min_distance = p_min_distance; } -void SkeletonIK::set_max_iterations(int p_iterations) { +void SkeletonIK3D::set_max_iterations(int p_iterations) { max_iterations = p_iterations; } -bool SkeletonIK::is_running() { +bool SkeletonIK3D::is_running() { return is_processing_internal(); } -void SkeletonIK::start(bool p_one_time) { +void SkeletonIK3D::start(bool p_one_time) { if (p_one_time) { set_process_internal(false); _solve_chain(); @@ -532,14 +532,14 @@ void SkeletonIK::start(bool p_one_time) { } } -void SkeletonIK::stop() { +void SkeletonIK3D::stop() { set_process_internal(false); } -Transform SkeletonIK::_get_target_transform() { +Transform SkeletonIK3D::_get_target_transform() { if (!target_node_override && !target_node_path_override.is_empty()) - target_node_override = Object::cast_to(get_node(target_node_path_override)); + target_node_override = Object::cast_to(get_node(target_node_path_override)); if (target_node_override) return target_node_override->get_global_transform(); @@ -547,7 +547,7 @@ Transform SkeletonIK::_get_target_transform() { return target; } -void SkeletonIK::reload_chain() { +void SkeletonIK3D::reload_chain() { FabrikInverseKinematic::free_task(task); task = NULL; @@ -562,14 +562,14 @@ void SkeletonIK::reload_chain() { } } -void SkeletonIK::reload_goal() { +void SkeletonIK3D::reload_goal() { if (!task) return; FabrikInverseKinematic::set_goal(task, _get_target_transform()); } -void SkeletonIK::_solve_chain() { +void SkeletonIK3D::_solve_chain() { if (!task) return; FabrikInverseKinematic::solve(task, interpolation, override_tip_basis, use_magnet, magnet_position); diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h index 02d5aba5ba..938c912065 100644 --- a/scene/animation/skeleton_ik.h +++ b/scene/animation/skeleton_ik.h @@ -38,7 +38,7 @@ */ #include "core/math/transform.h" -#include "scene/3d/skeleton.h" +#include "scene/3d/skeleton_3d.h" class FabrikInverseKinematic { @@ -54,7 +54,7 @@ class FabrikInverseKinematic { // Bone info BoneId bone; - PhysicalBone *pb; + PhysicalBone3D *pb; real_t length; /// Positions relative to root bone @@ -100,7 +100,7 @@ class FabrikInverseKinematic { public: struct Task { RID self; - Skeleton *skeleton; + Skeleton3D *skeleton; Chain chain; @@ -125,7 +125,7 @@ private: /// Init a chain that starts from the root to tip static bool build_chain(Task *p_task, bool p_force_simple_chain = true); - static void update_chain(const Skeleton *p_sk, ChainItem *p_chain_item); + static void update_chain(const Skeleton3D *p_sk, ChainItem *p_chain_item); static void solve_simple(Task *p_task, bool p_solve_magnet); /// Special solvers that solve only chains with one end effector @@ -133,7 +133,7 @@ private: static void solve_simple_forwards(Chain &r_chain, bool p_solve_magnet); public: - static Task *create_simple_task(Skeleton *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform); + static Task *create_simple_task(Skeleton3D *p_sk, BoneId root_bone, BoneId tip_bone, const Transform &goal_transform); static void free_task(Task *p_task); // The goal of chain should be always in local space static void set_goal(Task *p_task, const Transform &p_goal); @@ -141,8 +141,8 @@ public: static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position); }; -class SkeletonIK : public Node { - GDCLASS(SkeletonIK, Node); +class SkeletonIK3D : public Node { + GDCLASS(SkeletonIK3D, Node); StringName root_bone; StringName tip_bone; @@ -156,8 +156,8 @@ class SkeletonIK : public Node { real_t min_distance; int max_iterations; - Skeleton *skeleton; - Spatial *target_node_override; + Skeleton3D *skeleton; + Node3D *target_node_override; FabrikInverseKinematic::Task *task; protected: @@ -168,8 +168,8 @@ protected: virtual void _notification(int p_what); public: - SkeletonIK(); - virtual ~SkeletonIK(); + SkeletonIK3D(); + virtual ~SkeletonIK3D(); void set_root_bone(const StringName &p_root_bone); StringName get_root_bone() const; @@ -201,7 +201,7 @@ public: void set_max_iterations(int p_iterations); int get_max_iterations() const { return max_iterations; } - Skeleton *get_parent_skeleton() const { return skeleton; } + Skeleton3D *get_parent_skeleton() const { return skeleton; } bool is_running(); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index e6b2575f98..48b3fcacb3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -189,7 +189,7 @@ private: void _flush_delete_queue(); //optimization friend class CanvasItem; - friend class Spatial; + friend class Node3D; friend class Viewport; SelfList::List xform_change_list; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index e49674663a..aaebd448b2 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -36,10 +36,10 @@ #include "core/os/os.h" #include "core/project_settings.h" #include "scene/2d/collision_object_2d.h" -#include "scene/3d/camera.h" -#include "scene/3d/collision_object.h" -#include "scene/3d/listener.h" -#include "scene/3d/spatial.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/collision_object_3d.h" +#include "scene/3d/listener_3d.h" +#include "scene/3d/node_3d.h" #include "scene/3d/world_environment.h" #include "scene/gui/control.h" #include "scene/gui/label.h" @@ -218,7 +218,7 @@ void Viewport::update_worlds() { find_world()->_update(get_tree()->get_frame()); } -void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { +void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { Transform object_transform = p_object->get_global_transform(); Transform camera_transform = p_camera->get_global_transform(); @@ -489,8 +489,8 @@ void Viewport::_notification(int p_what) { case NOTIFICATION_READY: { #ifndef _3D_DISABLED if (listeners.size() && !listener) { - Listener *first = NULL; - for (Set::Element *E = listeners.front(); E; E = E->next()) { + Listener3D *first = NULL; + for (Set::Element *E = listeners.front(); E; E = E->next()) { if (first == NULL || first->is_greater_than(E->get())) { first = E->get(); @@ -503,8 +503,8 @@ void Viewport::_notification(int p_what) { if (cameras.size() && !camera) { //there are cameras but no current camera, pick first in tree and make it current - Camera *first = NULL; - for (Set::Element *E = cameras.front(); E; E = E->next()) { + Camera3D *first = NULL; + for (Set::Element *E = cameras.front(); E; E = E->next()) { if (first == NULL || first->is_greater_than(E->get())) { first = E->get(); @@ -528,7 +528,6 @@ void Viewport::_notification(int p_what) { world_2d->_remove_viewport(this); VisualServer::get_singleton()->viewport_set_scenario(viewport, RID()); - // SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID()); VisualServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); if (contact_2d_debug.is_valid()) { VisualServer::get_singleton()->free(contact_2d_debug); @@ -587,7 +586,7 @@ void Viewport::_notification(int p_what) { #ifndef _3D_DISABLED Vector2 last_pos(1e20, 1e20); - CollisionObject *last_object = NULL; + CollisionObject3D *last_object = NULL; ObjectID last_id; #endif PhysicsDirectSpaceState::RayResult result; @@ -773,7 +772,7 @@ void Viewport::_notification(int p_what) { if (physics_object_capture.is_valid()) { - CollisionObject *co = Object::cast_to(ObjectDB::get_instance(physics_object_capture)); + CollisionObject3D *co = Object::cast_to(ObjectDB::get_instance(physics_object_capture)); if (co && camera) { _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0); captured = true; @@ -813,7 +812,7 @@ void Viewport::_notification(int p_what) { ObjectID new_collider; if (col) { - CollisionObject *co = Object::cast_to(result.collider); + CollisionObject3D *co = Object::cast_to(result.collider); if (co) { _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape); @@ -830,7 +829,7 @@ void Viewport::_notification(int p_what) { if (physics_object_over.is_valid()) { - CollisionObject *co = Object::cast_to(ObjectDB::get_instance(physics_object_over)); + CollisionObject3D *co = Object::cast_to(ObjectDB::get_instance(physics_object_over)); if (co) { co->_mouse_exit(); } @@ -838,7 +837,7 @@ void Viewport::_notification(int p_what) { if (new_collider.is_valid()) { - CollisionObject *co = Object::cast_to(ObjectDB::get_instance(new_collider)); + CollisionObject3D *co = Object::cast_to(ObjectDB::get_instance(new_collider)); if (co) { co->_mouse_enter(); } @@ -927,13 +926,6 @@ Rect2 Viewport::get_visible_rect() const { } void Viewport::_update_listener() { - /* - if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (Object::cast_to(get_parent()) && Object::cast_to(get_parent())->is_visible_in_tree()))) { - SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, find_world()->get_sound_space()); - } else { - SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID()); - } -*/ } void Viewport::_update_listener_2d() { @@ -1041,14 +1033,9 @@ Transform2D Viewport::get_global_canvas_transform() const { } void Viewport::_listener_transform_changed_notify() { - -#ifndef _3D_DISABLED -//if (listener) -// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, listener->get_listener_transform()); -#endif } -void Viewport::_listener_set(Listener *p_listener) { +void Viewport::_listener_set(Listener3D *p_listener) { #ifndef _3D_DISABLED @@ -1062,13 +1049,13 @@ void Viewport::_listener_set(Listener *p_listener) { #endif } -bool Viewport::_listener_add(Listener *p_listener) { +bool Viewport::_listener_add(Listener3D *p_listener) { listeners.insert(p_listener); return listeners.size() == 1; } -void Viewport::_listener_remove(Listener *p_listener) { +void Viewport::_listener_remove(Listener3D *p_listener) { listeners.erase(p_listener); if (listener == p_listener) { @@ -1077,10 +1064,10 @@ void Viewport::_listener_remove(Listener *p_listener) { } #ifndef _3D_DISABLED -void Viewport::_listener_make_next_current(Listener *p_exclude) { +void Viewport::_listener_make_next_current(Listener3D *p_exclude) { if (listeners.size() > 0) { - for (Set::Element *E = listeners.front(); E; E = E->next()) { + for (Set::Element *E = listeners.front(); E; E = E->next()) { if (p_exclude == E->get()) continue; @@ -1104,13 +1091,10 @@ void Viewport::_listener_make_next_current(Listener *p_exclude) { void Viewport::_camera_transform_changed_notify() { #ifndef _3D_DISABLED -// If there is an active listener in the scene, it takes priority over the camera -// if (camera && !listener) -// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform()); #endif } -void Viewport::_camera_set(Camera *p_camera) { +void Viewport::_camera_set(Camera3D *p_camera) { #ifndef _3D_DISABLED @@ -1118,7 +1102,7 @@ void Viewport::_camera_set(Camera *p_camera) { return; if (camera) { - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); + camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT); } camera = p_camera; @@ -1131,7 +1115,7 @@ void Viewport::_camera_set(Camera *p_camera) { } if (camera) { - camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); + camera->notification(Camera3D::NOTIFICATION_BECAME_CURRENT); } _update_listener(); @@ -1139,25 +1123,25 @@ void Viewport::_camera_set(Camera *p_camera) { #endif } -bool Viewport::_camera_add(Camera *p_camera) { +bool Viewport::_camera_add(Camera3D *p_camera) { cameras.insert(p_camera); return cameras.size() == 1; } -void Viewport::_camera_remove(Camera *p_camera) { +void Viewport::_camera_remove(Camera3D *p_camera) { cameras.erase(p_camera); if (camera == p_camera) { - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); + camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT); camera = NULL; } } #ifndef _3D_DISABLED -void Viewport::_camera_make_next_current(Camera *p_exclude) { +void Viewport::_camera_make_next_current(Camera3D *p_exclude) { - for (Set::Element *E = cameras.front(); E; E = E->next()) { + for (Set::Element *E = cameras.front(); E; E = E->next()) { if (p_exclude == E->get()) continue; @@ -1239,9 +1223,9 @@ void Viewport::_propagate_enter_world(Node *p_node) { if (!p_node->is_inside_tree()) //may not have entered scene yet return; - if (Object::cast_to(p_node) || Object::cast_to(p_node)) { + if (Object::cast_to(p_node) || Object::cast_to(p_node)) { - p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD); + p_node->notification(Node3D::NOTIFICATION_ENTER_WORLD); } else { Viewport *v = Object::cast_to(p_node); if (v) { @@ -1276,9 +1260,9 @@ void Viewport::_propagate_exit_world(Node *p_node) { if (!p_node->is_inside_tree()) //may have exited scene already return; - if (Object::cast_to(p_node) || Object::cast_to(p_node)) { + if (Object::cast_to(p_node) || Object::cast_to(p_node)) { - p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD); + p_node->notification(Node3D::NOTIFICATION_EXIT_WORLD); } else { Viewport *v = Object::cast_to(p_node); if (v) { @@ -1350,12 +1334,12 @@ Ref Viewport::find_world() const { return Ref(); } -Listener *Viewport::get_listener() const { +Listener3D *Viewport::get_listener() const { return listener; } -Camera *Viewport::get_camera() const { +Camera3D *Viewport::get_camera() const { return camera; } @@ -2626,7 +2610,7 @@ void Viewport::_drop_physics_mouseover() { #ifndef _3D_DISABLED if (physics_object_over.is_valid()) { - CollisionObject *co = Object::cast_to(ObjectDB::get_instance(physics_object_over)); + CollisionObject3D *co = Object::cast_to(ObjectDB::get_instance(physics_object_over)); if (co) { co->_mouse_exit(); } @@ -3545,7 +3529,6 @@ Viewport::Viewport() { viewport_textures.insert(default_texture.ptr()); default_texture->proxy = VS::get_singleton()->texture_proxy_create(texture_rid); - //internal_listener = SpatialSoundServer::get_singleton()->listener_create(); audio_listener = false; //internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create(); audio_listener_2d = false; @@ -3626,8 +3609,6 @@ Viewport::~Viewport() { E->get()->vp = NULL; } VisualServer::get_singleton()->free(viewport); - //SpatialSoundServer::get_singleton()->free(internal_listener); - //SpatialSound2DServer::get_singleton()->free(internal_listener_2d); } ///////////////////////////////// diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 6b68bc0c94..31eb461cee 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -38,9 +38,9 @@ #include "servers/display_server.h" #include "servers/visual_server.h" -class Camera; +class Camera3D; class Camera2D; -class Listener; +class Listener3D; class Control; class CanvasItem; class CanvasLayer; @@ -48,7 +48,7 @@ class Panel; class Label; class Timer; class Viewport; -class CollisionObject; +class CollisionObject3D; class ViewportTexture : public Texture2D { @@ -160,8 +160,8 @@ private: Viewport *parent; - Listener *listener; - Set listeners; + Listener3D *listener; + Set listeners; struct CameraOverrideData { Transform transform; @@ -181,8 +181,8 @@ private: } } camera_override; - Camera *camera; - Set cameras; + Camera3D *camera; + Set cameras; Set canvas_layers; RID viewport; @@ -237,7 +237,7 @@ private: } physics_last_mouse_state; - void _collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); + void _collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); bool handle_input_locally; bool local_input_handled; @@ -396,19 +396,19 @@ private: bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check); - friend class Listener; + friend class Listener3D; void _listener_transform_changed_notify(); - void _listener_set(Listener *p_listener); - bool _listener_add(Listener *p_listener); //true if first - void _listener_remove(Listener *p_listener); - void _listener_make_next_current(Listener *p_exclude); + void _listener_set(Listener3D *p_listener); + bool _listener_add(Listener3D *p_listener); //true if first + void _listener_remove(Listener3D *p_listener); + void _listener_make_next_current(Listener3D *p_exclude); - friend class Camera; + friend class Camera3D; void _camera_transform_changed_notify(); - void _camera_set(Camera *p_camera); - bool _camera_add(Camera *p_camera); //true if first - void _camera_remove(Camera *p_camera); - void _camera_make_next_current(Camera *p_exclude); + void _camera_set(Camera3D *p_camera); + bool _camera_add(Camera3D *p_camera); //true if first + void _camera_remove(Camera3D *p_camera); + void _camera_make_next_current(Camera3D *p_exclude); friend class CanvasLayer; void _canvas_layer_add(CanvasLayer *p_canvas_layer); @@ -444,8 +444,8 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: - Listener *get_listener() const; - Camera *get_camera() const; + Listener3D *get_listener() const; + Camera3D *get_camera() const; void enable_camera_override(bool p_enable); bool is_camera_override_enabled() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 41c43a586b..d9a0d4c682 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -33,7 +33,7 @@ #include "core/class_db.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "scene/2d/animated_sprite.h" +#include "scene/2d/animated_sprite_2d.h" #include "scene/2d/area_2d.h" #include "scene/2d/audio_stream_player_2d.h" #include "scene/2d/back_buffer_copy.h" @@ -62,7 +62,7 @@ #include "scene/2d/ray_cast_2d.h" #include "scene/2d/remote_transform_2d.h" #include "scene/2d/skeleton_2d.h" -#include "scene/2d/sprite.h" +#include "scene/2d/sprite_2d.h" #include "scene/2d/tile_map.h" #include "scene/2d/touch_screen_button.h" #include "scene/2d/visibility_notifier_2d.h" @@ -131,15 +131,15 @@ #include "scene/main/window.h" #include "scene/resources/audio_stream_sample.h" #include "scene/resources/bit_map.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" +#include "scene/resources/box_shape_3d.h" #include "scene/resources/capsule_shape_2d.h" +#include "scene/resources/capsule_shape_3d.h" #include "scene/resources/circle_shape_2d.h" -#include "scene/resources/concave_polygon_shape.h" #include "scene/resources/concave_polygon_shape_2d.h" -#include "scene/resources/convex_polygon_shape.h" +#include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_2d.h" -#include "scene/resources/cylinder_shape.h" +#include "scene/resources/convex_polygon_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/default_theme/default_theme.h" #include "scene/resources/dynamic_font.h" #include "scene/resources/gradient.h" @@ -160,7 +160,7 @@ #include "scene/resources/segment_shape_2d.h" #include "scene/resources/sky.h" #include "scene/resources/sky_material.h" -#include "scene/resources/sphere_shape.h" +#include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/text_file.h" #include "scene/resources/texture.h" @@ -170,46 +170,46 @@ #include "scene/resources/visual_shader_nodes.h" #include "scene/resources/world.h" #include "scene/resources/world_2d.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/world_margin_shape_3d.h" #include "scene/scene_string_names.h" #ifndef _3D_DISABLED -#include "scene/3d/area.h" +#include "scene/3d/area_3d.h" #include "scene/3d/arvr_nodes.h" #include "scene/3d/audio_stream_player_3d.h" #include "scene/3d/baked_lightmap.h" -#include "scene/3d/bone_attachment.h" -#include "scene/3d/camera.h" -#include "scene/3d/collision_polygon.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/cpu_particles.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/gi_probe.h" -#include "scene/3d/immediate_geometry.h" -#include "scene/3d/interpolated_camera.h" -#include "scene/3d/light.h" -#include "scene/3d/listener.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/multimesh_instance.h" -#include "scene/3d/navigation.h" -#include "scene/3d/navigation_agent.h" -#include "scene/3d/navigation_obstacle.h" -#include "scene/3d/navigation_region.h" -#include "scene/3d/particles.h" -#include "scene/3d/path.h" -#include "scene/3d/physics_body.h" -#include "scene/3d/physics_joint.h" +#include "scene/3d/gpu_particles_3d.h" +#include "scene/3d/immediate_geometry_3d.h" + +#include "scene/3d/light_3d.h" +#include "scene/3d/listener_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/multimesh_instance_3d.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/navigation_agent_3d.h" +#include "scene/3d/navigation_obstacle_3d.h" +#include "scene/3d/navigation_region_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/path_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/3d/physics_joint_3d.h" #include "scene/3d/position_3d.h" -#include "scene/3d/proximity_group.h" -#include "scene/3d/ray_cast.h" +#include "scene/3d/proximity_group_3d.h" +#include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" -#include "scene/3d/remote_transform.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/soft_body.h" -#include "scene/3d/spatial.h" -#include "scene/3d/spring_arm.h" +#include "scene/3d/remote_transform_3d.h" +#include "scene/3d/skeleton_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.h" -#include "scene/3d/visibility_notifier.h" +#include "scene/3d/visibility_notifier_3d.h" #include "scene/3d/world_environment.h" #include "scene/animation/skeleton_ik.h" #include "scene/resources/environment.h" @@ -370,9 +370,9 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -400,32 +400,31 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init #ifndef _3D_DISABLED - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); //ClassDB::register_class(); //ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -433,48 +432,48 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); OS::get_singleton()->yield(); //may take time to init @@ -559,10 +558,10 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_class(); //ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); //ClassDB::register_type(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -642,20 +641,20 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class(); + ClassDB::register_class(); #endif ClassDB::register_class(); @@ -743,6 +742,10 @@ void register_scene_types() { ClassDB::register_virtual_class(); //sorry, you can't create it #ifndef DISABLE_DEPRECATED + + ClassDB::add_compatibility_class("AnimatedSprite", "AnimatedSprite2D"); + ClassDB::add_compatibility_class("Sprite", "Sprite2D"); + ClassDB::add_compatibility_class("SpatialMaterial", "StandardMaterial3D"); ClassDB::add_compatibility_class("Mesh", "ArrayMesh"); ClassDB::add_compatibility_class("AnimationTreePlayer", "AnimationTree"); @@ -750,9 +753,79 @@ void register_scene_types() { ClassDB::add_compatibility_class("VisualShaderNodeScalarUniform", "VisualShaderNodeFloatUniform"); ClassDB::add_compatibility_class("VisualShaderNodeScalarOp", "VisualShaderNodeFloatOp"); ClassDB::add_compatibility_class("VisualShaderNodeScalarFunc", "VisualShaderNodeFloatFunc"); - ClassDB::add_compatibility_class("NavigationMeshInstance", "NavigationRegion"); + ClassDB::add_compatibility_class("NavigationMeshInstance", "NavigationRegion3D"); ClassDB::add_compatibility_class("NavigationPolygonInstance", "NavigationRegion2D"); - ClassDB::add_compatibility_class("PlaneShape", "WorldMarginShape"); + ClassDB::add_compatibility_class("PlaneShape", "WorldMarginShape3D"); + ClassDB::add_compatibility_class("WorldMarginShape", "WorldMarginShape3D"); + + ClassDB::add_compatibility_class("Spatial", "Node3D"); + ClassDB::add_compatibility_class("Area", "Area3D"); + ClassDB::add_compatibility_class("Camera", "Camera3D"); + + ClassDB::add_compatibility_class("Particles", "GPUParticles3D"); + ClassDB::add_compatibility_class("CPUParticles", "CPUParticles3D"); + + ClassDB::add_compatibility_class("Particles2D", "GPUParticles2D"); + + ClassDB::add_compatibility_class("Light", "Light3D"); + ClassDB::add_compatibility_class("DirectionalLight", "DirectionalLight3D"); + ClassDB::add_compatibility_class("SpotLight", "SpotLight3D"); + ClassDB::add_compatibility_class("OmniLight", "OmniLight3D"); + + ClassDB::add_compatibility_class("Listener", "Listener3D"); + + ClassDB::add_compatibility_class("MeshInstance", "MeshInstance3D"); + ClassDB::add_compatibility_class("MultiMeshInstance", "MultiMeshInstance3D"); + ClassDB::add_compatibility_class("ImmediateGeometry", "ImmediateGeometry3D"); + + ClassDB::add_compatibility_class("Navigation", "Navigation3D"); + ClassDB::add_compatibility_class("NavigationAgent", "NavigationAgent3D"); + ClassDB::add_compatibility_class("NavigationObstacle", "NavigationObstacle3D"); + ClassDB::add_compatibility_class("NavigationRegion", "NavigationRegion3D"); + + ClassDB::add_compatibility_class("Path", "Path3D"); + ClassDB::add_compatibility_class("PathFollow", "PathFollow3D"); + + ClassDB::add_compatibility_class("ProximityGroup", "ProximityGroup3D"); + + ClassDB::add_compatibility_class("RayCast", "RayCast3D"); + ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); + + ClassDB::add_compatibility_class("Skeleton", "Skeleton3D"); + ClassDB::add_compatibility_class("SkeletonIK", "SkeletonIK3D"); + + ClassDB::add_compatibility_class("VisibilityNotifier", "VisibilityNotifier3D"); + ClassDB::add_compatibility_class("VisibilityEnabler", "VisibilityEnabler3D"); + + ClassDB::add_compatibility_class("CollisionObject", "CollisionObject3D"); + ClassDB::add_compatibility_class("CollisionShape", "CollisionShape3D"); + ClassDB::add_compatibility_class("CollisionPolygon", "CollisionPolygon3D"); + + ClassDB::add_compatibility_class("PhysicsBody", "PhysicsBody3D"); + ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); + ClassDB::add_compatibility_class("StaticBody", "StaticBody3D"); + ClassDB::add_compatibility_class("KinematicBody", "KinematicBody3D"); + ClassDB::add_compatibility_class("SoftBody", "SoftBody3D"); + ClassDB::add_compatibility_class("PhysicalBone", "PhysicalBone3D"); + ClassDB::add_compatibility_class("KinematicCollision", "KinematicCollision3D"); + ClassDB::add_compatibility_class("SpringArm", "SpringArm3D"); + + ClassDB::add_compatibility_class("Shape", "Shape3D"); + ClassDB::add_compatibility_class("RayShape", "RayShape3D"); + ClassDB::add_compatibility_class("SphereShape", "SphereShape3D"); + ClassDB::add_compatibility_class("BoxShape", "BoxShape3D"); + ClassDB::add_compatibility_class("CylinderShape", "CylinderShape3D"); + ClassDB::add_compatibility_class("CapsuleShape", "CapsuleShape3D"); + ClassDB::add_compatibility_class("ConvexPolygonShape", "ConvexPolygonShape3D"); + ClassDB::add_compatibility_class("ConcavePolygonShape", "ConcavePolygonShape3D"); + + ClassDB::add_compatibility_class("Joint", "Joint3D"); + ClassDB::add_compatibility_class("PinJoint", "PinJoint3D"); + ClassDB::add_compatibility_class("SliderJoint", "SliderJoint3D"); + ClassDB::add_compatibility_class("HingeJoint", "HingeJoint3D"); + ClassDB::add_compatibility_class("ConeTwistJoint", "ConeTwistJoint3D"); + ClassDB::add_compatibility_class("Generic6DOFJoint", "Generic6DOFJoint3D"); + #endif OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp deleted file mode 100644 index e1f485bae6..0000000000 --- a/scene/resources/box_shape.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************/ -/* box_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "box_shape.h" -#include "servers/physics_server.h" - -Vector BoxShape::get_debug_mesh_lines() { - - Vector lines; - AABB aabb; - aabb.position = -get_extents(); - aabb.size = aabb.position * -2; - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - return lines; -} - -real_t BoxShape::get_enclosing_radius() const { - return extents.length(); -} - -void BoxShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents); - Shape::_update_shape(); -} - -void BoxShape::set_extents(const Vector3 &p_extents) { - - extents = p_extents; - _update_shape(); - notify_change_to_owners(); - _change_notify("extents"); -} - -Vector3 BoxShape::get_extents() const { - - return extents; -} - -void BoxShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BoxShape::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &BoxShape::get_extents); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); -} - -BoxShape::BoxShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_BOX)) { - - set_extents(Vector3(1, 1, 1)); -} diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape.h deleted file mode 100644 index fb164cc300..0000000000 --- a/scene/resources/box_shape.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* box_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BOX_SHAPE_H -#define BOX_SHAPE_H - -#include "scene/resources/shape.h" - -class BoxShape : public Shape { - - GDCLASS(BoxShape, Shape); - Vector3 extents; - -protected: - static void _bind_methods(); - - virtual void _update_shape(); - -public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - BoxShape(); -}; - -#endif // BOX_SHAPE_H diff --git a/scene/resources/box_shape_3d.cpp b/scene/resources/box_shape_3d.cpp new file mode 100644 index 0000000000..3ac29642d7 --- /dev/null +++ b/scene/resources/box_shape_3d.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* box_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "box_shape_3d.h" +#include "servers/physics_server.h" + +Vector BoxShape3D::get_debug_mesh_lines() { + + Vector lines; + AABB aabb; + aabb.position = -get_extents(); + aabb.size = aabb.position * -2; + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + return lines; +} + +real_t BoxShape3D::get_enclosing_radius() const { + return extents.length(); +} + +void BoxShape3D::_update_shape() { + + PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents); + Shape3D::_update_shape(); +} + +void BoxShape3D::set_extents(const Vector3 &p_extents) { + + extents = p_extents; + _update_shape(); + notify_change_to_owners(); + _change_notify("extents"); +} + +Vector3 BoxShape3D::get_extents() const { + + return extents; +} + +void BoxShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BoxShape3D::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &BoxShape3D::get_extents); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); +} + +BoxShape3D::BoxShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_BOX)) { + + set_extents(Vector3(1, 1, 1)); +} diff --git a/scene/resources/box_shape_3d.h b/scene/resources/box_shape_3d.h new file mode 100644 index 0000000000..a93fd8d33a --- /dev/null +++ b/scene/resources/box_shape_3d.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* box_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BOX_SHAPE_H +#define BOX_SHAPE_H + +#include "scene/resources/shape_3d.h" + +class BoxShape3D : public Shape3D { + + GDCLASS(BoxShape3D, Shape3D); + Vector3 extents; + +protected: + static void _bind_methods(); + + virtual void _update_shape(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + BoxShape3D(); +}; + +#endif // BOX_SHAPE_H diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp deleted file mode 100644 index dddbd7fef3..0000000000 --- a/scene/resources/capsule_shape.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/*************************************************************************/ -/* capsule_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "capsule_shape.h" -#include "servers/physics_server.h" - -Vector CapsuleShape::get_debug_mesh_lines() { - - float radius = get_radius(); - float height = get_height(); - - Vector points; - - Vector3 d(0, height * 0.5, 0); - for (int i = 0; i < 360; i++) { - - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); - Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; - Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; - - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(b.x, 0, b.y) + d); - - points.push_back(Vector3(a.x, 0, a.y) - d); - points.push_back(Vector3(b.x, 0, b.y) - d); - - if (i % 90 == 0) { - - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(a.x, 0, a.y) - d); - } - - Vector3 dud = i < 180 ? d : -d; - - points.push_back(Vector3(0, a.x, a.y) + dud); - points.push_back(Vector3(0, b.x, b.y) + dud); - points.push_back(Vector3(a.y, a.x, 0) + dud); - points.push_back(Vector3(b.y, b.x, 0) + dud); - } - - return points; -} - -real_t CapsuleShape::get_enclosing_radius() const { - return radius + height * 0.5; -} - -void CapsuleShape::_update_shape() { - - Dictionary d; - d["radius"] = radius; - d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); -} - -void CapsuleShape::set_radius(float p_radius) { - - radius = p_radius; - _update_shape(); - notify_change_to_owners(); - _change_notify("radius"); -} - -float CapsuleShape::get_radius() const { - - return radius; -} - -void CapsuleShape::set_height(float p_height) { - - height = p_height; - _update_shape(); - notify_change_to_owners(); - _change_notify("height"); -} - -float CapsuleShape::get_height() const { - - return height; -} - -void CapsuleShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape::get_height); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); -} - -CapsuleShape::CapsuleShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CAPSULE)) { - - radius = 1.0; - height = 1.0; - _update_shape(); -} diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape.h deleted file mode 100644 index f097e51175..0000000000 --- a/scene/resources/capsule_shape.h +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************/ -/* capsule_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CAPSULE_SHAPE_H -#define CAPSULE_SHAPE_H - -#include "scene/resources/shape.h" - -class CapsuleShape : public Shape { - - GDCLASS(CapsuleShape, Shape); - float radius; - float height; - -protected: - static void _bind_methods(); - - virtual void _update_shape(); - -public: - void set_radius(float p_radius); - float get_radius() const; - void set_height(float p_height); - float get_height() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - CapsuleShape(); -}; - -#endif // CAPSULE_SHAPE_H diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp new file mode 100644 index 0000000000..a929caa275 --- /dev/null +++ b/scene/resources/capsule_shape_3d.cpp @@ -0,0 +1,128 @@ +/*************************************************************************/ +/* capsule_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "capsule_shape_3d.h" +#include "servers/physics_server.h" + +Vector CapsuleShape3D::get_debug_mesh_lines() { + + float radius = get_radius(); + float height = get_height(); + + Vector points; + + Vector3 d(0, height * 0.5, 0); + for (int i = 0; i < 360; i++) { + + float ra = Math::deg2rad((float)i); + float rb = Math::deg2rad((float)i + 1); + Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; + Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; + + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(b.x, 0, b.y) + d); + + points.push_back(Vector3(a.x, 0, a.y) - d); + points.push_back(Vector3(b.x, 0, b.y) - d); + + if (i % 90 == 0) { + + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(a.x, 0, a.y) - d); + } + + Vector3 dud = i < 180 ? d : -d; + + points.push_back(Vector3(0, a.x, a.y) + dud); + points.push_back(Vector3(0, b.x, b.y) + dud); + points.push_back(Vector3(a.y, a.x, 0) + dud); + points.push_back(Vector3(b.y, b.x, 0) + dud); + } + + return points; +} + +real_t CapsuleShape3D::get_enclosing_radius() const { + return radius + height * 0.5; +} + +void CapsuleShape3D::_update_shape() { + + Dictionary d; + d["radius"] = radius; + d["height"] = height; + PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); +} + +void CapsuleShape3D::set_radius(float p_radius) { + + radius = p_radius; + _update_shape(); + notify_change_to_owners(); + _change_notify("radius"); +} + +float CapsuleShape3D::get_radius() const { + + return radius; +} + +void CapsuleShape3D::set_height(float p_height) { + + height = p_height; + _update_shape(); + notify_change_to_owners(); + _change_notify("height"); +} + +float CapsuleShape3D::get_height() const { + + return height; +} + +void CapsuleShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape3D::get_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape3D::get_height); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); +} + +CapsuleShape3D::CapsuleShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CAPSULE)) { + + radius = 1.0; + height = 1.0; + _update_shape(); +} diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h new file mode 100644 index 0000000000..dca7a6c983 --- /dev/null +++ b/scene/resources/capsule_shape_3d.h @@ -0,0 +1,59 @@ +/*************************************************************************/ +/* capsule_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CAPSULE_SHAPE_H +#define CAPSULE_SHAPE_H + +#include "scene/resources/shape_3d.h" + +class CapsuleShape3D : public Shape3D { + + GDCLASS(CapsuleShape3D, Shape3D); + float radius; + float height; + +protected: + static void _bind_methods(); + + virtual void _update_shape(); + +public: + void set_radius(float p_radius); + float get_radius() const; + void set_height(float p_height); + float get_height() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + CapsuleShape3D(); +}; + +#endif // CAPSULE_SHAPE_H diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp deleted file mode 100644 index fe123a2df7..0000000000 --- a/scene/resources/concave_polygon_shape.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************/ -/* concave_polygon_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "concave_polygon_shape.h" - -#include "servers/physics_server.h" - -Vector ConcavePolygonShape::get_debug_mesh_lines() { - - Set edges; - - Vector data = get_faces(); - int datalen = data.size(); - ERR_FAIL_COND_V((datalen % 3) != 0, Vector()); - - const Vector3 *r = data.ptr(); - - for (int i = 0; i < datalen; i += 3) { - - for (int j = 0; j < 3; j++) { - - DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]); - edges.insert(de); - } - } - - Vector points; - points.resize(edges.size() * 2); - int idx = 0; - for (Set::Element *E = edges.front(); E; E = E->next()) { - - points.write[idx + 0] = E->get().a; - points.write[idx + 1] = E->get().b; - idx += 2; - } - - return points; -} - -real_t ConcavePolygonShape::get_enclosing_radius() const { - Vector data = get_faces(); - const Vector3 *read = data.ptr(); - real_t r = 0; - for (int i(0); i < data.size(); i++) { - r = MAX(read[i].length_squared(), r); - } - return Math::sqrt(r); -} - -void ConcavePolygonShape::_update_shape() { - Shape::_update_shape(); -} - -void ConcavePolygonShape::set_faces(const Vector &p_faces) { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), p_faces); - notify_change_to_owners(); -} - -Vector ConcavePolygonShape::get_faces() const { - - return PhysicsServer::get_singleton()->shape_get_data(get_shape()); -} - -void ConcavePolygonShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape::set_faces); - ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape::get_faces); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); -} - -ConcavePolygonShape::ConcavePolygonShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON)) { - - //set_planes(Vector3(1,1,1)); -} diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape.h deleted file mode 100644 index 63aabb27d7..0000000000 --- a/scene/resources/concave_polygon_shape.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************/ -/* concave_polygon_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CONCAVE_POLYGON_SHAPE_H -#define CONCAVE_POLYGON_SHAPE_H - -#include "scene/resources/shape.h" - -class ConcavePolygonShape : public Shape { - - GDCLASS(ConcavePolygonShape, Shape); - - struct DrawEdge { - - Vector3 a; - Vector3 b; - bool operator<(const DrawEdge &p_edge) const { - if (a == p_edge.a) - return b < p_edge.b; - else - return a < p_edge.a; - } - - DrawEdge(const Vector3 &p_a = Vector3(), const Vector3 &p_b = Vector3()) { - a = p_a; - b = p_b; - if (a < b) { - SWAP(a, b); - } - } - }; - -protected: - static void _bind_methods(); - - virtual void _update_shape(); - -public: - void set_faces(const Vector &p_faces); - Vector get_faces() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - ConcavePolygonShape(); -}; - -#endif // CONCAVE_POLYGON_SHAPE_H diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp new file mode 100644 index 0000000000..6be4a087ad --- /dev/null +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -0,0 +1,103 @@ +/*************************************************************************/ +/* concave_polygon_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "concave_polygon_shape_3d.h" + +#include "servers/physics_server.h" + +Vector ConcavePolygonShape3D::get_debug_mesh_lines() { + + Set edges; + + Vector data = get_faces(); + int datalen = data.size(); + ERR_FAIL_COND_V((datalen % 3) != 0, Vector()); + + const Vector3 *r = data.ptr(); + + for (int i = 0; i < datalen; i += 3) { + + for (int j = 0; j < 3; j++) { + + DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]); + edges.insert(de); + } + } + + Vector points; + points.resize(edges.size() * 2); + int idx = 0; + for (Set::Element *E = edges.front(); E; E = E->next()) { + + points.write[idx + 0] = E->get().a; + points.write[idx + 1] = E->get().b; + idx += 2; + } + + return points; +} + +real_t ConcavePolygonShape3D::get_enclosing_radius() const { + Vector data = get_faces(); + const Vector3 *read = data.ptr(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} + +void ConcavePolygonShape3D::_update_shape() { + Shape3D::_update_shape(); +} + +void ConcavePolygonShape3D::set_faces(const Vector &p_faces) { + + PhysicsServer::get_singleton()->shape_set_data(get_shape(), p_faces); + notify_change_to_owners(); +} + +Vector ConcavePolygonShape3D::get_faces() const { + + return PhysicsServer::get_singleton()->shape_get_data(get_shape()); +} + +void ConcavePolygonShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces); + ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); +} + +ConcavePolygonShape3D::ConcavePolygonShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON)) { + + //set_planes(Vector3(1,1,1)); +} diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h new file mode 100644 index 0000000000..b4e96c662f --- /dev/null +++ b/scene/resources/concave_polygon_shape_3d.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* concave_polygon_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONCAVE_POLYGON_SHAPE_3D_H +#define CONCAVE_POLYGON_SHAPE_3D_H + +#include "scene/resources/shape_3d.h" + +class ConcavePolygonShape3D : public Shape3D { + + GDCLASS(ConcavePolygonShape3D, Shape3D); + + struct DrawEdge { + + Vector3 a; + Vector3 b; + bool operator<(const DrawEdge &p_edge) const { + if (a == p_edge.a) + return b < p_edge.b; + else + return a < p_edge.a; + } + + DrawEdge(const Vector3 &p_a = Vector3(), const Vector3 &p_b = Vector3()) { + a = p_a; + b = p_b; + if (a < b) { + SWAP(a, b); + } + } + }; + +protected: + static void _bind_methods(); + + virtual void _update_shape(); + +public: + void set_faces(const Vector &p_faces); + Vector get_faces() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + ConcavePolygonShape3D(); +}; + +#endif // CONCAVE_POLYGON_SHAPE_H diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp deleted file mode 100644 index b7463605b4..0000000000 --- a/scene/resources/convex_polygon_shape.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************/ -/* convex_polygon_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "convex_polygon_shape.h" -#include "core/math/quick_hull.h" -#include "servers/physics_server.h" - -Vector ConvexPolygonShape::get_debug_mesh_lines() { - - Vector points = get_points(); - - if (points.size() > 3) { - - Vector varr = Variant(points); - Geometry::MeshData md; - Error err = QuickHull::build(varr, md); - if (err == OK) { - Vector lines; - lines.resize(md.edges.size() * 2); - for (int i = 0; i < md.edges.size(); i++) { - lines.write[i * 2 + 0] = md.vertices[md.edges[i].a]; - lines.write[i * 2 + 1] = md.vertices[md.edges[i].b]; - } - return lines; - } - } - - return Vector(); -} - -real_t ConvexPolygonShape::get_enclosing_radius() const { - Vector data = get_points(); - const Vector3 *read = data.ptr(); - real_t r = 0; - for (int i(0); i < data.size(); i++) { - r = MAX(read[i].length_squared(), r); - } - return Math::sqrt(r); -} - -void ConvexPolygonShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), points); - Shape::_update_shape(); -} - -void ConvexPolygonShape::set_points(const Vector &p_points) { - - points = p_points; - _update_shape(); - notify_change_to_owners(); -} - -Vector ConvexPolygonShape::get_points() const { - - return points; -} - -void ConvexPolygonShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape::set_points); - ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape::get_points); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "points"), "set_points", "get_points"); -} - -ConvexPolygonShape::ConvexPolygonShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON)) { -} diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape.h deleted file mode 100644 index fcd733887e..0000000000 --- a/scene/resources/convex_polygon_shape.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* convex_polygon_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CONVEX_POLYGON_SHAPE_H -#define CONVEX_POLYGON_SHAPE_H - -#include "scene/resources/shape.h" - -class ConvexPolygonShape : public Shape { - - GDCLASS(ConvexPolygonShape, Shape); - Vector points; - -protected: - static void _bind_methods(); - - virtual void _update_shape(); - -public: - void set_points(const Vector &p_points); - Vector get_points() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - ConvexPolygonShape(); -}; - -#endif // CONVEX_POLYGON_SHAPE_H diff --git a/scene/resources/convex_polygon_shape_3d.cpp b/scene/resources/convex_polygon_shape_3d.cpp new file mode 100644 index 0000000000..e25301b2eb --- /dev/null +++ b/scene/resources/convex_polygon_shape_3d.cpp @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* convex_polygon_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "convex_polygon_shape_3d.h" +#include "core/math/quick_hull.h" +#include "servers/physics_server.h" + +Vector ConvexPolygonShape3D::get_debug_mesh_lines() { + + Vector points = get_points(); + + if (points.size() > 3) { + + Vector varr = Variant(points); + Geometry::MeshData md; + Error err = QuickHull::build(varr, md); + if (err == OK) { + Vector lines; + lines.resize(md.edges.size() * 2); + for (int i = 0; i < md.edges.size(); i++) { + lines.write[i * 2 + 0] = md.vertices[md.edges[i].a]; + lines.write[i * 2 + 1] = md.vertices[md.edges[i].b]; + } + return lines; + } + } + + return Vector(); +} + +real_t ConvexPolygonShape3D::get_enclosing_radius() const { + Vector data = get_points(); + const Vector3 *read = data.ptr(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} + +void ConvexPolygonShape3D::_update_shape() { + + PhysicsServer::get_singleton()->shape_set_data(get_shape(), points); + Shape3D::_update_shape(); +} + +void ConvexPolygonShape3D::set_points(const Vector &p_points) { + + points = p_points; + _update_shape(); + notify_change_to_owners(); +} + +Vector ConvexPolygonShape3D::get_points() const { + + return points; +} + +void ConvexPolygonShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape3D::set_points); + ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape3D::get_points); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "points"), "set_points", "get_points"); +} + +ConvexPolygonShape3D::ConvexPolygonShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON)) { +} diff --git a/scene/resources/convex_polygon_shape_3d.h b/scene/resources/convex_polygon_shape_3d.h new file mode 100644 index 0000000000..51e4c8eb0b --- /dev/null +++ b/scene/resources/convex_polygon_shape_3d.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* convex_polygon_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONVEX_POLYGON_SHAPE_H +#define CONVEX_POLYGON_SHAPE_H + +#include "scene/resources/shape_3d.h" + +class ConvexPolygonShape3D : public Shape3D { + + GDCLASS(ConvexPolygonShape3D, Shape3D); + Vector points; + +protected: + static void _bind_methods(); + + virtual void _update_shape(); + +public: + void set_points(const Vector &p_points); + Vector get_points() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + ConvexPolygonShape3D(); +}; + +#endif // CONVEX_POLYGON_SHAPE_H diff --git a/scene/resources/cylinder_shape.cpp b/scene/resources/cylinder_shape.cpp deleted file mode 100644 index 53d368d32a..0000000000 --- a/scene/resources/cylinder_shape.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************/ -/* cylinder_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "cylinder_shape.h" -#include "servers/physics_server.h" - -Vector CylinderShape::get_debug_mesh_lines() { - - float radius = get_radius(); - float height = get_height(); - - Vector points; - - Vector3 d(0, height * 0.5, 0); - for (int i = 0; i < 360; i++) { - - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); - Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; - Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; - - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(b.x, 0, b.y) + d); - - points.push_back(Vector3(a.x, 0, a.y) - d); - points.push_back(Vector3(b.x, 0, b.y) - d); - - if (i % 90 == 0) { - - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(a.x, 0, a.y) - d); - } - } - - return points; -} - -real_t CylinderShape::get_enclosing_radius() const { - return Vector2(radius, height * 0.5).length(); -} - -void CylinderShape::_update_shape() { - - Dictionary d; - d["radius"] = radius; - d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); -} - -void CylinderShape::set_radius(float p_radius) { - - radius = p_radius; - _update_shape(); - notify_change_to_owners(); - _change_notify("radius"); -} - -float CylinderShape::get_radius() const { - - return radius; -} - -void CylinderShape::set_height(float p_height) { - - height = p_height; - _update_shape(); - notify_change_to_owners(); - _change_notify("height"); -} - -float CylinderShape::get_height() const { - - return height; -} - -void CylinderShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CylinderShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CylinderShape::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderShape::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CylinderShape::get_height); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); -} - -CylinderShape::CylinderShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CYLINDER)) { - - radius = 1.0; - height = 2.0; - _update_shape(); -} diff --git a/scene/resources/cylinder_shape.h b/scene/resources/cylinder_shape.h deleted file mode 100644 index a26fda10cd..0000000000 --- a/scene/resources/cylinder_shape.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* cylinder_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CYLINDER_SHAPE_H -#define CYLINDER_SHAPE_H - -#include "scene/resources/shape.h" - -class CylinderShape : public Shape { - - GDCLASS(CylinderShape, Shape); - float radius; - float height; - -protected: - static void _bind_methods(); - virtual void _update_shape(); - -public: - void set_radius(float p_radius); - float get_radius() const; - void set_height(float p_height); - float get_height() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - CylinderShape(); -}; - -#endif // CYLINDER_SHAPE_H diff --git a/scene/resources/cylinder_shape_3d.cpp b/scene/resources/cylinder_shape_3d.cpp new file mode 100644 index 0000000000..7636c55346 --- /dev/null +++ b/scene/resources/cylinder_shape_3d.cpp @@ -0,0 +1,121 @@ +/*************************************************************************/ +/* cylinder_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "cylinder_shape_3d.h" +#include "servers/physics_server.h" + +Vector CylinderShape3D::get_debug_mesh_lines() { + + float radius = get_radius(); + float height = get_height(); + + Vector points; + + Vector3 d(0, height * 0.5, 0); + for (int i = 0; i < 360; i++) { + + float ra = Math::deg2rad((float)i); + float rb = Math::deg2rad((float)i + 1); + Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; + Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; + + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(b.x, 0, b.y) + d); + + points.push_back(Vector3(a.x, 0, a.y) - d); + points.push_back(Vector3(b.x, 0, b.y) - d); + + if (i % 90 == 0) { + + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(a.x, 0, a.y) - d); + } + } + + return points; +} + +real_t CylinderShape3D::get_enclosing_radius() const { + return Vector2(radius, height * 0.5).length(); +} + +void CylinderShape3D::_update_shape() { + + Dictionary d; + d["radius"] = radius; + d["height"] = height; + PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); +} + +void CylinderShape3D::set_radius(float p_radius) { + + radius = p_radius; + _update_shape(); + notify_change_to_owners(); + _change_notify("radius"); +} + +float CylinderShape3D::get_radius() const { + + return radius; +} + +void CylinderShape3D::set_height(float p_height) { + + height = p_height; + _update_shape(); + notify_change_to_owners(); + _change_notify("height"); +} + +float CylinderShape3D::get_height() const { + + return height; +} + +void CylinderShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CylinderShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CylinderShape3D::get_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderShape3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CylinderShape3D::get_height); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); +} + +CylinderShape3D::CylinderShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CYLINDER)) { + + radius = 1.0; + height = 2.0; + _update_shape(); +} diff --git a/scene/resources/cylinder_shape_3d.h b/scene/resources/cylinder_shape_3d.h new file mode 100644 index 0000000000..7b37f733e0 --- /dev/null +++ b/scene/resources/cylinder_shape_3d.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* cylinder_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CYLINDER_SHAPE_3D_H +#define CYLINDER_SHAPE_3D_H + +#include "scene/resources/shape_3d.h" + +class CylinderShape3D : public Shape3D { + + GDCLASS(CylinderShape3D, Shape3D); + float radius; + float height; + +protected: + static void _bind_methods(); + virtual void _update_shape(); + +public: + void set_radius(float p_radius); + float get_radius() const; + void set_height(float p_height); + float get_height() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + CylinderShape3D(); +}; + +#endif // CYLINDER_SHAPE_H diff --git a/scene/resources/height_map_shape.cpp b/scene/resources/height_map_shape.cpp index fa45ddcabb..34f5ed8558 100644 --- a/scene/resources/height_map_shape.cpp +++ b/scene/resources/height_map_shape.cpp @@ -89,7 +89,7 @@ void HeightMapShape::_update_shape() { d["min_height"] = min_height; d["max_height"] = max_height; PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + Shape3D::_update_shape(); } void HeightMapShape::set_map_width(int p_new) { @@ -192,7 +192,7 @@ void HeightMapShape::_bind_methods() { } HeightMapShape::HeightMapShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_HEIGHTMAP)) { + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_HEIGHTMAP)) { map_width = 2; map_depth = 2; diff --git a/scene/resources/height_map_shape.h b/scene/resources/height_map_shape.h index b8204f6c98..e740388a02 100644 --- a/scene/resources/height_map_shape.h +++ b/scene/resources/height_map_shape.h @@ -31,10 +31,10 @@ #ifndef HEIGHT_MAP_SHAPE_H #define HEIGHT_MAP_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class HeightMapShape : public Shape { - GDCLASS(HeightMapShape, Shape); +class HeightMapShape : public Shape3D { + GDCLASS(HeightMapShape, Shape3D); int map_width; int map_depth; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 9f3433be0f..0d32fdb0fa 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -31,8 +31,8 @@ #include "mesh.h" #include "core/pair.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" #include "surface_tool.h" #include @@ -226,28 +226,28 @@ Vector Mesh::get_faces() const { */ } -Ref Mesh::create_convex_shape() const { +Ref Mesh::create_convex_shape() const { Vector vertices; for (int i = 0; i < get_surface_count(); i++) { Array a = surface_get_arrays(i); - ERR_FAIL_COND_V(a.empty(), Ref()); + ERR_FAIL_COND_V(a.empty(), Ref()); Vector v = a[ARRAY_VERTEX]; vertices.append_array(v); } - Ref shape = memnew(ConvexPolygonShape); + Ref shape = memnew(ConvexPolygonShape3D); shape->set_points(vertices); return shape; } -Ref Mesh::create_trimesh_shape() const { +Ref Mesh::create_trimesh_shape() const { Vector faces = get_faces(); if (faces.size() == 0) - return Ref(); + return Ref(); Vector face_points; face_points.resize(faces.size() * 3); @@ -260,7 +260,7 @@ Ref Mesh::create_trimesh_shape() const { face_points.set(i + 2, f.vertex[2]); } - Ref shape = memnew(ConcavePolygonShape); + Ref shape = memnew(ConcavePolygonShape3D); shape->set_faces(face_points); return shape; } @@ -541,15 +541,15 @@ void Mesh::clear_cache() const { debug_lines.clear(); } -Vector> Mesh::convex_decompose() const { +Vector> Mesh::convex_decompose() const { - ERR_FAIL_COND_V(!convex_composition_function, Vector>()); + ERR_FAIL_COND_V(!convex_composition_function, Vector>()); const Vector faces = get_faces(); Vector> decomposed = convex_composition_function(faces); - Vector> ret; + Vector> ret; for (int i = 0; i < decomposed.size(); i++) { Set points; @@ -569,7 +569,7 @@ Vector> Mesh::convex_decompose() const { } } - Ref shape; + Ref shape; shape.instance(); shape->set_points(convex_points); ret.push_back(shape); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index e0cc214301..e5f87dbbe5 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -35,7 +35,7 @@ #include "core/math/triangle_mesh.h" #include "core/resource.h" #include "scene/resources/material.h" -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" #include "servers/visual_server.h" class Mesh : public Resource { @@ -131,8 +131,8 @@ public: void generate_debug_mesh_lines(Vector &r_lines); void generate_debug_mesh_indices(Vector &r_points); - Ref create_trimesh_shape() const; - Ref create_convex_shape() const; + Ref create_trimesh_shape() const; + Ref create_convex_shape() const; Ref create_outline(float p_margin) const; @@ -146,7 +146,7 @@ public: static ConvexDecompositionFunc convex_composition_function; - Vector> convex_decompose() const; + Vector> convex_decompose() const; Mesh(); }; diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index b256e86b96..55001f2545 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -34,8 +34,8 @@ #include "core/map.h" #include "core/resource.h" #include "mesh.h" -#include "scene/3d/navigation_region.h" -#include "shape.h" +#include "scene/3d/navigation_region_3d.h" +#include "shape_3d.h" class MeshLibrary : public Resource { @@ -44,7 +44,7 @@ class MeshLibrary : public Resource { public: struct ShapeData { - Ref shape; + Ref shape; Transform local_transform; }; struct Item { diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 7059682904..549c29a7f3 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -35,7 +35,7 @@ #include "core/io/resource_loader.h" #include "core/project_settings.h" #include "scene/2d/node_2d.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" #include "scene/gui/control.h" #include "scene/main/instance_placeholder.h" @@ -159,8 +159,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } WARN_PRINT(String("Warning node of type " + snames[n.type].operator String() + " does not exist.").ascii().get_data()); if (n.parent >= 0 && n.parent < nc && ret_nodes[n.parent]) { - if (Object::cast_to(ret_nodes[n.parent])) { - obj = memnew(Spatial); + if (Object::cast_to(ret_nodes[n.parent])) { + obj = memnew(Node3D); } else if (Object::cast_to(ret_nodes[n.parent])) { obj = memnew(Control); } else if (Object::cast_to(ret_nodes[n.parent])) { diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp index 906abaf60c..f4f8eff1bd 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape.cpp @@ -32,7 +32,7 @@ #include "servers/physics_server.h" -Vector RayShape::get_debug_mesh_lines() { +Vector RayShape3D::get_debug_mesh_lines() { Vector points; points.push_back(Vector3()); @@ -41,20 +41,20 @@ Vector RayShape::get_debug_mesh_lines() { return points; } -real_t RayShape::get_enclosing_radius() const { +real_t RayShape3D::get_enclosing_radius() const { return length; } -void RayShape::_update_shape() { +void RayShape3D::_update_shape() { Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + Shape3D::_update_shape(); } -void RayShape::set_length(float p_length) { +void RayShape3D::set_length(float p_length) { length = p_length; _update_shape(); @@ -62,12 +62,12 @@ void RayShape::set_length(float p_length) { _change_notify("length"); } -float RayShape::get_length() const { +float RayShape3D::get_length() const { return length; } -void RayShape::set_slips_on_slope(bool p_active) { +void RayShape3D::set_slips_on_slope(bool p_active) { slips_on_slope = p_active; _update_shape(); @@ -75,24 +75,24 @@ void RayShape::set_slips_on_slope(bool p_active) { _change_notify("slips_on_slope"); } -bool RayShape::get_slips_on_slope() const { +bool RayShape3D::get_slips_on_slope() const { return slips_on_slope; } -void RayShape::_bind_methods() { +void RayShape3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &RayShape::get_length); + ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape3D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &RayShape3D::get_length); - ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape::set_slips_on_slope); - ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape::get_slips_on_slope); + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape3D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape3D::get_slips_on_slope); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); } -RayShape::RayShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) { +RayShape3D::RayShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) { length = 1.0; slips_on_slope = false; diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h index c89705ad7d..1d8c482c93 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape.h @@ -30,11 +30,11 @@ #ifndef RAY_SHAPE_H #define RAY_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class RayShape : public Shape { +class RayShape3D : public Shape3D { - GDCLASS(RayShape, Shape); + GDCLASS(RayShape3D, Shape3D); float length; bool slips_on_slope; @@ -52,6 +52,6 @@ public: virtual Vector get_debug_mesh_lines(); virtual real_t get_enclosing_radius() const; - RayShape(); + RayShape3D(); }; #endif // RAY_SHAPE_H diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp deleted file mode 100644 index 4a6da18f2b..0000000000 --- a/scene/resources/shape.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************/ -/* shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shape.h" - -#include "core/os/os.h" -#include "scene/main/scene_tree.h" -#include "scene/resources/mesh.h" -#include "servers/physics_server.h" - -void Shape::add_vertices_to_array(Vector &array, const Transform &p_xform) { - - Vector toadd = get_debug_mesh_lines(); - - if (toadd.size()) { - - int base = array.size(); - array.resize(base + toadd.size()); - Vector3 *w = array.ptrw(); - for (int i = 0; i < toadd.size(); i++) { - w[i + base] = p_xform.xform(toadd[i]); - } - } -} - -real_t Shape::get_margin() const { - return margin; -} - -void Shape::set_margin(real_t p_margin) { - margin = p_margin; - PhysicsServer::get_singleton()->shape_set_margin(shape, margin); -} - -Ref Shape::get_debug_mesh() { - - if (debug_mesh_cache.is_valid()) - return debug_mesh_cache; - - Vector lines = get_debug_mesh_lines(); - - debug_mesh_cache = Ref(memnew(ArrayMesh)); - - if (!lines.empty()) { - //make mesh - Vector array; - array.resize(lines.size()); - { - - Vector3 *w = array.ptrw(); - for (int i = 0; i < lines.size(); i++) { - w[i] = lines[i]; - } - } - - Array arr; - arr.resize(Mesh::ARRAY_MAX); - arr[Mesh::ARRAY_VERTEX] = array; - - SceneTree *st = Object::cast_to(OS::get_singleton()->get_main_loop()); - - debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); - - if (st) { - debug_mesh_cache->surface_set_material(0, st->get_debug_collision_material()); - } - } - - return debug_mesh_cache; -} - -void Shape::_update_shape() { - emit_changed(); - debug_mesh_cache.unref(); -} - -void Shape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &Shape::get_margin); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin"); -} - -Shape::Shape() : - margin(0.04) { - - ERR_PRINT("Constructor must not be called!"); -} - -Shape::Shape(RID p_shape) : - margin(0.04) { - - shape = p_shape; -} - -Shape::~Shape() { - - PhysicsServer::get_singleton()->free(shape); -} diff --git a/scene/resources/shape.h b/scene/resources/shape.h deleted file mode 100644 index e5ccbf7e28..0000000000 --- a/scene/resources/shape.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHAPE_H -#define SHAPE_H - -#include "core/resource.h" - -class ArrayMesh; - -class Shape : public Resource { - - GDCLASS(Shape, Resource); - OBJ_SAVE_TYPE(Shape); - RES_BASE_EXTENSION("shape"); - RID shape; - real_t margin; - - Ref debug_mesh_cache; - -protected: - static void _bind_methods(); - - _FORCE_INLINE_ RID get_shape() const { return shape; } - Shape(RID p_shape); - - virtual void _update_shape(); - -public: - virtual RID get_rid() const { return shape; } - - Ref get_debug_mesh(); - virtual Vector get_debug_mesh_lines() = 0; // { return Vector(); } - /// Returns the radius of a sphere that fully enclose this shape - virtual real_t get_enclosing_radius() const = 0; - - void add_vertices_to_array(Vector &array, const Transform &p_xform); - - real_t get_margin() const; - void set_margin(real_t p_margin); - - Shape(); - ~Shape(); -}; - -#endif // SHAPE_H diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp new file mode 100644 index 0000000000..c3aeba857a --- /dev/null +++ b/scene/resources/shape_3d.cpp @@ -0,0 +1,127 @@ +/*************************************************************************/ +/* shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shape_3d.h" + +#include "core/os/os.h" +#include "scene/main/scene_tree.h" +#include "scene/resources/mesh.h" +#include "servers/physics_server.h" + +void Shape3D::add_vertices_to_array(Vector &array, const Transform &p_xform) { + + Vector toadd = get_debug_mesh_lines(); + + if (toadd.size()) { + + int base = array.size(); + array.resize(base + toadd.size()); + Vector3 *w = array.ptrw(); + for (int i = 0; i < toadd.size(); i++) { + w[i + base] = p_xform.xform(toadd[i]); + } + } +} + +real_t Shape3D::get_margin() const { + return margin; +} + +void Shape3D::set_margin(real_t p_margin) { + margin = p_margin; + PhysicsServer::get_singleton()->shape_set_margin(shape, margin); +} + +Ref Shape3D::get_debug_mesh() { + + if (debug_mesh_cache.is_valid()) + return debug_mesh_cache; + + Vector lines = get_debug_mesh_lines(); + + debug_mesh_cache = Ref(memnew(ArrayMesh)); + + if (!lines.empty()) { + //make mesh + Vector array; + array.resize(lines.size()); + { + + Vector3 *w = array.ptrw(); + for (int i = 0; i < lines.size(); i++) { + w[i] = lines[i]; + } + } + + Array arr; + arr.resize(Mesh::ARRAY_MAX); + arr[Mesh::ARRAY_VERTEX] = array; + + SceneTree *st = Object::cast_to(OS::get_singleton()->get_main_loop()); + + debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); + + if (st) { + debug_mesh_cache->surface_set_material(0, st->get_debug_collision_material()); + } + } + + return debug_mesh_cache; +} + +void Shape3D::_update_shape() { + emit_changed(); + debug_mesh_cache.unref(); +} + +void Shape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape3D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &Shape3D::get_margin); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin"); +} + +Shape3D::Shape3D() : + margin(0.04) { + + ERR_PRINT("Constructor must not be called!"); +} + +Shape3D::Shape3D(RID p_shape) : + margin(0.04) { + + shape = p_shape; +} + +Shape3D::~Shape3D() { + + PhysicsServer::get_singleton()->free(shape); +} diff --git a/scene/resources/shape_3d.h b/scene/resources/shape_3d.h new file mode 100644 index 0000000000..e7a516412d --- /dev/null +++ b/scene/resources/shape_3d.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHAPE_3D_H +#define SHAPE_3D_H + +#include "core/resource.h" + +class ArrayMesh; + +class Shape3D : public Resource { + + GDCLASS(Shape3D, Resource); + OBJ_SAVE_TYPE(Shape3D); + RES_BASE_EXTENSION("shape"); + RID shape; + real_t margin; + + Ref debug_mesh_cache; + +protected: + static void _bind_methods(); + + _FORCE_INLINE_ RID get_shape() const { return shape; } + Shape3D(RID p_shape); + + virtual void _update_shape(); + +public: + virtual RID get_rid() const { return shape; } + + Ref get_debug_mesh(); + virtual Vector get_debug_mesh_lines() = 0; // { return Vector(); } + /// Returns the radius of a sphere that fully enclose this shape + virtual real_t get_enclosing_radius() const = 0; + + void add_vertices_to_array(Vector &array, const Transform &p_xform); + + real_t get_margin() const; + void set_margin(real_t p_margin); + + Shape3D(); + ~Shape3D(); +}; + +#endif // SHAPE_H diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp deleted file mode 100644 index 825708d1e2..0000000000 --- a/scene/resources/sphere_shape.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*************************************************************************/ -/* sphere_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "sphere_shape.h" -#include "servers/physics_server.h" - -Vector SphereShape::get_debug_mesh_lines() { - - float r = get_radius(); - - Vector points; - - for (int i = 0; i <= 360; i++) { - - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); - Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; - Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; - - points.push_back(Vector3(a.x, 0, a.y)); - points.push_back(Vector3(b.x, 0, b.y)); - points.push_back(Vector3(0, a.x, a.y)); - points.push_back(Vector3(0, b.x, b.y)); - points.push_back(Vector3(a.x, a.y, 0)); - points.push_back(Vector3(b.x, b.y, 0)); - } - - return points; -} - -real_t SphereShape::get_enclosing_radius() const { - return radius; -} - -void SphereShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius); - Shape::_update_shape(); -} - -void SphereShape::set_radius(float p_radius) { - - radius = p_radius; - _update_shape(); - notify_change_to_owners(); - _change_notify("radius"); -} - -float SphereShape::get_radius() const { - - return radius; -} - -void SphereShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &SphereShape::get_radius); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_radius", "get_radius"); -} - -SphereShape::SphereShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_SPHERE)) { - - set_radius(1.0); -} diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape.h deleted file mode 100644 index 07e8f1e233..0000000000 --- a/scene/resources/sphere_shape.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* sphere_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPHERE_SHAPE_H -#define SPHERE_SHAPE_H - -#include "scene/resources/shape.h" - -class SphereShape : public Shape { - - GDCLASS(SphereShape, Shape); - float radius; - -protected: - static void _bind_methods(); - - virtual void _update_shape(); - -public: - void set_radius(float p_radius); - float get_radius() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const; - - SphereShape(); -}; - -#endif // SPHERE_SHAPE_H diff --git a/scene/resources/sphere_shape_3d.cpp b/scene/resources/sphere_shape_3d.cpp new file mode 100644 index 0000000000..46f7c96ce1 --- /dev/null +++ b/scene/resources/sphere_shape_3d.cpp @@ -0,0 +1,93 @@ +/*************************************************************************/ +/* sphere_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sphere_shape_3d.h" +#include "servers/physics_server.h" + +Vector SphereShape3D::get_debug_mesh_lines() { + + float r = get_radius(); + + Vector points; + + for (int i = 0; i <= 360; i++) { + + float ra = Math::deg2rad((float)i); + float rb = Math::deg2rad((float)i + 1); + Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; + Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; + + points.push_back(Vector3(a.x, 0, a.y)); + points.push_back(Vector3(b.x, 0, b.y)); + points.push_back(Vector3(0, a.x, a.y)); + points.push_back(Vector3(0, b.x, b.y)); + points.push_back(Vector3(a.x, a.y, 0)); + points.push_back(Vector3(b.x, b.y, 0)); + } + + return points; +} + +real_t SphereShape3D::get_enclosing_radius() const { + return radius; +} + +void SphereShape3D::_update_shape() { + + PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius); + Shape3D::_update_shape(); +} + +void SphereShape3D::set_radius(float p_radius) { + + radius = p_radius; + _update_shape(); + notify_change_to_owners(); + _change_notify("radius"); +} + +float SphereShape3D::get_radius() const { + + return radius; +} + +void SphereShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &SphereShape3D::get_radius); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_radius", "get_radius"); +} + +SphereShape3D::SphereShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_SPHERE)) { + + set_radius(1.0); +} diff --git a/scene/resources/sphere_shape_3d.h b/scene/resources/sphere_shape_3d.h new file mode 100644 index 0000000000..3ed50cfe83 --- /dev/null +++ b/scene/resources/sphere_shape_3d.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* sphere_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPHERE_SHAPE_3D_H +#define SPHERE_SHAPE_3D_H + +#include "scene/resources/shape_3d.h" + +class SphereShape3D : public Shape3D { + + GDCLASS(SphereShape3D, Shape3D); + float radius; + +protected: + static void _bind_methods(); + + virtual void _update_shape(); + +public: + void set_radius(float p_radius); + float get_radius() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const; + + SphereShape3D(); +}; + +#endif // SPHERE_SHAPE_H diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index fecef88792..c4a019c728 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1034,7 +1034,7 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const { void VisualShader::_get_property_list(List *p_list) const { //mode - p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Spatial,CanvasItem,Particles,Sky")); + p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky")); //render modes Map blend_mode_enums; diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index a7e519479f..43903db277 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -32,13 +32,13 @@ #include "core/math/camera_matrix.h" #include "core/math/octree.h" -#include "scene/3d/camera.h" -#include "scene/3d/visibility_notifier.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/visibility_notifier_3d.h" #include "scene/scene_string_names.h" struct SpatialIndexer { - Octree octree; + Octree octree; struct NotifierData { @@ -46,25 +46,25 @@ struct SpatialIndexer { OctreeElementID id; }; - Map notifiers; + Map notifiers; struct CameraData { - Map notifiers; + Map notifiers; }; - Map cameras; + Map cameras; enum { VISIBILITY_CULL_MAX = 32768 }; - Vector cull; + Vector cull; bool changed; uint64_t pass; uint64_t last_frame; - void _notifier_add(VisibilityNotifier *p_notifier, const AABB &p_rect) { + void _notifier_add(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { ERR_FAIL_COND(notifiers.has(p_notifier)); notifiers[p_notifier].aabb = p_rect; @@ -72,9 +72,9 @@ struct SpatialIndexer { changed = true; } - void _notifier_update(VisibilityNotifier *p_notifier, const AABB &p_rect) { + void _notifier_update(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { - Map::Element *E = notifiers.find(p_notifier); + Map::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); if (E->get().aabb == p_rect) return; @@ -84,18 +84,18 @@ struct SpatialIndexer { changed = true; } - void _notifier_remove(VisibilityNotifier *p_notifier) { + void _notifier_remove(VisibilityNotifier3D *p_notifier) { - Map::Element *E = notifiers.find(p_notifier); + Map::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); octree.erase(E->get().id); notifiers.erase(p_notifier); - List removed; - for (Map::Element *F = cameras.front(); F; F = F->next()) { + List removed; + for (Map::Element *F = cameras.front(); F; F = F->next()) { - Map::Element *G = F->get().notifiers.find(p_notifier); + Map::Element *G = F->get().notifiers.find(p_notifier); if (G) { F->get().notifiers.erase(G); @@ -112,7 +112,7 @@ struct SpatialIndexer { changed = true; } - void _add_camera(Camera *p_camera) { + void _add_camera(Camera3D *p_camera) { ERR_FAIL_COND(cameras.has(p_camera)); CameraData vd; @@ -120,17 +120,17 @@ struct SpatialIndexer { changed = true; } - void _update_camera(Camera *p_camera) { + void _update_camera(Camera3D *p_camera) { - Map::Element *E = cameras.find(p_camera); + Map::Element *E = cameras.find(p_camera); ERR_FAIL_COND(!E); changed = true; } - void _remove_camera(Camera *p_camera) { + void _remove_camera(Camera3D *p_camera) { ERR_FAIL_COND(!cameras.has(p_camera)); - List removed; - for (Map::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) { + List removed; + for (Map::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) { removed.push_back(E->key()); } @@ -152,26 +152,26 @@ struct SpatialIndexer { if (!changed) return; - for (Map::Element *E = cameras.front(); E; E = E->next()) { + for (Map::Element *E = cameras.front(); E; E = E->next()) { pass++; - Camera *c = E->key(); + Camera3D *c = E->key(); Vector planes = c->get_frustum(); int culled = octree.cull_convex(planes, cull.ptrw(), cull.size()); - VisibilityNotifier **ptr = cull.ptrw(); + VisibilityNotifier3D **ptr = cull.ptrw(); - List added; - List removed; + List added; + List removed; for (int i = 0; i < culled; i++) { //notifiers in frustum - Map::Element *H = E->get().notifiers.find(ptr[i]); + Map::Element *H = E->get().notifiers.find(ptr[i]); if (!H) { E->get().notifiers.insert(ptr[i], pass); @@ -181,7 +181,7 @@ struct SpatialIndexer { } } - for (Map::Element *F = E->get().notifiers.front(); F; F = F->next()) { + for (Map::Element *F = E->get().notifiers.front(); F; F = F->next()) { if (F->get() != pass) removed.push_back(F->key()); @@ -210,41 +210,41 @@ struct SpatialIndexer { } }; -void World::_register_camera(Camera *p_camera) { +void World::_register_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_add_camera(p_camera); #endif } -void World::_update_camera(Camera *p_camera) { +void World::_update_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_update_camera(p_camera); #endif } -void World::_remove_camera(Camera *p_camera) { +void World::_remove_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_remove_camera(p_camera); #endif } -void World::_register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { +void World::_register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_add(p_notifier, p_rect); #endif } -void World::_update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { +void World::_update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_update(p_notifier, p_rect); #endif } -void World::_remove_notifier(VisibilityNotifier *p_notifier) { +void World::_remove_notifier(VisibilityNotifier3D *p_notifier) { #ifndef _3D_DISABLED indexer->_notifier_remove(p_notifier); @@ -325,9 +325,9 @@ PhysicsDirectSpaceState *World::get_direct_space_state() { return PhysicsServer::get_singleton()->space_get_direct_state(space); } -void World::get_camera_list(List *r_cameras) { +void World::get_camera_list(List *r_cameras) { - for (Map::Element *E = indexer->cameras.front(); E; E = E->next()) { + for (Map::Element *E = indexer->cameras.front(); E; E = E->next()) { r_cameras->push_back(E->key()); } } diff --git a/scene/resources/world.h b/scene/resources/world.h index 6fd79abaaf..8132a018d2 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -36,8 +36,8 @@ #include "servers/physics_server.h" #include "servers/visual_server.h" -class Camera; -class VisibilityNotifier; +class Camera3D; +class VisibilityNotifier3D; struct SpatialIndexer; class World : public Resource { @@ -55,16 +55,16 @@ private: protected: static void _bind_methods(); - friend class Camera; - friend class VisibilityNotifier; + friend class Camera3D; + friend class VisibilityNotifier3D; - void _register_camera(Camera *p_camera); - void _update_camera(Camera *p_camera); - void _remove_camera(Camera *p_camera); + void _register_camera(Camera3D *p_camera); + void _update_camera(Camera3D *p_camera); + void _remove_camera(Camera3D *p_camera); - void _register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); - void _update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); - void _remove_notifier(VisibilityNotifier *p_notifier); + void _register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect); + void _update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect); + void _remove_notifier(VisibilityNotifier3D *p_notifier); friend class Viewport; void _update(uint64_t p_frame); @@ -81,7 +81,7 @@ public: void set_camera_effects(const Ref &p_camera_effects); Ref get_camera_effects() const; - void get_camera_list(List *r_cameras); + void get_camera_list(List *r_cameras); PhysicsDirectSpaceState *get_direct_space_state(); diff --git a/scene/resources/world_margin_shape.cpp b/scene/resources/world_margin_shape.cpp deleted file mode 100644 index b5b701327c..0000000000 --- a/scene/resources/world_margin_shape.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************/ -/* world_margin_shape.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "world_margin_shape.h" - -#include "servers/physics_server.h" - -Vector WorldMarginShape::get_debug_mesh_lines() { - - Plane p = get_plane(); - Vector points; - - Vector3 n1 = p.get_any_perpendicular_normal(); - Vector3 n2 = p.normal.cross(n1).normalized(); - - Vector3 pface[4] = { - p.normal * p.d + n1 * 10.0 + n2 * 10.0, - p.normal * p.d + n1 * 10.0 + n2 * -10.0, - p.normal * p.d + n1 * -10.0 + n2 * -10.0, - p.normal * p.d + n1 * -10.0 + n2 * 10.0, - }; - - points.push_back(pface[0]); - points.push_back(pface[1]); - points.push_back(pface[1]); - points.push_back(pface[2]); - points.push_back(pface[2]); - points.push_back(pface[3]); - points.push_back(pface[3]); - points.push_back(pface[0]); - points.push_back(p.normal * p.d); - points.push_back(p.normal * p.d + p.normal * 3); - - return points; -} - -void WorldMarginShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), plane); - Shape::_update_shape(); -} - -void WorldMarginShape::set_plane(Plane p_plane) { - - plane = p_plane; - _update_shape(); - notify_change_to_owners(); - _change_notify("plane"); -} - -Plane WorldMarginShape::get_plane() const { - - return plane; -} - -void WorldMarginShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_plane", "plane"), &WorldMarginShape::set_plane); - ClassDB::bind_method(D_METHOD("get_plane"), &WorldMarginShape::get_plane); - - ADD_PROPERTY(PropertyInfo(Variant::PLANE, "plane"), "set_plane", "get_plane"); -} - -WorldMarginShape::WorldMarginShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_PLANE)) { - - set_plane(Plane(0, 1, 0, 0)); -} diff --git a/scene/resources/world_margin_shape.h b/scene/resources/world_margin_shape.h deleted file mode 100644 index 78ea570212..0000000000 --- a/scene/resources/world_margin_shape.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* world_margin_shape.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef WORLD_MARGIN_SHAPE_H -#define WORLD_MARGIN_SHAPE_H - -#include "scene/resources/shape.h" - -class WorldMarginShape : public Shape { - - GDCLASS(WorldMarginShape, Shape); - Plane plane; - -protected: - static void _bind_methods(); - virtual void _update_shape(); - -public: - void set_plane(Plane p_plane); - Plane get_plane() const; - - virtual Vector get_debug_mesh_lines(); - virtual real_t get_enclosing_radius() const { - // Should be infinite? - return 0; - } - - WorldMarginShape(); -}; -#endif // WORLD_MARGIN_SHAPE_H diff --git a/scene/resources/world_margin_shape_3d.cpp b/scene/resources/world_margin_shape_3d.cpp new file mode 100644 index 0000000000..3bea3111ef --- /dev/null +++ b/scene/resources/world_margin_shape_3d.cpp @@ -0,0 +1,95 @@ +/*************************************************************************/ +/* world_margin_shape_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "world_margin_shape_3d.h" + +#include "servers/physics_server.h" + +Vector WorldMarginShape3D::get_debug_mesh_lines() { + + Plane p = get_plane(); + Vector points; + + Vector3 n1 = p.get_any_perpendicular_normal(); + Vector3 n2 = p.normal.cross(n1).normalized(); + + Vector3 pface[4] = { + p.normal * p.d + n1 * 10.0 + n2 * 10.0, + p.normal * p.d + n1 * 10.0 + n2 * -10.0, + p.normal * p.d + n1 * -10.0 + n2 * -10.0, + p.normal * p.d + n1 * -10.0 + n2 * 10.0, + }; + + points.push_back(pface[0]); + points.push_back(pface[1]); + points.push_back(pface[1]); + points.push_back(pface[2]); + points.push_back(pface[2]); + points.push_back(pface[3]); + points.push_back(pface[3]); + points.push_back(pface[0]); + points.push_back(p.normal * p.d); + points.push_back(p.normal * p.d + p.normal * 3); + + return points; +} + +void WorldMarginShape3D::_update_shape() { + + PhysicsServer::get_singleton()->shape_set_data(get_shape(), plane); + Shape3D::_update_shape(); +} + +void WorldMarginShape3D::set_plane(Plane p_plane) { + + plane = p_plane; + _update_shape(); + notify_change_to_owners(); + _change_notify("plane"); +} + +Plane WorldMarginShape3D::get_plane() const { + + return plane; +} + +void WorldMarginShape3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_plane", "plane"), &WorldMarginShape3D::set_plane); + ClassDB::bind_method(D_METHOD("get_plane"), &WorldMarginShape3D::get_plane); + + ADD_PROPERTY(PropertyInfo(Variant::PLANE, "plane"), "set_plane", "get_plane"); +} + +WorldMarginShape3D::WorldMarginShape3D() : + Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_PLANE)) { + + set_plane(Plane(0, 1, 0, 0)); +} diff --git a/scene/resources/world_margin_shape_3d.h b/scene/resources/world_margin_shape_3d.h new file mode 100644 index 0000000000..5e0f046628 --- /dev/null +++ b/scene/resources/world_margin_shape_3d.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* world_margin_shape_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef WORLD_MARGIN_SHAPE_3D_H +#define WORLD_MARGIN_SHAPE_3D_H + +#include "scene/resources/shape_3d.h" + +class WorldMarginShape3D : public Shape3D { + + GDCLASS(WorldMarginShape3D, Shape3D); + Plane plane; + +protected: + static void _bind_methods(); + virtual void _update_shape(); + +public: + void set_plane(Plane p_plane); + Plane get_plane() const; + + virtual Vector get_debug_mesh_lines(); + virtual real_t get_enclosing_radius() const { + // Should be infinite? + return 0; + } + + WorldMarginShape3D(); +}; +#endif // WORLD_MARGIN_SHAPE_H diff --git a/servers/navigation_server.h b/servers/navigation_server.h index 546e543db3..2ea8e787cf 100644 --- a/servers/navigation_server.h +++ b/servers/navigation_server.h @@ -37,7 +37,7 @@ #include "core/object.h" #include "core/rid.h" -#include "scene/3d/navigation_region.h" +#include "scene/3d/navigation_region_3d.h" /// This server uses the concept of internal mutability. /// All the constant functions can be called in multithread because internally -- cgit v1.2.3