mirror of
https://github.com/godotengine/godot.git
synced 2025-10-20 00:13:30 +00:00
Create CollisionObject debug shapes using VS
(cherry picked from commit 60ee8c9639
)
This commit is contained in:
parent
5193c3c8eb
commit
140cf0f2cb
5 changed files with 103 additions and 51 deletions
|
@ -38,6 +38,21 @@
|
||||||
void CollisionObject::_notification(int p_what) {
|
void CollisionObject::_notification(int p_what) {
|
||||||
|
|
||||||
switch (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: {
|
case NOTIFICATION_ENTER_WORLD: {
|
||||||
|
|
||||||
|
@ -63,6 +78,8 @@ void CollisionObject::_notification(int p_what) {
|
||||||
else
|
else
|
||||||
PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform());
|
PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform());
|
||||||
|
|
||||||
|
_on_transform_changed();
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||||
|
|
||||||
|
@ -77,11 +94,6 @@ void CollisionObject::_notification(int p_what) {
|
||||||
PhysicsServer::get_singleton()->body_set_space(rid, RID());
|
PhysicsServer::get_singleton()->body_set_space(rid, RID());
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_PREDELETE: {
|
|
||||||
if (debug_shape_count > 0) {
|
|
||||||
_clear_debug_shapes();
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +132,33 @@ void CollisionObject::_update_pickable() {
|
||||||
PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable);
|
PhysicsServer::get_singleton()->body_set_ray_pickable(rid, 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() {
|
void CollisionObject::_update_debug_shapes() {
|
||||||
for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
|
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())) {
|
if (shapes.has(shapedata_idx->get())) {
|
||||||
|
@ -127,24 +166,27 @@ void CollisionObject::_update_debug_shapes() {
|
||||||
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
|
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
|
||||||
for (int i = 0; i < shapedata.shapes.size(); i++) {
|
for (int i = 0; i < shapedata.shapes.size(); i++) {
|
||||||
ShapeData::ShapeBase &s = shapes[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) {
|
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();
|
Ref<Mesh> mesh = s.shape->get_debug_mesh();
|
||||||
MeshInstance *mi = memnew(MeshInstance);
|
VS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid());
|
||||||
mi->set_transform(shapedata.xform);
|
VS::get_singleton()->instance_set_transform(s.debug_shape, get_global_transform() * shapedata.xform);
|
||||||
mi->set_mesh(mesh);
|
|
||||||
add_child(mi);
|
|
||||||
|
|
||||||
mi->force_update_transform();
|
|
||||||
s.debug_shape = mi;
|
|
||||||
++debug_shape_count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,22 +199,29 @@ void CollisionObject::_clear_debug_shapes() {
|
||||||
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
|
ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw();
|
||||||
for (int i = 0; i < shapedata.shapes.size(); i++) {
|
for (int i = 0; i < shapedata.shapes.size(); i++) {
|
||||||
ShapeData::ShapeBase &s = shapes[i];
|
ShapeData::ShapeBase &s = shapes[i];
|
||||||
if (s.debug_shape) {
|
if (s.debug_shape.is_valid()) {
|
||||||
s.debug_shape->queue_delete();
|
VS::get_singleton()->free(s.debug_shape);
|
||||||
s.debug_shape = nullptr;
|
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) {
|
void CollisionObject::_on_transform_changed() {
|
||||||
if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) {
|
if (debug_shapes_count > 0 && !debug_shape_old_transform.is_equal_approx(get_global_transform())) {
|
||||||
if (debug_shapes_to_update.empty()) {
|
debug_shape_old_transform = get_global_transform();
|
||||||
call_deferred("_update_debug_shapes");
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +260,7 @@ void CollisionObject::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner);
|
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("_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")));
|
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")));
|
||||||
|
|
||||||
|
@ -253,7 +303,11 @@ void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled
|
||||||
ERR_FAIL_COND(!shapes.has(p_owner));
|
ERR_FAIL_COND(!shapes.has(p_owner));
|
||||||
|
|
||||||
ShapeData &sd = shapes[p_owner];
|
ShapeData &sd = shapes[p_owner];
|
||||||
|
if (sd.disabled == p_disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
sd.disabled = p_disabled;
|
sd.disabled = p_disabled;
|
||||||
|
|
||||||
for (int i = 0; i < sd.shapes.size(); i++) {
|
for (int i = 0; i < sd.shapes.size(); i++) {
|
||||||
if (area) {
|
if (area) {
|
||||||
PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
|
PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
|
||||||
|
@ -365,7 +419,7 @@ void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
|
||||||
ERR_FAIL_COND(!shapes.has(p_owner));
|
ERR_FAIL_COND(!shapes.has(p_owner));
|
||||||
ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size());
|
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;
|
int index_to_remove = s.index;
|
||||||
|
|
||||||
if (area) {
|
if (area) {
|
||||||
|
@ -374,9 +428,12 @@ void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) {
|
||||||
PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove);
|
PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.debug_shape) {
|
if (s.debug_shape.is_valid()) {
|
||||||
s.debug_shape->queue_delete();
|
VS::get_singleton()->free(s.debug_shape);
|
||||||
--debug_shape_count;
|
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);
|
shapes[p_owner].shapes.remove(p_shape);
|
||||||
|
|
|
@ -47,7 +47,7 @@ class CollisionObject : public Spatial {
|
||||||
Object *owner;
|
Object *owner;
|
||||||
Transform xform;
|
Transform xform;
|
||||||
struct ShapeBase {
|
struct ShapeBase {
|
||||||
Node *debug_shape = nullptr;
|
RID debug_shape;
|
||||||
Ref<Shape> shape;
|
Ref<Shape> shape;
|
||||||
int index;
|
int index;
|
||||||
};
|
};
|
||||||
|
@ -69,11 +69,16 @@ class CollisionObject : public Spatial {
|
||||||
bool ray_pickable;
|
bool ray_pickable;
|
||||||
|
|
||||||
Set<uint32_t> debug_shapes_to_update;
|
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();
|
void _update_pickable();
|
||||||
|
|
||||||
|
bool _are_collision_shapes_visible();
|
||||||
void _update_shape_data(uint32_t p_owner);
|
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:
|
protected:
|
||||||
CollisionObject(RID p_rid, bool p_area);
|
CollisionObject(RID p_rid, bool p_area);
|
||||||
|
@ -85,8 +90,7 @@ protected:
|
||||||
virtual void _mouse_enter();
|
virtual void _mouse_enter();
|
||||||
virtual void _mouse_exit();
|
virtual void _mouse_exit();
|
||||||
|
|
||||||
void _update_debug_shapes();
|
void _on_transform_changed();
|
||||||
void _clear_debug_shapes();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t create_shape_owner(Object *p_owner);
|
uint32_t create_shape_owner(Object *p_owner);
|
||||||
|
|
|
@ -158,8 +158,6 @@ void CollisionShape::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
|
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::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::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
|
||||||
}
|
}
|
||||||
|
@ -170,12 +168,10 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
|
||||||
}
|
}
|
||||||
if (!shape.is_null()) {
|
if (!shape.is_null()) {
|
||||||
shape->unregister_owner(this);
|
shape->unregister_owner(this);
|
||||||
shape->disconnect("changed", this, "_shape_changed");
|
|
||||||
}
|
}
|
||||||
shape = p_shape;
|
shape = p_shape;
|
||||||
if (!shape.is_null()) {
|
if (!shape.is_null()) {
|
||||||
shape->register_owner(this);
|
shape->register_owner(this);
|
||||||
shape->connect("changed", this, "_shape_changed");
|
|
||||||
}
|
}
|
||||||
update_gizmo();
|
update_gizmo();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
@ -185,8 +181,10 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_inside_tree())
|
if (is_inside_tree() && parent) {
|
||||||
_shape_changed();
|
// If this is a heightfield shape our center may have changed
|
||||||
|
_update_in_shape_owner(true);
|
||||||
|
}
|
||||||
update_configuration_warning();
|
update_configuration_warning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,10 +221,3 @@ CollisionShape::~CollisionShape() {
|
||||||
shape->unregister_owner(this);
|
shape->unregister_owner(this);
|
||||||
//VisualServer::get_singleton()->free(indicator);
|
//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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,8 +48,6 @@ class CollisionShape : public Spatial {
|
||||||
bool disabled;
|
bool disabled;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _shape_changed();
|
|
||||||
|
|
||||||
void _update_in_shape_owner(bool p_xform_only = false);
|
void _update_in_shape_owner(bool p_xform_only = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -457,6 +457,7 @@ void RigidBody::_direct_state_changed(Object *p_state) {
|
||||||
if (get_script_instance())
|
if (get_script_instance())
|
||||||
get_script_instance()->call("_integrate_forces", state);
|
get_script_instance()->call("_integrate_forces", state);
|
||||||
set_ignore_transform_notification(false);
|
set_ignore_transform_notification(false);
|
||||||
|
_on_transform_changed();
|
||||||
|
|
||||||
if (contact_monitor) {
|
if (contact_monitor) {
|
||||||
|
|
||||||
|
@ -2224,6 +2225,7 @@ void PhysicalBone::_direct_state_changed(Object *p_state) {
|
||||||
set_ignore_transform_notification(true);
|
set_ignore_transform_notification(true);
|
||||||
set_global_transform(global_transform);
|
set_global_transform(global_transform);
|
||||||
set_ignore_transform_notification(false);
|
set_ignore_transform_notification(false);
|
||||||
|
_on_transform_changed();
|
||||||
|
|
||||||
// Update skeleton
|
// Update skeleton
|
||||||
if (parent_skeleton) {
|
if (parent_skeleton) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue