Example #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;
        }
Example #2
0
        public void CopyRect(TileMap tilemap, int startGridX, int startGridY, int endGridX, int endGridY)
        {
            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.UpdateMeshImmediate();
        }
Example #3
0
        public uint[,] GetBrushPattern()
        {
            uint[,] brushPattern = new uint[tileMap.GridWidth, tileMap.GridHeight];
            for (int y = tileMap.min_grid_y; y <= tileMap.max_grid_y; ++y)
            {
                for (int x = tileMap.min_grid_x; x <= tileMap.max_grid_x; ++x)
                {
                    brushPattern[x - tileMap.min_grid_x, y - tileMap.min_grid_x] =
                        tileMap.GetTileData(x, y);
                }
            }

            return(brushPattern);
        }
Example #4
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);
                }
            }
        }
Example #5
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");
        }
Example #6
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(TileMap tilemap, int gridX, int gridY, uint tileData, List <Vector2> outFilledPoints, uint maxPoints = uint.MaxValue)
        {
            if (
                gridX >= tilemap.min_grid_x && gridX <= tilemap.max_grid_x &&
                gridY >= tilemap.min_grid_y && gridY <= tilemap.max_grid_y
                )
            {
                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.cell_size));
                filledPoints[(gridY - tilemap.min_grid_y) * tilemap.GridWidth + gridX - tilemap.min_grid_x] = true;
                bool isBrush = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0;
                if (
                    isBrush ?
                    TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(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.min_grid_x && next.X <= tilemap.max_grid_x &&
                                next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y
                                )
                            {
                                if (filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x])
                                {
                                    continue;                                                                                // skip already filled points
                                }
                                uint nextTileData = tilemap.GetTileData(next.X, next.Y);
                                if (
                                    isBrush ?
                                    TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(nextTileData)
                    :
                                    floodFrom == nextTileData
                                    )
                                {
                                    check.AddLast(next);
                                    filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x] = true;
                                    outFilledPoints.Add(Vector2.Scale(new Vector2(next.X, next.Y), tilemap.cell_size));
                                    if (outFilledPoints.Count >= maxPoints)
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }