/// <inheritdoc />
        public override void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
        {
            if (brushTarget.layer == 31)
            {
                base.MoveEnd(gridLayout, brushTarget, position);
                return;
            }

            if (IsInvalid(brushTarget, out var mapPart))
            {
                return;
            }

            // when moving items, we may overlap the start region, in which case, we can't blindly erase the
            // objects at the given position.  Therefore, keep track of all of the items we're moving
            // and if we encounter them when needing to erase objects, don't erase them (they'll simply
            // move position)
            var itemsToKeep = new HashSet <GameObject>(_moveData.OfType <GameObject>().Where(it => it != null));

            // destroy the given object if it's not in our keep list
            void DestroyIfNeeded(GameObject it)
            {
                if (it != null && !itemsToKeep.Contains(it))
                {
                    Undo.DestroyObjectImmediate(it);
                }
            }

            // iterate through all of the new positions
            foreach (var childPosition in position.allPositionsWithin)
            {
                // if there's something already there, delete it
                var existingInstance = GetObjectInCell(gridLayout, brushTarget.transform, childPosition);
                DestroyIfNeeded(existingInstance);

                // and then move the old object over to the new position
                var newInstance = _moveData[childPosition.x - position.xMin, childPosition.y - position.yMin];
                if (newInstance != null)
                {
                    if (mapPart.IsValidPosition(childPosition))
                    {
                        MoveInstanceToCellPosition(gridLayout, brushTarget, childPosition, newInstance);
                    }
                    else
                    {
                        Undo.DestroyObjectImmediate(newInstance);
                    }
                }
            }

            // clear our existing move data so that we don't accidentally do anything with it later
            _moveData = null;
        }