diff options
Diffstat (limited to 'scene/3d/collision_object_3d.cpp')
-rw-r--r-- | scene/3d/collision_object_3d.cpp | 109 |
1 files changed, 101 insertions, 8 deletions
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 39880db29c..688509a979 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -75,9 +75,72 @@ void CollisionObject3D::_notification(int p_what) { } } break; + case NOTIFICATION_PREDELETE: { + if (debug_shape_count > 0) { + _clear_debug_shapes(); + } + } break; + } +} + +void CollisionObject3D::set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + if (area) { + PhysicsServer3D::get_singleton()->area_set_collision_layer(get_rid(), p_layer); + } else { + PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), p_layer); } } +uint32_t CollisionObject3D::get_collision_layer() const { + return collision_layer; +} + +void CollisionObject3D::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; + if (area) { + PhysicsServer3D::get_singleton()->area_set_collision_mask(get_rid(), p_mask); + } else { + PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), p_mask); + } +} + +uint32_t CollisionObject3D::get_collision_mask() const { + return collision_mask; +} + +void CollisionObject3D::set_collision_layer_bit(int p_bit, bool p_value) { + ERR_FAIL_INDEX_MSG(p_bit, 32, "Collision layer bit must be between 0 and 31 inclusive."); + uint32_t collision_layer = get_collision_layer(); + if (p_value) { + collision_layer |= 1 << p_bit; + } else { + collision_layer &= ~(1 << p_bit); + } + set_collision_layer(collision_layer); +} + +bool CollisionObject3D::get_collision_layer_bit(int p_bit) const { + ERR_FAIL_INDEX_V_MSG(p_bit, 32, false, "Collision layer bit must be between 0 and 31 inclusive."); + return get_collision_layer() & (1 << p_bit); +} + +void CollisionObject3D::set_collision_mask_bit(int p_bit, bool p_value) { + ERR_FAIL_INDEX_MSG(p_bit, 32, "Collision mask bit must be between 0 and 31 inclusive."); + uint32_t mask = get_collision_mask(); + if (p_value) { + mask |= 1 << p_bit; + } else { + mask &= ~(1 << p_bit); + } + set_collision_mask(mask); +} + +bool CollisionObject3D::get_collision_mask_bit(int p_bit) const { + ERR_FAIL_INDEX_V_MSG(p_bit, 32, false, "Collision mask bit must be between 0 and 31 inclusive."); + return get_collision_mask() & (1 << p_bit); +} + void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { if (get_script_instance()) { get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); @@ -116,11 +179,13 @@ void CollisionObject3D::_update_debug_shapes() { for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) { if (shapes.has(shapedata_idx->get())) { ShapeData &shapedata = shapes[shapedata_idx->get()]; + ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); for (int i = 0; i < shapedata.shapes.size(); i++) { - ShapeData::ShapeBase &s = shapedata.shapes.write[i]; + ShapeData::ShapeBase &s = shapes[i]; if (s.debug_shape) { s.debug_shape->queue_delete(); s.debug_shape = nullptr; + --debug_shape_count; } if (s.shape.is_null() || shapedata.disabled) { continue; @@ -133,12 +198,30 @@ void CollisionObject3D::_update_debug_shapes() { add_child(mi); mi->force_update_transform(); s.debug_shape = mi; + ++debug_shape_count; } } } debug_shapes_to_update.clear(); } +void CollisionObject3D::_clear_debug_shapes() { + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + ShapeData &shapedata = E->get(); + ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); + for (int i = 0; i < shapedata.shapes.size(); i++) { + ShapeData::ShapeBase &s = shapes[i]; + if (s.debug_shape) { + s.debug_shape->queue_delete(); + s.debug_shape = nullptr; + --debug_shape_count; + } + } + } + + debug_shape_count = 0; +} + void CollisionObject3D::_update_shape_data(uint32_t p_owner) { if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) { if (debug_shapes_to_update.is_empty()) { @@ -158,6 +241,14 @@ bool CollisionObject3D::is_ray_pickable() const { } void CollisionObject3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CollisionObject3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &CollisionObject3D::get_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CollisionObject3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &CollisionObject3D::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CollisionObject3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject3D::get_collision_layer_bit); + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject3D::get_collision_mask_bit); ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable); ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable); ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag); @@ -187,6 +278,11 @@ void CollisionObject3D::_bind_methods() { ADD_SIGNAL(MethodInfo("mouse_entered")); ADD_SIGNAL(MethodInfo("mouse_exited")); + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Input", "input_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); } @@ -395,17 +491,14 @@ bool CollisionObject3D::get_capture_input_on_drag() const { return capture_input_on_drag; } -String CollisionObject3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray<String> CollisionObject3D::get_configuration_warnings() const { + TypedArray<String> warnings = Node::get_configuration_warnings(); if (shapes.is_empty()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape."); + warnings.push_back(TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape.")); } - return warning; + return warnings; } CollisionObject3D::CollisionObject3D() { |