Browse Source

-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!

Juan Linietsky 8 years ago
parent
commit
6ba1e4677b

+ 10 - 7
editor/plugins/tile_set_editor_plugin.cpp

@@ -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?
 				}
 			}
 		}

+ 173 - 166
scene/2d/collision_object_2d.cpp

@@ -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,82 +76,197 @@ 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 (shapes.size() == 0) {
+		id = 1;
+	} else {
+		id = shapes.back()->key() + 1;
+	}
+
+	sd.owner = p_owner;
+
+	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::is_shape_owner_disabled(uint32_t p_owner) const {
+
+	ERR_FAIL_COND_V(!shapes.has(p_owner), false);
+
+	return shapes[p_owner].disabled;
+}
+
+void CollisionObject2D::shape_owner_set_one_way_collision(uint32_t p_owner, bool p_enable) {
 
 	if (area)
-		Physics2DServer::get_singleton()->area_clear_shapes(rid);
-	else
-		Physics2DServer::get_singleton()->body_clear_shapes(rid);
-
-	for (int i = 0; i < shapes.size(); i++) {
-
-		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);
+		return; //not for areas
+
+	ERR_FAIL_COND(!shapes.has(p_owner));
+
+	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 {
 
-bool CollisionObject2D::_set(const StringName &p_name, const Variant &p_value) {
-	String name = p_name;
+	ERR_FAIL_COND_V(!shapes.has(p_owner), Transform2D());
 
-	if (name.begins_with("shapes/")) {
+	return shapes[p_owner].xform;
+}
 
-		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;
+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;
 }
 
-bool CollisionObject2D::_get(const StringName &p_name, Variant &r_ret) const {
+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;
+			}
+		}
+	}
 
-	String name = p_name;
+	total_subshapes--;
+}
 
-	if (name.begins_with("shapes/")) {
+void CollisionObject2D::shape_owner_clear_shapes(uint32_t 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;
+	ERR_FAIL_COND(!shapes.has(p_owner));
 
-	return true;
+	while (shape_owner_get_shape_count(p_owner) > 0) {
+		shape_owner_remove_shape(p_owner, 0);
+	}
 }
 
-void CollisionObject2D::_get_property_list(List<PropertyInfo> *p_list) const {
+uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const {
 
-	//p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
+	ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);
 
-	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));
+	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) {
@@ -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);
 }
 

+ 39 - 23
scene/2d/collision_object_2d.h

@@ -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;
-
-	void _update_shapes();
+	int total_subshapes;
 
-	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;

+ 83 - 103
scene/2d/collision_polygon_2d.cpp

@@ -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,79 +254,69 @@ Rect2 CollisionPolygon2D::get_item_rect() const {
 	return aabb;
 }
 
-void CollisionPolygon2D::set_trigger(bool p_trigger) {
+String CollisionPolygon2D::get_configuration_warning() const {
 
-	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);
-		}
+	if (!get_parent()->cast_to<CollisionObject2D>()) {
+		return TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
 	}
-}
 
-bool CollisionPolygon2D::is_trigger() const {
+	if (polygon.empty()) {
+		return TTR("An empty CollisionPolygon2D has no effect on collision.");
+	}
 
-	return trigger;
+	return String();
 }
 
-void CollisionPolygon2D::_set_shape_range(const Vector2 &p_range) {
-
-	shape_from = p_range.x;
-	shape_to = p_range.y;
+void CollisionPolygon2D::set_disabled(bool p_disabled) {
+	disabled = p_disabled;
+	update();
+	if (parent) {
+		parent->shape_owner_set_disabled(owner_id, p_disabled);
+	}
 }
 
-Vector2 CollisionPolygon2D::_get_shape_range() const {
-
-	return Vector2(shape_from, shape_to);
+bool CollisionPolygon2D::is_disabled() const {
+	return disabled;
 }
 
-String CollisionPolygon2D::get_configuration_warning() const {
-
-	if (!get_parent()->cast_to<CollisionObject2D>()) {
-		return TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
+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);
 	}
+}
 
-	if (polygon.empty()) {
-		return TTR("An empty CollisionPolygon2D has no effect on collision.");
-	}
+bool CollisionPolygon2D::is_one_way_collision_enabled() const {
 
-	return String();
+	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;
 }

+ 14 - 18
scene/2d/collision_polygon_2d.h

@@ -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();
 };
 

+ 83 - 93
scene/2d/collision_shape_2d.cpp

@@ -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,72 +161,65 @@ Rect2 CollisionShape2D::get_item_rect() const {
 	return rect;
 }
 
-void CollisionShape2D::set_trigger(bool p_trigger) {
+String CollisionShape2D::get_configuration_warning() const {
 
-	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);
-		}
+	if (!get_parent()->cast_to<CollisionObject2D>()) {
+		return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
 	}
-}
 
-bool CollisionShape2D::is_trigger() const {
+	if (!shape.is_valid()) {
+		return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!");
+	}
 
-	return trigger;
+	return String();
 }
 
-void CollisionShape2D::_set_update_shape_index(int p_index) {
-
-	update_shape_index = p_index;
+void CollisionShape2D::set_disabled(bool p_disabled) {
+	disabled = p_disabled;
+	update();
+	if (parent) {
+		parent->shape_owner_set_disabled(owner_id, p_disabled);
+	}
 }
 
-int CollisionShape2D::_get_update_shape_index() const {
-
-	return update_shape_index;
+bool CollisionShape2D::is_disabled() const {
+	return disabled;
 }
 
-String CollisionShape2D::get_configuration_warning() const {
-
-	if (!get_parent()->cast_to<CollisionObject2D>()) {
-		return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
+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);
 	}
+}
 
-	if (!shape.is_valid()) {
-		return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!");
-	}
+bool CollisionShape2D::is_one_way_collision_enabled() const {
 
-	return String();
+	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;
 }

+ 12 - 14
scene/2d/collision_shape_2d.h

@@ -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;
 

+ 0 - 30
scene/2d/physics_body_2d.cpp

@@ -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);
 }
 

+ 0 - 8
scene/2d/physics_body_2d.h

@@ -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();
 };
 

+ 13 - 2
servers/physics_2d/area_pair_2d_sw.cpp

@@ -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) {
 

+ 0 - 2
servers/physics_2d/body_2d_sw.cpp

@@ -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;

+ 0 - 15
servers/physics_2d/body_2d_sw.h

@@ -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();

+ 10 - 5
servers/physics_2d/body_pair_2d_sw.cpp

@@ -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;

+ 2 - 1
servers/physics_2d/collision_object_2d_sw.cpp

@@ -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();

+ 11 - 4
servers/physics_2d/collision_object_2d_sw.h

@@ -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; }

+ 16 - 36
servers/physics_2d/physics_2d_server_sw.cpp

@@ -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 {
-
-	const Body2DSW *body = body_owner.get(p_body);
-	ERR_FAIL_COND_V(!body, false);
+	Body2DSW *body = body_owner.get(p_body);
+	ERR_FAIL_COND(!body);
 
-	ERR_FAIL_INDEX_V(p_shape_idx, body->get_shape_count(), false);
+	ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
 
-	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);

+ 4 - 8
servers/physics_2d/physics_2d_server_sw.h

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

+ 3 - 8
servers/physics_2d/physics_2d_server_wrap_mt.h

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

+ 24 - 82
servers/physics_2d/space_2d_sw.cpp

@@ -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) {
-
-						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;
-						*/
+					if (col_obj->is_shape_set_as_one_way_collision(j)) {
 
-						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;

+ 3 - 8
servers/physics_2d_server.cpp

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

+ 4 - 8
servers/physics_2d_server.h

@@ -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;