-Trigger shapes removed in 2D, they became obsolete long ago when areas could detect their own overlap

-Added ability to disable individual collisionshape/polygon
-Moved One Way Collision to shape, allowing more flexibility
-Changed internals of CollisionObject, shapes are generated from child nodes on the fly, not stored inside any longer.
-Modifying a CollisionPolygon2D on the fly now works, it can even be animated.

Will port this to 3D once well tested. Have fun!
This commit is contained in:
Juan Linietsky 2017-06-23 23:30:43 -03:00
parent 683f50bef4
commit 6ba1e4677b
21 changed files with 512 additions and 649 deletions

View File

@ -105,13 +105,16 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
if (!child2->cast_to<StaticBody2D>())
continue;
StaticBody2D *sb = child2->cast_to<StaticBody2D>();
int shape_count = sb->get_shape_count();
if (shape_count == 0)
continue;
for (int shape_index = 0; shape_index < shape_count; ++shape_index) {
Ref<Shape2D> collision = sb->get_shape(shape_index);
if (collision.is_valid()) {
collisions.push_back(collision);
List<uint32_t> shapes;
sb->get_shape_owners(&shapes);
for (List<uint32_t>::Element *E = shapes.front(); E; E = E->next()) {
for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
Ref<Shape> shape = sb->shape_owner_get_shape(E->get(), k);
collisions.push_back(shape); //uh what about transform?
}
}
}

View File

