Skip to content

Commit

Permalink
Create CollisionObject debug shapes using VS
Browse files Browse the repository at this point in the history
  • Loading branch information
trollodel committed May 9, 2021
1 parent c03c6ae commit 60ee8c9
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 51 deletions.
122 changes: 90 additions & 32 deletions scene/3d/collision_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@

void CollisionObject::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (_are_collision_shapes_visible()) {
debug_shape_old_transform = get_global_transform();
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
debug_shapes_to_update.insert(E->key());
}
_update_debug_shapes();
}
} break;

case NOTIFICATION_EXIT_TREE: {
if (debug_shapes_count > 0) {
_clear_debug_shapes();
}
} break;

case NOTIFICATION_ENTER_WORLD: {
if (area) {
PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform());
Expand All @@ -62,6 +78,8 @@ void CollisionObject::_notification(int p_what) {
PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform());
}

_on_transform_changed();

} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
Expand All @@ -75,11 +93,6 @@ void CollisionObject::_notification(int p_what) {
}

} break;
case NOTIFICATION_PREDELETE: {
if (debug_shape_count > 0) {
_clear_debug_shapes();
}
} break;
}
}

Expand Down Expand Up @@ -171,31 +184,61 @@ void CollisionObject::_update_pickable() {
}
}

bool CollisionObject::_are_collision_shapes_visible() {
return is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint();
}

void CollisionObject::_update_shape_data(uint32_t p_owner) {
if (_are_collision_shapes_visible()) {
if (debug_shapes_to_update.empty()) {
call_deferred("_update_debug_shapes");
}
debug_shapes_to_update.insert(p_owner);
}
}

void CollisionObject::_shape_changed(const Ref<Shape> &p_shape) {
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.shape == p_shape && s.debug_shape.is_valid()) {
Ref<Mesh> mesh = s.shape->get_debug_mesh();
VS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
}
}
}
}

void CollisionObject::_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 = 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;
if (s.debug_shape.is_valid()) {
VS::get_singleton()->free(s.debug_shape);
s.debug_shape = RID();
--debug_shapes_count;
}
}
if (!s.debug_shape.is_valid()) {
s.debug_shape = VS::get_singleton()->instance_create();
VS::get_singleton()->instance_set_scenario(s.debug_shape, get_world()->get_scenario());

if (!s.shape->is_connected("changed", this, "_shape_changed")) {
s.shape->connect("changed", this, "_shape_changed", varray(s.shape), CONNECT_DEFERRED);
}

++debug_shapes_count;
}

Ref<Mesh> mesh = s.shape->get_debug_mesh();
MeshInstance *mi = memnew(MeshInstance);
mi->set_transform(shapedata.xform);
mi->set_mesh(mesh);
add_child(mi);

mi->force_update_transform();
s.debug_shape = mi;
++debug_shape_count;
VS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
VS::get_singleton()->instance_set_transform(s.debug_shape, get_global_transform() * shapedata.xform);
}
}
}
Expand All @@ -208,22 +251,29 @@ void CollisionObject::_clear_debug_shapes() {
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;
if (s.debug_shape.is_valid()) {
VS::get_singleton()->free(s.debug_shape);
s.debug_shape = RID();
if (s.shape.is_valid() && s.shape->is_connected("changed", this, "_shape_changed")) {
s.shape->disconnect("changed", this, "_shape_changed");
}
}
}
}

debug_shape_count = 0;
debug_shapes_count = 0;
}

void CollisionObject::_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.empty()) {
call_deferred("_update_debug_shapes");
void CollisionObject::_on_transform_changed() {
if (debug_shapes_count > 0 && !debug_shape_old_transform.is_equal_approx(get_global_transform())) {
debug_shape_old_transform = get_global_transform();
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
ShapeData &shapedata = E->get();
const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr();
for (int i = 0; i < shapedata.shapes.size(); i++) {
VS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform);
}
}
debug_shapes_to_update.insert(p_owner);
}
}

Expand Down Expand Up @@ -267,6 +317,7 @@ void CollisionObject::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner);

ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject::_update_debug_shapes);
ClassDB::bind_method(D_METHOD("_shape_changed", "shape"), &CollisionObject::_shape_changed);

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")));

Expand Down Expand Up @@ -312,7 +363,11 @@ void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled
ERR_FAIL_COND(!shapes.has(p_owner));

