diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-07-15 01:23:10 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-07-15 08:32:34 -0300 |
commit | 2e73be99d8d86d9dad7bcb99518a4d3cbb5c373c (patch) | |
tree | d863db50852afe5d4b0bc15b8452054498004cb1 /scene/3d/collision_object.cpp | |
parent | e64b82ebfcc3475c7a7d2a9196bfe20d6c9e3614 (diff) | |
download | redot-engine-2e73be99d8d86d9dad7bcb99518a4d3cbb5c373c.tar.gz |
Lots of work on Audio & Physics engine:
-Added new 3D stream player node
-Added ability for Area to capture sound from streams
-Added small features in physics to be able to properly guess distance to areas for sound
-Fixed 3D CollisionObject so shapes are added the same as in 2D, directly from children
-Fixed KinematicBody API to make it the same as 2D.
Diffstat (limited to 'scene/3d/collision_object.cpp')
-rw-r--r-- | scene/3d/collision_object.cpp | 287 |
1 files changed, 143 insertions, 144 deletions
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 1b27313d3b..874e5f01ea 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -30,17 +30,6 @@ #include "collision_object.h" #include "scene/scene_string_names.h" #include "servers/physics_server.h" -void CollisionObject::_update_shapes_from_children() { - - shapes.clear(); - for (int i = 0; i < get_child_count(); i++) { - - Node *n = get_child(i); - n->call("_add_to_collision_object", this); - } - - _update_shapes(); -} void CollisionObject::_notification(int p_what) { @@ -87,91 +76,6 @@ void CollisionObject::_notification(int p_what) { } } -void CollisionObject::_update_shapes() { - - if (!rid.is_valid()) - return; - - if (area) - PhysicsServer::get_singleton()->area_clear_shapes(rid); - else - PhysicsServer::get_singleton()->body_clear_shapes(rid); - - for (int i = 0; i < shapes.size(); i++) { - - if (shapes[i].shape.is_null()) - continue; - if (area) - PhysicsServer::get_singleton()->area_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - else { - PhysicsServer::get_singleton()->body_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform); - if (shapes[i].trigger) - PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, i, shapes[i].trigger); - } - } -} - -bool CollisionObject::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; - - if (name == "shape_count") { - - shapes.resize(p_value); - _update_shapes(); - _change_notify(); - - } else if (name.begins_with("shapes/")) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") - set_shape(idx, RefPtr(p_value)); - else if (what == "transform") - set_shape_transform(idx, p_value); - else if (what == "trigger") - set_shape_as_trigger(idx, p_value); - - } else - return false; - - return true; -} - -bool CollisionObject::_get(const StringName &p_name, Variant &r_ret) const { - - String name = p_name; - - if (name == "shape_count") { - r_ret = shapes.size(); - } else if (name.begins_with("shapes/")) { - - int idx = name.get_slicec('/', 1).to_int(); - String what = name.get_slicec('/', 2); - if (what == "shape") - r_ret = get_shape(idx); - else if (what == "transform") - r_ret = get_shape_transform(idx); - else if (what == "trigger") - r_ret = is_shape_set_as_trigger(idx); - - } else - return false; - - return true; -} - -void CollisionObject::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::INT, "shape_count", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - - for (int i = 0; i < shapes.size(); i++) { - String path = "shapes/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::OBJECT, path + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::TRANSFORM, path + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "trigger", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE)); - } -} - void CollisionObject::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { if (get_script_instance()) { @@ -219,17 +123,6 @@ bool CollisionObject::is_ray_pickable() const { void CollisionObject::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shape", "shape:Shape", "transform"), &CollisionObject::add_shape, DEFVAL(Transform())); - ClassDB::bind_method(D_METHOD("get_shape_count"), &CollisionObject::get_shape_count); - ClassDB::bind_method(D_METHOD("set_shape", "shape_idx", "shape:Shape"), &CollisionObject::set_shape); - ClassDB::bind_method(D_METHOD("set_shape_transform", "shape_idx", "transform"), &CollisionObject::set_shape_transform); - // ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform); - ClassDB::bind_method(D_METHOD("set_shape_as_trigger", "shape_idx", "enable"), &CollisionObject::set_shape_as_trigger); - ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger", "shape_idx"), &CollisionObject::is_shape_set_as_trigger); - ClassDB::bind_method(D_METHOD("get_shape:Shape", "shape_idx"), &CollisionObject::get_shape); - ClassDB::bind_method(D_METHOD("get_shape_transform", "shape_idx"), &CollisionObject::get_shape_transform); - ClassDB::bind_method(D_METHOD("remove_shape", "shape_idx"), &CollisionObject::remove_shape); - ClassDB::bind_method(D_METHOD("clear_shapes"), &CollisionObject::clear_shapes); ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject::set_ray_pickable); ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject::is_ray_pickable); ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject::set_capture_input_on_drag); @@ -245,72 +138,176 @@ void CollisionObject::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); } -void CollisionObject::add_shape(const Ref<Shape> &p_shape, const Transform &p_transform) { +uint32_t CollisionObject::create_shape_owner(Object *p_owner) { + + ShapeData sd; + uint32_t id; + + if (shapes.size() == 0) { + id = 1; + } else { + id = shapes.back()->key() + 1; + } + + sd.owner = p_owner; + + shapes[id] = sd; - ShapeData sdata; - sdata.shape = p_shape; - sdata.xform = p_transform; - shapes.push_back(sdata); - _update_shapes(); + return id; } -int CollisionObject::get_shape_count() const { - return shapes.size(); +void CollisionObject::remove_shape_owner(uint32_t owner) { + + ERR_FAIL_COND(!shapes.has(owner)); + + shape_owner_clear_shapes(owner); + + shapes.erase(owner); } -void CollisionObject::set_shape(int p_shape_idx, const Ref<Shape> &p_shape) { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].shape = p_shape; - _update_shapes(); +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]; + 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); + } else { + PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + } } -void CollisionObject::set_shape_transform(int p_shape_idx, const Transform &p_transform) { +bool CollisionObject::is_shape_owner_disabled(uint32_t p_owner) const { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].xform = p_transform; + ERR_FAIL_COND_V(!shapes.has(p_owner), false); - _update_shapes(); + return shapes[p_owner].disabled; } -Ref<Shape> CollisionObject::get_shape(int p_shape_idx) const { +void CollisionObject::get_shape_owners(List<uint32_t> *r_owners) { - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Ref<Shape>()); - return shapes[p_shape_idx].shape; + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + r_owners->push_back(E->key()); + } } -Transform CollisionObject::get_shape_transform(int p_shape_idx) const { - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Transform()); - return shapes[p_shape_idx].xform; +void CollisionObject::shape_owner_set_transform(uint32_t p_owner, const Transform &p_transform) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + ShapeData &sd = shapes[p_owner]; + sd.xform = p_transform; + for (int i = 0; i < sd.shapes.size(); i++) { + if (area) { + PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } else { + PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + } } -void CollisionObject::remove_shape(int p_shape_idx) { +Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes.remove(p_shape_idx); + ERR_FAIL_COND_V(!shapes.has(p_owner), Transform()); - _update_shapes(); + return shapes[p_owner].xform; } -void CollisionObject::clear_shapes() { +Object *CollisionObject::shape_owner_get_owner(uint32_t p_owner) const { - shapes.clear(); + ERR_FAIL_COND_V(!shapes.has(p_owner), NULL); - _update_shapes(); + return shapes[p_owner].owner; } -void CollisionObject::set_shape_as_trigger(int p_shape_idx, bool p_trigger) { +void CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape) { - ERR_FAIL_INDEX(p_shape_idx, shapes.size()); - shapes[p_shape_idx].trigger = p_trigger; - if (!area && rid.is_valid()) { + ERR_FAIL_COND(!shapes.has(p_owner)); + ERR_FAIL_COND(p_shape.is_null()); - PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid, p_shape_idx, p_trigger); + ShapeData &sd = shapes[p_owner]; + ShapeData::ShapeBase s; + s.index = total_subshapes; + s.shape = p_shape; + if (area) { + PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform); + } else { + PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform); } + sd.shapes.push_back(s); + + total_subshapes++; } +int CollisionObject::shape_owner_get_shape_count(uint32_t p_owner) const { -bool CollisionObject::is_shape_set_as_trigger(int p_shape_idx) const { + ERR_FAIL_COND_V(!shapes.has(p_owner), 0); - ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), false); - return shapes[p_shape_idx].trigger; + return shapes[p_owner].shapes.size(); +} +Ref<Shape> CollisionObject::shape_owner_get_shape(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), Ref<Shape>()); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), Ref<Shape>()); + + return shapes[p_owner].shapes[p_shape].shape; +} +int CollisionObject::shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const { + + ERR_FAIL_COND_V(!shapes.has(p_owner), -1); + ERR_FAIL_INDEX_V(p_shape, shapes[p_owner].shapes.size(), -1); + + return shapes[p_owner].shapes[p_shape].index; +} + +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()); + + int index_to_remove = shapes[p_owner].shapes[p_shape].index; + if (area) { + PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); + } else { + PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + } + + shapes[p_owner].shapes.remove(p_shape); + + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index > index_to_remove) { + E->get().shapes[i].index -= 1; + } + } + } + + total_subshapes--; +} + +void CollisionObject::shape_owner_clear_shapes(uint32_t p_owner) { + + ERR_FAIL_COND(!shapes.has(p_owner)); + + while (shape_owner_get_shape_count(p_owner) > 0) { + shape_owner_remove_shape(p_owner, 0); + } +} + +uint32_t CollisionObject::shape_find_owner(int p_shape_index) const { + + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); + + for (const Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + for (int i = 0; i < E->get().shapes.size(); i++) { + if (E->get().shapes[i].index == p_shape_index) { + return E->key(); + } + } + } + + //in theory it should be unreachable + return 0; } CollisionObject::CollisionObject(RID p_rid, bool p_area) { @@ -320,6 +317,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) { capture_input_on_drag = false; ray_pickable = true; set_notify_transform(true); + total_subshapes = 0; + if (p_area) { PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid, get_instance_ID()); } else { |