mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 12:12:28 +00:00
-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:
parent
683f50bef4
commit
6ba1e4677b
@ -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?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user