瀏覽代碼

Import old tiles in SINGLE_TILE mode as atlases

Gilles Roudière 4 年之前
父節點
當前提交
047e9b19f8
共有 3 個文件被更改,包括 175 次插入35 次删除
  1. 11 10
      scene/2d/tile_map.cpp
  2. 147 12
      scene/resources/tile_set.cpp
  3. 17 13
      scene/resources/tile_set.h

+ 11 - 10
scene/2d/tile_map.cpp

@@ -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);
 			}
-
-			set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
 #endif
 		}
 	}

+ 147 - 12
scene/resources/tile_set.cpp

@@ -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
-				// TODO
-				break;
-			case 1: // AUTO_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 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;
 		}

+ 17 - 13
scene/resources/tile_set.h

@@ -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;
 
-public:
-	int compatibility_get_source_for_tile_id(int p_old_source) {
-		return compatibility_source_mapping[p_old_source];
-	};
+	void _compatibility_conversion();
 
+public:
+	// 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: