mirror of
https://github.com/godotengine/godot
synced 2024-09-05 05:38:35 +00:00
Add support for collision layers and masks in CSG shapes
This commit is contained in:
parent
cf124b1415
commit
0059930644
|
@ -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_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_set_space(root_collision_instance, get_world()->get_space());
|
||||||
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
|
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
|
_make_dirty(); //force update
|
||||||
} else {
|
} else {
|
||||||
PhysicsServer::get_singleton()->free(root_collision_instance);
|
PhysicsServer::get_singleton()->free(root_collision_instance);
|
||||||
root_collision_instance = RID();
|
root_collision_instance = RID();
|
||||||
root_collision_shape.unref();
|
root_collision_shape.unref();
|
||||||
}
|
}
|
||||||
|
_change_notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSGShape::is_using_collision() const {
|
bool CSGShape::is_using_collision() const {
|
||||||
return use_collision;
|
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 {
|
bool CSGShape::is_root_shape() const {
|
||||||
|
|
||||||
return !parent;
|
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_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_set_space(root_collision_instance, get_world()->get_space());
|
||||||
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
|
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();
|
_make_dirty();
|
||||||
|
@ -477,7 +537,7 @@ void CSGShape::_notification(int p_what) {
|
||||||
parent->_make_dirty();
|
parent->_make_dirty();
|
||||||
parent = NULL;
|
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);
|
PhysicsServer::get_singleton()->free(root_collision_instance);
|
||||||
root_collision_instance = RID();
|
root_collision_instance = RID();
|
||||||
root_collision_shape.unref();
|
root_collision_shape.unref();
|
||||||
|
@ -506,9 +566,12 @@ bool CSGShape::is_calculating_tangents() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSGShape::_validate_property(PropertyInfo &property) 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
|
//hide collision if not root
|
||||||
property.usage = PROPERTY_USAGE_NOEDITOR;
|
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("set_operation", "operation"), &CSGShape::set_operation);
|
||||||
ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_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("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("is_using_collision"), &CSGShape::is_using_collision);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
|
ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer);
|
||||||
ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
|
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("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents);
|
||||||
ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents);
|
ClassDB::bind_method(D_METHOD("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::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::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_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_UNION);
|
||||||
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
|
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
|
||||||
BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION);
|
BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSGShape::CSGShape() {
|
CSGShape::CSGShape() {
|
||||||
brush = NULL;
|
|
||||||
set_notify_local_transform(true);
|
|
||||||
dirty = false;
|
|
||||||
parent = NULL;
|
|
||||||
use_collision = false;
|
|
||||||
operation = OPERATION_UNION;
|
operation = OPERATION_UNION;
|
||||||
|
parent = NULL;
|
||||||
|
brush = NULL;
|
||||||
|
dirty = false;
|
||||||
snap = 0.001;
|
snap = 0.001;
|
||||||
|
use_collision = false;
|
||||||
|
collision_layer = 1;
|
||||||
|
collision_mask = 1;
|
||||||
calculate_tangents = true;
|
calculate_tangents = true;
|
||||||
|
set_notify_local_transform(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSGShape::~CSGShape() {
|
CSGShape::~CSGShape() {
|
||||||
|
|
|
@ -61,6 +61,8 @@ private:
|
||||||
float snap;
|
float snap;
|
||||||
|
|
||||||
bool use_collision;
|
bool use_collision;
|
||||||
|
uint32_t collision_layer;
|
||||||
|
uint32_t collision_mask;
|
||||||
Ref<ConcavePolygonShape> root_collision_shape;
|
Ref<ConcavePolygonShape> root_collision_shape;
|
||||||
RID root_collision_instance;
|
RID root_collision_instance;
|
||||||
|
|
||||||
|
@ -126,6 +128,18 @@ public:
|
||||||
void set_use_collision(bool p_enable);
|
void set_use_collision(bool p_enable);
|
||||||
bool is_using_collision() const;
|
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);
|
void set_snap(float p_snap);
|
||||||
float get_snap() const;
|
float get_snap() const;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,46 @@
|
||||||
Returns true if this is a root shape and is thus the object that is rendered.
|
Returns true if this is a root shape and is thus the object that is rendered.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</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>
|
</methods>
|
||||||
<members>
|
<members>
|
||||||
<member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents">
|
<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">
|
<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.
|
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>
|
||||||
|
<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>
|
</members>
|
||||||
<constants>
|
<constants>
|
||||||
<constant name="OPERATION_UNION" value="0" enum="Operation">
|
<constant name="OPERATION_UNION" value="0" enum="Operation">
|
||||||
|
|
Loading…
Reference in a new issue