Merge pull request #25649 from bojidar-bg/4454-promote-tilemap-shapes

Allow CollisionObject2D to get shapes from tilemaps
This commit is contained in:
Rémi Verschelde 2019-06-29 15:35:13 +02:00 committed by GitHub
commit cd423f4712
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 189 additions and 44 deletions

View file

@ -218,12 +218,13 @@ void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transf
ERR_FAIL_COND(!shapes.has(p_owner)); ERR_FAIL_COND(!shapes.has(p_owner));
ShapeData &sd = shapes[p_owner]; ShapeData &sd = shapes[p_owner];
sd.xform = p_transform; sd.xform = p_transform;
for (int i = 0; i < sd.shapes.size(); i++) { for (int i = 0; i < sd.shapes.size(); i++) {
if (area) { if (area) {
Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, sd.xform);
} else { } else {
Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, sd.xform);
} }
} }
} }
@ -387,7 +388,7 @@ String CollisionObject2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning(); String warning = Node2D::get_configuration_warning();
if (shapes.empty()) { if (shapes.empty()) {
if (warning == String()) { if (!warning.empty()) {
warning += "\n"; warning += "\n";
} }
warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape."); warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape.");

View file

@ -30,9 +30,11 @@
#include "tile_map.h" #include "tile_map.h"
#include "collision_object_2d.h"
#include "core/io/marshalls.h" #include "core/io/marshalls.h"
#include "core/method_bind_ext.gen.inc" #include "core/method_bind_ext.gen.inc"
#include "core/os/os.h" #include "core/os/os.h"
#include "scene/2d/area_2d.h"
#include "servers/physics_2d_server.h" #include "servers/physics_2d_server.h"
int TileMap::_get_quadrant_size() const { int TileMap::_get_quadrant_size() const {
@ -60,14 +62,21 @@ void TileMap::_notification(int p_what) {
c = Object::cast_to<Node2D>(c->get_parent()); c = Object::cast_to<Node2D>(c->get_parent());
} }
if (use_parent) {
_clear_quadrants();
collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
}
pending_update = true; pending_update = true;
_recreate_quadrants(); _recreate_quadrants();
update_dirty_quadrants(); update_dirty_quadrants();
RID space = get_world_2d()->get_space(); RID space = get_world_2d()->get_space();
_update_quadrant_transform(); _update_quadrant_transform();
_update_quadrant_space(space); _update_quadrant_space(space);
update_configuration_warning();
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
_update_quadrant_space(RID()); _update_quadrant_space(RID());
@ -82,30 +91,46 @@ void TileMap::_notification(int p_what) {
q.navpoly_ids.clear(); q.navpoly_ids.clear();
} }
if (collision_parent) {
collision_parent->remove_shape_owner(q.shape_owner_id);
q.shape_owner_id = -1;
}
for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) { for (Map<PosKey, Quadrant::Occluder>::Element *F = q.occluder_instances.front(); F; F = F->next()) {
VS::get_singleton()->free(F->get().id); VS::get_singleton()->free(F->get().id);
} }
q.occluder_instances.clear(); q.occluder_instances.clear();
} }
collision_parent = NULL;
navigation = NULL; navigation = NULL;
} break; } break;
case NOTIFICATION_TRANSFORM_CHANGED: { case NOTIFICATION_TRANSFORM_CHANGED: {
//move stuff //move stuff
_update_quadrant_transform(); _update_quadrant_transform();
} break; } break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (use_parent) {
_recreate_quadrants();
}
} break;
} }
} }
void TileMap::_update_quadrant_space(const RID &p_space) { void TileMap::_update_quadrant_space(const RID &p_space) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { if (!use_parent) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get(); Quadrant &q = E->get();
Physics2DServer::get_singleton()->body_set_space(q.body, p_space); Physics2DServer::get_singleton()->body_set_space(q.body, p_space);
}
} }
} }
@ -116,6 +141,10 @@ void TileMap::_update_quadrant_transform() {
Transform2D global_transform = get_global_transform(); Transform2D global_transform = get_global_transform();
Transform2D local_transform;
if (collision_parent)
local_transform = get_transform();
Transform2D nav_rel; Transform2D nav_rel;
if (navigation) if (navigation)
nav_rel = get_relative_transform_to_parent(navigation); nav_rel = get_relative_transform_to_parent(navigation);
@ -125,8 +154,11 @@ void TileMap::_update_quadrant_transform() {
Quadrant &q = E->get(); Quadrant &q = E->get();
Transform2D xform; Transform2D xform;
xform.set_origin(q.pos); xform.set_origin(q.pos);
xform = global_transform * xform;
Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform); if (!use_parent) {
xform = global_transform * xform;
Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
}
if (navigation) { if (navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) { for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
@ -225,6 +257,34 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const
xform.elements[2] += offset; xform.elements[2] += offset;
} }
void TileMap::_add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata) {
Physics2DServer *ps = Physics2DServer::get_singleton();
if (!use_parent) {
ps->body_add_shape(p_q.body, p_shape->get_rid(), p_xform);
ps->body_set_shape_metadata(p_q.body, shape_idx, p_metadata);
ps->body_set_shape_as_one_way_collision(p_q.body, shape_idx, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
} else if (collision_parent) {
Transform2D xform = p_xform;
xform.set_origin(xform.get_origin() + p_q.pos);
collision_parent->shape_owner_add_shape(p_q.shape_owner_id, p_shape);
int real_index = collision_parent->shape_owner_get_shape_index(p_q.shape_owner_id, shape_idx);
RID rid = collision_parent->get_rid();
if (Object::cast_to<Area2D>(collision_parent) != NULL) {
ps->area_set_shape_transform(rid, real_index, get_transform() * xform);
} else {
ps->body_set_shape_transform(rid, real_index, get_transform() * xform);
ps->body_set_shape_metadata(rid, real_index, p_metadata);
ps->body_set_shape_as_one_way_collision(rid, real_index, p_shape_data.one_way_collision, p_shape_data.one_way_collision_margin);
}
}
shape_idx++;
}
void TileMap::update_dirty_quadrants() { void TileMap::update_dirty_quadrants() {
if (!pending_update) if (!pending_update)
@ -268,7 +328,11 @@ void TileMap::update_dirty_quadrants() {
q.canvas_items.clear(); q.canvas_items.clear();
ps->body_clear_shapes(q.body); if (!use_parent) {
ps->body_clear_shapes(q.body);
} else if (collision_parent) {
collision_parent->shape_owner_clear_shapes(q.shape_owner_id);
}
int shape_idx = 0; int shape_idx = 0;
if (navigation) { if (navigation) {
@ -427,10 +491,7 @@ void TileMap::update_dirty_quadrants() {
for (int k = 0; k < _shapes.size(); k++) { for (int k = 0; k < _shapes.size(); k++) {
Ref<ConvexPolygonShape2D> convex = _shapes[k]; Ref<ConvexPolygonShape2D> convex = _shapes[k];
if (convex.is_valid()) { if (convex.is_valid()) {
ps->body_add_shape(q.body, convex->get_rid(), xform); _add_shape(shape_idx, q, convex, shapes[j], xform, Vector2(E->key().x, E->key().y));
ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin);
shape_idx++;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
} else { } else {
print_error("The TileSet assigned to the TileMap " + get_name() + " has an invalid convex shape."); print_error("The TileSet assigned to the TileMap " + get_name() + " has an invalid convex shape.");
@ -438,10 +499,7 @@ void TileMap::update_dirty_quadrants() {
} }
} }
} else { } else {
ps->body_add_shape(q.body, shape->get_rid(), xform); _add_shape(shape_idx, q, shape, shapes[j], xform, Vector2(E->key().x, E->key().y));
ps->body_set_shape_metadata(q.body, shape_idx, Vector2(E->key().x, E->key().y));
ps->body_set_shape_as_one_way_collision(q.body, shape_idx, shapes[j].one_way_collision, shapes[j].one_way_collision_margin);
shape_idx++;
} }
} }
} }
@ -616,23 +674,30 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons
xform.set_origin(q.pos); xform.set_origin(q.pos);
//q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); //q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
q.body = Physics2DServer::get_singleton()->body_create(); if (!use_parent) {
Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC); q.body = Physics2DServer::get_singleton()->body_create();
Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC);
Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id()); Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id());
Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction);
Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce);
if (is_inside_tree()) { if (is_inside_tree()) {
xform = get_global_transform() * xform; xform = get_global_transform() * xform;
RID space = get_world_2d()->get_space(); RID space = get_world_2d()->get_space();
Physics2DServer::get_singleton()->body_set_space(q.body, space); Physics2DServer::get_singleton()->body_set_space(q.body, space);
}
Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
} else if (collision_parent) {
xform = get_transform() * xform;
q.shape_owner_id = collision_parent->create_shape_owner(this);
} else {
q.shape_owner_id = -1;
} }
Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform);
rect_cache_dirty = true; rect_cache_dirty = true;
quadrant_order_dirty = true; quadrant_order_dirty = true;
return quadrant_map.insert(p_qk, q); return quadrant_map.insert(p_qk, q);
@ -641,7 +706,12 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons
void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) { void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) {
Quadrant &q = Q->get(); Quadrant &q = Q->get();
Physics2DServer::get_singleton()->free(q.body); if (!use_parent) {
Physics2DServer::get_singleton()->free(q.body);
} else if (collision_parent) {
collision_parent->remove_shape_owner(q.shape_owner_id);
}
for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) { for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
VisualServer::get_singleton()->free(E->get()); VisualServer::get_singleton()->free(E->get());
@ -1135,20 +1205,24 @@ Rect2 TileMap::_edit_get_rect() const {
void TileMap::set_collision_layer(uint32_t p_layer) { void TileMap::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer; collision_layer = p_layer;
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { if (!use_parent) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get(); Quadrant &q = E->get();
Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer);
}
} }
} }
void TileMap::set_collision_mask(uint32_t p_mask) { void TileMap::set_collision_mask(uint32_t p_mask) {
collision_mask = p_mask; collision_mask = p_mask;
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { if (!use_parent) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get(); Quadrant &q = E->get();
Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask);
}
} }
} }
@ -1184,13 +1258,40 @@ void TileMap::set_collision_use_kinematic(bool p_use_kinematic) {
_recreate_quadrants(); _recreate_quadrants();
} }
bool TileMap::get_collision_use_parent() const {
return use_parent;
}
void TileMap::set_collision_use_parent(bool p_use_parent) {
if (use_parent == p_use_parent) return;
_clear_quadrants();
use_parent = p_use_parent;
set_notify_local_transform(use_parent);
if (use_parent && is_inside_tree()) {
collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
} else {
collision_parent = NULL;
}
_recreate_quadrants();
_change_notify();
update_configuration_warning();
}
void TileMap::set_collision_friction(float p_friction) { void TileMap::set_collision_friction(float p_friction) {
friction = p_friction; friction = p_friction;
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { if (!use_parent) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get(); Quadrant &q = E->get();
Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, p_friction); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, p_friction);
}
} }
} }
@ -1202,10 +1303,12 @@ float TileMap::get_collision_friction() const {
void TileMap::set_collision_bounce(float p_bounce) { void TileMap::set_collision_bounce(float p_bounce) {
bounce = p_bounce; bounce = p_bounce;
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) { if (!use_parent) {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get(); Quadrant &q = E->get();
Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, p_bounce); Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, p_bounce);
}
} }
} }
float TileMap::get_collision_bounce() const { float TileMap::get_collision_bounce() const {
@ -1404,6 +1507,12 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(p); p_list->push_back(p);
} }
void TileMap::_validate_property(PropertyInfo &property) const {
if (use_parent && property.name != "collision_use_parent" && property.name.begins_with("collision_")) {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
Vector2 TileMap::map_to_world(const Vector2 &p_pos, bool p_ignore_ofs) const { Vector2 TileMap::map_to_world(const Vector2 &p_pos, bool p_ignore_ofs) const {
return _map_to_world(p_pos.x, p_pos.y, p_ignore_ofs); return _map_to_world(p_pos.x, p_pos.y, p_ignore_ofs);
@ -1552,6 +1661,20 @@ bool TileMap::get_clip_uv() const {
return clip_uv; return clip_uv;
} }
String TileMap::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
if (use_parent && !collision_parent) {
if (!warning.empty()) {
warning += "\n";
}
return TTR("TileMap with Use Parent on needs a parent CollisionObject2D to give shapes to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.");
}
return warning;
}
void TileMap::_bind_methods() { void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset); ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
@ -1587,6 +1710,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_use_kinematic", "use_kinematic"), &TileMap::set_collision_use_kinematic); ClassDB::bind_method(D_METHOD("set_collision_use_kinematic", "use_kinematic"), &TileMap::set_collision_use_kinematic);
ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"), &TileMap::get_collision_use_kinematic); ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"), &TileMap::get_collision_use_kinematic);
ClassDB::bind_method(D_METHOD("set_collision_use_parent", "use_parent"), &TileMap::set_collision_use_parent);
ClassDB::bind_method(D_METHOD("get_collision_use_parent"), &TileMap::get_collision_use_parent);
ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &TileMap::set_collision_layer); ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &TileMap::set_collision_layer);
ClassDB::bind_method(D_METHOD("get_collision_layer"), &TileMap::get_collision_layer); ClassDB::bind_method(D_METHOD("get_collision_layer"), &TileMap::get_collision_layer);
@ -1652,6 +1778,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv");
ADD_GROUP("Collision", "collision_"); ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_parent", PROPERTY_HINT_NONE, ""), "set_collision_use_parent", "get_collision_use_parent");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
@ -1700,7 +1827,8 @@ TileMap::TileMap() {
bounce = 0; bounce = 0;
mode = MODE_SQUARE; mode = MODE_SQUARE;
half_offset = HALF_OFFSET_DISABLED; half_offset = HALF_OFFSET_DISABLED;
use_kinematic = false; use_parent = false;
collision_parent = NULL;
navigation = NULL; navigation = NULL;
y_sort_mode = false; y_sort_mode = false;
occluder_light_mask = 1; occluder_light_mask = 1;
@ -1710,6 +1838,7 @@ TileMap::TileMap() {
fp_adjust = 0.00001; fp_adjust = 0.00001;
tile_origin = TILE_ORIGIN_TOP_LEFT; tile_origin = TILE_ORIGIN_TOP_LEFT;
set_notify_transform(true); set_notify_transform(true);
set_notify_local_transform(false);
} }
TileMap::~TileMap() { TileMap::~TileMap() {

View file

@ -37,6 +37,8 @@
#include "scene/2d/node_2d.h" #include "scene/2d/node_2d.h"
#include "scene/resources/tile_set.h" #include "scene/resources/tile_set.h"
class CollisionObject2D;
class TileMap : public Node2D { class TileMap : public Node2D {
GDCLASS(TileMap, Node2D); GDCLASS(TileMap, Node2D);
@ -74,6 +76,8 @@ private:
Mode mode; Mode mode;
Transform2D custom_transform; Transform2D custom_transform;
HalfOffset half_offset; HalfOffset half_offset;
bool use_parent;
CollisionObject2D *collision_parent;
bool use_kinematic; bool use_kinematic;
Navigation2D *navigation; Navigation2D *navigation;
@ -123,6 +127,7 @@ private:
Vector2 pos; Vector2 pos;
List<RID> canvas_items; List<RID> canvas_items;
RID body; RID body;
uint32_t shape_owner_id;
SelfList<Quadrant> dirty_list; SelfList<Quadrant> dirty_list;
@ -145,6 +150,7 @@ private:
pos = q.pos; pos = q.pos;
canvas_items = q.canvas_items; canvas_items = q.canvas_items;
body = q.body; body = q.body;
shape_owner_id = q.shape_owner_id;
cells = q.cells; cells = q.cells;
navpoly_ids = q.navpoly_ids; navpoly_ids = q.navpoly_ids;
occluder_instances = q.occluder_instances; occluder_instances = q.occluder_instances;
@ -154,6 +160,7 @@ private:
pos = q.pos; pos = q.pos;
canvas_items = q.canvas_items; canvas_items = q.canvas_items;
body = q.body; body = q.body;
shape_owner_id = q.shape_owner_id;
cells = q.cells; cells = q.cells;
occluder_instances = q.occluder_instances; occluder_instances = q.occluder_instances;
navpoly_ids = q.navpoly_ids; navpoly_ids = q.navpoly_ids;
@ -188,6 +195,8 @@ private:
void _fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc); void _fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc);
void _add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata);
Map<PosKey, Quadrant>::Element *_create_quadrant(const PosKey &p_qk); Map<PosKey, Quadrant>::Element *_create_quadrant(const PosKey &p_qk);
void _erase_quadrant(Map<PosKey, Quadrant>::Element *Q); void _erase_quadrant(Map<PosKey, Quadrant>::Element *Q);
void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true); void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true);
@ -218,6 +227,7 @@ protected:
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const;
virtual void _changed_callback(Object *p_changed, const char *p_prop); virtual void _changed_callback(Object *p_changed, const char *p_prop);
public: public:
@ -271,6 +281,9 @@ public:
void set_collision_use_kinematic(bool p_use_kinematic); void set_collision_use_kinematic(bool p_use_kinematic);
bool get_collision_use_kinematic() const; bool get_collision_use_kinematic() const;
void set_collision_use_parent(bool p_use_parent);
bool get_collision_use_parent() const;
void set_collision_friction(float p_friction); void set_collision_friction(float p_friction);
float get_collision_friction() const; float get_collision_friction() const;
@ -314,6 +327,8 @@ public:
void set_clip_uv(bool p_enable); void set_clip_uv(bool p_enable);
bool get_clip_uv() const; bool get_clip_uv() const;
String get_configuration_warning() const;
void fix_invalid_tiles(); void fix_invalid_tiles();
void clear(); void clear();