Import old tiles in SINGLE_TILE mode as atlases

This commit is contained in:
Gilles Roudière 2021-06-30 12:03:22 +02:00
parent 88bf6e1c6d
commit 047e9b19f8
3 changed files with 175 additions and 35 deletions

View file

@ -805,19 +805,16 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
if (format == FORMAT_3) {
uint16_t source_id = decode_uint16(&local[4]);
uint16_t atlas_coords_x = decode_uint16(&local[6]);
uint16_t atlas_coords_y = decode_uint32(&local[8]);
uint16_t atlas_coords_y = decode_uint16(&local[8]);
uint16_t alternative_tile = decode_uint16(&local[10]);
set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
} else {
#ifndef DISABLE_DEPRECATED
uint32_t v = decode_uint32(&local[4]);
v &= (1 << 29) - 1;
// We generate an alternative tile number out of the the flags
// An option should create the alternative in the tileset for compatibility
bool flip_h = v & (1 << 29);
bool flip_v = v & (1 << 30);
bool transpose = v & (1 << 31);
v &= (1 << 29) - 1;
int16_t coord_x = 0;
int16_t coord_y = 0;
if (format == FORMAT_2) {
@ -825,13 +822,17 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
coord_y = decode_uint16(&local[10]);
}
int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
if (tile_set.is_valid()) {
v = tile_set->compatibility_get_source_for_tile_id(v);
Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
if (a.size() == 3) {
set_cell(Vector2i(x, y), a[0], a[1], a[2]);
} else {
ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose));
}
} else {
int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
}
#endif
}
}

View file

@ -1539,7 +1539,7 @@ const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
#ifndef DISABLE_DEPRECATED
void TileSet::compatibility_conversion() {
void TileSet::_compatibility_conversion() {
for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
CompatibilityTileData *ctd = E->value();
@ -1551,13 +1551,94 @@ void TileSet::compatibility_conversion() {
// Handle each tile as a new source. Not optimal but at least it should stay compatible.
switch (ctd->tile_mode) {
case 0: // SINGLE_TILE
case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
atlas_source->set_margins(ctd->region.get_position());
atlas_source->set_texture_region_size(ctd->region.get_size());
Vector2i coords = Vector2i(0, 0);
for (int flags = 0; flags < 8; flags++) {
bool flip_h = flags & 1;
bool flip_v = flags & 2;
bool transpose = flags & 4;
int alternative_tile = 0;
if (!atlas_source->has_tile(coords)) {
atlas_source->create_tile(coords);
} else {
alternative_tile = atlas_source->create_alternative_tile(coords);
}
// Add to the mapping.
Array key_array;
key_array.push_back(flip_h);
key_array.push_back(flip_v);
key_array.push_back(transpose);
Array value_array;
value_array.push_back(source_id);
value_array.push_back(coords);
value_array.push_back(alternative_tile);
if (!compatibility_tilemap_mapping.has(E->key())) {
compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
}
compatibility_tilemap_mapping[E->key()][key_array] = value_array;
compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_SINGLE_TILE;
print_line(vformat("Added conversion from:%s to%s", key_array, value_array));
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
tile_data->set_flip_h(flip_h);
tile_data->set_flip_v(flip_v);
tile_data->set_transpose(transpose);
tile_data->tile_set_material(ctd->material);
tile_data->set_modulate(ctd->modulate);
tile_data->set_z_index(ctd->z_index);
if (ctd->occluder.is_valid()) {
if (get_occlusion_layers_count() < 1) {
set_occlusion_layers_count(1);
}
tile_data->set_occluder(0, ctd->occluder);
}
if (ctd->navigation.is_valid()) {
if (get_navigation_layers_count() < 1) {
set_navigation_layers_count(1);
}
tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
}
tile_data->set_z_index(ctd->z_index);
// Add the shapes.
if (ctd->shapes.size() > 0) {
if (get_physics_layers_count() < 1) {
set_physics_layers_count(1);
}
}
for (int k = 0; k < ctd->shapes.size(); k++) {
CompatibilityShapeData csd = ctd->shapes[k];
if (csd.autotile_coords == coords) {
Ref<ConvexPolygonShape2D> convex_shape = csd.shape; // Only ConvexPolygonShape2D are supported, which is the default type used by the 3.x editor
if (convex_shape.is_valid()) {
Vector<Vector2> polygon = convex_shape->get_points();
for (int point_index = 0; point_index < polygon.size(); point_index++) {
polygon.write[point_index] = csd.transform.xform(polygon[point_index]);
}
tile_data->set_collision_polygons_count(0, tile_data->get_collision_polygons_count(0) + 1);
int index = tile_data->get_collision_polygons_count(0) - 1;
tile_data->set_collision_polygon_one_way(0, index, csd.one_way);
tile_data->set_collision_polygon_one_way_margin(0, index, csd.one_way_margin);
tile_data->set_collision_polygon_points(0, index, polygon);
}
}
}
}
} break;
case COMPATIBILITY_TILE_MODE_AUTO_TILE: {
// TODO
break;
case 1: // AUTO_TILE
// TODO
break;
case 2: // ATLAS_TILE
} break;
case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
atlas_source->set_margins(ctd->region.get_position());
atlas_source->set_separation(Vector2i(ctd->autotile_spacing, ctd->autotile_spacing));
atlas_source->set_texture_region_size(ctd->autotile_tile_size);
@ -1578,6 +1659,26 @@ void TileSet::compatibility_conversion() {
} else {
alternative_tile = atlas_source->create_alternative_tile(coords);
}
// Add to the mapping.
Array key_array;
key_array.push_back(coords);
key_array.push_back(flip_h);
key_array.push_back(flip_v);
key_array.push_back(transpose);
Array value_array;
value_array.push_back(source_id);
value_array.push_back(coords);
value_array.push_back(alternative_tile);
if (!compatibility_tilemap_mapping.has(E->key())) {
compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
}
compatibility_tilemap_mapping[E->key()][key_array] = value_array;
compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_ATLAS_TILE;
print_line(vformat("Added conversion from:%s to%s", key_array, value_array));
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
tile_data->set_flip_h(flip_h);
@ -1641,7 +1742,7 @@ void TileSet::compatibility_conversion() {
}
}
}
break;
} break;
}
// Offset all shapes
@ -1655,9 +1756,6 @@ void TileSet::compatibility_conversion() {
convex->set_points(points);
}
}
// Add the mapping to the map
compatibility_source_mapping.insert(E->key(), source_id);
}
// Reset compatibility data
@ -1666,6 +1764,43 @@ void TileSet::compatibility_conversion() {
}
compatibility_data = Map<int, CompatibilityTileData *>();
}
Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose) {
Array cannot_convert_array;
cannot_convert_array.push_back(-1);
cannot_convert_array.push_back(TileSetAtlasSource::INVALID_ATLAS_COORDS);
cannot_convert_array.push_back(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
if (!compatibility_tilemap_mapping.has(p_tile_id)) {
return cannot_convert_array;
}
int tile_mode = compatibility_tilemap_mapping_tile_modes[p_tile_id];
switch (tile_mode) {
case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
Array a;
a.push_back(p_flip_h);
a.push_back(p_flip_v);
a.push_back(p_transpose);
return compatibility_tilemap_mapping[p_tile_id][a];
}
case COMPATIBILITY_TILE_MODE_AUTO_TILE:
return cannot_convert_array;
break;
case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
Array a;
a.push_back(p_coords);
a.push_back(p_flip_h);
a.push_back(p_flip_v);
a.push_back(p_transpose);
return compatibility_tilemap_mapping[p_tile_id][a];
}
default:
return cannot_convert_array;
break;
}
};
#endif // DISABLE_DEPRECATED
bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
@ -1831,7 +1966,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ctd->z_index = p_value;
// TODO: remove the conversion from here, it's not where it should be done
compatibility_conversion();
_compatibility_conversion();
} else {
return false;
}

