diff options
34 files changed, 813 insertions, 150 deletions
diff --git a/core/class_db.h b/core/class_db.h index f1d1879236..66a67f6c9f 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -39,6 +39,10 @@ @author Juan Linietsky <reduzio@gmail.com> */ +/** To bind more then 6 parameters include this: + * #include "method_bind_ext.gen.inc" + */ + #define DEFVAL(m_defval) (m_defval) //#define SIMPLE_METHODDEF diff --git a/core/color.cpp b/core/color.cpp index fcfcf20355..0d8cad1a5e 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -506,8 +506,11 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) { return Color(m + r, m + g, m + b, p_a); } +// FIXME: Remove once Godot 3.1 has been released float Color::gray() const { + ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation."); + WARN_DEPRECATED return (r + g + b) / 3.0; } diff --git a/core/image.cpp b/core/image.cpp index c94f2c3534..2fd7ea5c14 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2230,10 +2230,10 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { switch (format) { case FORMAT_L8: { - ptr[ofs] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255)); + ptr[ofs] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255)); } break; case FORMAT_LA8: { - ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255)); + ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255)); ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255)); } break; case FORMAT_R8: { diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 889d34544a..20ddfa99a8 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -1337,6 +1337,48 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(lines); p_gizmo->add_unscaled_billboard(icon, 0.05); p_gizmo->add_handles(handles, get_material("handles")); + + ClippedCamera *clipcam = Object::cast_to<ClippedCamera>(camera); + if (clipcam) { + Spatial *parent = Object::cast_to<Spatial>(camera->get_parent()); + if (!parent) { + return; + } + Vector3 cam_normal = -camera->get_global_transform().basis.get_axis(Vector3::AXIS_Z).normalized(); + Vector3 cam_x = camera->get_global_transform().basis.get_axis(Vector3::AXIS_X).normalized(); + Vector3 cam_y = camera->get_global_transform().basis.get_axis(Vector3::AXIS_Y).normalized(); + Vector3 cam_pos = camera->get_global_transform().origin; + Vector3 parent_pos = parent->get_global_transform().origin; + + Plane parent_plane(parent_pos, cam_normal); + Vector3 ray_from = parent_plane.project(cam_pos); + + lines.clear(); + lines.push_back(ray_from + cam_x * 0.5 + cam_y * 0.5); + lines.push_back(ray_from + cam_x * 0.5 + cam_y * -0.5); + + lines.push_back(ray_from + cam_x * 0.5 + cam_y * -0.5); + lines.push_back(ray_from + cam_x * -0.5 + cam_y * -0.5); + + lines.push_back(ray_from + cam_x * -0.5 + cam_y * -0.5); + lines.push_back(ray_from + cam_x * -0.5 + cam_y * 0.5); + + lines.push_back(ray_from + cam_x * -0.5 + cam_y * 0.5); + lines.push_back(ray_from + cam_x * 0.5 + cam_y * 0.5); + + if (parent_plane.distance_to(cam_pos) < 0) { + lines.push_back(ray_from); + lines.push_back(cam_pos); + } + + Transform local = camera->get_global_transform().affine_inverse(); + for (int i = 0; i < lines.size(); i++) { + lines.write[i] = local.xform(lines[i]); + } + + p_gizmo->add_lines(lines, material); + p_gizmo->add_collision_segments(lines); + } } ////// @@ -3613,7 +3655,7 @@ void NavigationMeshSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_segments(lines); } -////// + ////// #define BODY_A_RADIUS 0.25 #define BODY_B_RADIUS 0.27 diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 0139842470..70f70e7e5f 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -163,6 +163,18 @@ Variant BulletPhysicsServer::shape_get_data(RID p_shape) const { return shape->get_data(); } +void BulletPhysicsServer::shape_set_margin(RID p_shape, real_t p_margin) { + ShapeBullet *shape = shape_owner.get(p_shape); + ERR_FAIL_COND(!shape); + shape->set_margin(p_margin); +} + +real_t BulletPhysicsServer::shape_get_margin(RID p_shape) const { + ShapeBullet *shape = shape_owner.get(p_shape); + ERR_FAIL_COND_V(!shape, 0.0); + return shape->get_margin(); +} + real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const { //WARN_PRINT("Bias not supported by Bullet physics engine"); return 0.; diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 76716f1d1b..e9c568d605 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -99,6 +99,9 @@ public: virtual ShapeType shape_get_type(RID p_shape) const; virtual Variant shape_get_data(RID p_shape) const; + virtual void shape_set_margin(RID p_shape, real_t p_margin); + virtual real_t shape_get_margin(RID p_shape) const; + /// Not supported virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias); /// Not supported diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 85178bf83c..534034d707 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -30,6 +30,7 @@ #include "godot_result_callbacks.h" +#include "area_bullet.h" #include "bullet_types_converter.h" #include "collision_object_bullet.h" #include "rigid_body_bullet.h" @@ -51,11 +52,23 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co if (needs) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); + + if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { + if (!collide_with_areas) + return false; + } else { + if (!collide_with_bodies) + return false; + } + if (m_pickRay && !gObj->is_ray_pickable()) { return false; - } else if (m_exclude->has(gObj->get_self())) { + } + + if (m_exclude->has(gObj->get_self())) { return false; } + return true; } else { return false; @@ -124,6 +137,15 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) if (needs) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); + + if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { + if (!collide_with_areas) + return false; + } else { + if (!collide_with_bodies) + return false; + } + if (m_exclude->has(gObj->get_self())) { return false; } @@ -144,6 +166,15 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co if (needs) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); + + if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { + if (!collide_with_areas) + return false; + } else { + if (!collide_with_bodies) + return false; + } + if (m_exclude->has(gObj->get_self())) { return false; } @@ -189,6 +220,15 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr if (needs) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); + + if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { + if (!collide_with_areas) + return false; + } else { + if (!collide_with_bodies) + return false; + } + if (m_exclude->has(gObj->get_self())) { return false; } @@ -218,6 +258,15 @@ bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy if (needs) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); + + if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { + if (!collide_with_areas) + return false; + } else { + if (!collide_with_bodies) + return false; + } + if (m_exclude->has(gObj->get_self())) { return false; } diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index 363051f24c..3948f43c00 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -56,12 +56,17 @@ struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResult bool m_pickRay; int m_shapeId; + bool collide_with_bodies; + bool collide_with_areas; + public: - GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude) : + GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld), m_exclude(p_exclude), m_pickRay(false), - m_shapeId(0) {} + m_shapeId(0), + collide_with_bodies(p_collide_with_bodies), + collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; @@ -108,9 +113,14 @@ public: const Set<RID> *m_exclude; int m_shapeId; - GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude) : + bool collide_with_bodies; + bool collide_with_areas; + + GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), - m_exclude(p_exclude) {} + m_exclude(p_exclude), + collide_with_bodies(p_collide_with_bodies), + collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; @@ -125,12 +135,17 @@ public: int m_count; const Set<RID> *m_exclude; - GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) : + bool collide_with_bodies; + bool collide_with_areas; + + GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_results(p_results), m_exclude(p_exclude), m_resultMax(p_resultMax), - m_count(0) {} + m_count(0), + collide_with_bodies(p_collide_with_bodies), + collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; @@ -146,12 +161,17 @@ public: int m_count; const Set<RID> *m_exclude; - GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude) : + bool collide_with_bodies; + bool collide_with_areas; + + GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_results(p_results), m_exclude(p_exclude), m_resultMax(p_resultMax), - m_count(0) {} + m_count(0), + collide_with_bodies(p_collide_with_bodies), + collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; @@ -167,13 +187,17 @@ public: const btCollisionObject *m_rest_info_collision_object; btVector3 m_rest_info_bt_point; const Set<RID> *m_exclude; + bool collide_with_bodies; + bool collide_with_areas; - GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude) : + GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_result(p_result), m_exclude(p_exclude), m_collided(false), - m_min_distance(0) {} + m_min_distance(0), + collide_with_bodies(p_collide_with_bodies), + collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index e4c1a5f9b5..fab8d0cf3d 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -44,19 +44,20 @@ @author AndreaCatania */ -ShapeBullet::ShapeBullet() {} +ShapeBullet::ShapeBullet() : + margin(0.04) {} ShapeBullet::~ShapeBullet() {} -btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge) { btVector3 s; G_TO_B(p_implicit_scale, s); - return create_bt_shape(s, p_margin); + return create_bt_shape(s, p_extra_edge); } btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const { p_btShape->setUserPointer(const_cast<ShapeBullet *>(this)); - p_btShape->setMargin(0.); + p_btShape->setMargin(margin); return p_btShape; } @@ -93,6 +94,15 @@ const Map<ShapeOwnerBullet *, int> &ShapeBullet::get_owners() const { return owners; } +void ShapeBullet::set_margin(real_t p_margin) { + margin = p_margin; + notifyShapeChanged(); +} + +real_t ShapeBullet::get_margin() const { + return margin; +} + btEmptyShape *ShapeBullet::create_shape_empty() { return bulletnew(btEmptyShape); } @@ -166,7 +176,7 @@ void PlaneShapeBullet::setup(const Plane &p_plane) { notifyShapeChanged(); } -btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btVector3 btPlaneNormal; G_TO_B(plane.normal, btPlaneNormal); return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d)); @@ -194,8 +204,8 @@ void SphereShapeBullet::setup(real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_margin)); +btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_extra_edge)); } /* Box */ @@ -221,8 +231,8 @@ void BoxShapeBullet::setup(const Vector3 &p_half_extents) { notifyShapeChanged(); } -btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_margin, p_margin, p_margin))); +btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_extra_edge, p_extra_edge, p_extra_edge))); } /* Capsule */ @@ -254,8 +264,8 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin)); +btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge)); } /* Cylinder */ @@ -329,11 +339,10 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { notifyShapeChanged(); } -btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices)); cs->setLocalScaling(p_implicit_scale); prepare(cs); - cs->setMargin(p_margin); return cs; } @@ -402,14 +411,13 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { notifyShapeChanged(); } -btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape); if (!cs) // This is necessary since if 0 faces the creation of concave return NULL cs = ShapeBullet::create_shape_empty(); cs->setLocalScaling(p_implicit_scale); prepare(cs); - cs->setMargin(p_margin); return cs; } @@ -495,11 +503,10 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int notifyShapeChanged(); } -btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, min_height, max_height)); cs->setLocalScaling(p_implicit_scale); prepare(cs); - cs->setMargin(p_margin); return cs; } @@ -533,6 +540,6 @@ void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { notifyShapeChanged(); } -btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin, slips_on_slope)); +btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_extra_edge, slips_on_slope)); } diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index 16a5ac1fc6..638e044e6a 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -52,6 +52,7 @@ class btBvhTriangleMeshShape; class ShapeBullet : public RIDBullet { Map<ShapeOwnerBullet *, int> owners; + real_t margin; protected: /// return self @@ -62,14 +63,17 @@ public: ShapeBullet(); virtual ~ShapeBullet(); - btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin = 0); - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0) = 0; + btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0) = 0; void add_owner(ShapeOwnerBullet *p_owner); void remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody = false); bool is_owner(ShapeOwnerBullet *p_owner) const; const Map<ShapeOwnerBullet *, int> &get_owners() const; + void set_margin(real_t p_margin); + real_t get_margin() const; + /// Setup the shape virtual void set_data(const Variant &p_data) = 0; virtual Variant get_data() const = 0; @@ -100,7 +104,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(const Plane &p_plane); @@ -117,7 +121,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(real_t p_radius); @@ -134,7 +138,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(const Vector3 &p_half_extents); @@ -153,7 +157,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(real_t p_height, real_t p_radius); @@ -189,7 +193,7 @@ public: void get_vertices(Vector<Vector3> &out_vertices); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(const Vector<Vector3> &p_vertices); @@ -207,7 +211,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(PoolVector<Vector3> p_faces); @@ -227,7 +231,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height); @@ -244,7 +248,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: void setup(real_t p_length, bool p_slips_on_slope); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index e1a4e88db0..b5329bc347 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -61,7 +61,7 @@ BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_spac PhysicsDirectSpaceState(), space(p_space) {} -int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -69,13 +69,13 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape btVector3 bt_point; G_TO_B(p_point, bt_point); - btSphereShape sphere_point(0.f); + btSphereShape sphere_point(0.001f); btCollisionObject collision_object_point; collision_object_point.setCollisionShape(&sphere_point); collision_object_point.setWorldTransform(btTransform(btQuaternion::getIdentity(), bt_point)); // Setup query - GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude); + GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas); btResult.m_collisionFilterGroup = 0; btResult.m_collisionFilterMask = p_collision_mask; space->dynamicsWorld->contactTest(&collision_object_point, btResult); @@ -84,7 +84,7 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape return btResult.m_count; } -bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_pick_ray) { +bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { btVector3 btVec_from; btVector3 btVec_to; @@ -93,7 +93,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V G_TO_B(p_to, btVec_to); // setup query - GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude); + GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude, p_collide_with_bodies, p_collide_with_areas); btResult.m_collisionFilterGroup = 0; btResult.m_collisionFilterMask = p_collision_mask; btResult.m_pickRay = p_pick_ray; @@ -117,7 +117,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V } } -int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -139,7 +139,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra collision_object.setCollisionShape(btConvex); collision_object.setWorldTransform(bt_xform); - GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude); + GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; btQuery.m_closestDistanceThreshold = 0; @@ -150,7 +150,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra return btQuery.m_count; } -bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, ShapeRestInfo *r_info) { +bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); @@ -171,7 +171,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf btTransform bt_xform_to(bt_xform_from); bt_xform_to.getOrigin() += bt_motion; - GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude); + GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude, p_collide_with_bodies, p_collide_with_areas); btResult.m_collisionFilterGroup = 0; btResult.m_collisionFilterMask = p_collision_mask; @@ -197,7 +197,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf } /// Returns the list of contacts pairs in this order: Local contact, other body contact -bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -219,7 +219,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & collision_object.setCollisionShape(btConvex); collision_object.setWorldTransform(bt_xform); - GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude); + GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; btQuery.m_closestDistanceThreshold = 0; @@ -231,7 +231,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & return btQuery.m_count; } -bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); @@ -251,7 +251,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh collision_object.setCollisionShape(btConvex); collision_object.setWorldTransform(bt_xform); - GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude); + GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude, p_collide_with_bodies, p_collide_with_areas); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; btQuery.m_closestDistanceThreshold = 0; diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 95814d1fef..517ec67ffa 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -73,13 +73,13 @@ private: public: BulletPhysicsDirectSpaceState(SpaceBullet *p_space); - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_ray = false); - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, ShapeRestInfo *r_info = NULL); + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false); + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL); /// Returns the list of contacts pairs in this order: Local contact, other body contact - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const; }; diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs index 1195071bd3..49e04b333a 100644 --- a/modules/mono/glue/cs_files/Color.cs +++ b/modules/mono/glue/cs_files/Color.cs @@ -258,11 +258,6 @@ namespace Godot return res; } - public float Gray() - { - return (r + g + b) / 3.0f; - } - public Color Inverted() { return new Color( diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 83ef4df8f4..ff5f7062c4 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -119,7 +119,7 @@ void CollisionShape2D::_notification(int p_what) { Color draw_col = get_tree()->get_debug_collisions_color(); if (disabled) { - float g = draw_col.gray(); + float g = draw_col.get_v(); draw_col.r = g; draw_col.g = g; draw_col.b = g; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 255d2d38d5..9582c08110 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -209,7 +209,7 @@ void RayCast2D::_update_raycast_state() { Physics2DDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask)) { + 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; @@ -258,6 +258,26 @@ void RayCast2D::clear_exceptions() { exclude.clear(); } +void RayCast2D::set_collide_with_areas(bool p_clip) { + + collide_with_areas = p_clip; +} + +bool RayCast2D::is_collide_with_areas_enabled() const { + + return collide_with_areas; +} + +void RayCast2D::set_collide_with_bodies(bool p_clip) { + + collide_with_bodies = p_clip; +} + +bool RayCast2D::is_collide_with_bodies_enabled() const { + + return collide_with_bodies; +} + void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast2D::set_enabled); @@ -291,10 +311,20 @@ void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &RayCast2D::set_exclude_parent_body); ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &RayCast2D::get_exclude_parent_body); + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &RayCast2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &RayCast2D::is_collide_with_areas_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast2D::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::VECTOR2, "cast_to"), "set_cast_to", "get_cast_to"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_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"); } RayCast2D::RayCast2D() { @@ -306,4 +336,6 @@ RayCast2D::RayCast2D() { collision_mask = 1; cast_to = Vector2(0, 50); exclude_parent_body = true; + collide_with_bodies = true; + collide_with_areas = false; } diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 0850cdc7cc..a438be87b6 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -49,12 +49,21 @@ class RayCast2D : public Node2D { Vector2 cast_to; + 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; diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 2176b45faf..bcd015875b 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -31,9 +31,10 @@ #include "camera.h" #include "camera_matrix.h" +#include "collision_object.h" +#include "engine.h" #include "scene/resources/material.h" #include "scene/resources/surface_tool.h" - void Camera::_update_audio_listener_state() { } @@ -313,6 +314,32 @@ bool Camera::is_position_behind(const Vector3 &p_pos) const { return eyedir.dot(p_pos) < (eyedir.dot(t.origin) + near); } +Vector<Vector3> Camera::get_near_plane_points() const { + if (!is_inside_tree()) { + ERR_EXPLAIN("Camera is not inside scene."); + ERR_FAIL_COND_V(!is_inside_tree(), Vector<Vector3>()); + } + + 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<Vector3> 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 { if (!is_inside_tree()) { @@ -484,7 +511,7 @@ void Camera::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_znear", "get_znear"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar"); BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); @@ -638,3 +665,221 @@ 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; + } + set_process_internal(p_mode == CLIP_PROCESS_IDLE); + set_physics_process_internal(p_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<Spatial>(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<Vector3> 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).normalized() * 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<CollisionObject>(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<CollisionObject>(p_object); + if (!co) + return; + remove_exception_rid(co->get_rid()); +} + +void ClippedCamera::clear_exceptions() { + + exclude.clear(); +} + +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("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::REAL, "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"); +} +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 index 97705d8ae0..a35c9d6e7f 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -139,6 +139,8 @@ public: bool is_position_behind(const Vector3 &p_pos) const; virtual Vector3 project_position(const Point2 &p_point) const; + Vector<Vector3> get_near_plane_points() const; + void set_cull_mask(uint32_t p_layers); uint32_t get_cull_mask() const; @@ -172,4 +174,62 @@ 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<RID> exclude; + + Vector<Vector3> 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(); + + ClippedCamera(); + ~ClippedCamera(); +}; + +VARIANT_ENUM_CAST(ClippedCamera::ProcessMode); #endif diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 7f83e2c3ea..b846a5b6c0 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -208,7 +208,7 @@ void RayCast::_update_raycast_state() { PhysicsDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask)) { + 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; @@ -259,6 +259,26 @@ 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); @@ -292,10 +312,20 @@ void RayCast::_bind_methods() { 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() { @@ -370,4 +400,6 @@ RayCast::RayCast() { 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 index 20cea80700..e95382e1fe 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -45,7 +45,6 @@ class RayCast : public Spatial { Vector3 collision_normal; Vector3 cast_to; - Set<RID> exclude; uint32_t collision_mask; @@ -58,12 +57,21 @@ class RayCast : public Spatial { 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; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index e43c2da02d..f92b6e7583 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -444,7 +444,7 @@ void Viewport::_notification(int p_what) { Vector2 point = get_canvas_transform().affine_inverse().xform(pos); Physics2DDirectSpaceState::ShapeResult res[64]; - int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true); + int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true); for (int i = 0; i < rc; i++) { if (res[i].collider_id && res[i].collider) { @@ -527,7 +527,7 @@ void Viewport::_notification(int p_what) { PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); if (space) { - bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true); + bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true); ObjectID new_collider = 0; if (col) { @@ -563,7 +563,7 @@ void Viewport::_notification(int p_what) { PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); if (space) { - bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true); + bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true); ObjectID new_collider = 0; if (col) { CollisionObject *co = Object::cast_to<CollisionObject>(result.collider); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 673d44dab2..da4e2f991d 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -375,6 +375,7 @@ void register_scene_types() { ClassDB::register_virtual_class<VisualInstance>(); ClassDB::register_virtual_class<GeometryInstance>(); ClassDB::register_class<Camera>(); + ClassDB::register_class<ClippedCamera>(); ClassDB::register_class<Listener>(); ClassDB::register_class<ARVRCamera>(); ClassDB::register_class<ARVRController>(); diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 418d8ce819..a48ce0564b 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -50,6 +50,15 @@ void Shape::add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p } } +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<ArrayMesh> Shape::get_debug_mesh() { if (debug_mesh_cache.is_valid()) @@ -87,12 +96,22 @@ Ref<ArrayMesh> Shape::get_debug_mesh() { return debug_mesh_cache; } -Shape::Shape() { +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::REAL, "margin", PROPERTY_HINT_RANGE, "0.04,10,0.01"), "set_margin", "get_margin"); +} + +Shape::Shape() : + margin(0.04) { ERR_PRINT("Constructor must not be called!"); } -Shape::Shape(RID p_shape) { +Shape::Shape(RID p_shape) : + margin(0.04) { shape = p_shape; } diff --git a/scene/resources/shape.h b/scene/resources/shape.h index ad87a69679..0c44b86e92 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape.h @@ -40,10 +40,13 @@ class Shape : public Resource { OBJ_SAVE_TYPE(Shape); RES_BASE_EXTENSION("shape"); RID shape; + real_t margin; Ref<ArrayMesh> debug_mesh_cache; protected: + static void _bind_methods(); + _FORCE_INLINE_ RID get_shape() const { return shape; } Shape(RID p_shape); @@ -55,6 +58,9 @@ public: void add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform); + real_t get_margin() const; + void set_margin(real_t p_margin); + Shape(); ~Shape(); }; diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 61b014713f..472283833e 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -124,6 +124,13 @@ Variant PhysicsServerSW::shape_get_data(RID p_shape) const { return shape->get_data(); }; +void PhysicsServerSW::shape_set_margin(RID p_shape, real_t p_margin) { +} + +real_t PhysicsServerSW::shape_get_margin(RID p_shape) const { + return 0.0; +} + real_t PhysicsServerSW::shape_get_custom_solver_bias(RID p_shape) const { const ShapeSW *shape = shape_owner.get(p_shape); @@ -292,6 +299,7 @@ void PhysicsServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { area->set_shape(p_shape_idx, shape); } + void PhysicsServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { AreaSW *area = area_owner.get(p_area); diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index ad7aa4aa28..4131c5e248 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -85,6 +85,10 @@ public: virtual ShapeType shape_get_type(RID p_shape) const; virtual Variant shape_get_data(RID p_shape) const; + + virtual void shape_set_margin(RID p_shape, real_t p_margin); + virtual real_t shape_get_margin(RID p_shape) const; + virtual real_t shape_get_custom_solver_bias(RID p_shape) const; /* SPACE API */ diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 9d6ec958b4..cae2e6fb00 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -34,12 +34,22 @@ #include "physics_server_sw.h" #include "project_settings.h" -_FORCE_INLINE_ static bool _can_collide_with(CollisionObjectSW *p_object, uint32_t p_collision_mask) { +_FORCE_INLINE_ static bool _can_collide_with(CollisionObjectSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - return p_object->get_collision_layer() & p_collision_mask; + if (!(p_object->get_collision_layer() & p_collision_mask)) { + return false; + } + + if (p_object->get_type() == CollisionObjectSW::TYPE_AREA && !p_collide_with_areas) + return false; + + if (p_object->get_type() == CollisionObjectSW::TYPE_BODY && !p_collide_with_bodies) + return false; + + return true; } -int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ERR_FAIL_COND_V(space->locked, false); int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -52,7 +62,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu if (cc >= p_result_max) break; - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; //area can't be picked by ray (default) @@ -83,7 +93,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu return cc; } -bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_pick_ray) { +bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { ERR_FAIL_COND_V(space->locked, false); @@ -105,7 +115,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_pick_ray && !(static_cast<CollisionObjectSW *>(space->intersection_query_results[i])->is_ray_pickable())) @@ -161,7 +171,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto return true; } -int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -182,7 +192,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo if (cc >= p_result_max) break; - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; //area can't be picked by ray (default) @@ -212,7 +222,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo return cc; } -bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, ShapeRestInfo *r_info) { +bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, false); @@ -242,7 +252,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -326,7 +336,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform return true; } -bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -356,7 +366,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; const CollisionObjectSW *col_obj = space->intersection_query_results[i]; @@ -405,7 +415,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, rd->best_object = rd->object; rd->best_shape = rd->shape; } -bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, 0); @@ -422,7 +432,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_ for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; const CollisionObjectSW *col_obj = space->intersection_query_results[i]; diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index ed4b274d13..e7231df532 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -48,12 +48,12 @@ class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState { public: SpaceSW *space; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_ray = false); - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, ShapeRestInfo *r_info = NULL); - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false); + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL); + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const; PhysicsDirectSpaceStateSW(); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 6e45951f42..ecebd09436 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -34,12 +34,22 @@ #include "pair.h" #include "physics_2d_server_sw.h" -_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask) { +_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - return p_object->get_collision_layer() & p_collision_mask; + if (!(p_object->get_collision_layer() & p_collision_mask)) { + return false; + } + + if (p_object->get_type() == CollisionObject2DSW::TYPE_AREA && !p_collide_with_areas) + return false; + + if (p_object->get_type() == CollisionObject2DSW::TYPE_BODY && !p_collide_with_bodies) + return false; + + return true; } -int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_pick_point) { +int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { if (p_result_max <= 0) return 0; @@ -54,7 +64,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -90,7 +100,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe return cc; } -bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ERR_FAIL_COND_V(space->locked, false); @@ -112,7 +122,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -170,7 +180,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec return true; } -int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -190,7 +200,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans if (cc >= p_result_max) break; - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -215,7 +225,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans return cc; } -bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, false); @@ -236,7 +246,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -299,7 +309,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor return true; } -bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) return 0; @@ -330,7 +340,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; @@ -388,7 +398,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, rd->best_shape = rd->shape; } -bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask) { +bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, 0); @@ -406,7 +416,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) continue; const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 1247317b03..6e2e025185 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -48,12 +48,12 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { public: Space2DSW *space; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_point = false); - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF); + virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false); + virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); Physics2DDirectSpaceStateSW(); }; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 37c4bc83ad..a51b938541 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -203,6 +203,22 @@ Vector<RID> Physics2DShapeQueryParameters::get_exclude() const { return ret; } +void Physics2DShapeQueryParameters::set_collide_with_bodies(bool p_enable) { + collide_with_bodies = p_enable; +} + +bool Physics2DShapeQueryParameters::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +void Physics2DShapeQueryParameters::set_collide_with_areas(bool p_enable) { + collide_with_areas = p_enable; +} + +bool Physics2DShapeQueryParameters::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + void Physics2DShapeQueryParameters::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &Physics2DShapeQueryParameters::set_shape); @@ -224,6 +240,12 @@ void Physics2DShapeQueryParameters::_bind_methods() { ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &Physics2DShapeQueryParameters::set_exclude); ClassDB::bind_method(D_METHOD("get_exclude"), &Physics2DShapeQueryParameters::get_exclude); + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &Physics2DShapeQueryParameters::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &Physics2DShapeQueryParameters::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &Physics2DShapeQueryParameters::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &Physics2DShapeQueryParameters::is_collide_with_areas_enabled); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); @@ -231,22 +253,26 @@ void Physics2DShapeQueryParameters::_bind_methods() { //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } Physics2DShapeQueryParameters::Physics2DShapeQueryParameters() { margin = 0; collision_mask = 0x7FFFFFFF; + collide_with_bodies = true; + collide_with_areas = false; } -Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers) { +Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { RayResult inters; Set<RID> exclude; for (int i = 0; i < p_exclude.size(); i++) exclude.insert(p_exclude[i]); - bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers); + bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); if (!res) return Dictionary(); @@ -267,7 +293,7 @@ Array Physics2DDirectSpaceState::_intersect_shape(const Ref<Physics2DShapeQueryP Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask); + int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -287,7 +313,7 @@ Array Physics2DDirectSpaceState::_intersect_shape(const Ref<Physics2DShapeQueryP Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query) { float closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); if (!res) return Array(); Array ret; @@ -297,7 +323,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam return ret; } -Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers) { +Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { Set<RID> exclude; for (int i = 0; i < p_exclude.size(); i++) @@ -306,7 +332,7 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_ Vector<ShapeResult> ret; ret.resize(p_max_results); - int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers); + int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); if (rc == 0) return Array(); @@ -330,7 +356,7 @@ Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryPar Vector<Vector2> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); if (!res) return Array(); Array r; @@ -343,7 +369,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); Dictionary r; if (!res) return r; @@ -364,8 +390,8 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() { void Physics2DDirectSpaceState::_bind_methods() { - ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF)); - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF)); + ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32)); ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion); ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_collide_shape, DEFVAL(32)); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index f42d9868f0..82b4eb75d8 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -107,6 +107,9 @@ class Physics2DShapeQueryParameters : public Reference { Set<RID> exclude; uint32_t collision_mask; + bool collide_with_bodies; + bool collide_with_areas; + protected: static void _bind_methods(); @@ -127,6 +130,12 @@ public: void set_collision_mask(int p_collision_mask); int get_collision_mask() const; + void set_collide_with_bodies(bool p_enable); + bool is_collide_with_bodies_enabled() const; + + void set_collide_with_areas(bool p_enable); + bool is_collide_with_areas_enabled() const; + void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; @@ -137,9 +146,9 @@ class Physics2DDirectSpaceState : public Object { GDCLASS(Physics2DDirectSpaceState, Object); - Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0); + Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0); + Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32); Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query); Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32); @@ -160,7 +169,7 @@ public: Variant metadata; }; - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF) = 0; + virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; struct ShapeResult { @@ -171,13 +180,13 @@ public: Variant metadata; }; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_pick_point = false) = 0; + virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF) = 0; + virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF) = 0; + virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF) = 0; + virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; struct ShapeRestInfo { @@ -190,7 +199,7 @@ public: Variant metadata; }; - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF) = 0; + virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; Physics2DDirectSpaceState(); }; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index cda3856ecc..deb3cd9bbe 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "physics_server.h" + #include "core/project_settings.h" +#include "method_bind_ext.gen.inc" #include "print_string.h" PhysicsServer *PhysicsServer::singleton = NULL; @@ -198,6 +200,22 @@ Vector<RID> PhysicsShapeQueryParameters::get_exclude() const { return ret; } +void PhysicsShapeQueryParameters::set_collide_with_bodies(bool p_enable) { + collide_with_bodies = p_enable; +} + +bool PhysicsShapeQueryParameters::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +void PhysicsShapeQueryParameters::set_collide_with_areas(bool p_enable) { + collide_with_areas = p_enable; +} + +bool PhysicsShapeQueryParameters::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + void PhysicsShapeQueryParameters::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters::set_shape); @@ -216,18 +234,28 @@ void PhysicsShapeQueryParameters::_bind_methods() { ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsShapeQueryParameters::set_exclude); ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsShapeQueryParameters::get_exclude); + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsShapeQueryParameters::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsShapeQueryParameters::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsShapeQueryParameters::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters::is_collide_with_areas_enabled); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } PhysicsShapeQueryParameters::PhysicsShapeQueryParameters() { margin = 0; collision_mask = 0x7FFFFFFF; + collide_with_bodies = true; + collide_with_areas = false; } ///////////////////////////////////// @@ -262,14 +290,14 @@ Variant PhysicsDirectSpaceState::_intersect_shape(const RID& p_shape, const Tran } */ -Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask) { +Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { RayResult inters; Set<RID> exclude; for (int i = 0; i < p_exclude.size(); i++) exclude.insert(p_exclude[i]); - bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask); + bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas); if (!res) return Dictionary(); @@ -289,7 +317,7 @@ Array PhysicsDirectSpaceState::_intersect_shape(const Ref<PhysicsShapeQueryParam Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask); + int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -308,7 +336,7 @@ Array PhysicsDirectSpaceState::_intersect_shape(const Ref<PhysicsShapeQueryParam Array PhysicsDirectSpaceState::_cast_motion(const Ref<PhysicsShapeQueryParameters> &p_shape_query, const Vector3 &p_motion) { float closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); if (!res) return Array(); Array ret; @@ -322,7 +350,7 @@ Array PhysicsDirectSpaceState::_collide_shape(const Ref<PhysicsShapeQueryParamet Vector<Vector3> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); if (!res) return Array(); Array r; @@ -335,7 +363,7 @@ Dictionary PhysicsDirectSpaceState::_get_rest_info(const Ref<PhysicsShapeQueryPa ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask); + bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); Dictionary r; if (!res) return r; @@ -358,7 +386,7 @@ void PhysicsDirectSpaceState::_bind_methods() { //ClassDB::bind_method(D_METHOD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0)); //ClassDB::bind_method(D_METHOD("intersect_shape","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0)); - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer"), &PhysicsDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF)); + ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState::_intersect_shape, DEFVAL(32)); ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState::_cast_motion); ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState::_collide_shape, DEFVAL(32)); diff --git a/servers/physics_server.h b/servers/physics_server.h index 4ced915179..f2aa33a6cc 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -108,6 +108,9 @@ class PhysicsShapeQueryParameters : public Reference { Set<RID> exclude; uint32_t collision_mask; + bool collide_with_bodies; + bool collide_with_areas; + protected: static void _bind_methods(); @@ -128,6 +131,12 @@ public: void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; + void set_collide_with_bodies(bool p_enable); + bool is_collide_with_bodies_enabled() const; + + void set_collide_with_areas(bool p_enable); + bool is_collide_with_areas_enabled() const; + PhysicsShapeQueryParameters(); }; @@ -136,7 +145,7 @@ class PhysicsDirectSpaceState : public Object { GDCLASS(PhysicsDirectSpaceState, Object); private: - Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = 0); + Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); Array _intersect_shape(const Ref<PhysicsShapeQueryParameters> &p_shape_query, int p_max_results = 32); Array _cast_motion(const Ref<PhysicsShapeQueryParameters> &p_shape_query, const Vector3 &p_motion); Array _collide_shape(const Ref<PhysicsShapeQueryParameters> &p_shape_query, int p_max_results = 32); @@ -154,7 +163,7 @@ public: int shape; }; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF) = 0; + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; struct RayResult { @@ -166,9 +175,9 @@ public: int shape; }; - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_ray = false) = 0; + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF) = 0; + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; struct ShapeRestInfo { @@ -180,11 +189,11 @@ public: Vector3 linear_velocity; //velocity at contact point }; - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, ShapeRestInfo *r_info = NULL) = 0; + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL) = 0; - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF) = 0; + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF) = 0; + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0; @@ -243,6 +252,10 @@ public: virtual ShapeType shape_get_type(RID p_shape) const = 0; virtual Variant shape_get_data(RID p_shape) const = 0; + + virtual void shape_set_margin(RID p_shape, real_t p_margin) = 0; + virtual real_t shape_get_margin(RID p_shape) const = 0; + virtual real_t shape_get_custom_solver_bias(RID p_shape) const = 0; /* SPACE API */ |