public static GetLoopOrder ( tk2dTileMapData sortMethod, int w, int h, int &x0, int &x1, int &dx, int &y0, int &y1, int &dy ) : void | ||
sortMethod | tk2dTileMapData | |
w | int | |
h | int | |
x0 | int | |
x1 | int | |
dx | int | |
y0 | int | |
y1 | int | |
dy | int | |
return | void |
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List <Vector3> meshVertices = new List <Vector3>(); List <Color> meshColors = new List <Color>(); List <Vector2> meshUvs = new List <Vector2>(); List <Vector2> meshUv2s = new List <Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; tk2dSpriteDefinition firstSprite = tileMap.SpriteCollectionInst.FirstValidDefinition; bool buildNormals = (firstSprite != null && firstSprite.normals != null && firstSprite.normals.Length > 0); bool generateUv2 = tileMap.data.generateUv2; var colorMode = tileMap.data.colorMode; Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) { useColor = false; } int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); List <int>[] meshIndices = new List <int> [tileMap.SpriteCollectionInst.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) { meshIndices[j] = new List <int>(); } int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = x0; x != x1; x += dx) { int spriteId = spriteIds[y * tileMap.partitionSizeX + x]; int tile = BuilderUtil.GetTileFromRawTile(spriteId); bool flipH = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipX); bool flipV = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.FlipY); bool rot90 = BuilderUtil.IsRawTileFlagSet(spriteId, tk2dTileFlags.Rot90); Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) { continue; } if (skipPrefabs && tilePrefabs[tile]) { continue; } var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { Vector3 flippedPos = BuilderUtil.ApplySpriteVertexTileFlags(tileMap, sprite, sprite.positions[v], flipH, flipV, rot90); if (useColor && colorChunk != null) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; switch (colorMode) { case tk2dTileMapData.ColorMode.Interpolate: { Vector3 centeredSpriteVertex = flippedPos - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); break; } case tk2dTileMapData.ColorMode.Solid: { meshColors.Add(tileColorx0y0); break; } } } else { meshColors.Add(clearColor); } if (generateUv2) { if (sprite.normalizedUvs.Length == 0) { meshUv2s.Add(Vector2.zero); } else { meshUv2s.Add(sprite.normalizedUvs[v]); } } meshVertices.Add(currentPos + flippedPos); meshUvs.Add(sprite.uvs[v]); } bool reverseIndices = false; // flipped? if (flipH) { reverseIndices = !reverseIndices; } if (flipV) { reverseIndices = !reverseIndices; } List <int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) { int j = reverseIndices ? (sprite.indices.Length - 1 - i) : i; indices.Add(baseVertex + sprite.indices[j]); } } } if (chunk.mesh == null) { chunk.mesh = tk2dUtil.CreateMesh(); } chunk.mesh.Clear(); chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); if (generateUv2) { chunk.mesh.uv2 = meshUv2s.ToArray(); } chunk.mesh.colors = meshColors.ToArray(); List <Material> materials = new List <Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.SpriteCollectionInst.materialInsts[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.GetComponent <Renderer>().materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); if (buildNormals) { chunk.mesh.RecalculateNormals(); } var meshFilter = chunk.gameObject.GetComponent <MeshFilter>(); meshFilter.sharedMesh = chunk.mesh; }
public static void BuildForChunk(tk2dTileMap tileMap, SpriteChunk chunk, ColorChunk colorChunk, bool useColor, bool skipPrefabs, int baseX, int baseY) { List <Vector3> meshVertices = new List <Vector3>(); List <Color> meshColors = new List <Color>(); List <Vector2> meshUvs = new List <Vector2>(); //List<int> meshIndices = new List<int>(); int[] spriteIds = chunk.spriteIds; Vector3 tileSize = tileMap.data.tileSize; int spriteCount = tileMap.SpriteCollectionInst.spriteDefinitions.Length; Object[] tilePrefabs = tileMap.data.tilePrefabs; Color32 clearColor = (useColor && tileMap.ColorChannel != null)?tileMap.ColorChannel.clearColor:Color.white; // revert to no color mode (i.e. fill with clear color) when there isn't a color channel, or it is empty if (colorChunk == null || colorChunk.colors.Length == 0) { useColor = false; } int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, tileMap.partitionSizeX, tileMap.partitionSizeY, out x0, out x1, out dx, out y0, out y1, out dy); float xOffsetMult = 0.0f, yOffsetMult = 0.0f; tileMap.data.GetTileOffset(out xOffsetMult, out yOffsetMult); List <int>[] meshIndices = new List <int> [tileMap.SpriteCollectionInst.materials.Length]; for (int j = 0; j < meshIndices.Length; ++j) { meshIndices[j] = new List <int>(); } int colorChunkSize = tileMap.partitionSizeX + 1; for (int y = y0; y != y1; y += dy) { float xOffset = ((baseY + y) & 1) * xOffsetMult; for (int x = x0; x != x1; x += dx) { int tile = spriteIds[y * tileMap.partitionSizeX + x]; Vector3 currentPos = new Vector3(tileSize.x * (x + xOffset), tileSize.y * y, 0); if (tile < 0 || tile >= spriteCount) { continue; } if (skipPrefabs && tilePrefabs[tile]) { continue; } var sprite = tileMap.SpriteCollectionInst.spriteDefinitions[tile]; int baseVertex = meshVertices.Count; for (int v = 0; v < sprite.positions.Length; ++v) { if (useColor) { Color tileColorx0y0 = colorChunk.colors[y * colorChunkSize + x]; Color tileColorx1y0 = colorChunk.colors[y * colorChunkSize + x + 1]; Color tileColorx0y1 = colorChunk.colors[(y + 1) * colorChunkSize + x]; Color tileColorx1y1 = colorChunk.colors[(y + 1) * colorChunkSize + (x + 1)]; Vector3 centeredSpriteVertex = sprite.positions[v] - sprite.untrimmedBoundsData[0]; Vector3 alignedSpriteVertex = centeredSpriteVertex + tileMap.data.tileSize * 0.5f; float tileColorX = Mathf.Clamp01(alignedSpriteVertex.x / tileMap.data.tileSize.x); float tileColorY = Mathf.Clamp01(alignedSpriteVertex.y / tileMap.data.tileSize.y); Color color = Color.Lerp( Color.Lerp(tileColorx0y0, tileColorx1y0, tileColorX), Color.Lerp(tileColorx0y1, tileColorx1y1, tileColorX), tileColorY); meshColors.Add(color); } else { meshColors.Add(clearColor); } meshVertices.Add(currentPos + sprite.positions[v]); meshUvs.Add(sprite.uvs[v]); } List <int> indices = meshIndices[sprite.materialId]; for (int i = 0; i < sprite.indices.Length; ++i) { indices.Add(baseVertex + sprite.indices[i]); } } } if (chunk.mesh == null) { chunk.mesh = tileMap.GetOrCreateMesh(); } chunk.mesh.vertices = meshVertices.ToArray(); chunk.mesh.uv = meshUvs.ToArray(); chunk.mesh.colors = meshColors.ToArray(); List <Material> materials = new List <Material>(); int materialId = 0; int subMeshCount = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { materials.Add(tileMap.SpriteCollectionInst.materials[materialId]); subMeshCount++; } materialId++; } if (subMeshCount > 0) { chunk.mesh.subMeshCount = subMeshCount; chunk.gameObject.renderer.materials = materials.ToArray(); int subMeshId = 0; foreach (var indices in meshIndices) { if (indices.Count > 0) { chunk.mesh.SetTriangles(indices.ToArray(), subMeshId); subMeshId++; } } } chunk.mesh.RecalculateBounds(); if (tileMap.serializeRenderData) { chunk.mesh.RecalculateNormals(); } var meshFilter = chunk.gameObject.GetComponent <MeshFilter>(); meshFilter.sharedMesh = chunk.mesh; }
/// Creates render data for given tilemap public static void CreateRenderData(tk2dTileMap tileMap, bool editMode) { // Create render data if (tileMap.renderData == null) { tileMap.renderData = new GameObject(tileMap.name + " Render Data"); } tileMap.renderData.transform.position = tileMap.transform.position; float accumulatedLayerZ = 0.0f; // Create all objects int layerId = 0; foreach (var layer in tileMap.Layers) { // We skip offsetting the first one float layerInfoZ = tileMap.data.Layers[layerId].z; if (layerId != 0) { accumulatedLayerZ -= layerInfoZ; } if (layer.IsEmpty && layer.gameObject != null) { GameObject.DestroyImmediate(layer.gameObject); layer.gameObject = null; } else if (!layer.IsEmpty && layer.gameObject == null) { var go = layer.gameObject = new GameObject(""); go.transform.parent = tileMap.renderData.transform; } int unityLayer = tileMap.data.Layers[layerId].unityLayer; if (layer.gameObject != null) { #if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9 if (!editMode && layer.gameObject.active == false) { layer.gameObject.SetActiveRecursively(true); } #else if (!editMode && layer.gameObject.activeSelf == false) { layer.gameObject.SetActive(true); } #endif layer.gameObject.name = tileMap.data.Layers[layerId].name; layer.gameObject.transform.localPosition = new Vector3(0, 0, tileMap.data.layersFixedZ ? (-layerInfoZ) : accumulatedLayerZ); layer.gameObject.transform.localRotation = Quaternion.identity; layer.gameObject.transform.localScale = Vector3.one; layer.gameObject.layer = unityLayer; } int x0, x1, dx; int y0, y1, dy; BuilderUtil.GetLoopOrder(tileMap.data.sortMethod, layer.numColumns, layer.numRows, out x0, out x1, out dx, out y0, out y1, out dy); float z = 0.0f; for (int y = y0; y != y1; y += dy) { for (int x = x0; x != x1; x += dx) { var chunk = layer.GetChunk(x, y); bool isEmpty = layer.IsEmpty || chunk.IsEmpty; if (editMode) { isEmpty = false; } if (isEmpty && chunk.HasGameData) { chunk.DestroyGameData(tileMap); } else if (!isEmpty && chunk.gameObject == null) { string chunkName = "Chunk " + y.ToString() + " " + x.ToString(); var go = chunk.gameObject = new GameObject(chunkName); go.transform.parent = layer.gameObject.transform; // render mesh MeshFilter meshFilter = go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); chunk.mesh = new Mesh(); meshFilter.mesh = chunk.mesh; // collider mesh chunk.meshCollider = go.AddComponent <MeshCollider>(); chunk.meshCollider.sharedMesh = null; chunk.colliderMesh = null; } if (chunk.gameObject != null) { Vector3 tilePosition = GetTilePosition(tileMap, x * tileMap.partitionSizeX, y * tileMap.partitionSizeY); tilePosition.z += z; chunk.gameObject.transform.localPosition = tilePosition; chunk.gameObject.transform.localRotation = Quaternion.identity; chunk.gameObject.transform.localScale = Vector3.one; chunk.gameObject.layer = unityLayer; // We won't be generating collider data in edit mode, so clear everything if (editMode) { if (chunk.colliderMesh) { chunk.DestroyColliderData(tileMap); } } } z -= 0.000001f; } } ++layerId; } }