@ -31,18 +31,6 @@
#include "scene/scene_string_names.h"
#include "servers/physics_2d_server.h"
void CollisionObject2D::_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 CollisionObject2D::_notification(int p_what) {
switch (p_what) {
@ -88,84 +76,199 @@ void CollisionObject2D::_notification(int p_what) {
}
}
void CollisionObject2D::_update_shapes() {
uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) {
if (!rid.is_valid())
return;
ShapeData sd;
uint32_t id;
if (area)
Physics2DServer::get_singleton()->area_clear_shapes(rid);
else
Physics2DServer::get_singleton()->body_clear_shapes(rid);
if (shapes.size() == 0) {
id = 1;
} else {
id = shapes.back()->key() + 1;
}
for (int i = 0; i < shapes.size(); i++) {
sd.owner = p_owner;
if (shapes[i].shape.is_null())
continue;
if (area)
Physics2DServer::get_singleton()->area_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform);
else {
Physics2DServer::get_singleton()->body_add_shape(rid, shapes[i].shape->get_rid(), shapes[i].xform);
if (shapes[i].trigger)
Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid, i, shapes[i].trigger);
shapes[id] = sd;
return id;
}
void CollisionObject2D::remove_shape_owner(uint32_t owner) {
ERR_FAIL_COND(!shapes.has(owner));
shape_owner_clear_shapes(owner);
shapes.erase(owner);
}
void CollisionObject2D::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) {
Physics2DServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
} else {
Physics2DServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled);
}
}
}
bool CollisionObject2D::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
bool CollisionObject2D::is_shape_owner_disabled(uint32_t p_owner) const {
if (name.begins_with("shapes/")) {
ERR_FAIL_COND_V(!shapes.has(p_owner), false);
int idx = name.get_slicec('/', 1).to_int();
String what = name.get_slicec('/', 2);
if (what == "shape") {
if (idx >= shapes.size())
add_shape(RefPtr(p_value));
else
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;
return shapes[p_owner].disabled;
}
bool CollisionObject2D::_get(const StringName &p_name, Variant &r_ret) const {
void CollisionObject2D::shape_owner_set_one_way_collision(uint32_t p_owner, bool p_enable) {
String name = p_name;
if (area)
return; //not for areas
if (name.begins_with("shapes/")) {
ERR_FAIL_COND(!shapes.has(p_owner));
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 CollisionObject2D::_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, "Shape2D", 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));
ShapeData &sd = shapes[p_owner];
sd.one_way_collision = p_enable;
for (int i = 0; i < sd.shapes.size(); i++) {
Physics2DServer::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, p_enable);
}
}
bool CollisionObject2D::is_shape_owner_one_way_collision_enabled(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), false);
return shapes[p_owner].one_way_collision;
}
void CollisionObject2D::get_shape_owners(List<uint32_t> *r_owners) {
for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) {
r_owners->push_back(E->key());
}
}
void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transform2D &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) {
Physics2DServer::get_singleton()->area_set_shape_transform(rid, i, p_transform);
} else {
Physics2DServer::get_singleton()->body_set_shape_transform(rid, i, p_transform);
}
}
}
Transform2D CollisionObject2D::shape_owner_get_transform(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), Transform2D());
return shapes[p_owner].xform;
}
Object *CollisionObject2D::shape_owner_get_owner(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), NULL);
return shapes[p_owner].owner;
}
void CollisionObject2D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape) {
ERR_FAIL_COND(!shapes.has(p_owner));
ERR_FAIL_COND(p_shape.is_null());
ShapeData &sd = shapes[p_owner];
ShapeData::Shape s;
s.index = total_subshapes;
s.shape = p_shape;
if (area) {
Physics2DServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform);
} else {
Physics2DServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform);
}
sd.shapes.push_back(s);
total_subshapes++;
}
int CollisionObject2D::shape_owner_get_shape_count(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), 0);
return shapes[p_owner].shapes.size();
}
Ref<Shape> CollisionObject2D::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 CollisionObject2D::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 CollisionObject2D::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) {
Physics2DServer::get_singleton()->area_remove_shape(rid, index_to_remove);
} else {
Physics2DServer::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 CollisionObject2D::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 CollisionObject2D::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;
}
void CollisionObject2D::set_pickable(bool p_enabled) {
if (pickable == p_enabled)
@ -216,16 +319,6 @@ void CollisionObject2D::_update_pickable() {
void CollisionObject2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_shape", "shape:Shape2D", "transform"), &CollisionObject2D::add_shape, DEFVAL(Transform2D()));
ClassDB::bind_method(D_METHOD("get_shape_count"), &CollisionObject2D::get_shape_count);
ClassDB::bind_method(D_METHOD("set_shape", "shape_idx", "shape:Shape"), &CollisionObject2D::set_shape);
ClassDB::bind_method(D_METHOD("set_shape_transform", "shape_idx", "transform"), &CollisionObject2D::set_shape_transform);
ClassDB::bind_method(D_METHOD("set_shape_as_trigger", "shape_idx", "enable"), &CollisionObject2D::set_shape_as_trigger);
ClassDB::bind_method(D_METHOD("get_shape:Shape2D", "shape_idx"), &CollisionObject2D::get_shape);
ClassDB::bind_method(D_METHOD("get_shape_transform", "shape_idx"), &CollisionObject2D::get_shape_transform);
ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger", "shape_idx"), &CollisionObject2D::is_shape_set_as_trigger);
ClassDB::bind_method(D_METHOD("remove_shape", "shape_idx"), &CollisionObject2D::remove_shape);
ClassDB::bind_method(D_METHOD("clear_shapes"), &CollisionObject2D::clear_shapes);
ClassDB::bind_method(D_METHOD("get_rid"), &CollisionObject2D::get_rid);
ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable);
@ -242,100 +335,13 @@ void CollisionObject2D::_bind_methods() {
ADD_GROUP("", "");
}
void CollisionObject2D::add_shape(const Ref<Shape2D> &p_shape, const Transform2D &p_transform) {
ERR_FAIL_COND(p_shape.is_null());
ShapeData sdata;
sdata.shape = p_shape;
sdata.xform = p_transform;
sdata.trigger = false;
if (area)
Physics2DServer::get_singleton()->area_add_shape(get_rid(), p_shape->get_rid(), p_transform);
else
Physics2DServer::get_singleton()->body_add_shape(get_rid(), p_shape->get_rid(), p_transform);
shapes.push_back(sdata);
}
int CollisionObject2D::get_shape_count() const {
return shapes.size();
}
void CollisionObject2D::set_shape(int p_shape_idx, const Ref<Shape2D> &p_shape) {
ERR_FAIL_INDEX(p_shape_idx, shapes.size());
ERR_FAIL_COND(p_shape.is_null());
shapes[p_shape_idx].shape = p_shape;
if (area)
Physics2DServer::get_singleton()->area_set_shape(get_rid(), p_shape_idx, p_shape->get_rid());
else
Physics2DServer::get_singleton()->body_set_shape(get_rid(), p_shape_idx, p_shape->get_rid());
//_update_shapes();
}
void CollisionObject2D::set_shape_transform(int p_shape_idx, const Transform2D &p_transform) {
ERR_FAIL_INDEX(p_shape_idx, shapes.size());
shapes[p_shape_idx].xform = p_transform;
if (area)
Physics2DServer::get_singleton()->area_set_shape_transform(get_rid(), p_shape_idx, p_transform);
else
Physics2DServer::get_singleton()->body_set_shape_transform(get_rid(), p_shape_idx, p_transform);
//_update_shapes();
}
Ref<Shape2D> CollisionObject2D::get_shape(int p_shape_idx) const {
ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Ref<Shape2D>());
return shapes[p_shape_idx].shape;
}
Transform2D CollisionObject2D::get_shape_transform(int p_shape_idx) const {
ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), Transform2D());
return shapes[p_shape_idx].xform;
}
void CollisionObject2D::remove_shape(int p_shape_idx) {
ERR_FAIL_INDEX(p_shape_idx, shapes.size());
shapes.remove(p_shape_idx);
_update_shapes();
}
void CollisionObject2D::set_shape_as_trigger(int p_shape_idx, bool p_trigger) {
ERR_FAIL_INDEX(p_shape_idx, shapes.size());
shapes[p_shape_idx].trigger = p_trigger;
if (!area && rid.is_valid()) {
Physics2DServer::get_singleton()->body_set_shape_as_trigger(rid, p_shape_idx, p_trigger);
}
}
bool CollisionObject2D::is_shape_set_as_trigger(int p_shape_idx) const {
ERR_FAIL_INDEX_V(p_shape_idx, shapes.size(), false);
return shapes[p_shape_idx].trigger;
}
void CollisionObject2D::clear_shapes() {
shapes.clear();
_update_shapes();
}
CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
rid = p_rid;
area = p_area;
pickable = true;
set_notify_transform(true);
total_subshapes = 0;
if (p_area) {
@ -348,6 +354,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
CollisionObject2D::CollisionObject2D() {
//owner=
set_notify_transform(true);
}

View File

@ -35,37 +35,40 @@
class CollisionObject2D : public Node2D {
GDCLASS(CollisionObject2D, Node2D);
GDCLASS(CollisionObject2D, Node2D)
bool area;
RID rid;
bool pickable;
struct ShapeData {
Object *owner;
Transform2D xform;
Ref<Shape2D> shape;
bool trigger;
struct Shape {
Ref<Shape2D> shape;
int index;
};
Vector<Shape> shapes;
bool disabled;
bool one_way_collision;
ShapeData() {
trigger = false;
disabled = false;
one_way_collision = false;
owner = NULL;
}
};
Vector<ShapeData> shapes;
int total_subshapes;
void _update_shapes();
friend class CollisionShape2D;
friend class CollisionPolygon2D;
void _update_shapes_from_children();
Map<uint32_t, ShapeData> shapes;
protected:
CollisionObject2D(RID p_rid, bool p_area);
void _notification(int p_what);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
static void _bind_methods();
void _update_pickable();
@ -75,16 +78,29 @@ protected:
void _mouse_exit();
public:
void add_shape(const Ref<Shape2D> &p_shape, const Transform2D &p_transform = Transform2D());
int get_shape_count() const;
void set_shape(int p_shape_idx, const Ref<Shape2D> &p_shape);
void set_shape_transform(int p_shape_idx, const Transform2D &p_transform);
Ref<Shape2D> get_shape(int p_shape_idx) const;
Transform2D get_shape_transform(int p_shape_idx) const;
void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
bool is_shape_set_as_trigger(int p_shape_idx) const;
void remove_shape(int p_shape_idx);
void clear_shapes();
uint32_t create_shape_owner(Object *p_owner);
void remove_shape_owner(uint32_t owner);
void get_shape_owners(List<uint32_t> *r_owners);
void shape_owner_set_transform(uint32_t p_owner, const Transform2D &p_transform);
Transform2D shape_owner_get_transform(uint32_t p_owner) const;
Object *shape_owner_get_owner(uint32_t p_owner) const;
void shape_owner_set_disabled(uint32_t p_owner, bool p_disabled);
bool is_shape_owner_disabled(uint32_t p_owner) const;
void shape_owner_set_one_way_collision(uint32_t p_owner, bool p_enable);
bool is_shape_owner_one_way_collision_enabled(uint32_t p_owner) const;
void shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape);
int shape_owner_get_shape_count(uint32_t p_owner) const;
Ref<Shape> shape_owner_get_shape(uint32_t p_owner, int p_shape) const;
int shape_owner_get_shape_index(uint32_t p_owner, int p_shape) const;
void shape_owner_remove_shape(uint32_t p_owner, int p_shape);
void shape_owner_clear_shapes(uint32_t p_owner);
uint32_t shape_find_owner(int p_shape_index) const;
void set_pickable(bool p_enabled);
bool is_pickable() const;

View File

@ -35,13 +35,9 @@
#include "thirdparty/misc/triangulator.h"
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
void CollisionPolygon2D::_build_polygon() {
if (unparenting || !can_update_body)
return;
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
ERR_FAIL_COND(!co);
parent->shape_owner_clear_shapes(owner_id);
if (polygon.size() == 0)
return;
@ -53,18 +49,10 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
Vector<Vector<Vector2> > decomp = _decompose_in_convex();
shape_from = co->get_shape_count();
for (int i = 0; i < decomp.size(); i++) {
Ref<ConvexPolygonShape2D> convex = memnew(ConvexPolygonShape2D);
convex->set_points(decomp[i]);
co->add_shape(convex, get_transform());
if (trigger)
co->set_shape_as_trigger(co->get_shape_count() - 1, true);
}
shape_to = co->get_shape_count() - 1;
if (shape_to < shape_from) {
shape_from = -1;
shape_to = -1;
parent->shape_owner_add_shape(owner_id, convex);
}
} else {
@ -83,28 +71,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
w = PoolVector<Vector2>::Write();
concave->set_segments(segments);
co->add_shape(concave, get_transform());
if (trigger)
co->set_shape_as_trigger(co->get_shape_count() - 1, true);
shape_from = co->get_shape_count() - 1;
shape_to = co->get_shape_count() - 1;
parent->shape_owner_add_shape(owner_id, concave);
}
//co->add_shape(shape,get_transform());
}
void CollisionPolygon2D::_update_parent() {
if (!can_update_body)
return;
Node *parent = get_parent();
if (!parent)
return;
CollisionObject2D *co = parent->cast_to<CollisionObject2D>();
if (!co)
return;
co->_update_shapes_from_children();
}
Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() {
@ -155,33 +123,38 @@ Vector<Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() {
void CollisionPolygon2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting = false;
can_update_body = get_tree()->is_editor_hint();
if (!get_tree()->is_editor_hint()) {
case NOTIFICATION_PARENTED: {
parent = get_parent()->cast_to<CollisionObject2D>();
if (parent) {
owner_id = parent->create_shape_owner(this);
_build_polygon();
parent->shape_owner_set_transform(owner_id, get_transform());
parent->shape_owner_set_disabled(owner_id, disabled);
parent->shape_owner_set_one_way_collision(owner_id, one_way_collision);
}
/*if (get_tree()->is_editor_hint()) {
//display above all else
set_z_as_relative(false);
set_z(VS::CANVAS_ITEM_Z_MAX - 1);
}
}*/
} break;
case NOTIFICATION_EXIT_TREE: {
can_update_body = false;
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (!is_inside_tree())
break;
if (can_update_body) {
_update_parent();
} else if (shape_from >= 0 && shape_to >= 0) {
CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
for (int i = shape_from; i <= shape_to; i++) {
co->set_shape_transform(i, get_transform());
}
if (parent) {
parent->shape_owner_set_transform(owner_id, get_transform());
}
} break;
case NOTIFICATION_UNPARENTED: {
if (parent) {
parent->remove_shape_owner(owner_id);
}
owner_id = 0;
parent = NULL;
} break;
case NOTIFICATION_DRAW: {
@ -210,10 +183,22 @@ void CollisionPolygon2D::_notification(int p_what) {
draw_colored_polygon(polygon, get_tree()->get_debug_collisions_color());
#endif
} break;
case NOTIFICATION_UNPARENTED: {
unparenting = true;
_update_parent();
if (one_way_collision) {
Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4);
dcol.a = 1.0;
Vector2 line_to(0, 20);
draw_line(Vector2(), line_to, dcol, 3);
Vector<Vector2> pts;
float tsize = 8;
pts.push_back(line_to + (Vector2(0, tsize)));
pts.push_back(line_to + (Vector2(0.707 * tsize, 0)));
pts.push_back(line_to + (Vector2(-0.707 * tsize, 0)));
Vector<Color> cols;
for (int i = 0; i < 3; i++)
cols.push_back(dcol);
draw_primitive(pts, cols, Vector<Vector2>()); //small arrow
}
} break;
}
}
@ -222,7 +207,7 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) {
polygon = p_polygon;
if (can_update_body) {
{
for (int i = 0; i < polygon.size(); i++) {
if (i == 0)
aabb = Rect2(polygon[i], Size2());
@ -236,7 +221,10 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) {
aabb.position -= aabb.size * 0.3;
aabb.size += aabb.size * 0.6;
}
_update_parent();
}
if (parent) {
_build_polygon();
}
update();
update_configuration_warning();
@ -251,7 +239,9 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) {
ERR_FAIL_INDEX(p_mode, 2);
build_mode = p_mode;
_update_parent();
if (parent) {
_build_polygon();
}
}
CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const {
@ -264,34 +254,6 @@ Rect2 CollisionPolygon2D::get_item_rect() const {
return aabb;
}
void CollisionPolygon2D::set_trigger(bool p_trigger) {
trigger = p_trigger;
_update_parent();
if (!can_update_body && is_inside_tree() && shape_from >= 0 && shape_to >= 0) {
CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
for (int i = shape_from; i <= shape_to; i++) {
co->set_shape_as_trigger(i, p_trigger);
}
}
}
bool CollisionPolygon2D::is_trigger() const {
return trigger;
}
void CollisionPolygon2D::_set_shape_range(const Vector2 &p_range) {
shape_from = p_range.x;
shape_to = p_range.y;
}
Vector2 CollisionPolygon2D::_get_shape_range() const {
return Vector2(shape_from, shape_to);
}
String CollisionPolygon2D::get_configuration_warning() const {
if (!get_parent()->cast_to<CollisionObject2D>()) {
@ -305,38 +267,56 @@ String CollisionPolygon2D::get_configuration_warning() const {
return String();
}
void CollisionPolygon2D::set_disabled(bool p_disabled) {
disabled = p_disabled;
update();
if (parent) {
parent->shape_owner_set_disabled(owner_id, p_disabled);
}
}
bool CollisionPolygon2D::is_disabled() const {
return disabled;
}
void CollisionPolygon2D::set_one_way_collision(bool p_enable) {
one_way_collision = p_enable;
update();
if (parent) {
parent->shape_owner_set_one_way_collision(owner_id, p_enable);
}
}
bool CollisionPolygon2D::is_one_way_collision_enabled() const {
return one_way_collision;
}
void CollisionPolygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionPolygon2D::_add_to_collision_object);
ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CollisionPolygon2D::set_polygon);
ClassDB::bind_method(D_METHOD("get_polygon"), &CollisionPolygon2D::get_polygon);
ClassDB::bind_method(D_METHOD("set_build_mode", "build_mode"), &CollisionPolygon2D::set_build_mode);
ClassDB::bind_method(D_METHOD("get_build_mode"), &CollisionPolygon2D::get_build_mode);
ClassDB::bind_method(D_METHOD("set_trigger", "trigger"), &CollisionPolygon2D::set_trigger);
ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionPolygon2D::is_trigger);
ClassDB::bind_method(D_METHOD("_set_shape_range", "shape_range"), &CollisionPolygon2D::_set_shape_range);
ClassDB::bind_method(D_METHOD("_get_shape_range"), &CollisionPolygon2D::_get_shape_range);
ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"), &CollisionPolygon2D::get_collision_object_first_shape);
ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"), &CollisionPolygon2D::get_collision_object_last_shape);
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon2D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon2D::is_disabled);
ClassDB::bind_method(D_METHOD("set_one_way_collision", "enabled"), &CollisionPolygon2D::set_one_way_collision);
ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionPolygon2D::is_one_way_collision_enabled);
ADD_PROPERTY(PropertyInfo(Variant::INT, "build_mode", PROPERTY_HINT_ENUM, "Solids,Segments"), "set_build_mode", "get_build_mode");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shape_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_shape_range", "_get_shape_range");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled");
}
CollisionPolygon2D::CollisionPolygon2D() {
aabb = Rect2(-10, -10, 20, 20);
build_mode = BUILD_SOLIDS;
trigger = false;
unparenting = false;
shape_from = -1;
shape_to = -1;
can_update_body = false;
set_notify_local_transform(true);
parent = NULL;
owner_id = 0;
disabled = false;
one_way_collision = false;
}

