Пример #1
0
        public void Flood(Vector2Int32 pt)
        {
            int bitmapWidth  = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            int x = pt.X;
            int y = pt.Y;

            _wvm.CheckTiles = new bool[bitmapWidth * bitmapHeight];

            var originTile = (Tile)_wvm.CurrentWorld.Tiles[x, y].Clone();

            LinearFloodFill(ref x, ref y, ref originTile);

            while (_ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = _ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc,y+1);
                int upPxIdx   = (bitmapWidth * (range.Y - 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc, y - 1);
                int upY       = range.Y - 1;                                  //so we can pass the y coord by ref
                int downY     = range.Y + 1;
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    if (range.Y > 0 && (!_wvm.CheckTiles[upPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, upY]) && _wvm.Selection.IsValid(i, upY))
                    {
                        LinearFloodFill(ref i, ref upY, ref originTile);
                    }

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    if (range.Y < (bitmapHeight - 1) && (!_wvm.CheckTiles[downPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, downY]) && _wvm.Selection.IsValid(i, downY))
                    {
                        LinearFloodFill(ref i, ref downY, ref originTile);
                    }
                    downPxIdx++;
                    upPxIdx++;
                }

                if (upY < _minY)
                {
                    _minY = upY;
                }
                if (downY > _maxY)
                {
                    _maxY = downY;
                }
            }
        }
Пример #2
0
            /// <summary>Removes and returns the <see cref="FloodFillRange"/> at the beginning of the queue.</summary>
            public FloodFillRange Dequeue()
            {
                var range = new FloodFillRange();

                if (size > 0)
                {
                    range       = array[head];
                    array[head] = new FloodFillRange();
                    head++; //advance head position
                    size--; //update size to exclude dequeued item
                }
                return(range);
            }
Пример #3
0
            public FloodFillRange Dequeue()
            {
                FloodFillRange range = new FloodFillRange();

                if (size > 0)
                {
                    range       = array[head];
                    array[head] = new FloodFillRange();
                    head++;
                    size--;
                }
                return(range);
            }
Пример #4
0
        private static void PerformLinearFill(
            Layer layer, Queue <FloodFillRange> floodFillQueue,
            Coordinates coords, int width, SKColor colorToReplace, ref Int32Rect dirtyRect, bool[] visited, List <Coordinates> output)
        {
            // Find the Left Edge of the Color Area
            int fillXLeft = coords.X;

            while (true)
            {
                // Indicate that this pixel has been checked
                int pixelIndex = (coords.Y * width) + fillXLeft;
                visited[pixelIndex] = true;

                // Move one pixel to the left
                fillXLeft--;
                // Exit the loop if we're at edge of the bitmap or the color area
                if (fillXLeft < 0 || visited[pixelIndex - 1] || layer.GetPixelWithOffset(fillXLeft, coords.Y) != colorToReplace)
                {
                    break;
                }
            }
            int lastCheckedPixelLeft = fillXLeft + 1;

            // Find the Right Edge of the Color Area
            int fillXRight = coords.X;

            while (true)
            {
                int pixelIndex = (coords.Y * width) + fillXRight;
                visited[pixelIndex] = true;

                fillXRight++;
                if (fillXRight >= width || visited[pixelIndex + 1] || layer.GetPixelWithOffset(fillXRight, coords.Y) != colorToReplace)
                {
                    break;
                }
            }
            int lastCheckedPixelRight = fillXRight - 1;

            int relativeY = coords.Y;

            LineTool.CalculateBresenhamLine(new Coordinates(lastCheckedPixelLeft, relativeY), new Coordinates(lastCheckedPixelRight, relativeY), output);
            dirtyRect = dirtyRect.Expand(new Int32Rect(lastCheckedPixelLeft, coords.Y, lastCheckedPixelRight - lastCheckedPixelLeft + 1, 1));

            FloodFillRange range = new FloodFillRange(lastCheckedPixelLeft, lastCheckedPixelRight, coords.Y);

            floodFillQueue.Enqueue(range);
        }
Пример #5
0
            public override void FloodFill(CvPoint pt)
            {
                PrepareForFloodFill();

                unsafe
                {
                    scan0 = (byte *)bitmap.DataByte;
                    int   x = pt.X; int y = pt.Y;
                    int   loc      = CoordsToIndex(ref x, ref y);
                    byte *colorPtr = ((byte *)(scan0 + loc));
                    startColor = new byte[] { colorPtr[0], colorPtr[1], colorPtr[2] };
                    LinearFloodFill4(ref x, ref y);

                    bool[] pixelsChecked = this.pixelsChecked;

                    while (ranges.Count > 0)
                    {
                        FloodFillRange range = ranges.Dequeue();

                        //START THE LOOP UPWARDS AND DOWNWARDS
                        int   upY       = range.Y - 1;                //so we can pass the y coord by ref
                        int   downY     = range.Y + 1;
                        byte *upPtr     = (byte *)(scan0 + CoordsToIndex(ref range.StartX, ref upY));
                        byte *downPtr   = (byte *)(scan0 + CoordsToIndex(ref range.StartX, ref downY));
                        int   downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX;                    //CoordsToPixelIndex(range.StartX,range.Y+1);
                        int   upPxIdx   = (bitmapWidth * (range.Y - 1)) + range.StartX;                    //CoordsToPixelIndex(range.StartX, range.Y - 1);
                        for (int i = range.StartX; i <= range.EndX; i++)
                        {
                            //START LOOP UPWARDS
                            //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                            if (range.Y > 0 && CheckPixel(ref upPtr) && (!(pixelsChecked[upPxIdx])))
                            {
                                LinearFloodFill4(ref i, ref upY);
                            }
                            //START LOOP DOWNWARDS
                            if (range.Y < (bitmapHeight - 1) && CheckPixel(ref downPtr) && (!(pixelsChecked[downPxIdx])))
                            {
                                LinearFloodFill4(ref i, ref downY);
                            }
                            upPtr   += bitmapPixelFormatSize;
                            downPtr += bitmapPixelFormatSize;
                            downPxIdx++;
                            upPxIdx++;
                        }
                    }
                }
            }
Пример #6
0
        private static void LinearFloodFill(ref Vector2Int32 start, ref Vector2Int32 minBound, ref Vector2Int32 maxBound, Func <Vector2Int32, bool> validation, ref FloodFillRangeQueue ranges, ref HashSet <Vector2Int32> points)
        {
            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = start.X; //the location to check/fill on the left

            int x = start.X;
            int y = start.Y;

            points.Add(start);
            while (true)
            {
                points.Add(new Vector2Int32(lFillLoc, y));

                // Preform validation for next point
                lFillLoc--;
                var curPoint = new Vector2Int32(lFillLoc, y);
                if (lFillLoc <= minBound.X || !validation(curPoint) || points.Contains(curPoint))
                {
                    break;                               //exit loop if we're at edge of bitmap or match area
                }
            }
            lFillLoc++;

            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left

            while (true)
            {
                points.Add(new Vector2Int32(rFillLoc, y));

                rFillLoc++;
                var curPoint = new Vector2Int32(rFillLoc, y);
                if (rFillLoc >= maxBound.X || !validation(curPoint) || points.Contains(curPoint))
                {
                    break;                               //exit loop if we're at edge of bitmap or color area
                }
            }
            rFillLoc--;

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);

            ranges.Enqueue(ref r);
        }
Пример #7
0
        public static void Flood(Vector2Int32 start, Vector2Int32 minBound, Vector2Int32 maxBound, Func <Vector2Int32, bool> validation)
        {
            var ranges = new FloodFillRangeQueue();
            var points = new HashSet <Vector2Int32>();

            LinearFloodFill(ref start, ref minBound, ref maxBound, validation, ref ranges, ref points);

            while (ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int upY      = range.Y - 1;//so we can pass the y coord by ref
                int downY    = range.Y + 1;
                var curPoint = new Vector2Int32();
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    curPoint = new Vector2Int32(i, upY);
                    if (range.Y > 0 && (!points.Contains(curPoint) && validation(curPoint)))
                    {
                        LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points);
                    }

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    curPoint = new Vector2Int32(i, downY);
                    if (range.Y < (maxBound.Y - 1) && (!points.Contains(curPoint) && validation(curPoint)))
                    {
                        LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points);
                    }
                }
            }
        }
Пример #8
0
        private void LinearFill(ref int x, ref int y)
        {
            // Find left edge
            int lFillLoc = x;

            while (true) {
                TileCoord tid = new TileCoord(lFillLoc, y);

                if (SourceType == TileSourceType.Brush && ActiveBrush != null) {
                    ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y);
                }
                else {
                    _fillCommand.QueueReplacement(tid, _sourceStack);
                    _fillLayer[tid] = _sourceStack;
                }

                lFillLoc--;
                tid = new TileCoord(lFillLoc, y);

                if (lFillLoc < 0 || /*_sourceStack.Equals(_fillLayer[tid]) ||*/
                    !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid])))
                    break;
            }
            lFillLoc++;

            // Find right edge
            int rFillLoc = x;

            while (true) {
                TileCoord tid = new TileCoord(rFillLoc, y);

                /*if (!_sourceStack.Equals(_fillLayer[tid])) {*/
                    if (SourceType == TileSourceType.Brush && ActiveBrush != null) {
                        ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y);
                    }
                    else {
                        _fillCommand.QueueReplacement(tid, _sourceStack);
                        _fillLayer[tid] = _sourceStack;
                    }
                //}

                rFillLoc++;
                tid = new TileCoord(rFillLoc, y);

                if (rFillLoc >= _fillLayer.TilesWide || /*_sourceStack.Equals(_fillLayer[tid]) ||*/
                    !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid])))
                    break;
            }
            rFillLoc--;

            FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);
            _ranges.Enqueue(ref r);
        }
Пример #9
0
 public void Enqueue(ref FloodFillRange r)
 {
     if (size + head == array.Length) {
         FloodFillRange[] newArray = new FloodFillRange[2 * array.Length];
         Array.Copy(array, head, newArray, 0, size);
         array = newArray;
         head = 0;
     }
     array[head + (size++)] = r;
 }
Пример #10
0
 public FloodFillRange Dequeue()
 {
     FloodFillRange range = new FloodFillRange();
     if (size > 0) {
         range = array[head];
         array[head] = new FloodFillRange();
         head++;
         size--;
     }
     return range;
 }
Пример #11
0
 /// <summary>Removes and returns the <see cref="FloodFillRange"/> at the beginning of the queue.</summary>
 public FloodFillRange Dequeue()
 {
     var range = new FloodFillRange();
     if (size > 0)
     {
         range = array[head];
         array[head] = new FloodFillRange();
         head++;//advance head position
         size--;//update size to exclude dequeued item
     }
     return range;
 }
Пример #12
0
        private static void LinearFloodFill(ref Vector2Int32 start, ref Vector2Int32 minBound, ref Vector2Int32 maxBound, Func<Vector2Int32, bool> validation, ref FloodFillRangeQueue ranges, ref HashSet<Vector2Int32> points)
        {
            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = start.X; //the location to check/fill on the left

            int x = start.X;
            int y = start.Y;
            points.Add(start);
            while (true)
            {
                points.Add(new Vector2Int32(lFillLoc, y));

                // Preform validation for next point
                lFillLoc--;
                var curPoint = new Vector2Int32(lFillLoc, y);
                if (lFillLoc <= minBound.X || !validation(curPoint) || points.Contains(curPoint))
                    break;			 	 //exit loop if we're at edge of bitmap or match area

            }
            lFillLoc++;

            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left

            while (true)
            {
                points.Add(new Vector2Int32(rFillLoc, y));

                rFillLoc++;
                var curPoint = new Vector2Int32(rFillLoc, y);
                if (rFillLoc >= maxBound.X || !validation(curPoint) || points.Contains(curPoint))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            rFillLoc--;

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);
            ranges.Enqueue(ref r);
        }
Пример #13
0
        private void LinearFill(ref int x, ref int y)
        {
            // Find left edge
            int lFillLoc = x;

            while (true)
            {
                TileCoord tid = new TileCoord(lFillLoc, y);

                if (SourceType == TileSourceType.Brush && ActiveBrush != null)
                {
                    ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y);
                }
                else
                {
                    _fillCommand.QueueReplacement(tid, _sourceStack);
                    _fillLayer[tid] = _sourceStack;
                }

                lFillLoc--;
                tid = new TileCoord(lFillLoc, y);

                if (lFillLoc < 0 || /*_sourceStack.Equals(_fillLayer[tid]) ||*/
                    !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid])))
                {
                    break;
                }
            }
            lFillLoc++;

            // Find right edge
            int rFillLoc = x;

            while (true)
            {
                TileCoord tid = new TileCoord(rFillLoc, y);

                /*if (!_sourceStack.Equals(_fillLayer[tid])) {*/
                if (SourceType == TileSourceType.Brush && ActiveBrush != null)
                {
                    ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y);
                }
                else
                {
                    _fillCommand.QueueReplacement(tid, _sourceStack);
                    _fillLayer[tid] = _sourceStack;
                }
                //}

                rFillLoc++;
                tid = new TileCoord(rFillLoc, y);

                if (rFillLoc >= _fillLayer.TilesWide || /*_sourceStack.Equals(_fillLayer[tid]) ||*/
                    !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid])))
                {
                    break;
                }
            }
            rFillLoc--;

            FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);

            _ranges.Enqueue(ref r);
        }
Пример #14
0
        private void LinearFloodFill(ref int x, ref int y, ref Tile originTile)
        {
            int bitmapWidth  = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc  = x; //the location to check/fill on the left
            int tileIndex = (bitmapWidth * y) + x;

            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(lFillLoc, y);
                    _wvm.SetPixel(lFillLoc, y);
                    _wvm.UpdateRenderPixel(lFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                }

                lFillLoc--;
                tileIndex--;
                if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y))
                {
                    break; //exit loop if we're at edge of bitmap or color area
                }
            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1);

            lFillLoc++;
            if (lFillLoc < _minX)
            {
                _minX = lFillLoc;
            }
            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left

            tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(rFillLoc, y);
                    _wvm.SetPixel(rFillLoc, y);
                    _wvm.UpdateRenderPixel(rFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                    BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1);
                }

                rFillLoc++;
                tileIndex++;
                if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y))
                {
                    break; //exit loop if we're at edge of bitmap or color area
                }
            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1);

            rFillLoc--;
            if (rFillLoc > _maxX)
            {
                _maxX = rFillLoc;
            }

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);

            _ranges.Enqueue(ref r);
        }
Пример #15
0
        private void LinearFloodFill(ref int x, ref int y, ref Tile originTile)
        {
            int bitmapWidth = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = x; //the location to check/fill on the left
            int tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(lFillLoc, y);
                    _wvm.SetPixel(lFillLoc, y);
                    _wvm.UpdateRenderPixel(lFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                }

                lFillLoc--;
                tileIndex--;
                if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y))
                    break; //exit loop if we're at edge of bitmap or color area

            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1);

            lFillLoc++;
            if (lFillLoc < _minX)
                _minX = lFillLoc;
            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left
            tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(rFillLoc, y);
                    _wvm.SetPixel(rFillLoc, y);
                    _wvm.UpdateRenderPixel(rFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                    BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1);
                }

                rFillLoc++;
                tileIndex++;
                if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y))
                    break; //exit loop if we're at edge of bitmap or color area
            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1);

            rFillLoc--;
            if (rFillLoc > _maxX)
                _maxX = rFillLoc;

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);
            _ranges.Enqueue(ref r);
        }
Пример #16
0
        private void LinearFloodFill(ref int x, ref int y, ref TilePicker tp, ref Tile originTile)
        {
            int bitmapWidth = _world.Header.MaxTiles.X;
            int bitmapHeight = _world.Header.MaxTiles.Y;

            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = x; //the location to check/fill on the left
            int tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (HistMan.SaveHistory)
                    HistMan.AddTileToBuffer(lFillLoc, y, ref _world.Tiles[x, y]);
                _world.SetTileXY(ref lFillLoc, ref y, ref tp, ref _selection);
                tilesChecked[tileIndex] = true;

                lFillLoc--;
                tileIndex--;
                if (lFillLoc <= 0 || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[lFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(lFillLoc, y)))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            lFillLoc++;
            if (lFillLoc < minX)
                minX = lFillLoc;
            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left
            tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (HistMan.SaveHistory)
                    HistMan.AddTileToBuffer(rFillLoc, y, ref _world.Tiles[x, y]);
                _world.SetTileXY(ref rFillLoc, ref y, ref tp, ref _selection);
                tilesChecked[tileIndex] = true;

                rFillLoc++;
                tileIndex++;
                if (rFillLoc >= bitmapWidth || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[rFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(rFillLoc, y)))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            rFillLoc--;
            if (rFillLoc > maxX)
                maxX = rFillLoc;

            FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);
            ranges.Enqueue(ref r);
        }