Merge pull request #22973 from cyclopsian/csg-collision-fix
Add support for collision layers and masks in CSG shapes
This commit is contained in:
commit
a0519c7c31
3 changed files with 154 additions and 10 deletions
|
@ -48,18 +48,76 @@ void CSGShape::set_use_collision(bool p_enable) {
|
|||
PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
|
||||
PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
|
||||
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
|
||||
set_collision_layer(collision_layer);
|
||||
set_collision_mask(collision_mask);
|
||||
_make_dirty(); //force update
|
||||
} else {
|
||||
PhysicsServer::get_singleton()->free(root_collision_instance);
|
||||
root_collision_instance = RID();
|
||||
root_collision_shape.unref();
|
||||
}
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
bool CSGShape::is_using_collision() const {
|
||||
return use_collision;
|
||||
}
|
||||
|
||||
void CSGShape::set_collision_layer(uint32_t p_layer) {
|
||||
collision_layer = p_layer;
|
||||
if (root_collision_instance.is_valid()) {
|
||||
PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CSGShape::get_collision_layer() const {
|
||||
|
||||
return collision_layer;
|
||||
}
|
||||
|
||||
void CSGShape::set_collision_mask(uint32_t p_mask) {
|
||||
|
||||
collision_mask = p_mask;
|
||||
if (root_collision_instance.is_valid()) {
|
||||
PhysicsServer::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CSGShape::get_collision_mask() const {
|
||||
|
||||
return collision_mask;
|
||||
}
|
||||
|
||||
void CSGShape::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 CSGShape::get_collision_mask_bit(int p_bit) const {
|
||||
|
||||
return get_collision_mask() & (1 << p_bit);
|
||||
}
|
||||
|
||||
void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) {
|
||||
|
||||
uint32_t mask = get_collision_layer();
|
||||
if (p_value)
|
||||
mask |= 1 << p_bit;
|
||||
else
|
||||
mask &= ~(1 << p_bit);
|
||||
set_collision_layer(mask);
|
||||
}
|
||||
|
||||
bool CSGShape::get_collision_layer_bit(int p_bit) const {
|
||||
|
||||
return get_collision_layer() & (1 << p_bit);
|
||||
}
|
||||
|
||||
bool CSGShape::is_root_shape() const {
|
||||
|
||||
return !parent;
|
||||
|
@ -459,6 +517,8 @@ void CSGShape::_notification(int p_what) {
|
|||
PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
|
||||
PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
|
||||
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
|
||||
set_collision_layer(collision_layer);
|
||||
set_collision_mask(collision_mask);
|
||||
}
|
||||
|
||||
_make_dirty();
|
||||
|
@ -477,7 +537,7 @@ void CSGShape::_notification(int p_what) {
|
|||
parent->_make_dirty();
|
||||
parent = NULL;
|
||||
|
||||
if (use_collision && is_root_shape()) {
|
||||
if (use_collision && is_root_shape() && root_collision_instance.is_valid()) {
|
||||
PhysicsServer::get_singleton()->free(root_collision_instance);
|
||||
root_collision_instance = RID();
|
||||
root_collision_shape.unref();
|
||||
|
@ -506,9 +566,12 @@ bool CSGShape::is_calculating_tangents() const {
|
|||
}
|
||||
|
||||
void CSGShape::_validate_property(PropertyInfo &property) const {
|
||||
if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) {
|
||||
bool is_collision_prefixed = property.name.begins_with("collision_");
|
||||
if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) {
|
||||
//hide collision if not root
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
} else if (is_collision_prefixed && !bool(get("use_collision"))) {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,34 +583,52 @@ void CSGShape::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape::set_operation);
|
||||
ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_operation);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
|
||||
ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape::set_use_collision);
|
||||
ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape::is_using_collision);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
|
||||
ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
|
||||
ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape::get_collision_layer);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape::set_collision_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape::get_collision_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape::set_collision_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape::get_collision_mask_bit);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape::set_collision_layer_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape::get_collision_layer_bit);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents);
|
||||
ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents");
|
||||
|
||||
ADD_GROUP("Collision", "collision_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
|
||||
|
||||
BIND_ENUM_CONSTANT(OPERATION_UNION);
|
||||
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
|
||||
BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION);
|
||||
}
|
||||
|
||||
CSGShape::CSGShape() {
|
||||
brush = NULL;
|
||||
set_notify_local_transform(true);
|
||||
dirty = false;
|
||||
parent = NULL;
|
||||
use_collision = false;
|
||||
operation = OPERATION_UNION;
|
||||
parent = NULL;
|
||||
brush = NULL;
|
||||
dirty = false;
|
||||
snap = 0.001;
|
||||
use_collision = false;
|
||||
collision_layer = 1;
|
||||
collision_mask = 1;
|
||||
calculate_tangents = true;
|
||||
set_notify_local_transform(true);
|
||||
}
|
||||
|
||||
CSGShape::~CSGShape() {
|
||||
|
|
|
@ -61,6 +61,8 @@ private:
|
|||
float snap;
|
||||
|
||||
bool use_collision;
|
||||
uint32_t collision_layer;
|
||||
uint32_t collision_mask;
|
||||
Ref<ConcavePolygonShape> root_collision_shape;
|
||||
RID root_collision_instance;
|
||||
|
||||
|
@ -126,6 +128,18 @@ public:
|
|||
void set_use_collision(bool p_enable);
|
||||
bool is_using_collision() const;
|
||||
|
||||
void set_collision_layer(uint32_t p_layer);
|
||||
uint32_t get_collision_layer() const;
|
||||
|
||||
void set_collision_mask(uint32_t p_mask);
|
||||
uint32_t get_collision_mask() const;
|
||||
|
||||
void set_collision_layer_bit(int p_bit, bool p_value);
|
||||
bool get_collision_layer_bit(int p_bit) const;
|
||||
|
||||
void set_collision_mask_bit(int p_bit, bool p_value);
|
||||
bool get_collision_mask_bit(int p_bit) const;
|
||||
|
||||
void set_snap(float p_snap);
|
||||
float get_snap() const;
|
||||
|
||||
|
|
|
@ -18,6 +18,46 @@
|
|||
Returns true if this is a root shape and is thus the object that is rendered.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_collision_layer_bit" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="bit" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Returns an individual bit on the collision mask.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_collision_mask_bit" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="bit" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Returns an individual bit on the collision mask.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_collision_layer_bit">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="bit" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="value" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
Sets individual bits on the layer mask. Use this if you only need to change one layer's value.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_collision_mask_bit">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="bit" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="value" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
Sets individual bits on the collision mask. Use this if you only need to change one layer's value.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents">
|
||||
|
@ -31,6 +71,15 @@
|
|||
<member name="use_collision" type="bool" setter="set_use_collision" getter="is_using_collision">
|
||||
Adds a collision shape to the physics engine for our CSG shape. This will always act like a static body. Note that the collision shape is still active even if the CSG shape itself is hidden.
|
||||
</member>
|
||||
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
|
||||
The physics layers this area is in.
|
||||
Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property.
|
||||
A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.
|
||||
</member>
|
||||
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
|
||||
The physics layers this CSG shape scans for collisions.
|
||||
</member>
|
||||
</members>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="OPERATION_UNION" value="0" enum="Operation">
|
||||
|
|
Loading…
Reference in a new issue