summaryrefslogtreecommitdiff
path: root/scene/2d/tile_map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/tile_map.cpp')
-rw-r--r--scene/2d/tile_map.cpp149
1 files changed, 96 insertions, 53 deletions
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 13f1d258a8..e899b9a8ef 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -236,6 +236,8 @@ Vector2i TileMap::transform_coords_layout(Vector2i p_coords, TileSet::TileOffset
}
int TileMap::get_effective_quadrant_size(int p_layer) const {
+ ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), 1);
+
// When using YSort, the quadrant size is reduced to 1 to have one CanvasItem per quadrant
if (is_y_sort_enabled() && layers[p_layer].y_sort_enabled) {
return 1;
@@ -314,16 +316,38 @@ int TileMap::get_quadrant_size() const {
return quadrant_size;
}
-void TileMap::set_layers_count(int p_layers_count) {
- ERR_FAIL_COND(p_layers_count < 0);
- _clear_internals();
+int TileMap::get_layers_count() const {
+ return layers.size();
+}
+
+void TileMap::add_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = layers.size();
+ }
+
+ ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
+
+ layers.insert(p_to_pos, TileMapLayer());
+ _recreate_internals();
+ notify_property_list_changed();
- layers.resize(p_layers_count);
+ emit_signal(SNAME("changed"));
+
+ update_configuration_warnings();
+}
+
+void TileMap::move_layer(int p_layer, int p_to_pos) {
+ ERR_FAIL_INDEX(p_layer, (int)layers.size());
+ ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
+
+ TileMapLayer tl = layers[p_layer];
+ layers.insert(p_to_pos, tl);
+ layers.remove(p_to_pos < p_layer ? p_layer + 1 : p_layer);
_recreate_internals();
notify_property_list_changed();
- if (selected_layer >= p_layers_count) {
- selected_layer = -1;
+ if (selected_layer == p_layer) {
+ selected_layer = p_to_pos < p_layer ? p_to_pos - 1 : p_to_pos;
}
emit_signal(SNAME("changed"));
@@ -331,8 +355,20 @@ void TileMap::set_layers_count(int p_layers_count) {
update_configuration_warnings();
}
-int TileMap::get_layers_count() const {
- return layers.size();
+void TileMap::remove_layer(int p_layer) {
+ ERR_FAIL_INDEX(p_layer, (int)layers.size());
+
+ layers.remove(p_layer);
+ _recreate_internals();
+ notify_property_list_changed();
+
+ if (selected_layer >= p_layer) {
+ selected_layer -= 1;
+ }
+
+ emit_signal(SNAME("changed"));
+
+ update_configuration_warnings();
}
void TileMap::set_layer_name(int p_layer, String p_name) {
@@ -781,7 +817,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
if (atlas_source) {
// Get the tile data.
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile));
- Ref<ShaderMaterial> mat = tile_data->tile_get_material();
+ Ref<ShaderMaterial> mat = tile_data->get_material();
int z_index = tile_data->get_z_index();
// Quandrant pos.
@@ -1147,7 +1183,7 @@ void TileMap::_physics_create_quadrant(TileMapQuadrant *p_quadrant) {
PhysicsServer2D::get_singleton()->body_set_space(body, space);
Transform2D xform;
- xform.set_origin(map_to_world(p_quadrant->coords * get_effective_quadrant_size(layer)));
+ xform.set_origin(map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)));
xform = global_transform * xform;
PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
@@ -2821,50 +2857,57 @@ void TileMap::draw_cells_outline(Control *p_control, Set<Vector2i> p_cells, Colo
// Create a set.
Vector2i tile_size = tile_set->get_tile_size();
- Vector<Vector2> uvs;
+ Vector<Vector2> polygon = tile_set->get_tile_shape_polygon();
+ TileSet::TileShape shape = tile_set->get_tile_shape();
- if (tile_set->get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
- uvs.append(Vector2(1.0, 0.0));
- uvs.append(Vector2(1.0, 1.0));
- uvs.append(Vector2(0.0, 1.0));
- uvs.append(Vector2(0.0, 0.0));
- } else {
- float overlap = 0.0;
- switch (tile_set->get_tile_shape()) {
- case TileSet::TILE_SHAPE_ISOMETRIC:
- overlap = 0.5;
- break;
- case TileSet::TILE_SHAPE_HEXAGON:
- overlap = 0.25;
- break;
- case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE:
- overlap = 0.0;
- break;
- default:
- break;
- }
- uvs.append(Vector2(1.0, overlap));
- uvs.append(Vector2(1.0, 1.0 - overlap));
- uvs.append(Vector2(0.5, 1.0));
- uvs.append(Vector2(0.0, 1.0 - overlap));
- uvs.append(Vector2(0.0, overlap));
- uvs.append(Vector2(0.5, 0.0));
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- for (int i = 0; i < uvs.size(); i++) {
- uvs.write[i] = Vector2(uvs[i].y, uvs[i].x);
- }
- }
+ for (Set<Vector2i>::Element *E = p_cells.front(); E; E = E->next()) {
+ Vector2 center = map_to_world(E->get());
+
+#define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \
+ if (!p_cells.has(get_neighbor_cell(E->get(), side))) { \
+ Vector2 from = p_transform.xform(center + polygon[polygon_index_from] * tile_size); \
+ Vector2 to = p_transform.xform(center + polygon[polygon_index_to] * tile_size); \
+ p_control->draw_line(from, to, p_color); \
}
- for (Set<Vector2i>::Element *E = p_cells.front(); E; E = E->next()) {
- Vector2 top_left = map_to_world(E->get()) - tile_size / 2;
- TypedArray<Vector2i> surrounding_tiles = get_surrounding_tiles(E->get());
- for (int i = 0; i < surrounding_tiles.size(); i++) {
- if (!p_cells.has(surrounding_tiles[i])) {
- p_control->draw_line(p_transform.xform(top_left + uvs[i] * tile_size), p_transform.xform(top_left + uvs[(i + 1) % uvs.size()] * tile_size), p_color);
+ if (shape == TileSet::TILE_SHAPE_SQUARE) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
+ } else {
+ if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
+ } else {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
+ }
+ } else {
+ if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
+ } else {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
+ }
}
}
}
+#undef DRAW_SIDE_IF_NEEDED
}
TypedArray<String> TileMap::get_configuration_warnings() const {
@@ -2896,8 +2939,10 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_quadrant_size", "size"), &TileMap::set_quadrant_size);
ClassDB::bind_method(D_METHOD("get_quadrant_size"), &TileMap::get_quadrant_size);
- ClassDB::bind_method(D_METHOD("set_layers_count", "layers_count"), &TileMap::set_layers_count);
ClassDB::bind_method(D_METHOD("get_layers_count"), &TileMap::get_layers_count);
+ ClassDB::bind_method(D_METHOD("add_layer", "to_position"), &TileMap::add_layer);
+ ClassDB::bind_method(D_METHOD("move_layer", "layer", "to_position"), &TileMap::move_layer);
+ ClassDB::bind_method(D_METHOD("remove_layer", "layer"), &TileMap::remove_layer);
ClassDB::bind_method(D_METHOD("set_layer_name", "layer", "name"), &TileMap::set_layer_name);
ClassDB::bind_method(D_METHOD("get_layer_name", "layer"), &TileMap::get_layer_name);
ClassDB::bind_method(D_METHOD("set_layer_enabled", "layer", "enabled"), &TileMap::set_layer_enabled);
@@ -2907,7 +2952,7 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer_y_sort_origin", "layer", "y_sort_origin"), &TileMap::set_layer_y_sort_origin);
ClassDB::bind_method(D_METHOD("get_layer_y_sort_origin", "layer"), &TileMap::get_layer_y_sort_origin);
ClassDB::bind_method(D_METHOD("set_layer_z_index", "layer", "z_index"), &TileMap::set_layer_z_index);
- ClassDB::bind_method(D_METHOD("get_layer_z_indexd", "layer"), &TileMap::get_layer_z_index);
+ ClassDB::bind_method(D_METHOD("get_layer_z_index", "layer"), &TileMap::get_layer_z_index);
ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "collision_visibility_mode"), &TileMap::set_collision_visibility_mode);
ClassDB::bind_method(D_METHOD("get_collision_visibility_mode"), &TileMap::get_collision_visibility_mode);
@@ -2942,9 +2987,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");
- ADD_GROUP("Layers", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers_count"), "set_layers_count", "get_layers_count");
- ADD_PROPERTY_DEFAULT("layers_count", 1);
+ ADD_ARRAY("layers", "layer_");
ADD_PROPERTY_DEFAULT("format", FORMAT_1);