|
@@ -30,6 +30,7 @@
|
|
|
|
|
|
#include "collision_object_3d.h"
|
|
|
|
|
|
+#include "mesh_instance_3d.h"
|
|
|
#include "scene/scene_string_names.h"
|
|
|
#include "servers/physics_server_3d.h"
|
|
|
|
|
@@ -110,6 +111,42 @@ void CollisionObject3D::_update_pickable() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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()];
|
|
|
+ for (int i = 0; i < shapedata.shapes.size(); i++) {
|
|
|
+ ShapeData::ShapeBase &s = shapedata.shapes.write[i];
|
|
|
+ if (s.debug_shape) {
|
|
|
+ s.debug_shape->queue_delete();
|
|
|
+ s.debug_shape = nullptr;
|
|
|
+ }
|
|
|
+ if (s.shape.is_null() || shapedata.disabled) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Ref<Mesh> mesh = s.shape->get_debug_mesh();
|
|
|
+ MeshInstance3D *mi = memnew(MeshInstance3D);
|
|
|
+ mi->set_transform(shapedata.xform);
|
|
|
+ mi->set_mesh(mesh);
|
|
|
+ add_child(mi);
|
|
|
+ mi->force_update_transform();
|
|
|
+ s.debug_shape = mi;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ debug_shapes_to_update.clear();
|
|
|
+}
|
|
|
+
|
|
|
+void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
|
|
|
+ if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
|
|
|
+ if (debug_shapes_to_update.is_empty()) {
|
|
|
+ call_deferred("_update_debug_shapes");
|
|
|
+ }
|
|
|
+ debug_shapes_to_update.insert(p_owner);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) {
|
|
|
ray_pickable = p_ray_pickable;
|
|
|
_update_pickable();
|
|
@@ -141,6 +178,8 @@ void CollisionObject3D::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes);
|
|
|
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner);
|
|
|
|
|
|
+ ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes);
|
|
|
+
|
|
|
BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
|
|
|
|
|
|
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
|
|
@@ -188,6 +227,7 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl
|
|
|
PhysicsServer3D::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
|
|
|
}
|
|
|
}
|
|
|
+ _update_shape_data(p_owner);
|
|
|
}
|
|
|
|
|
|
bool CollisionObject3D::is_shape_owner_disabled(uint32_t p_owner) const {
|
|
@@ -223,6 +263,8 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf
|
|
|
PhysicsServer3D::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ _update_shape_data(p_owner);
|
|
|
}
|
|
|
|
|
|
Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const {
|
|
@@ -245,6 +287,7 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
|
|
|
ShapeData::ShapeBase s;
|
|
|
s.index = total_subshapes;
|
|
|
s.shape = p_shape;
|
|
|
+
|
|
|
if (area) {
|
|
|
PhysicsServer3D::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled);
|
|
|
} else {
|
|
@@ -253,6 +296,8 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
|
|
|
sd.shapes.push_back(s);
|
|
|
|
|
|
total_subshapes++;
|
|
|
+
|
|
|
+ _update_shape_data(p_owner);
|
|
|
}
|
|
|
|
|
|
int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
|
|
@@ -279,13 +324,19 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape)
|
|
|
ERR_FAIL_COND(!shapes.has(p_owner));
|
|
|
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
|
|
|
|
|
|
- int index_to_remove = shapes[p_owner].shapes[p_shape].index;
|
|
|
+ const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
|
|
|
+ int index_to_remove = s.index;
|
|
|
+
|
|
|
if (area) {
|
|
|
PhysicsServer3D::get_singleton()->area_remove_shape(rid, index_to_remove);
|
|
|
} else {
|
|
|
PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove);
|
|
|
}
|
|
|
|
|
|
+ if (s.debug_shape) {
|
|
|
+ s.debug_shape->queue_delete();
|
|
|
+ }
|
|
|
+
|
|
|
shapes[p_owner].shapes.remove(p_shape);
|
|
|
|
|
|
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
|