summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuri Sizov <yuris@humnom.net>2023-12-18 18:17:26 +0100
committerYuri Sizov <yuris@humnom.net>2023-12-18 18:17:26 +0100
commit612791ef8b93e3b14307066ddfdc5c8df0d0c5c7 (patch)
tree0bb0c4ffa48695b2c6bfc3ba8b219d2a6d4afc1a
parentee9ff6a52ce9f398682d7e7d64c2e9cd7e2ebc4d (diff)
parent0081a50e327612c53b93b2848d05a107da19c9b5 (diff)
downloadredot-engine-612791ef8b93e3b14307066ddfdc5c8df0d0c5c7.tar.gz
Merge pull request #79460 from AThousandShips/area_object
Prevent mapping areas with invalid IDs for `Area2D/3D`
-rw-r--r--doc/classes/Area2D.xml1
-rw-r--r--doc/classes/Area3D.xml1
-rw-r--r--scene/2d/area_2d.cpp30
-rw-r--r--scene/3d/area_3d.cpp34
4 files changed, 64 insertions, 2 deletions
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index 6fa8e4ae9f..98110748ef 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -6,6 +6,7 @@
<description>
[Area2D] is a region of 2D space defined by one or multiple [CollisionShape2D] or [CollisionPolygon2D] child nodes. It detects when other [CollisionObject2D]s enter or exit it, and it also keeps track of which collision objects haven't exited it yet (i.e. which one are overlapping it).
This node can also locally alter or override physics parameters (gravity, damping) and route audio to custom audio buses.
+ [b]Note:[/b] Areas and bodies created with [PhysicsServer2D] might not interact as expected with [Area2D]s, and might not emit signals or track objects correctly.
</description>
<tutorials>
<link title="Using Area2D">$DOCS_URL/tutorials/physics/using_area_2d.html</link>
diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml
index 4f89e9b015..918869b83d 100644
--- a/doc/classes/Area3D.xml
+++ b/doc/classes/Area3D.xml
@@ -6,6 +6,7 @@
<description>
[Area3D] is a region of 3D space defined by one or multiple [CollisionShape3D] or [CollisionPolygon3D] child nodes. It detects when other [CollisionObject3D]s enter or exit it, and it also keeps track of which collision objects haven't exited it yet (i.e. which one are overlapping it).
This node can also locally alter or override physics parameters (gravity, damping) and route audio to custom audio buses.
+ [b]Note:[/b] Areas and bodies created with [PhysicsServer3D] might not interact as expected with [Area3D]s, and might not emit signals or track objects correctly.
[b]Warning:[/b] Using a [ConcavePolygonShape3D] inside a [CollisionShape3D] child of this node (created e.g. by using the [b]Create Trimesh Collision Sibling[/b] option in the [b]Mesh[/b] menu that appears when selecting a [MeshInstance3D] node) may give unexpected results, since this collision shape is hollow. If this is not desired, it has to be split into multiple [ConvexPolygonShape3D]s or primitive shapes like [BoxShape3D], or in some cases it may be replaceable by a [CollisionPolygon3D].
</description>
<tutorials>
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 2c4bf08f34..b1ff94dda4 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -166,6 +166,21 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
bool body_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
+ // Exit early if instance is invalid.
+ if (objid.is_null()) {
+ // Emit the appropriate signals.
+ lock_callback();
+ locked = true;
+ if (body_in) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ } else {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ }
+ locked = false;
+ unlock_callback();
+ return;
+ }
+
Object *obj = ObjectDB::get_instance(objid);
Node *node = Object::cast_to<Node>(obj);
@@ -262,6 +277,21 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
bool area_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
+ // Exit early if instance is invalid.
+ if (objid.is_null()) {
+ // Emit the appropriate signals.
+ lock_callback();
+ locked = true;
+ if (area_in) {
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ } else {
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ }
+ locked = false;
+ unlock_callback();
+ return;
+ }
+
Object *obj = ObjectDB::get_instance(objid);
Node *node = Object::cast_to<Node>(obj);
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index 585bce09fb..014c33cad0 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -223,6 +223,21 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
bool body_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
+ // Exit early if instance is invalid.
+ if (objid.is_null()) {
+ lock_callback();
+ locked = true;
+ // Emit the appropriate signals.
+ if (body_in) {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ } else {
+ emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ }
+ locked = false;
+ unlock_callback();
+ return;
+ }
+
Object *obj = ObjectDB::get_instance(objid);
Node *node = Object::cast_to<Node>(obj);
@@ -254,7 +269,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
E->value.shapes.insert(ShapePair(p_body_shape, p_area_shape));
}
- if (E->value.in_tree) {
+ if (!node || E->value.in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
}
@@ -276,7 +291,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
}
}
- if (node && in_tree) {
+ if (!node || in_tree) {
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
}
}
@@ -414,6 +429,21 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
bool area_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
ObjectID objid = p_instance;
+ // Exit if instance is invalid.
+ if (objid.is_null()) {
+ lock_callback();
+ locked = true;
+ // Emit the appropriate signals.
+ if (area_in) {
+ emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ } else {
+ emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ }
+ locked = false;
+ unlock_callback();
+ return;
+ }
+
Object *obj = ObjectDB::get_instance(objid);
Node *node = Object::cast_to<Node>(obj);