ShapeData &sd = shapes[p_owner];
if (sd.disabled == p_disabled) {
return;
}
sd.disabled = p_disabled;

for (int i = 0; i < sd.shapes.size(); i++) {
if (area) {
PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
Expand Down Expand Up @@ -413,7 +468,7 @@ void CollisionObject::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());

const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape];
ShapeData::ShapeBase &s = shapes[p_owner].shapes.write[p_shape];
int index_to_remove = s.index;

if (area) {
Expand All @@ -422,9 +477,12 @@ void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove);
}

if (s.debug_shape) {
s.debug_shape->queue_delete();
--debug_shape_count;
if (s.debug_shape.is_valid()) {
VS::get_singleton()->free(s.debug_shape);
if (s.shape.is_valid() && s.shape->is_connected("changed", this, "_shape_changed")) {
s.shape->disconnect("changed", this, "_shape_changed");
}
--debug_shapes_count;
}

shapes[p_owner].shapes.remove(p_shape);
Expand Down
12 changes: 8 additions & 4 deletions scene/3d/collision_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class CollisionObject : public Spatial {
Object *owner;
Transform xform;
struct ShapeBase {
Node *debug_shape = nullptr;
RID debug_shape;
Ref<Shape> shape;
int index;
};
Expand All @@ -70,11 +70,16 @@ class CollisionObject : public Spatial {
bool ray_pickable;

Set<uint32_t> debug_shapes_to_update;
int debug_shape_count = 0;
int debug_shapes_count = 0;
Transform debug_shape_old_transform;

void _update_pickable();

bool _are_collision_shapes_visible();
void _update_shape_data(uint32_t p_owner);
void _shape_changed(const Ref<Shape> &p_shape);
void _update_debug_shapes();
void _clear_debug_shapes();

protected:
CollisionObject(RID p_rid, bool p_area);
Expand All @@ -86,8 +91,7 @@ class CollisionObject : public Spatial {
virtual void _mouse_enter();
virtual void _mouse_exit();

void _update_debug_shapes();
void _clear_debug_shapes();
void _on_transform_changed();

public:
void set_collision_layer(uint32_t p_layer);
Expand Down
16 changes: 3 additions & 13 deletions scene/3d/collision_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ void CollisionShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);

ClassDB::bind_method(D_METHOD("_shape_changed"), &CollisionShape::_shape_changed);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
}
Expand All @@ -163,12 +161,10 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
}
if (!shape.is_null()) {
shape->unregister_owner(this);
shape->disconnect("changed", this, "_shape_changed");
}
shape = p_shape;
if (!shape.is_null()) {
shape->register_owner(this);
shape->connect("changed", this, "_shape_changed");
}
update_gizmo();
if (parent) {
Expand All @@ -178,8 +174,9 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
}
}

if (is_inside_tree()) {
_shape_changed();
if (is_inside_tree() && parent) {
// If this is a heightfield shape our center may have changed
_update_in_shape_owner(true);
}
update_configuration_warning();
}
Expand Down Expand Up @@ -214,10 +211,3 @@ CollisionShape::~CollisionShape() {
}
//VisualServer::get_singleton()->free(indicator);
}

void CollisionShape::_shape_changed() {
// If this is a heightfield shape our center may have changed
if (parent) {
_update_in_shape_owner(true);
}
}
2 changes: 0 additions & 2 deletions scene/3d/collision_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ class CollisionShape : public Spatial {
bool disabled;

protected:
void _shape_changed();

void _update_in_shape_owner(bool p_xform_only = false);

protected:
Expand Down
2 changes: 2 additions & 0 deletions scene/3d/physics_body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ void RigidBody::_direct_state_changed(Object *p_state) {
get_script_instance()->call("_integrate_forces", state);
}
set_ignore_transform_notification(false);
_on_transform_changed();

if (contact_monitor) {
contact_monitor->locked = true;
Expand Down Expand Up @@ -2101,6 +2102,7 @@ void PhysicalBone::_direct_state_changed(Object *p_state) {
set_ignore_transform_notification(true);
set_global_transform(global_transform);
set_ignore_transform_notification(false);
_on_transform_changed();

// Update skeleton
if (parent_skeleton) {
Expand Down

0 comments on commit 60ee8c9

Please sign in to comment.