View file

@ -79,15 +79,15 @@ private:
Vector2 tex_offset;
Ref<ShaderMaterial> material;
Rect2 region;
int tile_mode;
Color modulate;
int tile_mode = 0;
Color modulate = Color(1, 1, 1);
// Atlas or autotiles data
int autotile_bitmask_mode;
int autotile_bitmask_mode = 0;
Vector2 autotile_icon_coordinate;
Size2i autotile_tile_size = Size2i(16, 16);
int autotile_spacing;
int autotile_spacing = 0;
Map<Vector2i, int> autotile_bitmask_flags;
Map<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map;
Map<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map;
@ -99,20 +99,24 @@ private:
Vector2 occluder_offset;
Ref<NavigationPolygon> navigation;
Vector2 navigation_offset;
int z_index;
int z_index = 0;
};
Map<int, CompatibilityTileData *> compatibility_data = Map<int, CompatibilityTileData *>();
Map<int, int> compatibility_source_mapping = Map<int, int>();
enum CompatibilityTileMode {
COMPATIBILITY_TILE_MODE_SINGLE_TILE = 0,
COMPATIBILITY_TILE_MODE_AUTO_TILE,
COMPATIBILITY_TILE_MODE_ATLAS_TILE,
};
private:
void compatibility_conversion();
Map<int, CompatibilityTileData *> compatibility_data;
Map<int, int> compatibility_tilemap_mapping_tile_modes;
Map<int, Map<Array, Array>> compatibility_tilemap_mapping;
void _compatibility_conversion();
public:
int compatibility_get_source_for_tile_id(int p_old_source) {
return compatibility_source_mapping[p_old_source];
};
// Format of output array [source_id, atlas_coords, alternative]
Array compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose);
#endif // DISABLE_DEPRECATED
public: