private void TileSetTextureField(TileSet tileSet) { int id = tileSet.firstGID; if (selectedTileSet == null) { tileRect = new Rect(-1, -1, 0, 0); } Texture2D currentTexture = GetTileSetTexture(tileSet, path); Texture2D tex = EditorGUILayout.ObjectField(currentTexture, typeof(Texture2D), false) as Texture2D; if (currentTexture != tex) { Uri textureURI = new Uri("/" + AssetDatabase.GetAssetPath(tex)); Uri tmxFileURI = new Uri("/" + Path.GetDirectoryName(path)); tileSet.image.source = "../" + tmxFileURI.MakeRelativeUri(textureURI); } if (tex == null) { return; } float x = Screen.width - 40; float y = tex.height * x / (float)tex.width; if (x > tex.width) { x = tex.width; y = tex.height; } Rect r = GUILayoutUtility.GetRect(x, y); r.width = r.height * (float)tex.width / (float)tex.height; r.height = r.width * (float)tex.height / (float)tex.width; r.x = (Screen.width - r.width) * 0.5f; EditorGUI.DrawPreviewTexture(r, tex, mat); if (selectedTileSet != null && selectedTileSet == tileSet && selectedTileIndex > 0) { TileRect uvTileRect = selectedTileSet.GetTileUVs(selectedTileIndex); tileRect = r; tileRect.x += uvTileRect.x * r.width; tileRect.y += (1 - (uvTileRect.y + uvTileRect.height)) * r.height; tileRect.width *= uvTileRect.width; tileRect.height *= uvTileRect.height; } Handles.DrawSolidRectangleWithOutline(tileRect, Color.clear, Color.white); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && r.Contains(Event.current.mousePosition)) { selectedTileSet = tileSet; selectedTileIndex = GetTileIndex(tileSet, r, Event.current.mousePosition); Event.current.Use(); } }
public TileRect GetTileUVs(int tileGID) { TileRect uvs = GetTileSpriteRect(tileGID); uvs.x /= (float)image.width; uvs.y /= (float)image.height; uvs.width /= (float)image.width; uvs.height /= (float)image.height; return(uvs); }
// TODO: Cache UVs public TileRect GetTileSpriteRect(int tileGID) { TileRect rect = new TileRect(); int tileIndex = tileGID - firstGID; int i = tileIndex % columns; int j = (rows - 1) - tileIndex / columns; rect.x = (margin + i * (tileWidth + spacing)); rect.y = (margin + j * (tileHeight + spacing)); rect.width = tileWidth; rect.height = tileHeight; return(rect); }
public override void OnPreviewGUI(Rect r, GUIStyle background) { if (Event.current.type != EventType.Repaint) { return; } Texture2D tex = GetTileSetTexture(selectedTileSet, path); TileRect uvTileRect = selectedTileSet.GetTileUVs(selectedTileIndex); Rect uvRect = new Rect(uvTileRect.x, uvTileRect.y, uvTileRect.width, uvTileRect.height); if (r.height > r.width) { r.height = r.width; r.x += (r.height - r.width) * 0.5f; } else if (r.width > r.height) { r.width = r.height; r.y += (r.width - r.height) * 0.5f; } r.x = (Screen.width - r.width) * 0.5f; GUI.DrawTextureWithTexCoords(r, tex, uvRect, true); Tile t = selectedTileSet.GetTile(selectedTileIndex); if (t != null && t.objectGroup != null && t.objectGroup.objects != null && t.objectGroup.objects.Length > 0) { foreach (TileObject obj in t.objectGroup.objects) { if (obj.polygonSpecified) { TilePoint[] path = obj.polygon.path; Vector3[] poly = System.Array.ConvertAll(path, (p) => { Vector3 v = new Vector3(p.x + obj.x, p.y + obj.y, 0); v.x *= r.width / (float)tmxFile.tileWidth; v.y *= r.height / (float)tmxFile.tileHeight; v.x += r.x; v.y += r.y; return(v); }); Handles.color = new Color(1, 1, 1, 0.1f); Handles.DrawAAConvexPolygon(poly); } } } }
public void CreateSpriteTile(GameObject group, TileObject tileObject) { int tileID = (int)tileObject.gid; GameObject g = new GameObject(tileObject.name); g.transform.SetParent(group.transform); float y = tmxFile.height * tmxFile.tileHeight - tileObject.y; g.transform.localPosition = new Vector3(tileObject.x, y, 0) / pixelsPerUnit; g.transform.localEulerAngles = Vector3.forward * -tileObject.rotation; SpriteRenderer sprite = g.AddComponent <SpriteRenderer>(); sprite.flipX = TMXFile.FlippedHorizontally(tileObject.gid); sprite.flipY = TMXFile.FlippedVertically(tileObject.gid); TileSet tileSet = tmxFile.GetTileSetByTileID(tileID); if (tileSet != null && tileSet.image != null && !string.IsNullOrEmpty(tileSet.image.source)) { g.transform.localScale = new Vector3(tileObject.width, tileObject.height, pixelsPerUnit) / pixelsPerUnit; int tileSetIndex = System.Array.IndexOf(tmxFile.tileSets, tileSet); Material mat = tileSetMaterials[tileSetIndex]; Texture2D tex = mat.mainTexture as Texture2D; TileRect r = tileSet.GetTileSpriteRect(tileID); Rect rect = new Rect(r.x, r.y, r.width, r.height); Vector2 pivot = Vector2.zero; sprite.sprite = Sprite.Create(tex, rect, pivot, pixelsPerUnit, 0, SpriteMeshType.FullRect); } else { int tileSetIndex = System.Array.IndexOf(tmxFile.tileSets, tileSet); sprite.sprite = tileSetSprites[tileSetIndex][tileID - tileSet.firstGID]; } if (idToPhysics.ContainsKey(tileID)) { float yOff = tmxFile.tileHeight / pixelsPerUnit; Vector2[] path = System.Array.ConvertAll(idToPhysics[tileID], (p) => new Vector2(p.x, p.y + yOff)); PolygonCollider2D poly = g.AddComponent <PolygonCollider2D>(); poly.pathCount = 1; poly.SetPath(0, path); } SetProperties(g, tileObject.properties); }
public void UpdateMesh(TileLayer layerData, int submeshIndex) { Dictionary <int, int> firstGIDToIndex = new Dictionary <int, int>(); for (int i = 0; i < tmxFile.tileSets.Length; i++) { firstGIDToIndex[tmxFile.tileSets[i].firstGID] = i; } int vertCount = 0; int[] triIDsPerMat = new int[tmxFile.tileSets.Length]; for (int tileIndex = submeshIndex * 16250; tileIndex < Mathf.Min((submeshIndex + 1) * 16250, layerData.tileIDs.Length); tileIndex++) { int tileID = layerData.tileIDs[tileIndex]; TileSet tileSet = tmxFile.GetTileSetByTileID(tileID); if (tileSet == null || tileID < tileSet.firstGID) { continue; } vertCount += 4; triIDsPerMat[firstGIDToIndex[tileSet.firstGID]] += 6; } List <List <IntPoint> > paths = new List <List <IntPoint> >(); Vector3[] verts = new Vector3[vertCount]; Vector3[] norms = new Vector3[vertCount]; Vector2[] uvs = new Vector2[vertCount]; Color[] colors = new Color[vertCount]; int[][] matTris = new int[tmxFile.tileSets.Length][]; for (int i = 0; i < triIDsPerMat.Length; i++) { matTris[i] = new int[triIDsPerMat[i]]; } bool isHexMap = tmxFile.orientation == "hexagonal"; bool isIsoMap = tmxFile.orientation == "isometric"; bool isStagMap = tmxFile.orientation == "staggered"; bool staggerX = tmxFile.staggerAxis == "x"; int staggerIndex = (tmxFile.staggerAxis == "even") ? 0 : 1; Color color = Color.white; if (layerData.tintColorSpecified) { color = TiledColorFromString(layerData.tintColor); } int vertIndex = 0; int[] matTriIndices = new int[tmxFile.tileSets.Length]; for (int tileIndex = submeshIndex * 16250; tileIndex < Mathf.Min((submeshIndex + 1) * 16250, layerData.tileIDs.Length); tileIndex++) { int tileID = layerData.tileIDs[tileIndex]; TileSet tileSet = tmxFile.GetTileSetByTileID(tileID); if (tileSet == null || tileID < tileSet.firstGID) { continue; } if (tileSet.columns == 0 || tileSet.rows == 0) { if (tileSet.image.width == 0 || tileSet.image.height == 0) { int tileSetIndex = System.Array.IndexOf(tmxFile.tileSets, tileSet); Texture2D tex = tileSetMaterials[tileSetIndex].mainTexture as Texture2D; tileSet.image.width = tex.width; tileSet.image.height = tex.height; } tileSet.columns = (tileSet.image.width - 2 * tileSet.margin) / (tileSet.tileWidth + tileSet.spacing); tileSet.rows = (tileSet.image.width - 2 * tileSet.margin) / (tileSet.tileWidth + tileSet.spacing); } TileRect uvRect = tileSet.GetTileUVs(tileID); bool flipX = layerData.FlippedHorizontally(tileIndex); bool flipY = layerData.FlippedVertically(tileIndex); bool flipAntiDiag = layerData.FlippedAntiDiagonally(tileIndex); bool rotated120 = layerData.RotatedHexagonal120(tileIndex); TilePoint tileLocation = layerData.GetTileLocation(tileIndex); Vector3 pos = new Vector3(offset.x + tileLocation.x * tileOffset.x, offset.y + tileLocation.y * tileOffset.y, 0); if (isHexMap || isStagMap) { if (staggerX) { pos.x = tileLocation.x * tileOffset.z; if (tileLocation.x % 2 == staggerIndex) { pos.y += tileOffset.w * 0.5f; } } else { pos.y = tileLocation.y * tileOffset.w; if (tileLocation.y % 2 == staggerIndex) { pos.x += tileOffset.z * 0.5f; } } } else if (isIsoMap) { pos.x = (tileLocation.x * tileOffset.x / 2) - (tileLocation.y * tileOffset.x / 2); pos.y = (tileLocation.y * tileOffset.y / 2) + (tileLocation.x * tileOffset.y / 2); } float widthMult = (float)tileSet.tileWidth / (float)tmxFile.tileWidth; float heightMult = (float)tileSet.tileHeight / (float)tmxFile.tileHeight; Vector3[] v = new Vector3[] { pos, pos + Vector3.up * tileOffset.y * heightMult, pos + new Vector3(tileOffset.x * widthMult, tileOffset.y * heightMult, 0), pos + Vector3.right * tileOffset.x * widthMult }; if (rotated120 || (flipAntiDiag && isHexMap)) { float angle = rotated120 ? 120 : 0; angle += flipAntiDiag ? 60 : 0; Vector3 center = (v[0] + v[2]) * 0.5f; for (int i = 0; i < 4; i++) { v[i] = Quaternion.Euler(0, 0, -angle) * (v[i] - center) + center; } } verts[vertIndex] = v[0]; verts[vertIndex + 1] = v[1]; verts[vertIndex + 2] = v[2]; verts[vertIndex + 3] = v[3]; if (idToPhysics.ContainsKey(tileID)) { Vector3[] phys = new Vector3[idToPhysics[tileID].Length]; Vector3 off = new Vector3(tileOffset.x * 0.5f, tileOffset.y * 0.5f, 0); for (int i = 0; i < phys.Length; i++) { phys[i] = idToPhysics[tileID][i] - off; if (flipAntiDiag) { phys[i] = Quaternion.AngleAxis(180, new Vector3(-1, 1, 0)) * phys[i]; if (flipX && flipY) { phys[i] = Quaternion.AngleAxis(180, Vector3.forward) * phys[i]; } else if (flipX) { phys[i] = Quaternion.AngleAxis(180, Vector3.up) * phys[i]; } else if (flipY) { phys[i] = Quaternion.AngleAxis(180, Vector3.right) * phys[i]; } } else { if (flipX) { phys[i] = Quaternion.AngleAxis(180, Vector3.up) * phys[i]; } if (flipY) { phys[i] = Quaternion.AngleAxis(180, Vector3.right) * phys[i]; } } phys[i] += off; } IntPoint[] path = System.Array.ConvertAll(phys, (p) => Vector2ToIntPoint((Vector2)(p + pos))); paths.Add(new List <IntPoint>(path)); } norms[vertIndex] = Vector3.back; norms[vertIndex + 1] = Vector3.back; norms[vertIndex + 2] = Vector3.back; norms[vertIndex + 3] = Vector3.back; float left = uvRect.left; float right = uvRect.right; float bottom = uvRect.bottom; float top = uvRect.top; Vector2[] uvArray = new Vector2[] { new Vector2(left, bottom), new Vector2(left, top), new Vector2(right, top), new Vector2(right, bottom) }; if (flipAntiDiag && !isHexMap) { Vector2 tmp = uvArray[0]; uvArray[0] = uvArray[2]; uvArray[2] = tmp; } if (tileOffset.x < 0 != flipX) { uvArray = new Vector2[] { uvArray[3], uvArray[2], uvArray[1], uvArray[0] }; } if (tileOffset.y < 0 != flipY) { uvArray = new Vector2[] { uvArray[1], uvArray[0], uvArray[3], uvArray[2] }; } uvs[vertIndex] = uvArray[0]; uvs[vertIndex + 1] = uvArray[1]; uvs[vertIndex + 2] = uvArray[2]; uvs[vertIndex + 3] = uvArray[3]; colors[vertIndex] = color; colors[vertIndex + 1] = color; colors[vertIndex + 2] = color; colors[vertIndex + 3] = color; int matIndex = firstGIDToIndex[tileSet.firstGID]; matTris[matIndex][matTriIndices[matIndex]] = vertIndex; matTris[matIndex][matTriIndices[matIndex] + 1] = vertIndex + 2; matTris[matIndex][matTriIndices[matIndex] + 2] = vertIndex + 1; matTris[matIndex][matTriIndices[matIndex] + 3] = vertIndex; matTris[matIndex][matTriIndices[matIndex] + 4] = vertIndex + 3; matTris[matIndex][matTriIndices[matIndex] + 5] = vertIndex + 2; matTriIndices[matIndex] += 6; vertIndex += 4; } int layerIndex = GetLayerIndexFromID(layerData.id); GameObject[] subMeshObjects = layerSubmeshObjects[layerIndex]; GameObject obj = subMeshObjects[submeshIndex]; MeshFilter filter = obj.GetComponent <MeshFilter>(); if (filter.sharedMesh == null) { filter.sharedMesh = new Mesh(); filter.sharedMesh.name = layerData.name; if (meshesPerLayer > 1) { filter.sharedMesh.name += "_submesh" + submeshIndex; } } filter.sharedMesh.Clear(); filter.sharedMesh.vertices = verts; filter.sharedMesh.normals = norms; filter.sharedMesh.uv = uvs; filter.sharedMesh.colors = colors; List <Material> mats = new List <Material>(); List <int[]> triLists = new List <int[]>(); for (int i = 0; i < tmxFile.tileSets.Length; i++) { int[] tris = matTris[i]; if (tris != null && tris.Length > 0) { mats.Add(tileSetMaterials[i]); triLists.Add(tris); } } obj.GetComponent <MeshRenderer>().sharedMaterials = mats.ToArray(); filter.sharedMesh.subMeshCount = mats.Count; for (int i = 0; i < filter.sharedMesh.subMeshCount; i++) { filter.sharedMesh.SetTriangles(triLists[i], i); } filter.sharedMesh.RecalculateBounds(); paths = Clipper.SimplifyPolygons(paths, PolyFillType.pftNonZero); paths = RemoveColinnearAndDoubles(paths); layerPaths[layerIndex][submeshIndex] = paths; }