Skip to content

Commit

Permalink
Allow CollisionShape2D nodes to be indirect children of bodies
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronfranke committed Jun 7, 2023
1 parent 3e32da2 commit e635433
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 25 deletions.
72 changes: 48 additions & 24 deletions scene/2d/collision_shape_2d.cpp
Expand Up @@ -39,14 +39,37 @@ void CollisionShape2D::_shape_changed() {
queue_redraw();
}

CollisionObject2D *CollisionShape2D::_get_ancestor_collision_object() const {
Node *parent = get_parent();
while (parent) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(parent);
if (co) {
return co;
}
parent = parent->get_parent();
}
return nullptr;
}

Transform2D CollisionShape2D::_get_transform_to_collision_object() const {
Transform2D transform = get_transform();

Check failure on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

declaration of 'transform' shadows a member of 'CollisionShape2D' [-Werror=shadow]

Check failure on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

declaration of 'transform' shadows a member of 'CollisionShape2D' [-Werror=shadow]

Check failure on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Template w/ Mono (target=template_release)

declaration of 'transform' shadows a member of 'CollisionShape2D' [-Werror=shadow]

Check failure on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Minimal template (target=template_release, everything disabled)

declaration of 'transform' shadows a member of 'CollisionShape2D' [-Werror=shadow]

Check failure on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release)

the following warning is treated as an error

Check warning on line 55 in scene/2d/collision_shape_2d.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release)

declaration of 'transform' hides class member
Node *parent = get_parent();
while (parent != collision_object) {
CanvasItem *parent_2d = Object::cast_to<CanvasItem>(parent);
transform = parent_2d->get_transform() * transform;
parent = parent->get_parent();
}
return transform;
}

void CollisionShape2D::_update_in_shape_owner(bool p_xform_only) {
parent->shape_owner_set_transform(owner_id, get_transform());
collision_object->shape_owner_set_transform(owner_id, get_transform());
if (p_xform_only) {
return;
}
parent->shape_owner_set_disabled(owner_id, disabled);
parent->shape_owner_set_one_way_collision(owner_id, one_way_collision);
parent->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin);
collision_object->shape_owner_set_disabled(owner_id, disabled);
collision_object->shape_owner_set_one_way_collision(owner_id, one_way_collision);
collision_object->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin);
}

Color CollisionShape2D::_get_default_debug_color() const {
Expand All @@ -57,34 +80,34 @@ Color CollisionShape2D::_get_default_debug_color() const {
void CollisionShape2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PARENTED: {
parent = Object::cast_to<CollisionObject2D>(get_parent());
if (parent) {
owner_id = parent->create_shape_owner(this);
collision_object = _get_ancestor_collision_object();
if (collision_object) {
owner_id = collision_object->create_shape_owner(this);
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
collision_object->shape_owner_add_shape(owner_id, shape);
}
_update_in_shape_owner();
}
} break;

case NOTIFICATION_ENTER_TREE: {
if (parent) {
if (collision_object) {
_update_in_shape_owner();
}
} break;

case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (parent) {
if (collision_object) {
_update_in_shape_owner(true);
}
} break;

case NOTIFICATION_UNPARENTED: {
if (parent) {
parent->remove_shape_owner(owner_id);
if (collision_object) {
collision_object->remove_shape_owner(owner_id);
}
owner_id = 0;
parent = nullptr;
collision_object = nullptr;
} break;

case NOTIFICATION_DRAW: {
Expand Down Expand Up @@ -146,10 +169,10 @@ void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) {
}
shape = p_shape;
queue_redraw();
if (parent) {
parent->shape_owner_clear_shapes(owner_id);
if (collision_object) {
collision_object->shape_owner_clear_shapes(owner_id);
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
collision_object->shape_owner_add_shape(owner_id, shape);
}
_update_in_shape_owner();
}
Expand All @@ -176,13 +199,14 @@ bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double
PackedStringArray CollisionShape2D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();

if (!Object::cast_to<CollisionObject2D>(get_parent())) {
CollisionObject2D *col_object = _get_ancestor_collision_object();
if (col_object == nullptr) {
warnings.push_back(RTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape."));
}
if (!shape.is_valid()) {
warnings.push_back(RTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"));
}
if (one_way_collision && Object::cast_to<Area2D>(get_parent())) {
if (one_way_collision && Object::cast_to<Area2D>(col_object)) {
warnings.push_back(RTR("The One Way Collision property will be ignored when the parent is an Area2D."));
}

Expand All @@ -198,8 +222,8 @@ PackedStringArray CollisionShape2D::get_configuration_warnings() const {
void CollisionShape2D::set_disabled(bool p_disabled) {
disabled = p_disabled;
queue_redraw();
if (parent) {
parent->shape_owner_set_disabled(owner_id, p_disabled);
if (collision_object) {
collision_object->shape_owner_set_disabled(owner_id, p_disabled);
}
}

Expand All @@ -210,8 +234,8 @@ bool CollisionShape2D::is_disabled() const {
void CollisionShape2D::set_one_way_collision(bool p_enable) {
one_way_collision = p_enable;
queue_redraw();
if (parent) {
parent->shape_owner_set_one_way_collision(owner_id, p_enable);
if (collision_object) {
collision_object->shape_owner_set_one_way_collision(owner_id, p_enable);
}
update_configuration_warnings();
}
Expand All @@ -222,8 +246,8 @@ bool CollisionShape2D::is_one_way_collision_enabled() const {

void CollisionShape2D::set_one_way_collision_margin(real_t p_margin) {
one_way_collision_margin = p_margin;
if (parent) {
parent->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin);
if (collision_object) {
collision_object->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin);
}
}

Expand Down
4 changes: 3 additions & 1 deletion scene/2d/collision_shape_2d.h
Expand Up @@ -41,12 +41,14 @@ class CollisionShape2D : public Node2D {
Ref<Shape2D> shape;
Rect2 rect = Rect2(-Point2(10, 10), Point2(20, 20));
uint32_t owner_id = 0;
CollisionObject2D *parent = nullptr;
CollisionObject2D *collision_object = nullptr;
bool disabled = false;
bool one_way_collision = false;
real_t one_way_collision_margin = 1.0;
Color debug_color;

CollisionObject2D *_get_ancestor_collision_object() const;
Transform2D _get_transform_to_collision_object() const;
void _shape_changed();
void _update_in_shape_owner(bool p_xform_only = false);
Color _get_default_debug_color() const;
Expand Down

0 comments on commit e635433

Please sign in to comment.