Esempio n. 1
0
        public void CutRect(STETilemap tilemap, int startGridX, int startGridY, int endGridX, int endGridY)
        {
            if (IsUndoEnabled)
            {
#if UNITY_EDITOR
                Undo.RecordObject(tilemap, STETilemap.k_UndoOpName + tilemap.name);
                Undo.RecordObjects(tilemap.GetComponentsInChildren <TilemapChunk>(), STETilemap.k_UndoOpName + tilemap.name);
#endif
            }
            tilemap.IsUndoEnabled = IsUndoEnabled;

            TileObjSourceTilemap       = tilemap;
            TileObjSourceTilemapOffset = new Vector2Int(startGridX, startGridY);
            for (int gridY = startGridY; gridY <= endGridY; ++gridY)
            {
                for (int gridX = startGridX; gridX <= endGridX; ++gridX)
                {
                    BrushTilemap.SetTileData(gridX - startGridX, gridY - startGridY, tilemap.GetTileData(gridX, gridY));
                    tilemap.SetTileData(gridX, gridY, Tileset.k_TileData_Empty);
                }
            }
            TileObjSourceTilemap = null;

            BrushTilemap.UpdateMeshImmediate();
            tilemap.UpdateMeshImmediate();

            tilemap.IsUndoEnabled = false;
        }
Esempio n. 2
0
        public bool AutotileWith(STETilemap tilemap, int selfBrushId, int gridX, int gridY)
        {
            bool isOutOfBounds = gridX > tilemap.MaxGridX || gridX <tilemap.MinGridX || gridY> tilemap.MaxGridY || gridY < tilemap.MinGridY;

            if ((AutotilingMode & eAutotilingMode.TilemapBounds) != 0 && isOutOfBounds)
            {
                return(true);
            }

            uint otherTileData = tilemap.GetTileData(gridX, gridY);

            if ((AutotilingMode & eAutotilingMode.EmptyCells) != 0 && otherTileData == Tileset.k_TileData_Empty)
            {
                return(true);
            }
            if ((AutotilingMode & eAutotilingMode.Group) != 0)
            {
                Tile tile = tilemap.Tileset.GetTile((int)(otherTileData & Tileset.k_TileDataMask_TileId));
                if (tile != null && Tileset.GetGroupAutotiling(Group, tile.autilingGroup))
                {
                    return(true);
                }
            }
            int otherBrushId = (int)((uint)(otherTileData & Tileset.k_TileDataMask_BrushId) >> 16);

            return(AutotileWith(selfBrushId, otherBrushId));
        }
Esempio n. 3
0
 public void CopyRect(STETilemap tilemap, int startGridX, int startGridY, int endGridX, int endGridY)
 {
     for (int gridY = startGridY; gridY <= endGridY; ++gridY)
     {
         for (int gridX = startGridX; gridX <= endGridX; ++gridX)
         {
             BrushTilemap.SetTileData(gridX - startGridX, gridY - startGridY, tilemap.GetTileData(gridX, gridY));
         }
     }
     BrushTilemap.UpdateMeshImmediate();
 }
Esempio n. 4
0
        public bool AutotileWith(STETilemap tilemap, int selfBrushId, int gridX, int gridY)
        {
            bool isOutOfBounds = gridX > tilemap.MaxGridX || gridX <tilemap.MinGridX || gridY> tilemap.MaxGridY || gridY < tilemap.MinGridY;

            if ((AutotilingMode & eAutotilingMode.TilemapBounds) != 0 && isOutOfBounds)
            {
                return(true);
            }
            uint otherTileData = tilemap.GetTileData(gridX, gridY);

            return(AutotileWith(tilemap.Tileset, selfBrushId, otherTileData));
        }
Esempio n. 5
0
        public void InitializeGrid()
        {
            mapTiles.Clear();

            for (int x = tilemap.MinGridX; x <= tilemap.MaxGridX; x++)
            {
                for (int y = tilemap.MinGridY; y <= tilemap.MaxGridY; y++)
                {
                    Tile tileSTE     = tilemap.GetTile(x, y);
                    uint tileDataSTE = tilemap.GetTileData(x, y);
                    uint dataSTE     = Tileset.GetTileFlagsFromTileData(tileDataSTE);

                    if (tileSTE == null)
                    {
                        continue;
                    }

                    LightTile tile = new LightTile();
                    tile.gridPosition = new Vector3Int(x, y, 0);
                    tile.uv           = tileSTE.uv;

                    bool flipX = (dataSTE & k_TileFlag_FlipH) != 0;
                    bool flipY = (dataSTE & k_TileFlag_FlipV) != 0;

                    Vector2 scale = Vector2.one;
                    if (flipX)
                    {
                        scale.x = -1;
                    }

                    if (flipY)
                    {
                        scale.y = -1;
                    }

                    tile.scale = scale;

                    bool dynamic = this.shadowTypeSTE == SuperTilemapEditorSupport.TilemapCollider2D.ShadowType.TileCollider;

                    if (dynamic)
                    {
                        List <Polygon2> polygons = TileColliderDataToPolygons(tileSTE.collData, tile.scale);

                        if (polygons.Count > 0)
                        {
                            tile.SetLocalPolygons(polygons);
                        }
                    }

                    mapTiles.Add(tile);
                }
            }
        }
Esempio n. 6
0
 public void CopyRect(STETilemap tilemap, int startGridX, int startGridY, int endGridX, int endGridY)
 {
     TileObjSourceTilemap       = tilemap;
     TileObjSourceTilemapOffset = new Vector2Int(startGridX, startGridY);
     for (int gridY = startGridY; gridY <= endGridY; ++gridY)
     {
         for (int gridX = startGridX; gridX <= endGridX; ++gridX)
         {
             BrushTilemap.SetTileData(gridX - startGridX, gridY - startGridY, tilemap.GetTileData(gridX, gridY));
         }
     }
     TileObjSourceTilemap = null;
     BrushTilemap.UpdateMeshImmediate();
 }
Esempio n. 7
0
 /// <summary>
 /// Iterate through all the tilemap cells and calls an action for each cell.
 /// Ex:
 /// void EraseTilesFromTilemap(Tilemap tilemap)
 /// {
 ///    IterateTilemapWithAction(tilemap, EraseTilesAction);
 /// }
 /// void EraseTilesAction(Tilemap tilemap, int gx, int gy)
 /// {
 ///    tilemap.Erase(gx, gy);
 /// }
 /// </summary>
 /// <param name="tilemap"></param>
 /// <param name="action"></param>
 static public void IterateTilemapWithAction(STETilemap tilemap, System.Action <STETilemap, int, int, uint> action)
 {
     if (tilemap)
     {
         for (int gy = tilemap.MinGridY; gy <= tilemap.MaxGridY; ++gy)
         {
             for (int gx = tilemap.MinGridX; gx <= tilemap.MaxGridX; ++gx)
             {
                 if (action != null)
                 {
                     action(tilemap, gx, gy, tilemap.GetTileData(gx, gy));
                 }
             }
         }
     }
 }
Esempio n. 8
0
        public void Paint(STETilemap tilemap, Vector2 localPos, bool skipEmptyTiles = false)
        {
            int minGridX = m_brushTilemap.MinGridX;
            int minGridY = m_brushTilemap.MinGridY;
            int maxGridX = m_brushTilemap.MaxGridX;
            int maxGridY = m_brushTilemap.MaxGridY;

            if (IsUndoEnabled)
            {
#if UNITY_EDITOR
                Undo.RecordObject(tilemap, STETilemap.k_UndoOpName + tilemap.name);
                Undo.RecordObjects(tilemap.GetComponentsInChildren <TilemapChunk>(), STETilemap.k_UndoOpName + tilemap.name);
#endif
            }
            tilemap.IsUndoEnabled = IsUndoEnabled;
            int  dstGy        = BrushUtil.GetGridY(localPos, tilemap.CellSize);
            bool doPaintEmpty = m_brushTilemap.GridWidth == 1 && m_brushTilemap.GridHeight == 1 || // don't copy empty tiles
                                m_brushPattern != null && m_brushPattern.GetLength(0) == 1 && m_brushPattern.GetLength(1) == 1;// unless the brush size is one
            doPaintEmpty              &= !skipEmptyTiles;
            TileObjSourceTilemap       = BrushTilemap;
            TileObjSourceTilemapOffset = new Vector2Int(-BrushUtil.GetGridX(localPos, tilemap.CellSize), -dstGy);
            for (int gridY = minGridY; gridY <= maxGridY; ++gridY, ++dstGy)
            {
                int dstGx = BrushUtil.GetGridX(localPos, tilemap.CellSize);
                for (int gridX = minGridX; gridX <= maxGridX; ++gridX, ++dstGx)
                {
                    uint tileData = m_brushTilemap.GetTileData(gridX, gridY);
                    if (
                        doPaintEmpty ||
                        tileData != Tileset.k_TileData_Empty
                        )
                    {
                        tilemap.SetTileData(dstGx, dstGy, tileData);
                    }
                }
            }

            tilemap.UpdateMeshImmediate();
            TileObjSourceTilemap = null;

            tilemap.IsUndoEnabled = false;
        }
Esempio n. 9
0
        public void SetTileData(int locGridX, int locGridY, uint tileData)
        {
            if (locGridX >= 0 && locGridX < m_width && locGridY >= 0 && locGridY < m_height)
            {
                int tileIdx = locGridY * m_width + locGridX;

                int  tileId = (int)(tileData & Tileset.k_TileDataMask_TileId);
                Tile tile   = Tileset.GetTile(tileId);

                int  prevTileId = (int)(m_tileDataList[tileIdx] & Tileset.k_TileDataMask_TileId);
                Tile prevTile   = Tileset.GetTile(prevTileId);

                int brushId     = Tileset.GetBrushIdFromTileData(tileData);
                int prevBrushId = Tileset.GetBrushIdFromTileData(m_tileDataList[tileIdx]);

                if (brushId != prevBrushId ||
                    brushId == 0)                //NOTE: because of the autotiling mode, neighbour tiles could be affected by this change, even if the tile is not a brush
                {
                    if (!s_currUpdatedTilechunk) // avoid this is chunks is being Updated from FillMeshData
                    {
                        // Refresh Neighbors ( and itself if needed )
                        for (int yf = -1; yf <= 1; ++yf)
                        {
                            for (int xf = -1; xf <= 1; ++xf)
                            {
                                if ((xf | yf) == 0)
                                {
                                    if (brushId > 0)
                                    {
                                        // Refresh itself
                                        tileData = (tileData & ~Tileset.k_TileFlag_Updated);
                                    }
                                }
                                else
                                {
                                    int          gx               = (locGridX + xf);
                                    int          gy               = (locGridY + yf);
                                    int          idx              = gy * m_width + gx;
                                    bool         isInsideChunk    = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height);
                                    uint         neighborTileData = isInsideChunk ? m_tileDataList[idx] : ParentTilemap.GetTileData(GridPosX + locGridX + xf, GridPosY + locGridY + yf);
                                    int          neighborBrushId  = (int)((neighborTileData & Tileset.k_TileDataMask_BrushId) >> 16);
                                    TilesetBrush neighborBrush    = ParentTilemap.Tileset.FindBrush(neighborBrushId);
                                    if (neighborBrush != null &&
                                        (neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, tileData) || neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, m_tileDataList[tileIdx])))
                                    {
                                        neighborTileData = (neighborTileData & ~Tileset.k_TileFlag_Updated); // force a refresh
                                        if (isInsideChunk)
                                        {
                                            m_tileDataList[idx] = neighborTileData;
                                        }
                                        else
                                        {
                                            ParentTilemap.SetTileData(GridPosX + gx, GridPosY + gy, neighborTileData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else if (brushId > 0)
                {
                    // Refresh itself
                    tileData = (tileData & ~Tileset.k_TileFlag_Updated);
                }

                m_needsRebuildMesh      |= (m_tileDataList[tileIdx] != tileData) || (tileData & Tileset.k_TileDataMask_TileId) == Tileset.k_TileId_Empty;
                m_needsRebuildColliders |= m_needsRebuildMesh &&
                                           (
                    (prevBrushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later)
                    (tile != null && tile.collData.type != eTileCollider.None) || (prevTile != null && prevTile.collData.type != eTileCollider.None)    // prev. or new tile has colliders
                                           );

                if (ParentTilemap.ColliderType != eColliderType.None && m_needsRebuildColliders)
                {
                    // Refresh Neighbors tilechunk colliders, to make the collider autotiling
                    // Only if neighbor is outside this tilechunk
                    for (int yf = -1; yf <= 1; ++yf)
                    {
                        for (int xf = -1; xf <= 1; ++xf)
                        {
                            if ((xf | yf) != 0) // skip this tile position xf = yf = 0
                            {
                                int  gx            = (locGridX + xf);
                                int  gy            = (locGridY + yf);
                                bool isInsideChunk = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height);
                                if (!isInsideChunk)
                                {
                                    ParentTilemap.InvalidateChunkAt(GridPosX + gx, GridPosY + gy, false, true);
                                }
                            }
                        }
                    }
                }

                // Update tile data
                m_tileDataList[tileIdx] = tileData;

                if (!STETilemap.DisableTilePrefabCreation)
                {
                    // Create tile Objects
                    if (tile != null && tile.prefabData.prefab != null)
                    {
                        CreateTileObject(tileIdx, tile.prefabData);
                    }
                    else
                    {
                        DestroyTileObject(tileIdx);
                    }
                }

                TilesetBrush brush = ParentTilemap.Tileset.FindBrush(brushId);
                if (brushId != prevBrushId)
                {
                    TilesetBrush prevBrush = ParentTilemap.Tileset.FindBrush(prevBrushId);
                    if (prevBrush != null)
                    {
                        prevBrush.OnErase(this, locGridX, locGridY, tileData, prevBrushId);
                    }
                }
                if (brush != null)
                {
                    tileData = brush.OnPaint(this, locGridX, locGridY, tileData);
                }
            }
        }
Esempio n. 10
0
        //https://social.msdn.microsoft.com/Forums/en-US/9d926a16-0051-4ca3-b77c-8095fb489ae2/flood-fill-c?forum=csharplanguage
        public static void FloodFill(STETilemap tilemap, int gridX, int gridY, uint[,] tileData, bool randomize = false)
        {
            float timeStamp;

            timeStamp = Time.realtimeSinceStartup;
            //float callTimeStamp = timeStamp;

            int patternW             = tileData.GetLength(0);
            int patternH             = tileData.GetLength(1);
            LinkedList <Point> check = new LinkedList <Point>();
            uint floodFrom           = tilemap.GetTileData(gridX, gridY);
            int  dataIdx0            = randomize ? Random.Range(0, patternW) : (gridX % patternW + patternW) % patternW;
            int  dataIdx1            = randomize ? Random.Range(0, patternH) : (gridY % patternH + patternH) % patternH;

            tilemap.SetTileData(gridX, gridY, tileData[dataIdx0, dataIdx1]);
            bool isBrush = Tileset.GetBrushIdFromTileData(floodFrom) != 0;

            //Debug.Log(" Flood Fill Starts +++++++++++++++ ");
            if (
                (patternW > 0 && patternH > 0) &&
                isBrush?
                Tileset.GetBrushIdFromTileData(floodFrom) != Tileset.GetBrushIdFromTileData(tileData[0, 0])
                :
                floodFrom != tileData[0, 0]
                )
            {
                check.AddLast(new Point(gridX, gridY));
                while (check.Count > 0)
                {
                    Point cur = check.First.Value;
                    check.RemoveFirst();

                    foreach (Point off in new Point[] {
                        new Point(0, -1), new Point(0, 1),
                        new Point(-1, 0), new Point(1, 0)
                    })
                    {
                        Point next         = new Point(cur.X + off.X, cur.Y + off.Y);
                        uint  nextTileData = tilemap.GetTileData(next.X, next.Y);
                        if (
                            next.X >= tilemap.MinGridX && next.X <= tilemap.MaxGridX &&
                            next.Y >= tilemap.MinGridY && next.Y <= tilemap.MaxGridY
                            )
                        {
                            if (
                                isBrush?
                                Tileset.GetBrushIdFromTileData(floodFrom) == Tileset.GetBrushIdFromTileData(nextTileData)
                                :
                                floodFrom == nextTileData
                                )
                            {
                                check.AddLast(next);
                                dataIdx0 = randomize ? Random.Range(0, patternW) : (next.X % patternW + patternW) % patternW;
                                dataIdx1 = randomize ? Random.Range(0, patternH) : (next.Y % patternH + patternH) % patternH;
                                tilemap.SetTileData(next.X, next.Y, tileData[dataIdx0, dataIdx1]);
                            }
                        }
                    }

                    float timePast = Time.realtimeSinceStartup - timeStamp;
                    if (timePast > k_timeToAbortFloodFill)
                    {
#if UNITY_EDITOR
                        int result = UnityEditor.EditorUtility.DisplayDialogComplex("FloodFill is taking too much time", "Do you want to continue for another " + k_timeToAbortFloodFill + " seconds?", "Wait", "Cancel", "Wait and Don't ask again");
                        if (result == 0)
                        {
                            timeStamp = Time.realtimeSinceStartup;
                        }
                        else if (result == 1)
                        {
                            break;
                        }
                        else if (result == 2)
                        {
                            timeStamp = float.MaxValue;
                        }
#else
                        check.Clear();
#endif
                    }
                }
            }

            //Debug.Log("FloodFill Time " + (int)((Time.realtimeSinceStartup - callTimeStamp) * 1000) + "ms");
        }
Esempio n. 11
0
        //Note: this is doing the same as FloodFill but not saving data in the tilemap, only saving the filled points and returning a list
        public static void FloodFillPreview(STETilemap tilemap, int gridX, int gridY, uint tileData, List <Vector2> outFilledPoints, uint maxPoints = uint.MaxValue)
        {
            if (
                gridX >= tilemap.MinGridX && gridX <= tilemap.MaxGridX &&
                gridY >= tilemap.MinGridY && gridY <= tilemap.MaxGridY
                )
            {
                bool[]             filledPoints = new bool[tilemap.GridWidth * tilemap.GridHeight];
                LinkedList <Point> check        = new LinkedList <Point>();
                uint floodFrom = tilemap.GetTileData(gridX, gridY);
                outFilledPoints.Add(Vector2.Scale(new Vector2(gridX, gridY), tilemap.CellSize));
                filledPoints[(gridY - tilemap.MinGridY) * tilemap.GridWidth + gridX - tilemap.MinGridX] = true;
                bool isBrush = Tileset.GetBrushIdFromTileData(floodFrom) != 0;
                if (
                    isBrush ?
                    Tileset.GetBrushIdFromTileData(floodFrom) != Tileset.GetBrushIdFromTileData(tileData)
                    :
                    floodFrom != tileData
                    )
                {
                    check.AddLast(new Point(gridX, gridY));
                    while (check.Count > 0)
                    {
                        Point cur = check.First.Value;
                        check.RemoveFirst();

                        foreach (Point off in new Point[] {
                            new Point(0, -1), new Point(0, 1),
                            new Point(-1, 0), new Point(1, 0)
                        })
                        {
                            Point next = new Point(cur.X + off.X, cur.Y + off.Y);

                            if (
                                next.X >= tilemap.MinGridX && next.X <= tilemap.MaxGridX &&
                                next.Y >= tilemap.MinGridY && next.Y <= tilemap.MaxGridY
                                )
                            {
                                if (filledPoints[(next.Y - tilemap.MinGridY) * tilemap.GridWidth + next.X - tilemap.MinGridX])
                                {
                                    continue;                                                                                            // skip already filled points
                                }
                                uint nextTileData = tilemap.GetTileData(next.X, next.Y);
                                if (
                                    isBrush ?
                                    Tileset.GetBrushIdFromTileData(floodFrom) == Tileset.GetBrushIdFromTileData(nextTileData)
                                    :
                                    floodFrom == nextTileData
                                    )
                                {
                                    check.AddLast(next);
                                    filledPoints[(next.Y - tilemap.MinGridY) * tilemap.GridWidth + next.X - tilemap.MinGridX] = true;
                                    outFilledPoints.Add(Vector2.Scale(new Vector2(next.X, next.Y), tilemap.CellSize));
                                    if (outFilledPoints.Count >= maxPoints)
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 12
0
 static public T GetTileParameter <T>(STETilemap tilemap, int gridX, int gridY, string paramName, T defaultValue = default(T))
 {
     return(GetTileParameter <T>(tilemap.Tileset, tilemap.GetTileData(gridX, gridY), paramName, defaultValue));
 }
Esempio n. 13
0
 static public T GetTileParameter <T>(STETilemap tilemap, Vector2 locPosition, string paramName, T defaultValue = default(T))
 {
     return(GetTileParameter <T>(tilemap.Tileset, tilemap.GetTileData(locPosition), paramName, defaultValue));
 }