示例#1
0
        public void CutRect(TileMap tilemap, int startGridX, int startGridY, int endGridX, int endGridY)
        {
            if (is_undo_enabled)
            {
#if UNITY_EDITOR
                Undo.RecordObject(tilemap, TileMapConst.Undo_Operation_Name + tilemap.name);
                Undo.RecordObjects(tilemap.GetComponentsInChildren <TileMapChunk>(),
                                   TileMapConst.Undo_Operation_Name + tilemap.name);
#endif
            }

            tilemap.is_undo_enabled = is_undo_enabled;

            for (int gridY = startGridY; gridY <= endGridY; ++gridY)
            {
                for (int gridX = startGridX; gridX <= endGridX; ++gridX)
                {
                    tileMap.SetTileData(gridX - startGridX, gridY - startGridY, tilemap.GetTileData(gridX, gridY));
                    tilemap.SetTileData(gridX, gridY, TileSetConst.TileData_Empty);
                }
            }

            tileMap.UpdateMeshImmediate();
            tilemap.UpdateMeshImmediate();

            tilemap.is_undo_enabled = false;
        }
示例#2
0
        public void Erase(TileMap tileMap, Vector2 local_pos)
        {
            int minGridX = this.tileMap.min_grid_x;
            int minGridY = this.tileMap.min_grid_y;
            int maxGridX = this.tileMap.max_grid_x;
            int maxGridY = this.tileMap.max_grid_y;

            if (is_undo_enabled)
            {
#if UNITY_EDITOR
                Undo.RecordObject(tileMap, TileMapConst.Undo_Operation_Name + tileMap.name);
                Undo.RecordObjects(tileMap.GetComponentsInChildren <TileMapChunk>(),
                                   TileMapConst.Undo_Operation_Name + tileMap.name);
#endif
            }

            tileMap.is_undo_enabled = is_undo_enabled;
            int dstGy = TileSetBrushUtil.GetGridY(local_pos, tileMap.cell_size);
            for (int gridY = minGridY; gridY <= maxGridY; ++gridY, ++dstGy)
            {
                int dstGx = TileSetBrushUtil.GetGridY(local_pos, tileMap.cell_size);
                for (int gridX = minGridX; gridX <= maxGridX; ++gridX, ++dstGx)
                {
                    tileMap.SetTileData(dstGx, dstGy, TileSetConst.TileData_Empty);
                }
            }

            tileMap.UpdateMeshImmediate();
            tileMap.is_undo_enabled = false;
        }
示例#3
0
        public static void DrawLineMirrored(TileMap tilemap, int x0, int y0, int x1, int y1, uint[,] tileData, bool randomize = false)
        {
            int w = tileData.GetLength(0);
            int h = tileData.GetLength(1);

            TileMapDrawingUtil.Line(x0, y0, x1, y1,
                                    (x, y) =>
            {
                int dataIdx0 = randomize ? Random.Range(0, w) : (x % w + w) % w;
                int dataIdx1 = randomize ? Random.Range(0, h) : (y % h + h) % h;
                tilemap.SetTileData(x, y, tileData[dataIdx0, dataIdx1]);
                dataIdx0 = randomize ? Random.Range(0, w) : ((x0 - x) % w + w) % w;
                dataIdx1 = randomize ? Random.Range(0, h) : ((y0 - y) % h + h) % h;
                tilemap.SetTileData(x0 - x, y0 - y, tileData[dataIdx0, dataIdx1]);
                return(true);
            }
                                    );
        }
示例#4
0
        public void Paint(TileMap tileMap, Vector2 local_pos, bool skipEmptyTiles = false)
        {
            int min_grid_x = this.tileMap.min_grid_x;
            int min_grid_y = this.tileMap.min_grid_y;
            int max_grid_x = this.tileMap.max_grid_x;
            int max_grid_y = this.tileMap.max_grid_y;

            if (is_undo_enabled)
            {
#if UNITY_EDITOR
                Undo.RecordObject(tileMap, TileMapConst.Undo_Operation_Name + tileMap.name);
                Undo.RecordObjects(tileMap.GetComponentsInChildren <TileMapChunk>(),
                                   TileMapConst.Undo_Operation_Name + tileMap.name);
#endif
            }

            tileMap.is_undo_enabled = is_undo_enabled;
            int  target_grid_y     = TileSetBrushUtil.GetGridY(local_pos, tileMap.cell_size);
            bool is_do_paint_empty =
                this.tileMap.GridWidth == 1 && this.tileMap.GridHeight == 1 || // don't copy empty tiles
                brushPattern != null && brushPattern.GetLength(0) == 1 &&
                brushPattern.GetLength(1) == 1; // unless the brush size is one
            is_do_paint_empty &= !skipEmptyTiles;



            for (int grid_y = min_grid_y; grid_y <= max_grid_y; ++grid_y, ++target_grid_y)
            {
                int target_grid_x = TileSetBrushUtil.GetGridX(local_pos, tileMap.cell_size);
                for (int grid_x = min_grid_x; grid_x <= max_grid_x; ++grid_x, ++target_grid_x)
                {
                    uint tileData = this.tileMap.GetTileData(grid_x, grid_y);
                    if (
                        is_do_paint_empty ||
                        tileData != TileSetConst.TileData_Empty
                        )
                    {
                        tileMap.SetTileData(target_grid_x, target_grid_y, tileData);
                    }
                }
            }

            tileMap.UpdateMeshImmediate();
            tileMap.is_undo_enabled = false;
        }
示例#5
0
        public static void DrawEllipse(TileMap tilemap, int x0, int y0, int x1, int y1, uint[,] tileData, bool isFilled, bool randomize = false)
        {
            int w  = tileData.GetLength(0);
            int h  = tileData.GetLength(1);
            int xf = 0;
            int yf = 0;

            //fix for cases where x1 x2 y1 or y2 are negative or x1 > x2 or y1 > y2
            // NOTE: I tested this only for case x1 == y1 == 0
            if (x0 > x1)
            {
                Swap <int>(ref x0, ref x1);
            }
            if (y0 > y1)
            {
                Swap <int>(ref y0, ref y1);
            }
            if (x0 < 0)
            {
                xf = x0; x0 = 0; x1 -= xf;
            }
            if (y0 < 0)
            {
                yf = y0; y0 = 0; y1 -= yf;
            }
            //
            TileMapDrawingUtil.Ellipse(x0, y0, x1, y1, isFilled,
                                       (x, y) =>
            {
                int dataIdx0 = randomize ? Random.Range(0, w) : ((x + xf) % w + w) % w;
                int dataIdx1 = randomize ? Random.Range(0, h) : ((y + yf) % h + h) % h;
                tilemap.SetTileData(x + xf, y + yf, tileData[dataIdx0, dataIdx1]);
                return(true);
            }
                                       );
        }
示例#6
0
        public void SetTileData(int local_grid_x, int local_grid_y, uint tileData)
        {
            if (local_grid_x >= 0 && local_grid_x < width && local_grid_y >= 0 && local_grid_y < height)
            {
                int tile_index = local_grid_y * width + local_grid_x;

                int  tileId = (int)(tileData & TileSetConst.TileDataMask_TileId);
                Tile tile   = tileSet.GetTile(tileId);

                int  prev_tileId = (int)(tileData_list[tile_index] & TileSetConst.TileDataMask_TileId);
                Tile prev_tile   = tileSet.GetTile(prev_tileId);

                int brushId      = TileSetUtil.GetTileSetBrushIdFromTileData(tileData);
                int prev_brushId = TileSetUtil.GetTileSetBrushIdFromTileData(tileData_list[tile_index]);

                if (brushId != prev_brushId)
                {
                    if (!current_updated_tileMapChunk) // avoid this is chunks is being Updated from FillMeshData
                    {
                        // Refresh Neighbors ( and itself if needed )
                        for (int y_offset = -1; y_offset <= 1; ++y_offset)
                        {
                            for (int x_offset = -1; x_offset <= 1; ++x_offset)
                            {
                                if ((x_offset | y_offset) == 0)
                                {
                                    if (brushId > 0)
                                    {
                                        // Refresh itself
                                        tileData = (tileData & ~TileSetConst.TileFlag_Updated);
                                    }
                                }
                                else
                                {
                                    int          grid_x                = (local_grid_x + x_offset);
                                    int          grid_y                = (local_grid_y + y_offset);
                                    int          index                 = grid_y * width + grid_x;
                                    bool         is_inside_chunk       = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height);
                                    uint         neighbor_tileData     = is_inside_chunk ? tileData_list[index] : parent_tileMap.GetTileData(offset_grid_x + local_grid_x + x_offset, offset_grid_y + local_grid_y + y_offset);
                                    int          neighbor_brushId      = (int)((neighbor_tileData & TileSetConst.TileDataMask_TileSetBrushId) >> 16);
                                    TileSetBrush neighbor_tileSetBrush = parent_tileMap.tileSet.FindTileSetBrush(neighbor_brushId);
                                    //if (brush != null && brush.AutotileWith(brushId, neighborBrushId) || prevBrush != null && prevBrush.AutotileWith(prevBrushId, neighborBrushId))
                                    if (neighbor_tileSetBrush != null &&
                                        (neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, brushId) || neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, prev_brushId)))
                                    {
                                        neighbor_tileData = (neighbor_tileData & ~TileSetConst.TileFlag_Updated); // force a refresh
                                        if (is_inside_chunk)
                                        {
                                            tileData_list[index] = neighbor_tileData;
                                        }
                                        else
                                        {
                                            parent_tileMap.SetTileData(offset_grid_x + grid_x, offset_grid_y + grid_y, neighbor_tileData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else if (brushId > 0)
                {
                    // Refresh itself
                    tileData = (tileData & ~TileSetConst.TileFlag_Updated);
                }

                is_need_rebuild_mesh      |= (tileData_list[tile_index] != tileData) || (tileData & TileSetConst.TileDataMask_TileId) == TileSetConst.TileId_Empty;
                is_need_rebuild_colliders |= is_need_rebuild_mesh &&
                                             (
                    (prev_brushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later)
                    (tile != null && tile.tileColliderData.type != TileColliderType.None) || (prev_tile != null && prev_tile.tileColliderData.type != TileColliderType.None) // prev. or new tile has colliders
                                             );

                if (parent_tileMap.tileMapColliderType != TileMapColliderType.None && is_need_rebuild_colliders)
                {
                    // Refresh Neighbors tilechunk colliders, to make the collider autotiling
                    // Only if neighbor is outside this tilechunk
                    for (int y_offset = -1; y_offset <= 1; ++y_offset)
                    {
                        for (int x_offset = -1; x_offset <= 1; ++x_offset)
                        {
                            if ((x_offset | y_offset) != 0) // skip this tile position xf = yf = 0
                            {
                                int  grid_x          = (local_grid_x + x_offset);
                                int  grid_y          = (local_grid_y + y_offset);
                                bool is_inside_chunk = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height);
                                if (!is_inside_chunk)
                                {
                                    parent_tileMap.InvalidateChunkAt(offset_grid_x + grid_x, offset_grid_y + grid_y, false, true);
                                }
                            }
                        }
                    }
                }

                // Update tile data
                tileData_list[tile_index] = tileData;

                if (!TileMap.Is_Disable_Tile_Prefab_Creation)
                {
                    // Create tile Objects
                    if (tile != null && tile.tilePrefabData.prefab != null)
                    {
                        CreateTileObject(tile_index, tile.tilePrefabData);
                    }
                    else
                    {
                        DestroyTileObject(tile_index);
                    }
                }

                TileSetBrush brush = parent_tileMap.tileSet.FindTileSetBrush(brushId);
                if (brushId != prev_brushId)
                {
                    TileSetBrush prevBrush = parent_tileMap.tileSet.FindTileSetBrush(prev_brushId);
                    if (prevBrush != null)
                    {
                        prevBrush.OnErase(this, local_grid_x, local_grid_y, tileData, prev_brushId);
                    }
                }
                if (brush != null)
                {
                    tileData = brush.OnPaint(this, local_grid_x, local_grid_y, tileData);
                }
            }
        }
示例#7
0
        public static void DrawRect(TileMap tilemap, int x0, int y0, int x1, int y1, uint[,] tileData, bool isFilled, bool is9Sliced = false, bool randomize = false)
        {
            int w = tileData.GetLength(0);
            int h = tileData.GetLength(1);

            if (x0 > x1)
            {
                Swap <int>(ref x0, ref x1);
            }
            if (y0 > y1)
            {
                Swap <int>(ref y0, ref y1);
            }
            TileMapDrawingUtil.Rect(x0, y0, x1, y1, isFilled,
                                    (x, y) =>
            {
                if (is9Sliced)
                {
                    if (x == x0 && y == y0)
                    {
                        tilemap.SetTileData(x, y, tileData[0, 0]);
                    }
                    else if (x == x0 && y == y1)
                    {
                        tilemap.SetTileData(x, y, tileData[0, h - 1]);
                    }
                    else if (x == x1 && y == y0)
                    {
                        tilemap.SetTileData(x, y, tileData[w - 1, 0]);
                    }
                    else if (x == x1 && y == y1)
                    {
                        tilemap.SetTileData(x, y, tileData[w - 1, h - 1]);
                    }
                    else
                    {
                        int cw = w - 2;
                        int ch = h - 2;
                        int cx = cw >= 1 ? 1 + (x % cw + cw) % cw : (x % w + w) % w;
                        int cy = ch >= 1 ? 1 + (y % ch + ch) % ch : (y % h + h) % h;
                        if (x == x0)
                        {
                            tilemap.SetTileData(x, y, tileData[0, cy]);
                        }
                        else if (x == x1)
                        {
                            tilemap.SetTileData(x, y, tileData[w - 1, cy]);
                        }
                        else if (y == y0)
                        {
                            tilemap.SetTileData(x, y, tileData[cx, 0]);
                        }
                        else if (y == y1)
                        {
                            tilemap.SetTileData(x, y, tileData[cx, h - 1]);
                        }
                        else
                        {
                            tilemap.SetTileData(x, y, tileData[cx, cy]);
                        }
                    }
                }
                else
                {
                    int dataIdx0 = randomize ? Random.Range(0, w) : (x % w + w) % w;
                    int dataIdx1 = randomize ? Random.Range(0, h) : (y % h + h) % h;
                    tilemap.SetTileData(x, y, tileData[dataIdx0, dataIdx1]);
                }
                return(true);
            }
                                    );
        }
示例#8
0
        //https://social.msdn.microsoft.com/Forums/en-US/9d926a16-0051-4ca3-b77c-8095fb489ae2/flood-fill-c?forum=csharplanguage
        public static void FloodFill(TileMap 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 = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0;

            //Debug.Log(" Flood Fill Starts +++++++++++++++ ");
            if (
                (patternW > 0 && patternH > 0) &&
                isBrush ?
                TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(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.min_grid_x && next.X <= tilemap.max_grid_x &&
                            next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y
                            )
                        {
                            if (
                                isBrush ?
                                TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(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");
        }