View File

@ -33,6 +33,8 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/shape_2d.h"
class CollisionObject2D;
class CollisionPolygon2D : public Node2D {
GDCLASS(CollisionPolygon2D, Node2D);
@ -47,29 +49,20 @@ protected:
Rect2 aabb;
BuildMode build_mode;
Vector<Point2> polygon;
bool trigger;
bool unparenting;
void _add_to_collision_object(Object *p_obj);
void _update_parent();
bool can_update_body;
int shape_from;
int shape_to;
void _set_shape_range(const Vector2 &p_range);
Vector2 _get_shape_range() const;
uint32_t owner_id;
CollisionObject2D *parent;
bool disabled;
bool one_way_collision;
Vector<Vector<Vector2> > _decompose_in_convex();
void _build_polygon();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
void set_trigger(bool p_trigger);
bool is_trigger() const;
void set_build_mode(BuildMode p_mode);
BuildMode get_build_mode() const;
@ -78,11 +71,14 @@ public:
virtual Rect2 get_item_rect() const;
int get_collision_object_first_shape() const { return shape_from; }
int get_collision_object_last_shape() const { return shape_to; }
virtual String get_configuration_warning() const;
void set_disabled(bool p_disabled);
bool is_disabled() const;
void set_one_way_collision(bool p_enable);
bool is_one_way_collision_enabled() const;
CollisionPolygon2D();
};

View File

@ -37,68 +37,48 @@
#include "scene/resources/segment_shape_2d.h"
#include "scene/resources/shape_line_2d.h"
void CollisionShape2D::_add_to_collision_object(Object *p_obj) {
if (unparenting)
return;
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
ERR_FAIL_COND(!co);
update_shape_index = co->get_shape_count();
co->add_shape(shape, get_transform());
if (trigger)
co->set_shape_as_trigger(co->get_shape_count() - 1, true);
}
void CollisionShape2D::_shape_changed() {
update();
_update_parent();
}
void CollisionShape2D::_update_parent() {
Node *parent = get_parent();
if (!parent)
return;
CollisionObject2D *co = parent->cast_to<CollisionObject2D>();
if (!co)
return;
co->_update_shapes_from_children();
}
void CollisionShape2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting = false;
can_update_body = get_tree()->is_editor_hint();
if (!get_tree()->is_editor_hint()) {
case NOTIFICATION_PARENTED: {
parent = get_parent()->cast_to<CollisionObject2D>();
if (parent) {
owner_id = parent->create_shape_owner(this);
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
}
parent->shape_owner_set_transform(owner_id, get_transform());
parent->shape_owner_set_disabled(owner_id, disabled);
parent->shape_owner_set_one_way_collision(owner_id, one_way_collision);
}
/*if (get_tree()->is_editor_hint()) {
//display above all else
set_z_as_relative(false);
set_z(VS::CANVAS_ITEM_Z_MAX - 1);
}
}*/
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (!is_inside_tree())
break;
if (can_update_body) {
_update_parent();
} else if (update_shape_index >= 0) {
CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
if (co) {
co->set_shape_transform(update_shape_index, get_transform());
}
if (parent) {
parent->shape_owner_set_transform(owner_id, get_transform());
}
} break;
case NOTIFICATION_EXIT_TREE: {
can_update_body = false;
case NOTIFICATION_UNPARENTED: {
if (parent) {
parent->remove_shape_owner(owner_id);
}
owner_id = 0;
parent = NULL;
} break;
/*
case NOTIFICATION_TRANSFORM_CHANGED: {
@ -121,15 +101,33 @@ void CollisionShape2D::_notification(int p_what) {
rect = Rect2();
Color draw_col = get_tree()->get_debug_collisions_color();
if (disabled) {
float g = draw_col.gray();
draw_col.r = g;
draw_col.g = g;
draw_col.b = g;
}
shape->draw(get_canvas_item(), draw_col);
rect = shape->get_rect();
rect = rect.grow(3);
} break;
case NOTIFICATION_UNPARENTED: {
unparenting = true;
_update_parent();
if (one_way_collision) {
Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4);
dcol.a = 1.0;
Vector2 line_to(0, 20);
draw_line(Vector2(), line_to, dcol, 3);
Vector<Vector2> pts;
float tsize = 8;
pts.push_back(line_to + (Vector2(0, tsize)));
pts.push_back(line_to + (Vector2(0.707 * tsize, 0)));
pts.push_back(line_to + (Vector2(-0.707 * tsize, 0)));
Vector<Color> cols;
for (int i = 0; i < 3; i++)
cols.push_back(dcol);
draw_primitive(pts, cols, Vector<Vector2>()); //small arrow
}
} break;
}
}
@ -140,14 +138,13 @@ void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) {
shape->disconnect("changed", this, "_shape_changed");
shape = p_shape;
update();
if (is_inside_tree() && can_update_body)
_update_parent();
if (is_inside_tree() && !can_update_body && update_shape_index >= 0) {
CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
if (co) {
co->set_shape(update_shape_index, p_shape);
if (parent) {
parent->shape_owner_clear_shapes(owner_id);
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
}
}
if (shape.is_valid())
shape->connect("changed", this, "_shape_changed");
@ -164,34 +161,6 @@ Rect2 CollisionShape2D::get_item_rect() const {
return rect;
}
void CollisionShape2D::set_trigger(bool p_trigger) {
trigger = p_trigger;
if (can_update_body) {
_update_parent();
} else if (is_inside_tree() && update_shape_index >= 0) {
CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
if (co) {
co->set_shape_as_trigger(update_shape_index, p_trigger);
}
}
}
bool CollisionShape2D::is_trigger() const {
return trigger;
}
void CollisionShape2D::_set_update_shape_index(int p_index) {
update_shape_index = p_index;
}
int CollisionShape2D::_get_update_shape_index() const {
return update_shape_index;
}
String CollisionShape2D::get_configuration_warning() const {
if (!get_parent()->cast_to<CollisionObject2D>()) {
@ -205,31 +174,52 @@ String CollisionShape2D::get_configuration_warning() const {
return String();
}
void CollisionShape2D::set_disabled(bool p_disabled) {
disabled = p_disabled;
update();
if (parent) {
parent->shape_owner_set_disabled(owner_id, p_disabled);
}
}
bool CollisionShape2D::is_disabled() const {
return disabled;
}
void CollisionShape2D::set_one_way_collision(bool p_enable) {
one_way_collision = p_enable;
update();
if (parent) {
parent->shape_owner_set_one_way_collision(owner_id, p_enable);
}
}
bool CollisionShape2D::is_one_way_collision_enabled() const {
return one_way_collision;
}
void CollisionShape2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape2D::set_shape);
ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape2D::get_shape);
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionShape2D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape2D::is_disabled);
ClassDB::bind_method(D_METHOD("set_one_way_collision", "enabled"), &CollisionShape2D::set_one_way_collision);
ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionShape2D::is_one_way_collision_enabled);
ClassDB::bind_method(D_METHOD("_shape_changed"), &CollisionShape2D::_shape_changed);
ClassDB::bind_method(D_METHOD("_add_to_collision_object"), &CollisionShape2D::_add_to_collision_object);
ClassDB::bind_method(D_METHOD("set_trigger", "enable"), &CollisionShape2D::set_trigger);
ClassDB::bind_method(D_METHOD("is_trigger"), &CollisionShape2D::is_trigger);
ClassDB::bind_method(D_METHOD("_set_update_shape_index", "index"), &CollisionShape2D::_set_update_shape_index);
ClassDB::bind_method(D_METHOD("_get_update_shape_index"), &CollisionShape2D::_get_update_shape_index);
ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"), &CollisionShape2D::get_collision_object_shape_index);
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trigger"), "set_trigger", "is_trigger");
ADD_PROPERTY(PropertyInfo(Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled");
}
CollisionShape2D::CollisionShape2D() {
rect = Rect2(-Point2(10, 10), Point2(20, 20));
set_notify_local_transform(true);
trigger = false;
unparenting = false;
can_update_body = false;
update_shape_index = -1;
owner_id = 0;
parent = NULL;
disabled = false;
one_way_collision = false;
}

View File

@ -33,35 +33,33 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/shape_2d.h"
class CollisionObject2D;
class CollisionShape2D : public Node2D {
GDCLASS(CollisionShape2D, Node2D);
GDCLASS(CollisionShape2D, Node2D)
Ref<Shape2D> shape;
Rect2 rect;
bool trigger;
bool unparenting;
bool can_update_body;
uint32_t owner_id;
CollisionObject2D *parent;
void _shape_changed();
int update_shape_index;
void _set_update_shape_index(int p_index);
int _get_update_shape_index() const;
bool disabled;
bool one_way_collision;
protected:
void _update_parent();
void _notification(int p_what);
static void _bind_methods();
void _add_to_collision_object(Object *p_obj);
public:
void set_shape(const Ref<Shape2D> &p_shape);
Ref<Shape2D> get_shape() const;
virtual Rect2 get_item_rect() const;
void set_trigger(bool p_trigger);
bool is_trigger() const;
int get_collision_object_shape_index() const { return _get_update_shape_index(); }
void set_disabled(bool p_disabled);
bool is_disabled() const;
void set_one_way_collision(bool p_enable);
bool is_one_way_collision_enabled() const;
virtual String get_configuration_warning() const;

View File

@ -44,28 +44,6 @@ void PhysicsBody2D::_notification(int p_what) {
*/
}
void PhysicsBody2D::set_one_way_collision_direction(const Vector2 &p_dir) {
one_way_collision_direction = p_dir;
Physics2DServer::get_singleton()->body_set_one_way_collision_direction(get_rid(), p_dir);
}
Vector2 PhysicsBody2D::get_one_way_collision_direction() const {
return one_way_collision_direction;
}
void PhysicsBody2D::set_one_way_collision_max_depth(float p_depth) {
one_way_collision_max_depth = p_depth;
Physics2DServer::get_singleton()->body_set_one_way_collision_max_depth(get_rid(), p_depth);
}
float PhysicsBody2D::get_one_way_collision_max_depth() const {
return one_way_collision_max_depth;
}
void PhysicsBody2D::_set_layers(uint32_t p_mask) {
set_collision_layer(p_mask);
@ -92,10 +70,6 @@ void PhysicsBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody2D::_set_layers);
ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody2D::_get_layers);
ClassDB::bind_method(D_METHOD("set_one_way_collision_direction", "dir"), &PhysicsBody2D::set_one_way_collision_direction);
ClassDB::bind_method(D_METHOD("get_one_way_collision_direction"), &PhysicsBody2D::get_one_way_collision_direction);
ClassDB::bind_method(D_METHOD("set_one_way_collision_max_depth", "depth"), &PhysicsBody2D::set_one_way_collision_max_depth);
ClassDB::bind_method(D_METHOD("get_one_way_collision_max_depth"), &PhysicsBody2D::get_one_way_collision_max_depth);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body:PhysicsBody2D"), &PhysicsBody2D::add_collision_exception_with);
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body:PhysicsBody2D"), &PhysicsBody2D::remove_collision_exception_with);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_PHYSICS, "", 0), "_set_layers", "_get_layers"); //for backwards compat
@ -103,9 +77,6 @@ void PhysicsBody2D::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_GROUP("", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "one_way_collision/direction"), "set_one_way_collision_direction", "get_one_way_collision_direction");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "one_way_collision/max_depth"), "set_one_way_collision_max_depth", "get_one_way_collision_max_depth");
}
void PhysicsBody2D::set_collision_layer(uint32_t p_layer) {
@ -164,7 +135,6 @@ PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode)
collision_layer = 1;
collision_mask = 1;
set_one_way_collision_max_depth(0);
set_pickable(false);
}

View File

@ -40,8 +40,6 @@ class PhysicsBody2D : public CollisionObject2D {
uint32_t collision_layer;
uint32_t collision_mask;
Vector2 one_way_collision_direction;
float one_way_collision_max_depth;
void _set_layers(uint32_t p_mask);
uint32_t _get_layers() const;
@ -68,12 +66,6 @@ public:
void add_collision_exception_with(Node *p_node); //must be physicsbody
void remove_collision_exception_with(Node *p_node);
void set_one_way_collision_direction(const Vector2 &p_dir);
Vector2 get_one_way_collision_direction() const;
void set_one_way_collision_max_depth(float p_dir);
float get_one_way_collision_max_depth() const;
PhysicsBody2D();
};

View File

@ -32,7 +32,13 @@
bool AreaPair2DSW::setup(real_t p_step) {
bool result = area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), NULL, this);
bool result = false;
if (area->is_shape_set_as_disabled(area_shape) || body->is_shape_set_as_disabled(body_shape)) {
result = false;
} else if (area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), NULL, this)) {
result = true;
}
if (result != colliding) {
@ -90,7 +96,12 @@ AreaPair2DSW::~AreaPair2DSW() {
bool Area2Pair2DSW::setup(real_t p_step) {
bool result = area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), NULL, this);
bool result = false;
if (area_a->is_shape_set_as_disabled(shape_a) || area_b->is_shape_set_as_disabled(shape_b)) {
result = false;
} else if (area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), NULL, this)) {
result = true;
}
if (result != colliding) {

View File

@ -676,8 +676,6 @@ Body2DSW::Body2DSW()
area_linear_damp = 0;
contact_count = 0;
gravity_scale = 1.0;
using_one_way_cache = false;
one_way_collision_max_depth = 0.1;
first_integration = false;
still_time = 0;

View File

@ -67,9 +67,6 @@ class Body2DSW : public CollisionObject2DSW {
Vector2 applied_force;
real_t applied_torque;
Vector2 one_way_collision_direction;
real_t one_way_collision_max_depth;
SelfList<Body2DSW> active_list;
SelfList<Body2DSW> inertia_update_list;
SelfList<Body2DSW> direct_state_query_list;
@ -81,7 +78,6 @@ class Body2DSW : public CollisionObject2DSW {
bool can_sleep;
bool first_time_kinematic;
bool first_integration;
bool using_one_way_cache;
void _update_inertia();
virtual void _shapes_changed();
Transform2D new_transform;
@ -246,17 +242,6 @@ public:
_FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode = p_mode; }
_FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; }
void set_one_way_collision_direction(const Vector2 &p_dir) {
one_way_collision_direction = p_dir;
using_one_way_cache = one_way_collision_direction != Vector2();
}
Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; }
void set_one_way_collision_max_depth(real_t p_depth) { one_way_collision_max_depth = p_depth; }
real_t get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
_FORCE_INLINE_ bool is_using_one_way_collision() const { return using_one_way_cache; }
void set_space(Space2DSW *p_space);
void update_inertias();

View File

@ -225,6 +225,11 @@ bool BodyPair2DSW::setup(real_t p_step) {
return false;
}
if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
collided = false;
return false;
}
//use local A coordinates to avoid numerical issues on collision detection
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
@ -280,8 +285,8 @@ bool BodyPair2DSW::setup(real_t p_step) {
//if (!prev_collided) {
{
if (A->is_using_one_way_collision()) {
Vector2 direction = A->get_one_way_collision_direction();
if (A->is_shape_set_as_one_way_collision(shape_A)) {
Vector2 direction = xform_A.get_axis(1).normalized();
bool valid = false;
if (B->get_linear_velocity().dot(direction) >= 0) {
for (int i = 0; i < contact_count; i++) {
@ -303,8 +308,8 @@ bool BodyPair2DSW::setup(real_t p_step) {
}
}
if (B->is_using_one_way_collision()) {
Vector2 direction = B->get_one_way_collision_direction();
if (B->is_shape_set_as_one_way_collision(shape_B)) {
Vector2 direction = xform_B.get_axis(1).normalized();
bool valid = false;
if (A->get_linear_velocity().dot(direction) >= 0) {
for (int i = 0; i < contact_count; i++) {
@ -390,7 +395,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
}
}
if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC)) {
if ((A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC)) {
c.active = false;
collided = false;
continue;

View File

@ -37,7 +37,8 @@ void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_tra
s.xform = p_transform;
s.xform_inv = s.xform.affine_inverse();
s.bpid = 0; //needs update
s.trigger = false;
s.disabled = false;
s.one_way_collision = false;
shapes.push_back(s);
p_shape->add_owner(this);
_update_shapes();

View File

@ -58,8 +58,12 @@ private:
Rect2 aabb_cache; //for rayqueries
Shape2DSW *shape;
Variant metadata;
bool trigger;
Shape() { trigger = false; }
bool disabled;
bool one_way_collision;
Shape() {
disabled = false;
one_way_collision = false;
}
};
Vector<Shape> shapes;
@ -116,8 +120,11 @@ public:
_FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space2DSW *get_space() const { return space; }
_FORCE_INLINE_ void set_shape_as_trigger(int p_idx, bool p_enable) { shapes[p_idx].trigger = p_enable; }
_FORCE_INLINE_ bool is_shape_set_as_trigger(int p_idx) const { return shapes[p_idx].trigger; }
_FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) { shapes[p_idx].disabled = p_disabled; }
_FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { return shapes[p_idx].disabled; }
_FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) { shapes[p_idx].one_way_collision = p_one_way_collision; }
_FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const { return shapes[p_idx].one_way_collision; }
void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; }
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }

View File

@ -352,6 +352,15 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co
area->set_shape_transform(p_shape_idx, p_transform);
}
void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
area->set_shape_as_disabled(p_shape, p_disabled);
}
int Physics2DServerSW::area_get_shape_count(RID p_area) const {
Area2DSW *area = area_owner.get(p_area);
@ -640,24 +649,23 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) {
body->remove_shape(0);
}
void Physics2DServerSW::body_set_shape_as_trigger(RID p_body, int p_shape_idx, bool p_enable) {
void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
body->set_shape_as_trigger(p_shape_idx, p_enable);
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable) {
bool Physics2DServerSW::body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
const Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
ERR_FAIL_INDEX_V(p_shape_idx, body->get_shape_count(), false);
return body->is_shape_set_as_trigger(p_shape_idx);
body->set_shape_as_one_way_collision(p_shape_idx, p_enable);
}
void Physics2DServerSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
@ -887,34 +895,6 @@ int Physics2DServerSW::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_contacts_reported();
}
void Physics2DServerSW::body_set_one_way_collision_direction(RID p_body, const Vector2 &p_direction) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
body->set_one_way_collision_direction(p_direction);
}
Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, Vector2());
return body->get_one_way_collision_direction();
}
void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body, real_t p_max_depth) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
body->set_one_way_collision_max_depth(p_max_depth);
}
real_t Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, 0);
return body->get_one_way_collision_max_depth();
}
void Physics2DServerSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) {
Body2DSW *body = body_owner.get(p_body);

View File

@ -123,6 +123,8 @@ public:
virtual RID area_get_shape(RID p_area, int p_shape_idx) const;
virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const;
virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled);
virtual void area_remove_shape(RID p_area, int p_shape_idx);
virtual void area_clear_shapes(RID p_area);
@ -167,8 +169,8 @@ public:
virtual void body_remove_shape(RID p_body, int p_shape_idx);
virtual void body_clear_shapes(RID p_body);
virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx, bool p_enable);
virtual bool body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const;
virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled);
virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled);
virtual void body_attach_object_instance_ID(RID p_body, uint32_t p_ID);
virtual uint32_t body_get_object_instance_ID(RID p_body) const;
@ -212,12 +214,6 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts);
virtual int body_get_max_contacts_reported(RID p_body) const;
virtual void body_set_one_way_collision_direction(RID p_body, const Vector2 &p_direction);
virtual Vector2 body_get_one_way_collision_direction(RID p_body) const;
virtual void body_set_one_way_collision_max_depth(RID p_body, real_t p_max_depth);
virtual real_t body_get_one_way_collision_max_depth(RID p_body) const;
virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant());
virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count);

View File

@ -145,6 +145,7 @@ public:
FUNC3(area_add_shape, RID, RID, const Transform2D &);
FUNC3(area_set_shape, RID, int, RID);
FUNC3(area_set_shape_transform, RID, int, const Transform2D &);
FUNC3(area_set_shape_disabled, RID, int, bool);
FUNC1RC(int, area_get_shape_count, RID);
FUNC2RC(RID, area_get_shape, RID, int);
@ -191,8 +192,8 @@ public:
FUNC2RC(Variant, body_get_shape_metadata, RID, int);
FUNC2RC(RID, body_get_shape, RID, int);
FUNC3(body_set_shape_as_trigger, RID, int, bool);
FUNC2RC(bool, body_is_shape_set_as_trigger, RID, int);
FUNC3(body_set_shape_disabled, RID, int, bool);
FUNC3(body_set_shape_as_one_way_collision, RID, int, bool);
FUNC2(body_remove_shape, RID, int);
FUNC1(body_clear_shapes, RID);
@ -232,12 +233,6 @@ public:
FUNC2(body_set_max_contacts_reported, RID, int);
FUNC1RC(int, body_get_max_contacts_reported, RID);
FUNC2(body_set_one_way_collision_direction, RID, const Vector2 &);
FUNC1RC(Vector2, body_get_one_way_collision_direction, RID);
FUNC2(body_set_one_way_collision_max_depth, RID, real_t);
FUNC1RC(real_t, body_get_one_way_collision_max_depth, RID);
FUNC2(body_set_contacts_reported_depth_treshold, RID, real_t);
FUNC1RC(real_t, body_get_contacts_reported_depth_treshold, RID);

View File

@ -265,14 +265,6 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
//test initial overlap
if (CollisionSolver2DSW::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, p_margin)) {
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
//if one way collision direction ignore initial overlap
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
if (body->get_one_way_collision_direction() != Vector2()) {
continue;
}
}
return false;
}
@ -297,27 +289,6 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
}
}
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
if (body->get_one_way_collision_direction() != Vector2()) {
Vector2 cd[2];
Physics2DServerSW::CollCbkData cbk;
cbk.max = 1;
cbk.amount = 0;
cbk.ptr = cd;
cbk.valid_dir = body->get_one_way_collision_direction();
cbk.valid_depth = body->get_one_way_collision_max_depth();
Vector2 sep = mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * (hi + space->contact_max_allowed_penetration), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, p_margin);
if (!collided || cbk.amount == 0) {
continue;
}
}
}
if (low < best_safe) {
best_safe = low;
best_unsafe = hi;
@ -369,15 +340,9 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
if (p_exclude.has(col_obj->get_self()))
continue;
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
cbk.valid_dir = body->get_one_way_collision_direction();
cbk.valid_depth = body->get_one_way_collision_max_depth();
} else {
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
}
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
collided = p_result_max == 0 || cbk.amount > 0;
@ -407,13 +372,10 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
_RestCallbackData2D *rd = (_RestCallbackData2D *)p_userdata;
if (rd->valid_dir != Vector2()) {
if (rd->valid_dir != Vector2()) {
if (p_point_A.distance_squared_to(p_point_B) > rd->valid_depth * rd->valid_depth)
return;
if (rd->valid_dir.dot((p_point_A - p_point_B).normalized()) < Math_PI * 0.25)
return;
}
if (p_point_A.distance_squared_to(p_point_B) > rd->valid_depth * rd->valid_depth)
return;
if (rd->valid_dir.dot((p_point_A - p_point_B).normalized()) < Math_PI * 0.25)
return;
}
Vector2 contact_rel = p_point_B - p_point_A;
@ -455,16 +417,8 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
if (p_exclude.has(col_obj->get_self()))
continue;
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
rcd.valid_dir = body->get_one_way_collision_direction();
rcd.valid_depth = body->get_one_way_collision_max_depth();
} else {
rcd.valid_dir = Vector2();
rcd.valid_depth = 0;
}
rcd.valid_dir = Vector2();
rcd.valid_depth = 0;
rcd.object = col_obj;
rcd.shape = shape_idx;
bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
@ -517,7 +471,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
keep = false;
else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self()))
keep = false;
else if (static_cast<Body2DSW *>(intersection_query_results[i])->is_shape_set_as_trigger(intersection_query_subindex_results[i]))
else if (static_cast<Body2DSW *>(intersection_query_results[i])->is_shape_set_as_disabled(intersection_query_subindex_results[i]))
keep = false;
if (!keep) {
@ -589,7 +543,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_trigger(j))
if (p_body->is_shape_set_as_disabled(j))
continue;
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
@ -599,18 +553,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
if (col_obj->is_shape_set_as_one_way_collision(j)) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
Vector2 cdir = body->get_one_way_collision_direction();
/*
if (cdir!=Vector2() && p_motion.dot(cdir)<0)
continue;
*/
cbk.valid_dir = cdir;
cbk.valid_depth = body->get_one_way_collision_max_depth();
cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
cbk.valid_depth = p_margin; //only valid depth is the collision margin
} else {
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
@ -678,7 +624,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_trigger(j))
if (p_body->is_shape_set_as_disabled(j))
continue;
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
@ -703,12 +649,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//test initial overlap
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
//if one way collision direction ignore initial overlap
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
if (body->get_one_way_collision_direction() != Vector2()) {
continue;
}
if (col_obj->is_shape_set_as_one_way_collision(j)) {
continue;
}
stuck = true;
@ -720,7 +662,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
real_t hi = 1;
Vector2 mnormal = p_motion.normalized();
for (int i = 0; i < 8; i++) { //steps should be customizable..
for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@ -739,15 +681,16 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
if (body->get_one_way_collision_direction() != Vector2()) {
if (col_obj->is_shape_set_as_one_way_collision(j)) {
Vector2 cd[2];
Physics2DServerSW::CollCbkData cbk;
cbk.max = 1;
cbk.amount = 0;
cbk.ptr = cd;
cbk.valid_dir = body->get_one_way_collision_direction();
cbk.valid_depth = body->get_one_way_collision_max_depth();
cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
;
cbk.valid_depth = 10e20;
Vector2 sep = mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
@ -816,11 +759,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
const Body2DSW *body = static_cast<const Body2DSW *>(col_obj);
rcd.valid_dir = body->get_one_way_collision_direction();
rcd.valid_depth = body->get_one_way_collision_max_depth();
rcd.valid_dir = body_shape_xform.get_axis(1).normalized();
rcd.valid_depth = 10e20;
} else {
rcd.valid_dir = Vector2();
rcd.valid_depth = 0;

View File

@ -496,6 +496,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D()));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &Physics2DServer::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &Physics2DServer::area_set_shape_transform);
ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disable"), &Physics2DServer::area_set_shape_disabled);
ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &Physics2DServer::area_get_shape_count);
ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &Physics2DServer::area_get_shape);
@ -539,8 +540,8 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &Physics2DServer::body_remove_shape);
ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &Physics2DServer::body_clear_shapes);
ClassDB::bind_method(D_METHOD("body_set_shape_as_trigger", "body", "shape_idx", "enable"), &Physics2DServer::body_set_shape_as_trigger);
ClassDB::bind_method(D_METHOD("body_is_shape_set_as_trigger", "body", "shape_idx"), &Physics2DServer::body_is_shape_set_as_trigger);
ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disable"), &Physics2DServer::body_set_shape_disabled);
ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable"), &Physics2DServer::body_set_shape_as_one_way_collision);
ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID", "body", "id"), &Physics2DServer::body_attach_object_instance_ID);
ClassDB::bind_method(D_METHOD("body_get_object_instance_ID", "body"), &Physics2DServer::body_get_object_instance_ID);
@ -571,12 +572,6 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported", "body", "amount"), &Physics2DServer::body_set_max_contacts_reported);
ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported", "body"), &Physics2DServer::body_get_max_contacts_reported);
ClassDB::bind_method(D_METHOD("body_set_one_way_collision_direction", "body", "normal"), &Physics2DServer::body_set_one_way_collision_direction);
ClassDB::bind_method(D_METHOD("body_get_one_way_collision_direction", "body"), &Physics2DServer::body_get_one_way_collision_direction);
ClassDB::bind_method(D_METHOD("body_set_one_way_collision_max_depth", "body", "depth"), &Physics2DServer::body_set_one_way_collision_max_depth);
ClassDB::bind_method(D_METHOD("body_get_one_way_collision_max_depth", "body"), &Physics2DServer::body_get_one_way_collision_max_depth);
ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &Physics2DServer::body_set_omit_force_integration);
ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &Physics2DServer::body_is_omitting_force_integration);

View File

@ -332,6 +332,8 @@ public:
virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0;
virtual void area_clear_shapes(RID p_area) = 0;
virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) = 0;
virtual void area_attach_object_instance_ID(RID p_area, ObjectID p_ID) = 0;
virtual ObjectID area_get_object_instance_ID(RID p_area) const = 0;
@ -380,8 +382,8 @@ public:
virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const = 0;
virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0;
virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx, bool p_enable) = 0;
virtual bool body_is_shape_set_as_trigger(RID p_body, int p_shape_idx) const = 0;
virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0;
virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled) = 0;
virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0;
virtual void body_clear_shapes(RID p_body) = 0;
@ -451,12 +453,6 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) = 0;
virtual int body_get_max_contacts_reported(RID p_body) const = 0;
virtual void body_set_one_way_collision_direction(RID p_body, const Vector2 &p_direction) = 0;
virtual Vector2 body_get_one_way_collision_direction(RID p_body) const = 0;
virtual void body_set_one_way_collision_max_depth(RID p_body, float p_max_depth) = 0;
virtual float body_get_one_way_collision_max_depth(RID p_body) const = 0;
//missing remove
virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) = 0;
virtual float body_get_contacts_reported_depth_treshold(RID p_body) const = 0;