diff options
author | Gilles Roudière <gilles.roudiere@gmail.com> | 2022-02-23 17:25:50 +0100 |
---|---|---|
committer | Gilles Roudière <gilles.roudiere@gmail.com> | 2022-06-10 14:37:39 +0200 |
commit | 62d2549e9ed1b8314827baa7f5799255ba9e8cdb (patch) | |
tree | 1fa3c1c9f728d1e4b727f82355f29f6bfc39021c /scene/resources | |
parent | 3dac7ff876edae8398cb0f3f27ec0bc68f1bbb8e (diff) |
Add terrain center bit
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/tile_set.cpp | 351 | ||||
-rw-r--r-- | scene/resources/tile_set.h | 52 |
2 files changed, 281 insertions, 122 deletions
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 9d2d4cdb20..8976aa17d2 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -236,6 +236,9 @@ bool TileSet::TerrainsPattern::operator<(const TerrainsPattern &p_terrains_patte return is_valid_bit[i] < p_terrains_pattern.is_valid_bit[i]; } } + if (terrain != p_terrains_pattern.terrain) { + return terrain < p_terrains_pattern.terrain; + } for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { if (is_valid_bit[i] && bits[i] != p_terrains_pattern.bits[i]) { return bits[i] < p_terrains_pattern.bits[i]; @@ -253,10 +256,23 @@ bool TileSet::TerrainsPattern::operator==(const TerrainsPattern &p_terrains_patt return false; } } + if (terrain != p_terrains_pattern.terrain) { + return false; + } return true; } -void TileSet::TerrainsPattern::set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain) { +void TileSet::TerrainsPattern::set_terrain(int p_terrain) { + ERR_FAIL_COND(p_terrain < -1); + + terrain = p_terrain; +} + +int TileSet::TerrainsPattern::get_terrain() const { + return terrain; +} + +void TileSet::TerrainsPattern::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain) { ERR_FAIL_COND(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX); ERR_FAIL_COND(!is_valid_bit[p_peering_bit]); ERR_FAIL_COND(p_terrain < -1); @@ -271,25 +287,27 @@ void TileSet::TerrainsPattern::set_terrain(TileSet::CellNeighbor p_peering_bit, bits[p_peering_bit] = p_terrain; } -int TileSet::TerrainsPattern::get_terrain(TileSet::CellNeighbor p_peering_bit) const { +int TileSet::TerrainsPattern::get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const { ERR_FAIL_COND_V(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX, -1); ERR_FAIL_COND_V(!is_valid_bit[p_peering_bit], -1); return bits[p_peering_bit]; } -void TileSet::TerrainsPattern::set_terrains_from_array(Array p_terrains) { - int in_array_index = 0; +void TileSet::TerrainsPattern::from_array(Array p_terrains) { + set_terrain(p_terrains[0]); + int in_array_index = 1; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { if (is_valid_bit[i]) { ERR_FAIL_INDEX(in_array_index, p_terrains.size()); - set_terrain(TileSet::CellNeighbor(i), p_terrains[in_array_index]); + set_terrain_peering_bit(TileSet::CellNeighbor(i), p_terrains[in_array_index]); in_array_index++; } } } -Array TileSet::TerrainsPattern::get_terrains_as_array() const { +Array TileSet::TerrainsPattern::as_array() const { Array output; + output.push_back(get_terrain()); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { if (is_valid_bit[i]) { output.push_back(bits[i]); @@ -297,10 +315,11 @@ Array TileSet::TerrainsPattern::get_terrains_as_array() const { } return output; } + TileSet::TerrainsPattern::TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set) { ERR_FAIL_COND(p_terrain_set < 0); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { - is_valid_bit[i] = (p_tile_set->is_valid_peering_bit_terrain(p_terrain_set, TileSet::CellNeighbor(i))); + is_valid_bit[i] = (p_tile_set->is_valid_terrain_peering_bit(p_terrain_set, TileSet::CellNeighbor(i))); bits[i] = -1; } valid = true; @@ -410,11 +429,16 @@ void TileSet::_update_terrains_cache() { TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern(); + // Main terrain. + if (terrains_pattern.get_terrain() >= 0) { + per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell); + } + // Terrain bits. for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { CellNeighbor bit = CellNeighbor(i); - if (is_valid_peering_bit_terrain(terrain_set, bit)) { - int terrain = terrains_pattern.get_terrain(bit); + if (is_valid_terrain_peering_bit(terrain_set, bit)) { + int terrain = terrains_pattern.get_terrain_peering_bit(bit); if (terrain >= 0) { per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell); } @@ -822,7 +846,7 @@ Color TileSet::get_terrain_color(int p_terrain_set, int p_terrain_index) const { return terrain_sets[p_terrain_set].terrains[p_terrain_index].color; } -bool TileSet::is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const { +bool TileSet::is_valid_terrain_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const { if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) { if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE || @@ -905,13 +929,13 @@ bool TileSet::is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, return false; } -bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const { +bool TileSet::is_valid_terrain_peering_bit(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const { if (p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count()) { return false; } TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set); - return is_valid_peering_bit_for_mode(terrain_mode, p_peering_bit); + return is_valid_terrain_peering_bit_for_mode(terrain_mode, p_peering_bit); } // Navigation @@ -1494,26 +1518,48 @@ void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform } } -Vector<Point2> TileSet::get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) { + if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { + return _get_square_terrain_polygon(tile_size); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + return _get_isometric_terrain_polygon(tile_size); + } else { + float overlap = 0.0; + switch (tile_shape) { + case TileSet::TILE_SHAPE_HEXAGON: + overlap = 0.25; + break; + case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE: + overlap = 0.0; + break; + default: + break; + } + return _get_half_offset_terrain_polygon(tile_size, overlap, tile_offset_axis); + } + return Vector<Point2>(); +} + +Vector<Point2> TileSet::get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) { ERR_FAIL_COND_V(p_terrain_set < 0 || p_terrain_set >= get_terrain_sets_count(), Vector<Point2>()); TileSet::TerrainMode terrain_mode = get_terrain_set_mode(p_terrain_set); if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - return _get_square_corner_or_side_terrain_bit_polygon(tile_size, p_bit); + return _get_square_corner_or_side_terrain_peering_bit_polygon(tile_size, p_bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - return _get_square_corner_terrain_bit_polygon(tile_size, p_bit); + return _get_square_corner_terrain_peering_bit_polygon(tile_size, p_bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - return _get_square_side_terrain_bit_polygon(tile_size, p_bit); + return _get_square_side_terrain_peering_bit_polygon(tile_size, p_bit); } } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - return _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, p_bit); + return _get_isometric_corner_or_side_terrain_peering_bit_polygon(tile_size, p_bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - return _get_isometric_corner_terrain_bit_polygon(tile_size, p_bit); + return _get_isometric_corner_terrain_peering_bit_polygon(tile_size, p_bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - return _get_isometric_side_terrain_bit_polygon(tile_size, p_bit); + return _get_isometric_side_terrain_peering_bit_polygon(tile_size, p_bit); } } else { float overlap = 0.0; @@ -1528,11 +1574,11 @@ Vector<Point2> TileSet::get_terrain_bit_polygon(int p_terrain_set, TileSet::Cell break; } if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - return _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis); + return _get_half_offset_corner_or_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - return _get_half_offset_corner_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis); + return _get_half_offset_corner_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - return _get_half_offset_side_terrain_bit_polygon(tile_size, p_bit, overlap, tile_offset_axis); + return _get_half_offset_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, p_bit); } } } @@ -1544,30 +1590,68 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, if (terrain_bits_meshes_dirty) { // Recompute the meshes. - terrain_bits_meshes.clear(); + terrain_peering_bits_meshes.clear(); for (int terrain_mode_index = 0; terrain_mode_index < 3; terrain_mode_index++) { TerrainMode terrain_mode = TerrainMode(terrain_mode_index); + + // Center terrain + Vector<Vector2> polygon; + if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { + polygon = _get_square_terrain_polygon(tile_size); + } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { + polygon = _get_isometric_terrain_polygon(tile_size); + } else { + float overlap = 0.0; + switch (tile_shape) { + case TileSet::TILE_SHAPE_HEXAGON: + overlap = 0.25; + break; + case TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE: + overlap = 0.0; + break; + default: + break; + } + polygon = _get_half_offset_terrain_polygon(tile_size, overlap, tile_offset_axis); + } + { + Ref<ArrayMesh> mesh; + mesh.instantiate(); + Vector<Vector2> uvs; + uvs.resize(polygon.size()); + Vector<Color> colors; + colors.resize(polygon.size()); + colors.fill(Color(1.0, 1.0, 1.0, 1.0)); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX] = polygon; + a[Mesh::ARRAY_TEX_UV] = uvs; + a[Mesh::ARRAY_COLOR] = colors; + a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon); + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES); + terrain_meshes[terrain_mode] = mesh; + } + // Peering bits for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { CellNeighbor bit = CellNeighbor(i); - if (is_valid_peering_bit_for_mode(terrain_mode, bit)) { - Vector<Vector2> polygon; + if (is_valid_terrain_peering_bit_for_mode(terrain_mode, bit)) { if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - polygon = _get_square_corner_or_side_terrain_bit_polygon(tile_size, bit); + polygon = _get_square_corner_or_side_terrain_peering_bit_polygon(tile_size, bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - polygon = _get_square_corner_terrain_bit_polygon(tile_size, bit); + polygon = _get_square_corner_terrain_peering_bit_polygon(tile_size, bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - polygon = _get_square_side_terrain_bit_polygon(tile_size, bit); + polygon = _get_square_side_terrain_peering_bit_polygon(tile_size, bit); } } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - polygon = _get_isometric_corner_or_side_terrain_bit_polygon(tile_size, bit); + polygon = _get_isometric_corner_or_side_terrain_peering_bit_polygon(tile_size, bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - polygon = _get_isometric_corner_terrain_bit_polygon(tile_size, bit); + polygon = _get_isometric_corner_terrain_peering_bit_polygon(tile_size, bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - polygon = _get_isometric_side_terrain_bit_polygon(tile_size, bit); + polygon = _get_isometric_side_terrain_peering_bit_polygon(tile_size, bit); } } else { float overlap = 0.0; @@ -1582,29 +1666,30 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, break; } if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - polygon = _get_half_offset_corner_or_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis); + polygon = _get_half_offset_corner_or_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit); } else if (terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - polygon = _get_half_offset_corner_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis); + polygon = _get_half_offset_corner_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit); } else { // TileData::TERRAIN_MODE_MATCH_SIDES - polygon = _get_half_offset_side_terrain_bit_polygon(tile_size, bit, overlap, tile_offset_axis); + polygon = _get_half_offset_side_terrain_peering_bit_polygon(tile_size, overlap, tile_offset_axis, bit); } } - - Ref<ArrayMesh> mesh; - mesh.instantiate(); - Vector<Vector2> uvs; - uvs.resize(polygon.size()); - Vector<Color> colors; - colors.resize(polygon.size()); - colors.fill(Color(1.0, 1.0, 1.0, 1.0)); - Array a; - a.resize(Mesh::ARRAY_MAX); - a[Mesh::ARRAY_VERTEX] = polygon; - a[Mesh::ARRAY_TEX_UV] = uvs; - a[Mesh::ARRAY_COLOR] = colors; - a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon); - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES); - terrain_bits_meshes[terrain_mode][bit] = mesh; + { + Ref<ArrayMesh> mesh; + mesh.instantiate(); + Vector<Vector2> uvs; + uvs.resize(polygon.size()); + Vector<Color> colors; + colors.resize(polygon.size()); + colors.fill(Color(1.0, 1.0, 1.0, 1.0)); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX] = polygon; + a[Mesh::ARRAY_TEX_UV] = uvs; + a[Mesh::ARRAY_COLOR] = colors; + a[Mesh::ARRAY_INDEX] = Geometry2D::triangulate_polygon(polygon); + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES); + terrain_peering_bits_meshes[terrain_mode][bit] = mesh; + } } } } @@ -1618,14 +1703,21 @@ void TileSet::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet::TerrainMode terrain_mode = get_terrain_set_mode(terrain_set); RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), p_transform); + int terrain_id = p_tile_data->get_terrain(); + if (terrain_id >= 0) { + Color color = get_terrain_color(terrain_set, terrain_id); + color.a = TERRAIN_ALPHA; + p_canvas_item->draw_mesh(terrain_meshes[terrain_mode], Ref<Texture2D>(), Transform2D(), color); + } + for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { CellNeighbor bit = CellNeighbor(i); - if (is_valid_peering_bit_terrain(terrain_set, bit)) { - int terrain_id = p_tile_data->get_peering_bit_terrain(bit); + if (is_valid_terrain_peering_bit(terrain_set, bit)) { + terrain_id = p_tile_data->get_terrain_peering_bit(bit); if (terrain_id >= 0) { Color color = get_terrain_color(terrain_set, terrain_id); color.a = TERRAIN_ALPHA; - p_canvas_item->draw_mesh(terrain_bits_meshes[terrain_mode][bit], Ref<Texture2D>(), Transform2D(), color); + p_canvas_item->draw_mesh(terrain_peering_bits_meshes[terrain_mode][bit], Ref<Texture2D>(), Transform2D(), color); } } } @@ -1670,13 +1762,16 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) { for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) { bit_counts[terrain] = 0; } + if (tile_data->get_terrain() >= 0) { + bit_counts[tile_data->get_terrain()] += 10; + } for (int terrain_bit = 0; terrain_bit < TileSet::CELL_NEIGHBOR_MAX; terrain_bit++) { TileSet::CellNeighbor cell_neighbor = TileSet::CellNeighbor(terrain_bit); - if (is_valid_peering_bit_terrain(terrain_set, cell_neighbor)) { - int terrain = tile_data->get_peering_bit_terrain(cell_neighbor); + if (is_valid_terrain_peering_bit(terrain_set, cell_neighbor)) { + int terrain = tile_data->get_terrain_peering_bit(cell_neighbor); if (terrain >= 0) { if (terrain >= (int)bit_counts.size()) { - WARN_PRINT(vformat("Invalid peering bit terrain: %d", terrain)); + WARN_PRINT(vformat("Invalid terrain peering bit: %d", terrain)); } else { bit_counts[terrain] += 1; } @@ -1730,7 +1825,17 @@ void TileSet::_source_changed() { emit_changed(); } -Vector<Point2> TileSet::_get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_square_terrain_polygon(Vector2i p_size) { + Rect2 rect(-Vector2(p_size) / 6.0, Vector2(p_size) / 3.0); + return { + rect.position, + Vector2(rect.get_end().x, rect.position.y), + rect.get_end(), + Vector2(rect.position.x, rect.get_end().y) + }; +} + +Vector<Point2> TileSet::_get_square_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Rect2 bit_rect; bit_rect.size = Vector2(p_size) / 3; switch (p_bit) { @@ -1773,7 +1878,7 @@ Vector<Point2> TileSet::_get_square_corner_or_side_terrain_bit_polygon(Vector2i return polygon; } -Vector<Point2> TileSet::_get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_square_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Vector2 unit = Vector2(p_size) / 6.0; Vector<Vector2> polygon; switch (p_bit) { @@ -1815,7 +1920,7 @@ Vector<Point2> TileSet::_get_square_corner_terrain_bit_polygon(Vector2i p_size, return polygon; } -Vector<Point2> TileSet::_get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_square_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Vector2 unit = Vector2(p_size) / 6.0; Vector<Vector2> polygon; switch (p_bit) { @@ -1849,7 +1954,17 @@ Vector<Point2> TileSet::_get_square_side_terrain_bit_polygon(Vector2i p_size, Ti return polygon; } -Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_isometric_terrain_polygon(Vector2i p_size) { + Vector2 unit = Vector2(p_size) / 6.0; + return { + Vector2(1, 0) * unit, + Vector2(0, 1) * unit, + Vector2(-1, 0) * unit, + Vector2(0, -1) * unit, + }; +} + +Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Vector2 unit = Vector2(p_size) / 6.0; Vector<Vector2> polygon; switch (p_bit) { @@ -1907,7 +2022,7 @@ Vector<Point2> TileSet::_get_isometric_corner_or_side_terrain_bit_polygon(Vector return polygon; } -Vector<Point2> TileSet::_get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_isometric_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Vector2 unit = Vector2(p_size) / 6.0; Vector<Vector2> polygon; switch (p_bit) { @@ -1949,7 +2064,7 @@ Vector<Point2> TileSet::_get_isometric_corner_terrain_bit_polygon(Vector2i p_siz return polygon; } -Vector<Point2> TileSet::_get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { +Vector<Point2> TileSet::_get_isometric_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit) { Vector2 unit = Vector2(p_size) / 6.0; Vector<Vector2> polygon; switch (p_bit) { @@ -1983,7 +2098,30 @@ Vector<Point2> TileSet::_get_isometric_side_terrain_bit_polygon(Vector2i p_size, return polygon; } -Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +Vector<Point2> TileSet::_get_half_offset_terrain_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { + Vector2 unit = Vector2(p_size) / 6.0; + if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + return { + Vector2(1, 1.0 - p_overlap * 2.0) * unit, + Vector2(0, 1) * unit, + Vector2(-1, 1.0 - p_overlap * 2.0) * unit, + Vector2(-1, -1.0 + p_overlap * 2.0) * unit, + Vector2(0, -1) * unit, + Vector2(1, -1.0 + p_overlap * 2.0) * unit, + }; + } else { + return { + Vector2(1, 0) * unit, + Vector2(1.0 - p_overlap * 2.0, -1) * unit, + Vector2(-1.0 + p_overlap * 2.0, -1) * unit, + Vector2(-1, 0) * unit, + Vector2(-1.0 + p_overlap * 2.0, 1) * unit, + Vector2(1.0 - p_overlap * 2.0, 1) * unit, + }; + } +} + +Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) { Vector<Vector2> point_list = { Vector2(3, (3.0 * (1.0 - p_overlap * 2.0)) / 2.0), Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)), @@ -2006,12 +2144,11 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect }; Vector2 unit = Vector2(p_size) / 6.0; - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = point_list[i] * unit; - } - Vector<Vector2> polygon; if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = point_list[i] * unit; + } switch (p_bit) { case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: polygon.push_back(point_list[17]); @@ -2071,10 +2208,8 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect break; } } else { - if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) { - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = Vector2(point_list[i].y, point_list[i].x); - } + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit; } switch (p_bit) { case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: @@ -2144,7 +2279,7 @@ Vector<Point2> TileSet::_get_half_offset_corner_or_side_terrain_bit_polygon(Vect return polygon; } -Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +Vector<Point2> TileSet::_get_half_offset_corner_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) { Vector<Vector2> point_list = { Vector2(3, 0), Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)), @@ -2161,12 +2296,11 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s }; Vector2 unit = Vector2(p_size) / 6.0; - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = point_list[i] * unit; - } - Vector<Vector2> polygon; if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = point_list[i] * unit; + } switch (p_bit) { case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER: polygon.push_back(point_list[0]); @@ -2202,10 +2336,8 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s break; } } else { - if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) { - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = Vector2(point_list[i].y, point_list[i].x); - } + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit; } switch (p_bit) { case TileSet::CELL_NEIGHBOR_RIGHT_CORNER: @@ -2251,7 +2383,7 @@ Vector<Point2> TileSet::_get_half_offset_corner_terrain_bit_polygon(Vector2i p_s return polygon; } -Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +Vector<Point2> TileSet::_get_half_offset_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit) { Vector<Vector2> point_list = { Vector2(3, 3.0 * (1.0 - p_overlap * 2.0)), Vector2(0, 3), @@ -2262,12 +2394,11 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_siz }; Vector2 unit = Vector2(p_size) / 6.0; - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = point_list[i] * unit; - } - Vector<Vector2> polygon; if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) { + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = point_list[i] * unit; + } switch (p_bit) { case TileSet::CELL_NEIGHBOR_RIGHT_SIDE: polygon.push_back(point_list[5]); @@ -2297,10 +2428,8 @@ Vector<Point2> TileSet::_get_half_offset_side_terrain_bit_polygon(Vector2i p_siz break; } } else { - if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) { - for (int i = 0; i < point_list.size(); i++) { - point_list.write[i] = Vector2(point_list[i].y, point_list[i].x); - } + for (int i = 0; i < point_list.size(); i++) { + point_list.write[i] = Vector2(point_list[i].y, point_list[i].x) * unit; } switch (p_bit) { case TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE: @@ -5114,36 +5243,51 @@ int TileData::get_terrain_set() const { return terrain_set; } -void TileData::set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) { +void TileData::set_terrain(int p_terrain) { + ERR_FAIL_COND(terrain_set < 0); + ERR_FAIL_COND(p_terrain < -1); + if (tile_set) { + ERR_FAIL_COND(p_terrain >= tile_set->get_terrains_count(terrain_set)); + } + terrain = p_terrain; + emit_signal(SNAME("changed")); +} + +int TileData::get_terrain() const { + return terrain; +} + +void TileData::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) { ERR_FAIL_INDEX(p_peering_bit, TileSet::CellNeighbor::CELL_NEIGHBOR_MAX); ERR_FAIL_COND(terrain_set < 0); ERR_FAIL_COND(p_terrain_index < -1); if (tile_set) { ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set)); - ERR_FAIL_COND(!is_valid_peering_bit_terrain(p_peering_bit)); + ERR_FAIL_COND(!is_valid_terrain_peering_bit(p_peering_bit)); } terrain_peering_bits[p_peering_bit] = p_terrain_index; emit_signal(SNAME("changed")); } -int TileData::get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const { - ERR_FAIL_COND_V(!is_valid_peering_bit_terrain(p_peering_bit), -1); +int TileData::get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const { + ERR_FAIL_COND_V(!is_valid_terrain_peering_bit(p_peering_bit), -1); return terrain_peering_bits[p_peering_bit]; } -bool TileData::is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const { +bool TileData::is_valid_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const { ERR_FAIL_COND_V(!tile_set, false); - return tile_set->is_valid_peering_bit_terrain(terrain_set, p_peering_bit); + return tile_set->is_valid_terrain_peering_bit(terrain_set, p_peering_bit); } TileSet::TerrainsPattern TileData::get_terrains_pattern() const { ERR_FAIL_COND_V(!tile_set, TileSet::TerrainsPattern()); TileSet::TerrainsPattern output(tile_set, terrain_set); + output.set_terrain(terrain); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { - if (tile_set->is_valid_peering_bit_terrain(terrain_set, TileSet::CellNeighbor(i))) { - output.set_terrain(TileSet::CellNeighbor(i), get_peering_bit_terrain(TileSet::CellNeighbor(i))); + if (tile_set->is_valid_terrain_peering_bit(terrain_set, TileSet::CellNeighbor(i))) { + output.set_terrain_peering_bit(TileSet::CellNeighbor(i), get_terrain_peering_bit(TileSet::CellNeighbor(i))); } } return output; @@ -5293,7 +5437,7 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (components[1] == TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]) { - set_peering_bit_terrain(bit, p_value); + set_terrain_peering_bit(bit, p_value); return true; } } @@ -5455,9 +5599,9 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); - if (is_valid_peering_bit_terrain(bit)) { + if (is_valid_terrain_peering_bit(bit)) { property_info = PropertyInfo(Variant::INT, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i])); - if (get_peering_bit_terrain(bit) == -1) { + if (get_terrain_peering_bit(bit) == -1) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } p_list->push_back(property_info); @@ -5531,8 +5675,10 @@ void TileData::_bind_methods() { // Terrain ClassDB::bind_method(D_METHOD("set_terrain_set", "terrain_set"), &TileData::set_terrain_set); ClassDB::bind_method(D_METHOD("get_terrain_set"), &TileData::get_terrain_set); - ClassDB::bind_method(D_METHOD("set_peering_bit_terrain", "peering_bit", "terrain"), &TileData::set_peering_bit_terrain); - ClassDB::bind_method(D_METHOD("get_peering_bit_terrain", "peering_bit"), &TileData::get_peering_bit_terrain); + ClassDB::bind_method(D_METHOD("set_terrain", "terrain"), &TileData::set_terrain); + ClassDB::bind_method(D_METHOD("get_terrain"), &TileData::get_terrain); + ClassDB::bind_method(D_METHOD("set_terrain_peering_bit", "peering_bit", "terrain"), &TileData::set_terrain_peering_bit); + ClassDB::bind_method(D_METHOD("get_terrain_peering_bit", "peering_bit"), &TileData::get_terrain_peering_bit); // Navigation ClassDB::bind_method(D_METHOD("set_navigation_polygon", "layer_id", "navigation_polygon"), &TileData::set_navigation_polygon); @@ -5560,6 +5706,7 @@ void TileData::_bind_methods() { ADD_GROUP("Terrains", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain_set"), "set_terrain_set", "get_terrain_set"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain"), "set_terrain", "get_terrain"); ADD_GROUP("Miscellaneous", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "probability"), "set_probability", "get_probability"); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 615ab35615..181782e5af 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -265,6 +265,7 @@ public: class TerrainsPattern { bool valid = false; + int terrain = -1; int bits[TileSet::CELL_NEIGHBOR_MAX]; bool is_valid_bit[TileSet::CELL_NEIGHBOR_MAX]; @@ -277,11 +278,14 @@ public: bool operator<(const TerrainsPattern &p_terrains_pattern) const; bool operator==(const TerrainsPattern &p_terrains_pattern) const; - void set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain); - int get_terrain(TileSet::CellNeighbor p_peering_bit) const; + void set_terrain(int p_terrain); + int get_terrain() const; - void set_terrains_from_array(Array p_terrains); - Array get_terrains_as_array() const; + void set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain); + int get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const; + + void from_array(Array p_terrains); + Array as_array() const; TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set); TerrainsPattern() {} @@ -333,7 +337,8 @@ private: }; Vector<TerrainSet> terrain_sets; - HashMap<TerrainMode, HashMap<CellNeighbor, Ref<ArrayMesh>>> terrain_bits_meshes; + HashMap<TerrainMode, Ref<ArrayMesh>> terrain_meshes; + HashMap<TerrainMode, HashMap<CellNeighbor, Ref<ArrayMesh>>> terrain_peering_bits_meshes; bool terrain_bits_meshes_dirty = true; LocalVector<RBMap<TileSet::TerrainsPattern, RBSet<TileMapCell>>> per_terrain_pattern_tiles; // Cached data. @@ -371,17 +376,20 @@ private: RBMap<Array, Array> alternative_level_proxies; // Helpers - Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_square_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_square_terrain_polygon(Vector2i p_size); + Vector<Point2> _get_square_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_square_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_square_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_isometric_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_isometric_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_isometric_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_isometric_terrain_polygon(Vector2i p_size); + Vector<Point2> _get_isometric_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_isometric_corner_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_isometric_side_terrain_peering_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit); - Vector<Point2> _get_half_offset_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis); - Vector<Point2> _get_half_offset_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis); - Vector<Point2> _get_half_offset_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis); + Vector<Point2> _get_half_offset_terrain_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis); + Vector<Point2> _get_half_offset_corner_or_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_half_offset_corner_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit); + Vector<Point2> _get_half_offset_side_terrain_peering_bit_polygon(Vector2i p_size, float p_overlap, TileSet::TileOffsetAxis p_offset_axis, TileSet::CellNeighbor p_bit); protected: static void _bind_methods(); @@ -454,8 +462,8 @@ public: String get_terrain_name(int p_terrain_set, int p_terrain_index) const; void set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color); Color get_terrain_color(int p_terrain_set, int p_terrain_index) const; - bool is_valid_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const; - bool is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const; + bool is_valid_terrain_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const; + bool is_valid_terrain_peering_bit(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const; // Navigation int get_navigation_layers_count() const; @@ -516,7 +524,8 @@ public: Vector<Vector2> get_tile_shape_polygon(); void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>()); - Vector<Point2> get_terrain_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit); + Vector<Point2> get_terrain_polygon(int p_terrain_set); + Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit); void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, const TileData *p_tile_data); Vector<Vector<Ref<Texture2D>>> generate_terrains_icons(Size2i p_size); @@ -798,6 +807,7 @@ private: // Terrain int terrain_set = -1; + int terrain = -1; int terrain_peering_bits[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // Navigation @@ -887,9 +897,11 @@ public: // Terrain void set_terrain_set(int p_terrain_id); int get_terrain_set() const; - void set_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain_id); - int get_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const; - bool is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit) const; + void set_terrain(int p_terrain_id); + int get_terrain() const; + void set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_id); + int get_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const; + bool is_valid_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit) const; TileSet::TerrainsPattern get_terrains_pattern() const; // Not exposed. |