static ImportedTile[] ImportEmbeddedTileset(TMX.TilesetReference embeddedTileset, string tilesetDir, string baseFolder, int cellWidth, int cellHeight, int pixelsPerUnit, out TSX.Tileset tilesetOut) { TSX.Tileset tileset = new TSX.Tileset(embeddedTileset); tilesetOut = tileset; if (!ImportUtils.CreateAssetFolderIfMissing(tilesetDir, true)) { return(null); } Debug.Log("Loading embedded tileset = " + tileset.name); return(ImportTileset(tileset, tilesetDir, baseFolder, cellWidth, cellHeight, pixelsPerUnit)); }
public static ImportedTemplate LoadTXFile(string path, string tilesetDir, int cellWidth, int cellHeight, int pixelsPerUnit) { TXTypes.Template template = ImportUtils.ReadXMLIntoObject <TXTypes.Template>(path); ImportedTileset tileset; if (template.tileset != null) { string baseFolder = Path.GetDirectoryName(path); tileset = TiledTSXImporter.ImportFromTilesetReference(template.tileset, baseFolder, tilesetDir, cellWidth, cellHeight, pixelsPerUnit); } else { tileset = null; } return(new ImportedTemplate(template, tileset)); }
static ImportedTile[] ImportTSXFile(string path, string tilesetDir, int cellWidth, int cellHeight, int pixelsPerUnit, out TSX.Tileset tilesetOut) { tilesetOut = null; if (!ImportUtils.CreateAssetFolderIfMissing(tilesetDir, true)) { return(null); } Debug.Log("Loading TSX file from " + path + " into " + tilesetDir); TSX.Tileset tileset = ImportUtils.ReadXMLIntoObject <TSX.Tileset>(path); if (tileset == null) { return(null); } tilesetOut = tileset; Debug.Log("Loading tileset = " + tileset.name); return(ImportTileset(tileset, tilesetDir, Path.GetDirectoryName(path), cellWidth, cellHeight, pixelsPerUnit)); }
static ImportedTile[] ImportTileset(TSX.Tileset tileset, string tilesetDir, string sourceTilesetDirectory, int cellWidth, int cellHeight, int pixelsPerUnit) { string tilesetSpriteTargetDir = tilesetDir + Path.DirectorySeparatorChar + tileset.name; if (!ImportUtils.CreateAssetFolderIfMissing(tilesetSpriteTargetDir, false)) { return(null); } string tilesetTileTargetDir = tilesetDir + Path.DirectorySeparatorChar + tileset.name + Path.DirectorySeparatorChar + "TileAssets"; if (!ImportUtils.CreateAssetFolderIfMissing(tilesetTileTargetDir, false)) { return(null); } TSX.Tile[] tiles = tileset.tiles; string[] imageTargetPaths = null; Sprite[] tileSprites = null; string[] tileTargetPaths = null; bool singleImageTileset = tileset.IsSingleImageTileset(); if (singleImageTileset) { if (tileset.image != null) { string imageSourcePath; string imageTargetPath; CreateSingleImageTilesetPaths(tileset, sourceTilesetDirectory, tilesetSpriteTargetDir, tilesetTileTargetDir, out imageSourcePath, out imageTargetPath, out tileTargetPaths); CopyImages(new string[] { imageSourcePath }, new string[] { imageTargetPath }); string subSpriteNameBase = Path.GetFileNameWithoutExtension(imageSourcePath); if (!CreateTilemapSprite(imageTargetPath, cellWidth, cellHeight, pixelsPerUnit, tileset /*tileset.image.width, tileset.image.height, tileset.tilewidth, tileset.tileheight, tileset.tilecount*/, subSpriteNameBase, out tileSprites)) { return(null); } } else { Debug.LogError("Tileset " + tileset.name + " is empty!"); } } else { string[] imageSourcePaths = new string[tiles.Length]; imageTargetPaths = new string[tiles.Length]; tileTargetPaths = new string[tiles.Length]; CreateTilePaths(tiles, sourceTilesetDirectory, tilesetSpriteTargetDir, tilesetTileTargetDir, imageSourcePaths, imageTargetPaths, tileTargetPaths); CopyImages(imageSourcePaths, imageTargetPaths); tileSprites = new Sprite[tiles.Length]; CreateSpriteAssets(tiles, tileset.name, pixelsPerUnit, cellWidth, cellHeight, imageTargetPaths, tileSprites); } if (tileSprites == null) { Debug.LogError("Tile sprites ended up null when importing tileset: " + tileset.name); return(null); } if (tileSprites.Length == 0) { Debug.LogError("0 tile sprites found from texture assets for tileset: " + tileset.name); return(null); } ImportedTile[] tileAssets; bool success = CreateTileAssets(tiles, singleImageTileset, tileset.name, pixelsPerUnit, tileSprites, tileTargetPaths, out tileAssets); EditorUtility.ClearProgressBar(); if (!success) { return(null); } CreatePalette(tileset.name, tilesetTileTargetDir, tileAssets, singleImageTileset, tileset.tilewidth, tileset.tileheight, tileset.columns, cellWidth, cellHeight); return(tileAssets); }
/* Entry point into this class */ public static bool ImportTMXFile(string path, string inTilesetDir, Grid targetGrid, string inImageLayerSpriteDir, bool setHiddenLayersToInactive) { s_tmxParentFolder = Path.GetDirectoryName(path); string filename = Path.GetFileNameWithoutExtension(path); s_imageLayerSpriteDir = inImageLayerSpriteDir; s_tilesetDir = inTilesetDir; s_orderInLayer = 0; s_setHiddenLayersToInactive = setHiddenLayersToInactive; s_map = ImportUtils.ReadXMLIntoObject <TMX.Map>(path); if (s_map == null) { return(false); } if (s_map.backgroundcolor != null) { Color backgroundColor; if (ColorUtility.TryParseHtmlString(s_map.backgroundcolor, out backgroundColor)) { Camera.main.backgroundColor = backgroundColor; } } if (s_map.tilesets != null) { // First we need to load (or import) all the tilesets referenced by the TMX file... s_cellWidth = s_map.tilewidth; s_cellHeight = s_map.tileheight; s_pixelsPerUnit = Mathf.Max(s_map.tilewidth, s_map.tileheight); s_importedTilesets = new ImportedTileset[s_map.tilesets.Length]; for (int i = 0; i < s_map.tilesets.Length; i++) { s_importedTilesets[i] = TiledTSXImporter.ImportFromTilesetReference(s_map.tilesets[i], s_tmxParentFolder, s_tilesetDir, s_cellWidth, s_cellHeight, s_pixelsPerUnit); if (s_importedTilesets[i] == null || s_importedTilesets[i].tiles == null || s_importedTilesets[i].tiles[0] == null) { Debug.LogError("Imported tileset is incomplete"); return(false); } } // Set up the Grid to store everything in s_gridGO = PrepareGrid(filename, targetGrid); s_importOperations = ImportUtils.GetObjectsThatImplementInterface <ITilemapImportOperation>(); s_sortOrder = TilemapRenderer.SortOrder.TopLeft; if (s_map.renderorder != null) { if (s_map.renderorder.Equals("right-down")) { s_sortOrder = TilemapRenderer.SortOrder.TopLeft; } else if (s_map.renderorder.Equals("right-up")) { s_sortOrder = TilemapRenderer.SortOrder.BottomLeft; } else if (s_map.renderorder.Equals("left-down")) { s_sortOrder = TilemapRenderer.SortOrder.TopRight; } else if (s_map.renderorder.Equals("left-up")) { s_sortOrder = TilemapRenderer.SortOrder.BottomRight; } } // Unity's isometric rendering only works well with TopRight sortorder if (s_map.orientation == "isometric") { s_sortOrder = TilemapRenderer.SortOrder.TopRight; } // Unity hex grid only supports even stagger index, so we need a workaround to compensate TileLayerImporter.s_needsHexOddToEvenConversion = s_map.orientation == "hexagonal" && s_map.staggerindex == "odd"; // Unity's isometric rendering is 90 degrees rotated anti-clockwise on the grid compared to Tiled, // so we need to rotate the grid clockwise 90 degrees to look correct in Unity TileLayerImporter.s_needsGridRotationToMatchUnityIsometric = s_map.orientation == "isometric"; ObjectLayerImporter.s_importedTemplates = new Dictionary <string, ImportedTemplate>(); bool loadedLayers = false; if (s_map.topLevelLayers != null) { loadedLayers = TreatLayers(s_gridGO, s_map.topLevelLayers); } else { loadedLayers = true; } // Handle the complete map's properties if (loadedLayers) { HandleCustomProperties(s_gridGO, s_map.properties); } } return(true); }
public static bool ImportTMXFile(string path, string tilesetDir, Grid targetGrid) { string tmxParentFolder = Path.GetDirectoryName(path); string filename = Path.GetFileNameWithoutExtension(path); TMX.Map map = ImportUtils.ReadXMLIntoObject <TMX.Map>(path); if (map == null) { return(false); } if (map.backgroundcolor != null) { Color backgroundColor; if (ColorUtility.TryParseHtmlString(map.backgroundcolor, out backgroundColor)) { Camera.main.backgroundColor = backgroundColor; } } if (map.tilesets != null) { // First we need to load (or import) all the tilesets referenced by the TMX file... int cellWidth = map.tilewidth; int cellHeight = map.tileheight; int pixelsPerUnit = Mathf.Max(map.tilewidth, map.tileheight); ImportedTileset[] importedTilesets = new ImportedTileset[map.tilesets.Length]; for (int i = 0; i < map.tilesets.Length; i++) { importedTilesets[i] = TiledTSXImporter.ImportFromTilesetReference(map.tilesets[i], tmxParentFolder, tilesetDir, cellWidth, cellHeight, pixelsPerUnit); if (importedTilesets[i] == null || importedTilesets[i].tiles == null || importedTilesets[i].tiles[0] == null) { Debug.LogError("Imported tileset is incomplete"); return(false); } } // Set up the Grid to store everything in GameObject newGrid = null; if (targetGrid != null) { newGrid = targetGrid.gameObject; for (int i = newGrid.transform.childCount - 1; i >= 0; --i) { Undo.DestroyObjectImmediate(newGrid.transform.GetChild(i).gameObject); } } else { newGrid = new GameObject(filename, typeof(Grid)); newGrid.GetComponent <Grid>().cellSize = new Vector3(1.0f, 1.0f, 0.0f); Undo.RegisterCreatedObjectUndo(newGrid, "Import map to new Grid"); } ITilemapImportOperation[] importOperations = ImportUtils.GetObjectsThatImplementInterface <ITilemapImportOperation>(); TilemapRenderer.SortOrder sortOrder = TilemapRenderer.SortOrder.TopLeft; if (map.renderorder.Equals("right-down")) { sortOrder = TilemapRenderer.SortOrder.TopLeft; } else if (map.renderorder.Equals("right-up")) { sortOrder = TilemapRenderer.SortOrder.BottomLeft; } else if (map.renderorder.Equals("left-down")) { sortOrder = TilemapRenderer.SortOrder.TopRight; } else if (map.renderorder.Equals("left-up")) { sortOrder = TilemapRenderer.SortOrder.BottomRight; } // Load all the tile layers if (map.layers != null) { for (int i = 0; i < map.layers.Length; i++) { TMX.Layer layer = map.layers[i]; bool success = ImportTileLayer(layer, newGrid, i, importedTilesets, importOperations, sortOrder, cellWidth, cellHeight, map.infinite); if (!success) { return(false); } } } Dictionary <string, ImportedTemplate> importedTemplates = new Dictionary <string, ImportedTemplate>(); // Load all the objects if (map.objectgroups != null) { for (int g = 0; g < map.objectgroups.Length; g++) { TMX.ObjectGroup objectGroup = map.objectgroups[g]; if (objectGroup != null && objectGroup.objects != null && objectGroup.objects.Length > 0) { GameObject newObjectLayer = new GameObject(objectGroup.name); newObjectLayer.transform.SetParent(newGrid.transform, false); Undo.RegisterCreatedObjectUndo(newObjectLayer, "Import object layer"); int sortingLayer = (map.layers == null ? 0 : map.layers.Length) + g; for (int i = 0; i < objectGroup.objects.Length; i++) { TMX.Object mapObject = objectGroup.objects[i]; bool success = ImportMapObject(mapObject, importedTilesets, importedTemplates, newObjectLayer, map.tilewidth, map.tileheight, sortingLayer, importOperations, tilesetDir, cellWidth, cellHeight, pixelsPerUnit, tmxParentFolder); if (!success) { return(false); } } Color objectColour = new Color(1.0f, 1.0f, 1.0f, 1.0f); if (objectGroup.color != null) { ColorUtility.TryParseHtmlString(objectGroup.color, out objectColour); } if (objectGroup.opacity != 1.0f) { objectColour.a = objectGroup.opacity; } SpriteRenderer[] renderers = newObjectLayer.GetComponentsInChildren <SpriteRenderer>(); foreach (SpriteRenderer r in renderers) { r.color = objectColour; } if (!objectGroup.visible) { foreach (SpriteRenderer r in renderers) { r.enabled = false; } } IDictionary <string, string> properties = (objectGroup.properties == null ? new Dictionary <string, string>() : objectGroup.properties.ToDictionary()); foreach (ITilemapImportOperation operation in importOperations) { operation.HandleCustomProperties(newObjectLayer, properties); } } } } } return(true); }
static bool ImportMapObject(TMX.Object mapObject, ImportedTileset[] importedTilesets, Dictionary <string, ImportedTemplate> importedTemplates, GameObject newObjectLayer, int mapTileWidth, int mapTileHeight, int sortingLayer, ITilemapImportOperation[] importOperations, string tilesetDir, int cellWidth, int cellHeight, int pixelsPerUnit, string tmxParentFolder) { ImportedTileset replacementTileset = null; if (mapObject.template != null) { // Fill out empty object fields with data from the template. // The template could have a tile from it's own tileset reference, so in that case, use the template tileset instead, and the template object GID TMX.Object combinedMapObject = ApplyTemplate(mapObject, tmxParentFolder, tilesetDir, cellWidth, cellHeight, pixelsPerUnit, importedTemplates, out replacementTileset); if (combinedMapObject == null) { Debug.LogError("Could not load template for map object " + mapObject); return(false); } else { mapObject = combinedMapObject; } } mapObject.InitialiseUnsetValues(); // We need special code to set defaults here, because setting them before merging with a template would give incorrect results. // Use the template's tileset (and the gid that's been set by ApplyTemplate) if (replacementTileset != null) { importedTilesets = new ImportedTileset[] { replacementTileset }; } ImportedTile importedTile; TSX.Tile tilesetTile; // Unused Matrix4x4 matrix; TiledUtils.FindTileDataAndMatrix(mapObject.gid.Value, importedTilesets, cellWidth, cellHeight, out importedTile, out tilesetTile, out matrix); Vector2 pixelsToUnits = new Vector2(1.0f / mapTileWidth, -1.0f / mapTileHeight); GameObject newObject = new GameObject(mapObject.name); newObject.transform.SetParent(newObjectLayer.transform, false); // So we gain the tile rotation/flipping newObject.transform.FromMatrix(matrix); Vector2 corner = Vector2.Scale(new Vector2(mapObject.x.Value, mapObject.y.Value), pixelsToUnits); if (importedTile != null) { Tile unityTile = importedTile.tile; Vector2 pivotProportion = new Vector2(unityTile.sprite.pivot.x / unityTile.sprite.rect.width, unityTile.sprite.pivot.y / unityTile.sprite.rect.height); Vector3 pivotWorldPosition = corner + Vector2.Scale(new Vector2(mapObject.width.Value * pivotProportion.x, mapObject.height.Value * -pivotProportion.y), pixelsToUnits); newObject.transform.localPosition += pivotWorldPosition; SpriteRenderer renderer = newObject.AddComponent <SpriteRenderer>(); renderer.sprite = unityTile.sprite; renderer.sortingOrder = sortingLayer; if (unityTile.colliderType == Tile.ColliderType.Sprite) { newObject.AddComponent <PolygonCollider2D>(); } else if (unityTile.colliderType == Tile.ColliderType.Grid) { newObject.AddComponent <BoxCollider2D>(); } Vector2 scale = new Vector2(mapObject.width.Value / unityTile.sprite.rect.width, mapObject.height.Value / unityTile.sprite.rect.height); newObject.transform.localScale = Vector3.Scale(newObject.transform.localScale, new Vector3(scale.x, scale.y, 1.0f)); } else { Vector3 pivotWorldPosition = corner + Vector2.Scale(new Vector2(mapObject.width.Value * 0.5f, mapObject.height.Value * 0.5f), pixelsToUnits); newObject.transform.localPosition += pivotWorldPosition; // If no tile used, must be a non-tile object of some sort (collision or text) if (mapObject.ellipse != null) { EllipseCollider2D collider = newObject.AddComponent <EllipseCollider2D>(); collider.RadiusX = (mapObject.width.Value * 0.5f) / mapTileWidth; collider.RadiusY = (mapObject.height.Value * 0.5f) / mapTileHeight; } else if (mapObject.polygon != null) { PolygonCollider2D collider = newObject.AddComponent <PolygonCollider2D>(); string points = mapObject.polygon.points; collider.points = ImportUtils.PointsFromString(points, pixelsToUnits); } else if (mapObject.polyline != null) { EdgeCollider2D collider = newObject.AddComponent <EdgeCollider2D>(); string points = mapObject.polyline.points; collider.points = ImportUtils.PointsFromString(points, pixelsToUnits); } else if (mapObject.text != null) { TextMesh textMesh = newObject.AddComponent <TextMesh>(); textMesh.text = mapObject.text.text; textMesh.anchor = TextAnchor.MiddleCenter; Color color = Color.white; if (mapObject.text.color != null) { ColorUtility.TryParseHtmlString(mapObject.text.color, out color); } textMesh.color = color; // Saving an OS font as an asset in unity (through script) is seemingly impossible right now in a platform independent way // So we'll skip fonts for now textMesh.fontSize = (int)mapObject.text.pixelsize; // Guess a good resolution for the font float targetWorldTextHeight = (float)mapObject.text.pixelsize / (float)mapTileHeight; textMesh.characterSize = targetWorldTextHeight * 10.0f / textMesh.fontSize; Renderer renderer = textMesh.gameObject.GetComponent <MeshRenderer>(); renderer.sortingOrder = sortingLayer; renderer.sortingLayerID = SortingLayer.GetLayerValueFromName("Default"); } else { // Regular box collision BoxCollider2D collider = newObject.AddComponent <BoxCollider2D>(); collider.size = new Vector2(mapObject.width.Value / mapTileWidth, mapObject.height.Value / mapTileHeight); } } if (mapObject.rotation != 0.0f) { newObject.transform.RotateAround(corner, new Vector3(0.0f, 0.0f, 1.0f), -mapObject.rotation.Value); } if (mapObject.visible == false) { Renderer renderer = newObject.GetComponent <Renderer>(); if (renderer != null) { renderer.enabled = false; } } IDictionary <string, string> properties = (mapObject.properties == null ? new Dictionary <string, string>() : mapObject.properties.ToDictionary()); foreach (ITilemapImportOperation operation in importOperations) { operation.HandleCustomProperties(newObject, properties); } return(true); }