public STETilemap GetDefaultTilemapForCurrentTileSelection() { if (SelectedTilemap && SelectedTilemap.Tileset) { if (SelectedTilemap.Tileset.SelectedTileId != Tileset.k_TileId_Empty) { return(GetDefaultTilemapForTileOrBrush(SelectedTilemap.Tileset.SelectedTileId, m_dicTileDefaultTilemap)); } else if (SelectedTilemap.Tileset.SelectedBrushId != Tileset.k_BrushId_Default) { return(GetDefaultTilemapForTileOrBrush(SelectedTilemap.Tileset.SelectedBrushId, m_dicBrushDefaultTilemap)); } else if (SelectedTilemap.Tileset.TileSelection != null && SelectedTilemap.Tileset.TileSelection.selectionData.Count > 0) { uint tileData = SelectedTilemap.Tileset.TileSelection.selectionData[0]; int brushId = Tileset.GetBrushIdFromTileData(tileData); if (brushId != Tileset.k_BrushId_Default) { return(GetDefaultTilemapForTileOrBrush(brushId, m_dicBrushDefaultTilemap)); } else { int tileId = Tileset.GetTileIdFromTileData(tileData); if (tileId != Tileset.k_TileId_Empty) { return(GetDefaultTilemapForTileOrBrush(tileId, m_dicTileDefaultTilemap)); } } } } return(null); }
/// <summary> /// Return the tile at the grid position /// </summary> /// <param name="gridX"></param> /// <param name="gridY"></param> /// <returns></returns> public Tile GetTile(int gridX, int gridY) { uint tileData = GetTileData(gridX, gridY); int tileId = Tileset.GetTileIdFromTileData(tileData); return(Tileset.GetTile(tileId)); }
static public Texture2D CreateTexture2DFromTilemap(Tilemap tilemap) { int tilePxSizeX = (int)tilemap.Tileset.TilePxSize.x; int tilePxSizeY = (int)tilemap.Tileset.TilePxSize.y; Texture2D output = new Texture2D(tilemap.GridWidth * tilePxSizeX, tilemap.GridHeight * tilePxSizeY, TextureFormat.ARGB32, false); output.filterMode = FilterMode.Point; output.SetPixels32(new Color32[output.width * output.height]); output.Apply(); Texture2D atlasTexture = tilemap.Tileset.AtlasTexture; System.Action <Tilemap, int, int, uint> action = (Tilemap source, int gridX, int gridY, uint tileData) => { gridX -= source.MinGridX; gridY -= source.MinGridY; Tile tile = tilemap.Tileset.GetTile(Tileset.GetTileIdFromTileData(tileData)); if (tile != null) { Color[] srcTileColors = atlasTexture.GetPixels(Mathf.RoundToInt(tile.uv.x * atlasTexture.width), Mathf.RoundToInt(tile.uv.y * atlasTexture.height), tilePxSizeX, tilePxSizeY); output.SetPixels(gridX * tilePxSizeX, gridY * tilePxSizeY, tilePxSizeX, tilePxSizeY, srcTileColors); } }; IterateTilemapWithAction(tilemap, action); output.Apply(); return(output); }
/// <summary> /// Return a tile parameter (bool, int, float, string or UnityEngine.Object) from a tiledata. /// It takes first the parameter from a brush, if possible, then from a tile. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tileset"></param> /// <param name="tileData"></param> /// <param name="paramName"></param> /// <param name="defaultValue"></param> /// <returns></returns> static public T GetTileParameter <T>(Tileset tileset, uint tileData, string paramName, T defaultValue = default(T)) { Tile tile = tileset.GetTile(Tileset.GetTileIdFromTileData(tileData)); TilesetBrush brush = tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData)); T value = defaultValue; if (brush) { value = brush.Params.GetParam <T>(paramName, defaultValue); } if (tile != null && EqualityComparer <T> .Default.Equals(value, defaultValue)) { value = tile.paramContainer.GetParam <T>(paramName, defaultValue); } return(value); }
private void SetDefaultTilemapFromTileData(STETilemap tilemap, int gx, int gy, uint tileData) { int brushId = Tileset.GetBrushIdFromTileData(tileData); if (brushId != Tileset.k_BrushId_Default) { m_target.SetBrushDefaultTilemap(brushId, tilemap); } else { int tileId = Tileset.GetTileIdFromTileData(tileData); if (tileId != Tileset.k_TileId_Empty) { m_target.SetTileDefaultTilemap(tileId, tilemap); } } }
public bool SetRenderTile(STETilemap tilemap, uint tileData) { m_parentTilemap = tilemap; Tile tile = tilemap.Tileset.GetTile(Tileset.GetTileIdFromTileData(tileData)); if (tile != null) { m_meshRenderer.material = tilemap.Material; m_meshRenderer.sortingLayerID = tilemap.SortingLayerID; m_meshRenderer.sortingOrder = tilemap.OrderInLayer; Vector2 cellSizeDiv2 = tilemap.CellSize / 2f; Vector3[] vertices = new Vector3[4] { new Vector3(-cellSizeDiv2.x, -cellSizeDiv2.y, 0), new Vector3(cellSizeDiv2.x, -cellSizeDiv2.y, 0), new Vector3(-cellSizeDiv2.x, cellSizeDiv2.y, 0), new Vector3(cellSizeDiv2.x, cellSizeDiv2.y, 0), }; int[] triangles = new int[] { 3, 0, 2, 0, 3, 1 }; Vector2[] uvs = new Vector2[] { new Vector2(tile.uv.xMin, tile.uv.yMin), new Vector2(tile.uv.xMax, tile.uv.yMin), new Vector2(tile.uv.xMin, tile.uv.yMax), new Vector2(tile.uv.xMax, tile.uv.yMax), }; if (!m_meshFilter.sharedMesh) { m_meshFilter.sharedMesh = new Mesh(); } m_meshFilter.sharedMesh.name = "Quad"; Mesh mesh = m_meshFilter.sharedMesh; mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.uv = uvs; mesh.RecalculateNormals(); return(true); } return(false); }
/// <summary> /// Get the parameter container from tileData if tileData contains a tile with parameters or Null in other case /// </summary> /// <param name="tilemap"></param> /// <param name="tileData"></param> /// <returns></returns> static public ParameterContainer GetParamsFromTileData(STETilemap tilemap, uint tileData) { int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = tilemap.Tileset.FindBrush(brushId); if (brush) { return(brush.Params); } else { int tileId = Tileset.GetTileIdFromTileData(tileData); Tile tile = tilemap.Tileset.GetTile(tileId); if (tile != null) { return(tile.paramContainer); } } return(null); }
public static Sprite GetOrCreateSprite(TilemapChunk.OnTilePrefabCreationData data) { Sprite sprite = null; int tileId = Tileset.GetTileIdFromTileData(data.ParentTilemap.GetTileData(data.GridX, data.GridY)); Tile tile = data.ParentTilemap.Tileset.GetTile(tileId); if (tile != null) { float pixelsPerUnit = data.ParentTilemap.Tileset.TilePxSize.x / data.ParentTilemap.CellSize.x; Vector2 atlasSize = new Vector2(data.ParentTilemap.Tileset.AtlasTexture.width, data.ParentTilemap.Tileset.AtlasTexture.height); Rect spriteUV = new Rect(Vector2.Scale(tile.uv.position, atlasSize), Vector2.Scale(tile.uv.size, atlasSize)); string spriteName = data.ParentTilemap.Tileset.name + "_" + tileId + "_" + pixelsPerUnit; if (!s_spriteCache.TryGetValue(spriteName, out sprite) || !sprite) { sprite = Sprite.Create(data.ParentTilemap.Tileset.AtlasTexture, spriteUV, new Vector2(.5f, .5f), pixelsPerUnit); sprite.name = spriteName; s_spriteCache[spriteName] = sprite; } } return(sprite); }
public override Vector2[] GetMergedSubtileColliderVertices(STETilemap tilemap, int gridX, int gridY, uint tileData) { uint[] subTiles = GetSubtiles(tilemap, gridX, gridY, tileData); if (subTiles != null) { s_mergedColliderVertexList.Clear(); for (int i = 0; i < subTiles.Length; ++i) { uint subTileData = subTiles[i]; Tile tile = tilemap.Tileset.GetTile(Tileset.GetTileIdFromTileData(subTiles[i])); if (tile != null && tile.collData.type != eTileCollider.None) { TileColliderData tileCollData = tile.collData; if ((subTileData & (Tileset.k_TileFlag_FlipH | Tileset.k_TileFlag_FlipV | Tileset.k_TileFlag_Rot90)) != 0) { tileCollData = tileCollData.Clone(); tileCollData.ApplyFlippingFlags(subTileData); } Vector2[] vertices = tile.collData.GetVertices(); if (vertices != null) { for (int v = 0; v < vertices.Length; ++v) { Vector2 v0, v1; if (v < vertices.Length - 1) { v0 = vertices[v]; v1 = vertices[v + 1]; } else { v0 = vertices[v]; v1 = vertices[0]; } if (i == 0 || i == 2) //left side { if (v0.x >= .5f && v1.x >= .5f) { continue; } float newY = v0.y + (.5f - v0.x) * (v1.y - v0.y) / (v1.x - v0.x); if (v0.x > .5f) { v0.y = newY; v0.x = .5f; } else if (v1.x > .5f) { v1.y = newY; v1.x = .5f; } } else // right side { if (v0.x <= .5f && v1.x <= .5f) { continue; } float newY = v0.y + (.5f - v0.x) * (v1.y - v0.y) / (v1.x - v0.x); if (v0.x < .5f) { v0.y = newY; v0.x = .5f; } else if (v1.x < .5f) { v1.y = newY; v1.x = .5f; } } if (i == 0 || i == 1) //bottom side { if (v0.y >= .5f && v1.y >= .5f) { continue; } float newX = v0.x + (.5f - v0.y) * (v1.x - v0.x) / (v1.y - v0.y); if (v0.y > .5f) { v0.x = newX; v0.y = .5f; } else if (v1.y > .5f) { v1.x = newX; v1.y = .5f; } } else // top side { if (v0.y <= .5f && v1.y <= .5f) { continue; } float newX = v0.x + (.5f - v0.y) * (v1.x - v0.x) / (v1.y - v0.y); if (v0.y < .5f) { v0.x = newX; v0.y = .5f; } else if (v1.y < .5f) { v1.x = newX; v1.y = .5f; } } s_mergedColliderVertexList.Add(v0); s_mergedColliderVertexList.Add(v1); } } } } return(s_mergedColliderVertexList.ToArray()); } return(null); }
private void DoPaintInspector() { Event e = Event.current; Tilemap tilemap = (Tilemap)target; if (DoToolBar() || DragAndDrop.objectReferences.Length > 0 || // hide brush when user is dragging a prefab into the scene EditorWindow.mouseOverWindow != SceneView.currentDrawingSceneView) // hide brush when it's not over the scene view { m_brushVisible = false; SceneView.RepaintAll(); return; } int controlID = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(controlID); EventType currentEventType = Event.current.GetTypeForControl(controlID); bool skip = false; int saveControl = GUIUtility.hotControl; try { if (currentEventType == EventType.Layout) { skip = true; } else if (currentEventType == EventType.ScrollWheel) { skip = true; } if (tilemap.Tileset == null) { return; } if (!skip) { if (e.type == EventType.KeyDown) { if (e.keyCode == ShortcutKeys.k_FlipH) { BrushBehaviour.GetOrCreateBrush(tilemap).FlipH(!e.shift); e.Use(); // Use key event } else if (e.keyCode == ShortcutKeys.k_FlipV) { BrushBehaviour.GetOrCreateBrush(tilemap).FlipV(!e.shift); e.Use(); // Use key event } else if (e.keyCode == ShortcutKeys.k_Rot90) { BrushBehaviour.GetOrCreateBrush(tilemap).Rot90(!e.shift); e.Use(); // Use key event } else if (e.keyCode == ShortcutKeys.k_Rot90Back) { BrushBehaviour.GetOrCreateBrush(tilemap).Rot90Back(!e.shift); e.Use(); // Use key event } } EditorGUIUtility.AddCursorRect(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), MouseCursor.Arrow); GUIUtility.hotControl = controlID; { Plane chunkPlane = new Plane(tilemap.transform.forward, tilemap.transform.position); Vector2 mousePos = Event.current.mousePosition; mousePos.y = Screen.height - mousePos.y; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); float dist; if (chunkPlane.Raycast(ray, out dist)) { Rect rTile = new Rect(0, 0, m_tilemap.CellSize.x, m_tilemap.CellSize.y); rTile.position = tilemap.transform.InverseTransformPoint(ray.GetPoint(dist)); Vector2 tilePos = rTile.position; if (tilePos.x < 0) { tilePos.x -= m_tilemap.CellSize.x; } if (tilePos.y < 0) { tilePos.y -= m_tilemap.CellSize.y; } tilePos.x -= tilePos.x % m_tilemap.CellSize.x; tilePos.y -= tilePos.y % m_tilemap.CellSize.y; rTile.position = tilePos; Vector2 startPos = new Vector2(Mathf.Min(m_startDragging.x, m_endDragging.x), Mathf.Min(m_startDragging.y, m_endDragging.y)); Vector2 endPos = new Vector2(Mathf.Max(m_startDragging.x, m_endDragging.x), Mathf.Max(m_startDragging.y, m_endDragging.y)); Vector2 selectionSnappedPos = BrushUtil.GetSnappedPosition(startPos, m_tilemap.CellSize); Vector2 selectionSize = BrushUtil.GetSnappedPosition(endPos, m_tilemap.CellSize) - selectionSnappedPos + m_tilemap.CellSize; BrushBehaviour brush = BrushBehaviour.GetOrCreateBrush(tilemap); // Update brush transform m_localPaintPos = (Vector2)tilemap.transform.InverseTransformPoint(ray.GetPoint(dist)); Vector2 brushSnappedPos = BrushUtil.GetSnappedPosition(brush.Offset + m_localPaintPos, m_tilemap.CellSize); brush.transform.rotation = tilemap.transform.rotation; brush.transform.localScale = tilemap.transform.lossyScale; brush.transform.position = tilemap.transform.TransformPoint(new Vector3(brushSnappedPos.x, brushSnappedPos.y, -0.01f)); //--- int prevMouseGridX = m_mouseGridX; int prevMouseGridY = m_mouseGridY; if (e.isMouse) { m_mouseGridX = BrushUtil.GetGridX(m_localPaintPos, tilemap.CellSize); m_mouseGridY = BrushUtil.GetGridY(m_localPaintPos, tilemap.CellSize); } bool isMouseGridChanged = prevMouseGridX != m_mouseGridX || prevMouseGridY != m_mouseGridY; //Update Fill Preview if (GetBrushMode() == eBrushMode.Fill && isMouseGridChanged) { m_fillPreview.Clear(); TilemapDrawingUtils.FloodFillPreview(tilemap, brush.Offset + m_localPaintPos, brush.BrushTilemap.GetTileData(0, 0), m_fillPreview); } if ( (EditorWindow.focusedWindow == EditorWindow.mouseOverWindow) && // fix painting tiles when closing another window popup over the SceneView like GameObject Selection window (e.type == EventType.MouseDown || e.type == EventType.MouseDrag && isMouseGridChanged) ) { if (e.button == 0) { if (m_dblClick.IsDblClick && brush.BrushTilemap.GridWidth == 1 && brush.BrushTilemap.GridHeight == 1) { // Restore previous tiledata modified by Paint, because before the double click, a single click is done before tilemap.SetTileData(brush.Offset + m_localPaintPos, m_floodFillRestoredTileData); brush.FloodFill(tilemap, brush.Offset + m_localPaintPos, brush.BrushTilemap.GetTileData(0, 0)); } // Do a brush paint action else { switch (GetBrushMode()) { case eBrushMode.Paint: m_floodFillRestoredTileData = tilemap.GetTileData(m_mouseGridX, m_mouseGridY); brush.Paint(tilemap, brush.Offset + m_localPaintPos); break; case eBrushMode.Erase: brush.Erase(tilemap, brush.Offset + m_localPaintPos); break; case eBrushMode.Fill: brush.FloodFill(tilemap, brush.Offset + m_localPaintPos, brush.BrushTilemap.GetTileData(0, 0)); break; } } } else if (e.button == 1) { if (e.type == EventType.MouseDown) { m_isDragging = true; brush.BrushTilemap.ClearMap(); m_startDragging = m_endDragging = m_localPaintPos; } else { m_endDragging = m_localPaintPos; } } } else if (e.type == EventType.MouseUp) { if (e.button == 1) // right mouse button { m_isDragging = false; ResetBrushMode(); // Copy one tile if (selectionSize.x <= m_tilemap.CellSize.x && selectionSize.y <= m_tilemap.CellSize.y) { uint tileData = tilemap.GetTileData(m_localPaintPos); if (tileData == Tileset.k_TileData_Empty) { tilemap.Tileset.SelectedTileId = Tileset.k_TileId_Empty; brush.BrushTilemap.SetTileData(0, 0, Tileset.k_TileData_Empty); } else { int brushId = Tileset.GetBrushIdFromTileData(tileData); int tileId = Tileset.GetTileIdFromTileData(tileData); // Select the copied tile in the tileset, alternating between the brush and the tile drawn by the brush if (brushId > 0 && brushId != tilemap.Tileset.SelectedBrushId) { tilemap.Tileset.SelectedBrushId = brushId; } else { tilemap.Tileset.SelectedTileId = tileId; brush.BrushTilemap.SetTileData(0, 0, tileData & ~Tileset.k_TileDataMask_BrushId); // keep tile flags } } // Cut tile if key shift is pressed if (e.shift) { int startGridX = BrushUtil.GetGridX(startPos, m_tilemap.CellSize); int startGridY = BrushUtil.GetGridY(startPos, m_tilemap.CellSize); brush.CutRect(tilemap, startGridX, startGridY, startGridX, startGridY); } brush.BrushTilemap.UpdateMesh(); brush.Offset = Vector2.zero; } // copy a rect of tiles else { int startGridX = BrushUtil.GetGridX(startPos, m_tilemap.CellSize); int startGridY = BrushUtil.GetGridY(startPos, m_tilemap.CellSize); int endGridX = BrushUtil.GetGridX(endPos, m_tilemap.CellSize); int endGridY = BrushUtil.GetGridY(endPos, m_tilemap.CellSize); // Cut tile if key shift is pressed if (e.shift) { brush.CutRect(tilemap, startGridX, startGridY, endGridX, endGridY); } else { brush.CopyRect(tilemap, startGridX, startGridY, endGridX, endGridY); } brush.Offset.x = m_endDragging.x > m_startDragging.x ? -(endGridX - startGridX) * tilemap.CellSize.x : 0f; brush.Offset.y = m_endDragging.y > m_startDragging.y ? -(endGridY - startGridY) * tilemap.CellSize.y : 0f; } } } if (m_isDragging) { Rect rGizmo = new Rect(selectionSnappedPos, selectionSize); HandlesEx.DrawRectWithOutline(tilemap.transform, rGizmo, new Color(), Color.white); } else // Draw brush border { Rect rBound = new Rect(brush.BrushTilemap.MapBounds.min, brush.BrushTilemap.MapBounds.size); Color fillColor; switch (GetBrushMode()) { case eBrushMode.Paint: fillColor = new Color(0, 0, 0, 0); break; case eBrushMode.Erase: fillColor = new Color(1f, 0f, 0f, 0.1f); break; case eBrushMode.Fill: fillColor = new Color(1f, 1f, 0f, 0.2f); break; default: fillColor = new Color(0, 0, 0, 0); break; } HandlesEx.DrawRectWithOutline(brush.transform, rBound, fillColor, new Color(1, 1, 1, 0.2f)); } } } if (currentEventType == EventType.MouseDrag && Event.current.button < 2) // 2 is for central mouse button { // avoid dragging the map Event.current.Use(); } } } // Avoid loosing the hotControl because of a triggered exception catch (System.Exception ex) { Debug.LogException(ex); } SceneView.RepaintAll(); GUIUtility.hotControl = saveControl; }
static public Texture2D CreateTexture2DFromTilemap(STETilemap tilemap) { MakeTextureReadable(tilemap.Tileset.AtlasTexture); int tilePxSizeX = (int)tilemap.Tileset.TilePxSize.x; int tilePxSizeY = (int)tilemap.Tileset.TilePxSize.y; Texture2D output = new Texture2D(tilemap.GridWidth * tilePxSizeX, tilemap.GridHeight * tilePxSizeY, TextureFormat.ARGB32, false); output.filterMode = FilterMode.Point; output.SetPixels32(new Color32[output.width * output.height]); output.Apply(); System.Action <STETilemap, int, int, uint> action = (STETilemap source, int gridX, int gridY, uint tileData) => { gridX -= source.MinGridX; gridY -= source.MinGridY; Tile tile = tilemap.Tileset.GetTile(Tileset.GetTileIdFromTileData(tileData)); if (tile != null) { Texture2D atlasTexture = tilemap.Tileset.AtlasTexture; int tx = Mathf.RoundToInt(tile.uv.x * atlasTexture.width); int ty = Mathf.RoundToInt(tile.uv.y * atlasTexture.height); int tw = tilePxSizeX; int th = tilePxSizeY; Sprite prefabSprite = null; if (tile.prefabData.prefab) { SpriteRenderer spriteRenderer = tile.prefabData.prefab.GetComponent <SpriteRenderer>(); if (spriteRenderer && spriteRenderer.sprite) { prefabSprite = spriteRenderer.sprite; MakeTextureReadable(spriteRenderer.sprite.texture); atlasTexture = spriteRenderer.sprite.texture; tx = Mathf.RoundToInt(spriteRenderer.sprite.textureRect.x); ty = Mathf.RoundToInt(spriteRenderer.sprite.textureRect.y); tw = Mathf.RoundToInt(spriteRenderer.sprite.textureRect.width); th = Mathf.RoundToInt(spriteRenderer.sprite.textureRect.height); } } bool flipH = (tileData & Tileset.k_TileFlag_FlipH) != 0; bool flipV = (tileData & Tileset.k_TileFlag_FlipV) != 0; bool rot90 = (tileData & Tileset.k_TileFlag_Rot90) != 0; Color[] srcTileColors = atlasTexture.GetPixels(tx, ty, tw, th); if (flipH) { Color[] tempArr = new Color[0]; for (int i = 0; i < th; ++i) { tempArr = tempArr.Concat(srcTileColors.Skip(tw * i).Take(tw).Reverse()).ToArray(); } srcTileColors = tempArr; } if (flipV) { Color[] tempArr = new Color[0]; for (int i = th - 1; i >= 0; --i) { tempArr = tempArr.Concat(srcTileColors.Skip(tw * i).Take(tw)).ToArray(); } srcTileColors = tempArr; } if (rot90) { Color[] tempArr = new Color[tw * th]; for (int x = tw - 1, i = 0; x >= 0; --x) { for (int y = 0; y < th; ++y, ++i) { tempArr[i] = srcTileColors[y * tw + x]; } } srcTileColors = tempArr; int temp = tw; tw = th; th = temp; } if (prefabSprite) { Vector2 tileSize = prefabSprite.textureRect.size; Vector2 pivot = prefabSprite.pivot - prefabSprite.textureRectOffset; if (flipV) { pivot.y = -pivot.y + prefabSprite.textureRect.height; } if (flipH) { pivot.x = -pivot.x + prefabSprite.textureRect.width; } if (rot90) { pivot = new Vector2(pivot.y, tileSize.x - pivot.x); tileSize.x = prefabSprite.textureRect.size.y; tileSize.y = prefabSprite.textureRect.size.x; } Vector2 offset = pivot - tilemap.Tileset.TilePxSize / 2;// sprite.pivot + sprite.textureRect.position - sprite.textureRectOffset; BlitPixels(output, gridX * tilePxSizeX - Mathf.RoundToInt(offset.x), gridY * tilePxSizeY - Mathf.RoundToInt(offset.y), Mathf.RoundToInt(tileSize.x), Mathf.RoundToInt(tileSize.y), srcTileColors); } else { output.SetPixels(gridX * tilePxSizeX, gridY * tilePxSizeY, tw, th, srcTileColors); } } }; TilemapUtils.IterateTilemapWithAction(tilemap, action); output.Apply(); return(output); }