summaryrefslogtreecommitdiff
path: root/scene/2d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/audio_stream_player_2d.cpp12
-rw-r--r--scene/2d/canvas_item.cpp217
-rw-r--r--scene/2d/canvas_item.h92
-rw-r--r--scene/2d/collision_object_2d.cpp339
-rw-r--r--scene/2d/collision_object_2d.h62
-rw-r--r--scene/2d/collision_polygon_2d.cpp186
-rw-r--r--scene/2d/collision_polygon_2d.h32
-rw-r--r--scene/2d/collision_shape_2d.cpp176
-rw-r--r--scene/2d/collision_shape_2d.h26
-rw-r--r--scene/2d/line_2d.cpp3
-rw-r--r--scene/2d/particles_2d.cpp35
-rw-r--r--scene/2d/particles_2d.h4
-rw-r--r--scene/2d/physics_body_2d.cpp452
-rw-r--r--scene/2d/physics_body_2d.h86
-rw-r--r--scene/2d/sprite.cpp2
-rw-r--r--scene/2d/tile_map.cpp2
16 files changed, 940 insertions, 786 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 3d9e64ae79..cef473dcdf 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -61,7 +61,7 @@ void AudioStreamPlayer2D::_mix_audio() {
for (int j = 0; j < buffer_size; j++) {
- target[j] = buffer[j] * vol;
+ target[j] += buffer[j] * vol;
vol += vol_inc;
}
@@ -76,8 +76,8 @@ void AudioStreamPlayer2D::_mix_audio() {
for (int j = 0; j < buffer_size; j++) {
AudioFrame frame = buffer[j] * vol;
- targets[0][j] = frame;
- targets[1][j] = frame;
+ targets[0][j] += frame;
+ targets[1][j] += frame;
vol += vol_inc;
}
@@ -93,9 +93,9 @@ void AudioStreamPlayer2D::_mix_audio() {
for (int j = 0; j < buffer_size; j++) {
AudioFrame frame = buffer[j] * vol;
- targets[0][j] = frame;
- targets[1][j] = frame;
- targets[2][j] = frame;
+ targets[0][j] += frame;
+ targets[1][j] += frame;
+ targets[2][j] += frame;
vol += vol_inc;
}
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 89b89a50d8..4a80aba355 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "canvas_item.h"
-#include "core/method_bind_ext.inc"
+#include "core/method_bind_ext.gen.inc"
#include "message_queue.h"
#include "os/input.h"
#include "scene/main/canvas_layer.h"
@@ -39,6 +39,196 @@
#include "scene/scene_string_names.h"
#include "servers/visual_server.h"
+Mutex *CanvasItemMaterial::material_mutex = NULL;
+SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials;
+Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map;
+
+void CanvasItemMaterial::init_shaders() {
+
+#ifndef NO_THREADS
+ material_mutex = Mutex::create();
+#endif
+}
+
+void CanvasItemMaterial::finish_shaders() {
+
+#ifndef NO_THREADS
+ memdelete(material_mutex);
+#endif
+}
+
+void CanvasItemMaterial::_update_shader() {
+
+ dirty_materials.remove(&element);
+
+ MaterialKey mk = _compute_key();
+ if (mk.key == current_key.key)
+ return; //no update required in the end
+
+ if (shader_map.has(current_key)) {
+ shader_map[current_key].users--;
+ if (shader_map[current_key].users == 0) {
+ //deallocate shader, as it's no longer in use
+ VS::get_singleton()->free(shader_map[current_key].shader);
+ shader_map.erase(current_key);
+ }
+ }
+
+ current_key = mk;
+
+ if (shader_map.has(mk)) {
+
+ VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader);
+ shader_map[mk].users++;
+ return;
+ }
+
+ //must create a shader!
+
+ String code = "shader_type canvas_item;\nrender_mode ";
+ switch (blend_mode) {
+ case BLEND_MODE_MIX: code += "blend_mix"; break;
+ case BLEND_MODE_ADD: code += "blend_add"; break;
+ case BLEND_MODE_SUB: code += "blend_sub"; break;
+ case BLEND_MODE_MUL: code += "blend_mul"; break;
+ case BLEND_MODE_PREMULT_ALPHA: code += "blend_premul_alpha"; break;
+ }
+
+ switch (light_mode) {
+ case LIGHT_MODE_NORMAL: break;
+ case LIGHT_MODE_UNSHADED: code += ",unshaded"; break;
+ case LIGHT_MODE_LIGHT_ONLY: code += ",light_only"; break;
+ }
+ code += ";\n"; //thats it.
+
+ ShaderData shader_data;
+ shader_data.shader = VS::get_singleton()->shader_create();
+ shader_data.users = 1;
+
+ VS::get_singleton()->shader_set_code(shader_data.shader, code);
+
+ shader_map[mk] = shader_data;
+
+ VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader);
+}
+
+void CanvasItemMaterial::flush_changes() {
+
+ if (material_mutex)
+ material_mutex->lock();
+
+ while (dirty_materials.first()) {
+
+ dirty_materials.first()->self()->_update_shader();
+ }
+
+ if (material_mutex)
+ material_mutex->unlock();
+}
+
+void CanvasItemMaterial::_queue_shader_change() {
+
+ if (material_mutex)
+ material_mutex->lock();
+
+ if (!element.in_list()) {
+ dirty_materials.add(&element);
+ }
+
+ if (material_mutex)
+ material_mutex->unlock();
+}
+
+bool CanvasItemMaterial::_is_shader_dirty() const {
+
+ bool dirty = false;
+
+ if (material_mutex)
+ material_mutex->lock();
+
+ dirty = element.in_list();
+
+ if (material_mutex)
+ material_mutex->unlock();
+
+ return dirty;
+}
+void CanvasItemMaterial::set_blend_mode(BlendMode p_blend_mode) {
+
+ blend_mode = p_blend_mode;
+ _queue_shader_change();
+}
+
+CanvasItemMaterial::BlendMode CanvasItemMaterial::get_blend_mode() const {
+ return blend_mode;
+}
+
+void CanvasItemMaterial::set_light_mode(LightMode p_light_mode) {
+
+ light_mode = p_light_mode;
+ _queue_shader_change();
+}
+
+CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const {
+
+ return light_mode;
+}
+
+void CanvasItemMaterial::_validate_property(PropertyInfo &property) const {
+}
+
+void CanvasItemMaterial::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_mode"), &CanvasItemMaterial::get_blend_mode);
+
+ ClassDB::bind_method(D_METHOD("set_light_mode", "light_mode"), &CanvasItemMaterial::set_light_mode);
+ ClassDB::bind_method(D_METHOD("get_light_mode"), &CanvasItemMaterial::get_light_mode);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,Premult Alpha"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode");
+
+ BIND_CONSTANT(BLEND_MODE_MIX);
+ BIND_CONSTANT(BLEND_MODE_ADD);
+ BIND_CONSTANT(BLEND_MODE_SUB);
+ BIND_CONSTANT(BLEND_MODE_MUL);
+ BIND_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
+ BIND_CONSTANT(LIGHT_MODE_NORMAL);
+ BIND_CONSTANT(LIGHT_MODE_UNSHADED);
+ BIND_CONSTANT(LIGHT_MODE_LIGHT_ONLY);
+}
+
+CanvasItemMaterial::CanvasItemMaterial()
+ : element(this) {
+
+ blend_mode = BLEND_MODE_MIX;
+ light_mode = LIGHT_MODE_NORMAL;
+
+ current_key.key = 0;
+ current_key.invalid_key = 1;
+ _queue_shader_change();
+}
+
+CanvasItemMaterial::~CanvasItemMaterial() {
+
+ if (material_mutex)
+ material_mutex->lock();
+
+ if (shader_map.has(current_key)) {
+ shader_map[current_key].users--;
+ if (shader_map[current_key].users == 0) {
+ //deallocate shader, as it's no longer in use
+ VS::get_singleton()->free(shader_map[current_key].shader);
+ shader_map.erase(current_key);
+ }
+
+ VS::get_singleton()->material_set_shader(_get_material(), RID());
+ }
+
+ if (material_mutex)
+ material_mutex->unlock();
+}
+
///////////////////////////////////////////////////////////////////
bool CanvasItem::is_visible_in_tree() const {
@@ -177,7 +367,9 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const {
}
Transform2D CanvasItem::get_global_transform() const {
-
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_V(!is_inside_tree(), get_transform());
+#endif
if (global_invalid) {
const CanvasItem *pi = get_parent_item();
@@ -575,8 +767,9 @@ float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const
void CanvasItem::_notify_transform(CanvasItem *p_node) {
- if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid)
+ if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) {
return; //nothing to do
+ }
p_node->global_invalid = true;
@@ -665,7 +858,7 @@ bool CanvasItem::is_draw_behind_parent_enabled() const {
return behind;
}
-void CanvasItem::set_material(const Ref<ShaderMaterial> &p_material) {
+void CanvasItem::set_material(const Ref<Material> &p_material) {
material = p_material;
RID rid;
@@ -686,7 +879,7 @@ bool CanvasItem::get_use_parent_material() const {
return use_parent_material;
}
-Ref<ShaderMaterial> CanvasItem::get_material() const {
+Ref<Material> CanvasItem::get_material() const {
return material;
}
@@ -788,8 +981,8 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d);
//ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport);
- ClassDB::bind_method(D_METHOD("set_material", "material:ShaderMaterial"), &CanvasItem::set_material);
- ClassDB::bind_method(D_METHOD("get_material:ShaderMaterial"), &CanvasItem::get_material);
+ ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &CanvasItem::set_material);
+ ClassDB::bind_method(D_METHOD("get_material:Material"), &CanvasItem::get_material);
ClassDB::bind_method(D_METHOD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material);
ClassDB::bind_method(D_METHOD("get_use_parent_material"), &CanvasItem::get_use_parent_material);
@@ -815,7 +1008,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTYNO(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
ADD_GROUP("Material", "");
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material");
//exporting these two things doesn't really make much sense i think
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), "set_as_toplevel","is_set_as_toplevel") ;
@@ -877,7 +1070,15 @@ bool CanvasItem::is_local_transform_notification_enabled() const {
}
void CanvasItem::set_notify_transform(bool p_enable) {
+ if (notify_transform == p_enable)
+ return;
+
notify_transform = p_enable;
+
+ if (notify_transform && is_inside_tree()) {
+ //this ensures that invalid globals get resolved, so notifications can be received
+ get_global_transform();
+ }
}
bool CanvasItem::is_transform_notification_enabled() const {
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 906a08d219..bffc171fc1 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -42,6 +42,92 @@ class Font;
class StyleBox;
+class CanvasItemMaterial : public Material {
+
+ GDCLASS(CanvasItemMaterial, Material)
+
+public:
+ enum BlendMode {
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ BLEND_MODE_PREMULT_ALPHA
+ };
+
+ enum LightMode {
+ LIGHT_MODE_NORMAL,
+ LIGHT_MODE_UNSHADED,
+ LIGHT_MODE_LIGHT_ONLY
+ };
+
+private:
+ union MaterialKey {
+
+ struct {
+ uint32_t blend_mode : 4;
+ uint32_t light_mode : 4;
+ uint32_t invalid_key : 1;
+ };
+
+ uint32_t key;
+
+ bool operator<(const MaterialKey &p_key) const {
+ return key < p_key.key;
+ }
+ };
+
+ struct ShaderData {
+ RID shader;
+ int users;
+ };
+
+ static Map<MaterialKey, ShaderData> shader_map;
+
+ MaterialKey current_key;
+
+ _FORCE_INLINE_ MaterialKey _compute_key() const {
+
+ MaterialKey mk;
+ mk.key = 0;
+ mk.blend_mode = blend_mode;
+ mk.light_mode = light_mode;
+ return mk;
+ }
+
+ static Mutex *material_mutex;
+ static SelfList<CanvasItemMaterial>::List dirty_materials;
+ SelfList<CanvasItemMaterial> element;
+
+ void _update_shader();
+ _FORCE_INLINE_ void _queue_shader_change();
+ _FORCE_INLINE_ bool _is_shader_dirty() const;
+
+ BlendMode blend_mode;
+ LightMode light_mode;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
+
+public:
+ void set_blend_mode(BlendMode p_blend_mode);
+ BlendMode get_blend_mode() const;
+
+ void set_light_mode(LightMode p_light_mode);
+ LightMode get_light_mode() const;
+
+ static void init_shaders();
+ static void finish_shaders();
+ static void flush_changes();
+
+ CanvasItemMaterial();
+ virtual ~CanvasItemMaterial();
+};
+
+VARIANT_ENUM_CAST(CanvasItemMaterial::BlendMode)
+VARIANT_ENUM_CAST(CanvasItemMaterial::LightMode)
+
class CanvasItem : public Node {
GDCLASS(CanvasItem, Node);
@@ -83,7 +169,7 @@ private:
bool notify_local_transform;
bool notify_transform;
- Ref<ShaderMaterial> material;
+ Ref<Material> material;
mutable Transform2D global_transform;
mutable bool global_invalid;
@@ -203,8 +289,8 @@ public:
RID get_canvas() const;
Ref<World2D> get_world_2d() const;
- void set_material(const Ref<ShaderMaterial> &p_material);
- Ref<ShaderMaterial> get_material() const;
+ void set_material(const Ref<Material> &p_material);
+ Ref<Material> get_material() const;
void set_use_parent_material(bool p_use_parent_material);
bool get_use_parent_material() const;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index caf9cf201a..c5c274e225 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/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, sd.shapes[i].index, p_transform);
+ } else {
+ Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, 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);
}
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 4d4611afd1..deffe8a002 100644
--- a/scene/2d/collision_object_2d.h
+++ b/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;
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 6b603c6473..bd669eb4c8 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/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;
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index b1a4a4822d..f0666ba9de 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/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();
};
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 1687a898db..ff4aa245ec 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/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;
}
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 3e63981010..1f2b96b91f 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/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;
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 1a57d24342..5438557d0b 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -310,12 +310,15 @@ void Line2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_color"), "set_default_color", "get_default_color");
+ ADD_GROUP("Fill", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "None,Tile"), "set_texture_mode", "get_texture_mode");
+ ADD_GROUP("Capping", "");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "joint_mode", PROPERTY_HINT_ENUM, "Sharp,Bevel,Round"), "set_joint_mode", "get_joint_mode");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "begin_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round"), "set_begin_cap_mode", "get_begin_cap_mode");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "end_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round"), "set_end_cap_mode", "get_end_cap_mode");
+ ADD_GROUP("Border", "");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), "set_sharp_limit", "get_sharp_limit");
ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), "set_round_precision", "get_round_precision");
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 7c864c3430..aa9258c7b4 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "particles_2d.h"
+
#include "scene/3d/particles.h"
#include "scene/scene_string_names.h"
@@ -49,6 +50,12 @@ void Particles2D::set_lifetime(float p_lifetime) {
lifetime = p_lifetime;
VS::get_singleton()->particles_set_lifetime(particles, lifetime);
}
+
+void Particles2D::set_one_shot(bool p_enable) {
+
+ one_shot = p_enable;
+ VS::get_singleton()->particles_set_one_shot(particles, one_shot);
+}
void Particles2D::set_pre_process_time(float p_time) {
pre_process_time = p_time;
@@ -83,7 +90,7 @@ void Particles2D::set_use_local_coordinates(bool p_enable) {
local_coords = p_enable;
VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords);
set_notify_transform(!p_enable);
- if (!p_enable) {
+ if (!p_enable && is_inside_tree()) {
_update_particle_emission_transform();
}
}
@@ -134,6 +141,11 @@ float Particles2D::get_lifetime() const {
return lifetime;
}
+
+bool Particles2D::get_one_shot() const {
+
+ return one_shot;
+}
float Particles2D::get_pre_process_time() const {
return pre_process_time;
@@ -263,6 +275,10 @@ int Particles2D::get_h_frames() const {
return h_frames;
}
+void Particles2D::restart() {
+ VS::get_singleton()->particles_restart(particles);
+}
+
void Particles2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -276,10 +292,12 @@ void Particles2D::_notification(int p_what) {
VS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid, normal_rid, h_frames, v_frames);
+#ifdef TOOLS_ENABLED
if (get_tree()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) {
draw_rect(visibility_rect, Color(0, 0.7, 0.9, 0.4), false);
}
+#endif
}
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
@@ -292,6 +310,7 @@ void Particles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &Particles2D::set_emitting);
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &Particles2D::set_amount);
ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &Particles2D::set_lifetime);
+ ClassDB::bind_method(D_METHOD("set_one_shot", "secs"), &Particles2D::set_one_shot);
ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles2D::set_pre_process_time);
ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles2D::set_explosiveness_ratio);
ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles2D::set_randomness_ratio);
@@ -305,6 +324,7 @@ void Particles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_emitting"), &Particles2D::is_emitting);
ClassDB::bind_method(D_METHOD("get_amount"), &Particles2D::get_amount);
ClassDB::bind_method(D_METHOD("get_lifetime"), &Particles2D::get_lifetime);
+ ClassDB::bind_method(D_METHOD("get_one_shot"), &Particles2D::get_one_shot);
ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles2D::get_pre_process_time);
ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles2D::get_explosiveness_ratio);
ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles2D::get_randomness_ratio);
@@ -332,21 +352,25 @@ void Particles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_h_frames", "frames"), &Particles2D::set_h_frames);
ClassDB::bind_method(D_METHOD("get_h_frames"), &Particles2D::get_h_frames);
- ADD_GROUP("Parameters", "");
+ ClassDB::bind_method(D_METHOD("restart"), &Particles2D::restart);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,100000,1"), "set_amount", "get_amount");
+ ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
+ ADD_GROUP("Drawing", "");
+ ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_rect"), "set_visibility_rect", "get_visibility_rect");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order");
ADD_GROUP("Process Material", "process_");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticlesMaterial,ShaderMaterial"), "set_process_material", "get_process_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material");
ADD_GROUP("Textures", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
@@ -362,6 +386,7 @@ Particles2D::Particles2D() {
particles = VS::get_singleton()->particles_create();
set_emitting(true);
+ set_one_shot(false);
set_amount(8);
set_lifetime(1);
set_fixed_fps(0);
diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h
index ab7dcb1464..23278ce746 100644
--- a/scene/2d/particles_2d.h
+++ b/scene/2d/particles_2d.h
@@ -48,6 +48,7 @@ private:
RID particles;
bool emitting;
+ bool one_shot;
int amount;
float lifetime;
float pre_process_time;
@@ -79,6 +80,7 @@ public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
void set_lifetime(float p_lifetime);
+ void set_one_shot(bool p_enabled);
void set_pre_process_time(float p_time);
void set_explosiveness_ratio(float p_ratio);
void set_randomness_ratio(float p_ratio);
@@ -90,6 +92,7 @@ public:
bool is_emitting() const;
int get_amount() const;
float get_lifetime() const;
+ bool get_one_shot() const;
float get_pre_process_time() const;
float get_explosiveness_ratio() const;
float get_randomness_ratio() const;
@@ -121,6 +124,7 @@ public:
void set_h_frames(int p_count);
int get_h_frames() const;
+ void restart();
Rect2 capture_rect() const;
Particles2D();
~Particles2D();
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 68270ed771..fd261117e1 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/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);
}
@@ -971,248 +941,105 @@ RigidBody2D::~RigidBody2D() {
//////////////////////////
-Variant KinematicBody2D::_get_collider() const {
-
- ObjectID oid = get_collider();
- if (oid == 0)
- return Variant();
- Object *obj = ObjectDB::get_instance(oid);
- if (!obj)
- return Variant();
-
- Reference *ref = obj->cast_to<Reference>();
- if (ref) {
- return Ref<Reference>(ref);
- }
-
- return obj;
-}
-
-void KinematicBody2D::revert_motion() {
+Dictionary KinematicBody2D::_move(const Vector2 &p_motion) {
+
+ Collision col;
+ if (move(p_motion, col)) {
+ Dictionary d;
+ d["position"] = col.collision;
+ d["normal"] = col.collision;
+ d["local_shape"] = col.local_shape;
+ d["travel"] = col.travel;
+ d["remainder"] = col.remainder;
+ d["collider_id"] = col.collider;
+ if (col.collider) {
+ d["collider"] = ObjectDB::get_instance(col.collider);
+ } else {
+ d["collider"] = Variant();
+ }
- Transform2D gt = get_global_transform();
- gt.elements[2] -= travel;
- travel = Vector2();
- set_global_transform(gt);
-}
+ d["collider_shape_index"] = col.collider_shape;
+ d["collider_metadata"] = col.collider_metadata;
-Vector2 KinematicBody2D::get_travel() const {
+ return d;
- return travel;
+ } else {
+ return Dictionary();
+ }
}
-Vector2 KinematicBody2D::move(const Vector2 &p_motion) {
-
-#if 1
+bool KinematicBody2D::move(const Vector2 &p_motion, Collision &r_collision) {
Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
- colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result);
-
- collider_metadata = result.collider_metadata;
- collider_shape = result.collider_shape;
- collider_vel = result.collider_velocity;
- collision = result.collision_point;
- normal = result.collision_normal;
- collider = result.collider_id;
-
- gt.elements[2] += result.motion;
- set_global_transform(gt);
- travel = result.motion;
-
- return result.remainder;
-
-#else
- //give me back regular physics engine logic
- //this is madness
- //and most people using this function will think
- //what it does is simpler than using physics
- //this took about a week to get right..
- //but is it right? who knows at this point..
-
- colliding = false;
- ERR_FAIL_COND_V(!is_inside_tree(), Vector2());
- Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space());
- ERR_FAIL_COND_V(!dss, Vector2());
- const int max_shapes = 32;
- Vector2 sr[max_shapes * 2];
- int res_shapes;
-
- Set<RID> exclude;
- exclude.insert(get_rid());
-
- //recover first
- int recover_attempts = 4;
-
- bool collided = false;
- uint32_t mask = 0;
- if (true)
- mask |= Physics2DDirectSpaceState::TYPE_MASK_STATIC_BODY;
- if (true)
- mask |= Physics2DDirectSpaceState::TYPE_MASK_KINEMATIC_BODY;
- if (true)
- mask |= Physics2DDirectSpaceState::TYPE_MASK_RIGID_BODY;
- if (true)
- mask |= Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY;
-
- //print_line("margin: "+rtos(margin));
- do {
-
- //motion recover
- for (int i = 0; i < get_shape_count(); i++) {
-
- if (is_shape_set_as_trigger(i))
- continue;
- if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), Vector2(), margin, sr, max_shapes, res_shapes, exclude, get_layer_mask(), mask))
- collided = true;
- }
-
- if (!collided)
- break;
-
- Vector2 recover_motion;
-
- for (int i = 0; i < res_shapes; i++) {
-
- Vector2 a = sr[i * 2 + 0];
- Vector2 b = sr[i * 2 + 1];
-
- float d = a.distance_to(b);
-
- /*
- if (d<margin)
- continue;
- */
- recover_motion += (b - a) * 0.4;
- }
-
- if (recover_motion == Vector2()) {
- collided = false;
- break;
- }
-
- Transform2D gt = get_global_transform();
- gt.elements[2] += recover_motion;
- set_global_transform(gt);
-
- recover_attempts--;
-
- } while (recover_attempts);
-
- //move second
- float safe = 1.0;
- float unsafe = 1.0;
- int best_shape = -1;
-
- for (int i = 0; i < get_shape_count(); i++) {
-
- if (is_shape_set_as_trigger(i))
- continue;
-
- float lsafe, lunsafe;
- bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0, lsafe, lunsafe, exclude, get_layer_mask(), mask);
- //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel));
- if (!valid) {
-
- safe = 0;
- unsafe = 0;
- best_shape = i; //sadly it's the best
- break;
- }
- if (lsafe == 1.0) {
- continue;
- }
- if (lsafe < safe) {
-
- safe = lsafe;
- unsafe = lunsafe;
- best_shape = i;
- }
+ bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result);
+
+ if (colliding) {
+ r_collision.collider_metadata = result.collider_metadata;
+ r_collision.collider_shape = result.collider_shape;
+ r_collision.collider_vel = result.collider_velocity;
+ r_collision.collision = result.collision_point;
+ r_collision.normal = result.collision_normal;
+ r_collision.collider = result.collider_id;
+ r_collision.travel = result.motion;
+ r_collision.remainder = result.remainder;
+ r_collision.local_shape = result.collision_local_shape;
}
- //print_line("best shape: "+itos(best_shape)+" motion "+p_motion);
-
- if (safe >= 1) {
- //not collided
- colliding = false;
-
- } else {
-
- //it collided, let's get the rest info in unsafe advance
- Transform2D ugt = get_global_transform();
- ugt.elements[2] += p_motion * unsafe;
- Physics2DDirectSpaceState::ShapeRestInfo rest_info;
- bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt * get_shape_transform(best_shape), Vector2(), margin, &rest_info, exclude, get_layer_mask(), mask);
- if (!c2) {
- //should not happen, but floating point precision is so weird..
-
- colliding = false;
- } else {
-
- //print_line("Travel: "+rtos(travel));
- colliding = true;
- collision = rest_info.point;
- normal = rest_info.normal;
- collider = rest_info.collider_id;
- collider_vel = rest_info.linear_velocity;
- collider_shape = rest_info.shape;
- collider_metadata = rest_info.metadata;
- }
- }
-
- Vector2 motion = p_motion * safe;
- Transform2D gt = get_global_transform();
- gt.elements[2] += motion;
+ gt.elements[2] += result.motion;
set_global_transform(gt);
- return p_motion - motion;
-#endif
+ return colliding;
}
Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) {
- Vector2 motion = (move_and_slide_floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
+ Vector2 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
Vector2 lv = p_linear_velocity;
- move_and_slide_on_floor = false;
- move_and_slide_on_ceiling = false;
- move_and_slide_on_wall = false;
- move_and_slide_colliders.clear();
- move_and_slide_floor_velocity = Vector2();
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
+ colliders.clear();
+ floor_velocity = Vector2();
while (p_max_bounces) {
- motion = move(motion);
+ Collision collision;
+
+ bool collided = move(motion, collision);
- if (is_colliding()) {
+ if (collided) {
+
+ motion = collision.remainder;
if (p_floor_direction == Vector2()) {
//all is a wall
- move_and_slide_on_wall = true;
+ on_wall = true;
} else {
- if (get_collision_normal().dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
+ if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
- move_and_slide_on_floor = true;
- move_and_slide_floor_velocity = get_collider_velocity();
+ on_floor = true;
+ floor_velocity = collision.collider_vel;
- if (get_travel().length() < 1 && ABS((lv.x - move_and_slide_floor_velocity.x)) < p_slope_stop_min_velocity) {
- revert_motion();
+ if (collision.travel.length() < 1 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) {
+ Transform2D gt = get_global_transform();
+ gt.elements[2] -= collision.travel;
+ set_global_transform(gt);
return Vector2();
}
- } else if (get_collision_normal().dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
- move_and_slide_on_ceiling = true;
+ } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
+ on_ceiling = true;
} else {
- move_and_slide_on_wall = true;
+ on_wall = true;
}
}
- Vector2 n = get_collision_normal();
+ Vector2 n = collision.normal;
motion = motion.slide(n);
lv = lv.slide(n);
- Variant collider = _get_collider();
- if (collider.get_type() != Variant::NIL) {
- move_and_slide_colliders.push_back(collider);
- }
+
+ colliders.push_back(collision);
} else {
break;
@@ -1226,26 +1053,22 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
return lv;
}
-bool KinematicBody2D::is_move_and_slide_on_floor() const {
+bool KinematicBody2D::is_on_floor() const {
- return move_and_slide_on_floor;
+ return on_floor;
}
-bool KinematicBody2D::is_move_and_slide_on_wall() const {
+bool KinematicBody2D::is_on_wall() const {
- return move_and_slide_on_wall;
+ return on_wall;
}
-bool KinematicBody2D::is_move_and_slide_on_ceiling() const {
+bool KinematicBody2D::is_on_ceiling() const {
- return move_and_slide_on_ceiling;
+ return on_ceiling;
}
-Array KinematicBody2D::get_move_and_slide_colliders() const {
- return move_and_slide_colliders;
-}
+Vector2 KinematicBody2D::get_floor_velocity() const {
-Vector2 KinematicBody2D::move_to(const Vector2 &p_position) {
-
- return move(p_position - get_global_position());
+ return floor_velocity;
}
bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion) {
@@ -1255,98 +1078,123 @@ bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_moti
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin);
}
-Vector2 KinematicBody2D::get_collision_pos() const {
+void KinematicBody2D::set_safe_margin(float p_margin) {
- ERR_FAIL_COND_V(!colliding, Vector2());
- return collision;
+ margin = p_margin;
}
-Vector2 KinematicBody2D::get_collision_normal() const {
+float KinematicBody2D::get_safe_margin() const {
- ERR_FAIL_COND_V(!colliding, Vector2());
- return normal;
+ return margin;
}
-Vector2 KinematicBody2D::get_collider_velocity() const {
+int KinematicBody2D::get_collision_count() const {
- return collider_vel;
+ return colliders.size();
}
+Vector2 KinematicBody2D::get_collision_position(int p_collision) const {
-ObjectID KinematicBody2D::get_collider() const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2());
- ERR_FAIL_COND_V(!colliding, 0);
- return collider;
+ return colliders[p_collision].collision;
}
-
-int KinematicBody2D::get_collider_shape() const {
-
- ERR_FAIL_COND_V(!colliding, 0);
- return collider_shape;
+Vector2 KinematicBody2D::get_collision_normal(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2());
+ return colliders[p_collision].normal;
}
-Variant KinematicBody2D::get_collider_metadata() const {
-
- ERR_FAIL_COND_V(!colliding, 0);
- return collider_metadata;
+Vector2 KinematicBody2D::get_collision_travel(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2());
+ return colliders[p_collision].travel;
}
-
-bool KinematicBody2D::is_colliding() const {
-
- return colliding;
+Vector2 KinematicBody2D::get_collision_remainder(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2());
+ return colliders[p_collision].remainder;
}
+Object *KinematicBody2D::get_collision_local_shape(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
+ uint32_t owner = shape_find_owner(colliders[p_collision].local_shape);
+ return shape_owner_get_owner(owner);
+}
+Object *KinematicBody2D::get_collision_collider(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
-void KinematicBody2D::set_collision_margin(float p_margin) {
+ if (colliders[p_collision].collider) {
+ return ObjectDB::get_instance(colliders[p_collision].collider);
+ }
- margin = p_margin;
+ return NULL;
}
+ObjectID KinematicBody2D::get_collision_collider_id(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), 0);
-float KinematicBody2D::get_collision_margin() const {
+ return colliders[p_collision].collider;
+}
+Object *KinematicBody2D::get_collision_collider_shape(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), NULL);
+ Object *collider = get_collision_collider(p_collision);
+ if (collider) {
+ CollisionObject2D *obj2d = collider->cast_to<CollisionObject2D>();
+ if (obj2d) {
+ uint32_t owner = shape_find_owner(colliders[p_collision].collider_shape);
+ return obj2d->shape_owner_get_owner(owner);
+ }
+ }
- return margin;
+ return NULL;
+}
+int KinematicBody2D::get_collision_collider_shape_index(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), -1);
+ return colliders[p_collision].collider_shape;
+}
+Vector2 KinematicBody2D::get_collision_collider_velocity(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Vector2());
+ return colliders[p_collision].collider_vel;
+}
+Variant KinematicBody2D::get_collision_collider_metadata(int p_collision) const {
+ ERR_FAIL_INDEX_V(p_collision, colliders.size(), Variant());
+ return colliders[p_collision].collider_metadata;
}
void KinematicBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody2D::move);
- ClassDB::bind_method(D_METHOD("move_to", "position"), &KinematicBody2D::move_to);
+ ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody2D::_move);
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody2D::test_move);
- ClassDB::bind_method(D_METHOD("get_travel"), &KinematicBody2D::get_travel);
- ClassDB::bind_method(D_METHOD("revert_motion"), &KinematicBody2D::revert_motion);
- ClassDB::bind_method(D_METHOD("is_colliding"), &KinematicBody2D::is_colliding);
+ ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity);
- ClassDB::bind_method(D_METHOD("get_collision_pos"), &KinematicBody2D::get_collision_pos);
- ClassDB::bind_method(D_METHOD("get_collision_normal"), &KinematicBody2D::get_collision_normal);
- ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicBody2D::get_collider_velocity);
- ClassDB::bind_method(D_METHOD("get_collider:Variant"), &KinematicBody2D::_get_collider);
- ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicBody2D::get_collider_shape);
- ClassDB::bind_method(D_METHOD("get_collider_metadata:Variant"), &KinematicBody2D::get_collider_metadata);
- ClassDB::bind_method(D_METHOD("get_move_and_slide_colliders"), &KinematicBody2D::get_move_and_slide_colliders);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_floor"), &KinematicBody2D::is_move_and_slide_on_floor);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_ceiling"), &KinematicBody2D::is_move_and_slide_on_ceiling);
- ClassDB::bind_method(D_METHOD("is_move_and_slide_on_wall"), &KinematicBody2D::is_move_and_slide_on_wall);
+ ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin);
+ ClassDB::bind_method(D_METHOD("get_safe_margin", "pixels"), &KinematicBody2D::get_safe_margin);
- ClassDB::bind_method(D_METHOD("set_collision_margin", "pixels"), &KinematicBody2D::set_collision_margin);
- ClassDB::bind_method(D_METHOD("get_collision_margin", "pixels"), &KinematicBody2D::get_collision_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_count"), &KinematicBody2D::get_collision_count);
+ ClassDB::bind_method(D_METHOD("get_collision_position", "collision"), &KinematicBody2D::get_collision_position);
+ ClassDB::bind_method(D_METHOD("get_collision_normal", "collision"), &KinematicBody2D::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collision_travel", "collision"), &KinematicBody2D::get_collision_travel);
+ ClassDB::bind_method(D_METHOD("get_collision_remainder", "collision"), &KinematicBody2D::get_collision_remainder);
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision"), &KinematicBody2D::get_collision_local_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_collider", "collision"), &KinematicBody2D::get_collision_collider);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_id", "collision"), &KinematicBody2D::get_collision_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_shape", "collision"), &KinematicBody2D::get_collision_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_shape_index", "collision"), &KinematicBody2D::get_collision_collider_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_velocity", "collision"), &KinematicBody2D::get_collision_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collision_collider_metadata", "collision"), &KinematicBody2D::get_collision_collider_metadata);
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_collision_margin", "get_collision_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
KinematicBody2D::KinematicBody2D()
: PhysicsBody2D(Physics2DServer::BODY_MODE_KINEMATIC) {
- colliding = false;
- collider = 0;
-
- collider_shape = 0;
-
margin = 0.08;
- move_and_slide_on_floor = false;
- move_and_slide_on_ceiling = false;
- move_and_slide_on_wall = false;
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
}
KinematicBody2D::~KinematicBody2D() {
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 50c9865f18..8c8e4ebc77 100644
--- a/scene/2d/physics_body_2d.h
+++ b/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();
};
@@ -272,54 +264,60 @@ class KinematicBody2D : public PhysicsBody2D {
GDCLASS(KinematicBody2D, PhysicsBody2D);
+public:
+ struct Collision {
+ Vector2 collision;
+ Vector2 normal;
+ Vector2 collider_vel;
+ ObjectID collider;
+ int collider_shape;
+ Variant collider_metadata;
+ Vector2 remainder;
+ Vector2 travel;
+ int local_shape;
+ };
+
+private:
float margin;
- bool colliding;
- Vector2 collision;
- Vector2 normal;
- Vector2 collider_vel;
- ObjectID collider;
- int collider_shape;
- Variant collider_metadata;
- Vector2 travel;
-
- Vector2 move_and_slide_floor_velocity;
- bool move_and_slide_on_floor;
- bool move_and_slide_on_ceiling;
- bool move_and_slide_on_wall;
- Array move_and_slide_colliders;
-
- Variant _get_collider() const;
+
+ Vector2 floor_velocity;
+ bool on_floor;
+ bool on_ceiling;
+ bool on_wall;
+ Vector<Collision> colliders;
_FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const;
+ Dictionary _move(const Vector2 &p_motion);
+
protected:
static void _bind_methods();
public:
- Vector2 move(const Vector2 &p_motion);
- Vector2 move_to(const Vector2 &p_position);
-
+ bool move(const Vector2 &p_motion, Collision &r_collision);
bool test_move(const Transform2D &p_from, const Vector2 &p_motion);
- bool is_colliding() const;
-
- Vector2 get_travel() const;
- void revert_motion();
-
- Vector2 get_collision_pos() const;
- Vector2 get_collision_normal() const;
- Vector2 get_collider_velocity() const;
- ObjectID get_collider() const;
- int get_collider_shape() const;
- Variant get_collider_metadata() const;
- void set_collision_margin(float p_margin);
- float get_collision_margin() const;
+ void set_safe_margin(float p_margin);
+ float get_safe_margin() const;
Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45));
- bool is_move_and_slide_on_floor() const;
- bool is_move_and_slide_on_wall() const;
- bool is_move_and_slide_on_ceiling() const;
- Array get_move_and_slide_colliders() const;
+ bool is_on_floor() const;
+ bool is_on_wall() const;
+ bool is_on_ceiling() const;
+ Vector2 get_floor_velocity() const;
+
+ int get_collision_count() const;
+ Vector2 get_collision_position(int p_collision) const;
+ Vector2 get_collision_normal(int p_collision) const;
+ Vector2 get_collision_travel(int p_collision) const;
+ Vector2 get_collision_remainder(int p_collision) const;
+ Object *get_collision_local_shape(int p_collision) const;
+ Object *get_collision_collider(int p_collision) const;
+ ObjectID get_collision_collider_id(int p_collision) const;
+ Object *get_collision_collider_shape(int p_collision) const;
+ int get_collision_collider_shape_index(int p_collision) const;
+ Vector2 get_collision_collider_velocity(int p_collision) const;
+ Variant get_collision_collider_metadata(int p_collision) const;
KinematicBody2D();
~KinematicBody2D();
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index ff574a6bd6..450f8e2474 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -351,10 +351,12 @@ void Sprite::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
+ ADD_GROUP("Offset", "");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
+ ADD_GROUP("Animation", "");
ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame");
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 4676f2c4c1..098bdf93de 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "tile_map.h"
#include "io/marshalls.h"
-#include "method_bind_ext.inc"
+#include "method_bind_ext.gen.inc"
#include "os/os.h"
#include "servers/physics_2d_server.h"