コード例 #1
0
        /// <summary>
        /// Checks whether the given area with the given center tile is a subset of the given layer.
        /// </summary>
        /// <param name="map">Reference to the map.</param>
        /// <param name="center">The center of the area to check.</param>
        /// <param name="layer">The terrain type of the layer to check.</param>
        /// <param name="area">The area to check.</param>
        /// <returns>True if the area is a subset of the given layer, false otherwise.</returns>
        private bool CheckLayer(IMapAccess map, IIsoTile center, ITerrainType layer, FloodArea area)
        {
            foreach (FloodItem floodItem in area)
            {
                IIsoTile checkedTile = map.GetIsoTile(center.MapCoords + floodItem.Coordinates);
                if (checkedTile != null)
                {
                    if (checkedTile.Type.TerrainA.IsDescendantOf(layer) || checkedTile.Type.TerrainA == layer)
                    {
                        continue;
                    }

                    if (checkedTile.Type.Combination != TerrainCombination.Simple)
                    {
                        if (checkedTile.Type.TerrainB == layer)
                        {
                            /// We have to check the combinations
                            if (((int)floodItem.Combination & (int)checkedTile.Type.Combination) != (int)floodItem.Combination)
                            {
                                return(false);
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
コード例 #2
0
        /// <see cref="IMapTerrainView.GetIsoTileDisplayCoords"/>
        public RCIntVector GetIsoTileDisplayCoords(RCIntVector position)
        {
            RCIntVector navCellCoords = this.MapWindowBC.AttachedWindow.WindowToMapCoords(position).Round();
            IIsoTile    isotile       = this.Map.GetCell(navCellCoords).ParentIsoTile;

            return(this.MapWindowBC.AttachedWindow.CellToWindowRect(new RCIntRectangle(isotile.GetCellMapCoords(new RCIntVector(0, 0)), isotile.CellSize)).Location);
        }
コード例 #3
0
ファイル: Form1.cs プロジェクト: kovacsgabor55/marsara
 private void Form1_MouseClick(object sender, MouseEventArgs e)
 {
     if (e.Button == System.Windows.Forms.MouseButtons.Left)
     {
         RCIntVector screenCoords = new RCIntVector(e.X, e.Y);
         RCIntVector mapCoords    = (screenCoords / 16) - new RCIntVector(1, 16);
         IIsoTile    target       = map.GetIsoTile(mapCoords);
         if (target != null)
         {
             this.replacedTiles.Clear();
             IEnumerable <IIsoTile> replacedTiles = this.mapEditor.DrawTerrain(this.map, target, map.Tileset.GetTerrainType(this.terrainTypes[this.selectedTerrain]));
             foreach (IIsoTile item in replacedTiles)
             {
                 this.replacedTiles.Add(item);
             }
         }
         this.Invalidate();
     }
     else if (e.Button == System.Windows.Forms.MouseButtons.Right)
     {
         this.selectedTerrain++;
         if (this.selectedTerrain == this.terrainTypes.Count)
         {
             this.selectedTerrain = 0;
         }
         this.Text = this.terrainTypes[this.selectedTerrain];
     }
 }
コード例 #4
0
ファイル: IsoTileType.cs プロジェクト: kovacsgabor55/marsara
        /// <see cref="IIsoTileType.GetVariant"/>
        public IIsoTileVariant GetVariant(IIsoTile isoTile, int variantIdx)
        {
            if (isoTile == null)
            {
                throw new ArgumentNullException("isoTile");
            }
            if (variantIdx < 0)
            {
                throw new ArgumentOutOfRangeException("variantIdx", "Variant index must be non-negative!");
            }

            foreach (Tuple <List <IsoTileVariant>, IIsoTileCondition> branch in this.variants)
            {
                if (branch.Item2 == null || branch.Item2.Check(isoTile))
                {
                    if (variantIdx >= branch.Item1.Count)
                    {
                        throw new ArgumentOutOfRangeException("variantIdx", string.Format("Variant with index {0} doesn't exists for isometric tile at {1}!", variantIdx, isoTile.MapCoords));
                    }
                    return(branch.Item1[variantIdx]);
                }
            }

            throw new MapException(string.Format("No matching conditional branch found for isometric tile at {0}!", isoTile.MapCoords));
        }
コード例 #5
0
        /// <see cref="ITerrainObjectConstraint.Check"/>
        public RCSet <RCIntVector> Check(IMapAccess map, RCIntVector position)
        {
            if (map == null)
            {
                throw new ArgumentNullException("map");
            }
            if (position == RCIntVector.Undefined)
            {
                throw new ArgumentNullException("position");
            }

            RCSet <RCIntVector> retList       = new RCSet <RCIntVector>();
            RCIntVector         absQuadCoords = position + this.quadCoords;

            if (absQuadCoords.X >= 0 && absQuadCoords.X < map.Size.X &&
                absQuadCoords.Y >= 0 && absQuadCoords.Y < map.Size.Y)
            {
                IQuadTile checkedQuadTile = map.GetQuadTile(absQuadCoords);
                IIsoTile  checkedIsoTile  = checkedQuadTile.PrimaryIsoTile;
                if (checkedIsoTile.Type.TerrainA != this.terrainA ||
                    checkedIsoTile.Type.TerrainB != this.terrainB ||
                    !this.allowedCombinations.Contains(checkedIsoTile.Type.Combination))
                {
                    retList.Add(this.quadCoords);
                    foreach (IQuadTile neighbour in checkedQuadTile.Neighbours)
                    {
                        if (neighbour.PrimaryIsoTile == checkedIsoTile)
                        {
                            retList.Add(neighbour.MapCoords - position);
                        }
                    }
                }
            }
            return(retList);
        }
コード例 #6
0
        /// <see cref="IIsoTileCondition.Check"/>
        public bool Check(IIsoTile isoTile)
        {
            bool retVal;

            if (this.logicalOp == LogicalOp.AND)
            {
                retVal = true;
                foreach (IIsoTileCondition subcond in this.subconditions)
                {
                    if (!subcond.Check(isoTile))
                    {
                        retVal = false; break;
                    }
                }
            }
            else if (this.logicalOp == LogicalOp.OR)
            {
                retVal = false;
                foreach (IIsoTileCondition subcond in this.subconditions)
                {
                    if (subcond.Check(isoTile))
                    {
                        retVal = true; break;
                    }
                }
            }
            else
            {
                retVal = !this.subconditions[0].Check(isoTile);
            }
            return(retVal);
        }
コード例 #7
0
ファイル: MapLoader.cs プロジェクト: kovacsgabor55/marsara
        /// <summary>
        /// Creates the package that contains the description of the isometric tiles of the given map.
        /// </summary>
        /// <param name="map">Reference to the map.</param>
        /// <returns>The data package that contains the description of the isometric tiles of the given map.</returns>
        private RCPackage CreateIsoTileListPackage(IMapAccess map)
        {
            RCPackage isotileList = RCPackage.CreateCustomDataPackage(MapFileFormat.ISOTILE_LIST);

            /// Create the terrain type index table.
            List <string> terrainTypeList = new List <string>();
            Dictionary <ITerrainType, int> terrainTypeIndexTable = new Dictionary <ITerrainType, int>();
            int terrainTypeIndex = 0;

            foreach (ITerrainType terrainType in map.Tileset.TerrainTypes)
            {
                terrainTypeList.Add(terrainType.Name);
                terrainTypeIndexTable.Add(terrainType, terrainTypeIndex);
                terrainTypeIndex++;
            }
            isotileList.WriteStringArray(0, terrainTypeList.ToArray());

            /// Create the packages of the isometric tiles.
            RCSet <IIsoTile> processedIsoTiles = new RCSet <IIsoTile>();
            List <RCPackage> isotilePackages   = new List <RCPackage>();
            int isotileInfoLength = 0;

            for (int row = 0; row < map.Size.Y; row++)
            {
                for (int column = 0; column < map.Size.X; column++)
                {
                    IIsoTile currIsoTile = map.GetQuadTile(new RCIntVector(column, row)).PrimaryIsoTile;
                    if (!processedIsoTiles.Contains(currIsoTile))
                    {
                        RCPackage isotilePackage = RCPackage.CreateCustomDataPackage(MapFileFormat.ISOTILE);
                        isotilePackage.WriteShort(0, (short)column);
                        isotilePackage.WriteShort(1, (short)row);
                        isotilePackage.WriteByte(2, (byte)terrainTypeIndexTable[currIsoTile.Type.TerrainA]);
                        isotilePackage.WriteByte(3, currIsoTile.Type.TerrainB != null ?
                                                 (byte)terrainTypeIndexTable[currIsoTile.Type.TerrainB] :
                                                 (byte)0);
                        isotilePackage.WriteByte(4, (byte)currIsoTile.Type.Combination);
                        isotilePackage.WriteByte(5, (byte)currIsoTile.VariantIdx);

                        isotilePackages.Add(isotilePackage);
                        processedIsoTiles.Add(currIsoTile);
                        isotileInfoLength += isotilePackage.PackageLength;
                    }
                }
            }

            /// Write the isometric tile packages into the final package
            byte[] isotileInfoBytes = new byte[isotileInfoLength];
            int    offset           = 0;

            foreach (RCPackage isotilePackage in isotilePackages)
            {
                offset += isotilePackage.WritePackageToBuffer(isotileInfoBytes, offset);
            }

            isotileList.WriteByteArray(1, isotileInfoBytes);
            return(isotileList);
        }
コード例 #8
0
ファイル: MinimapView.cs プロジェクト: kovacsgabor55/marsara
 /// <summary>
 /// Converts the given isometric tile into a SpriteInst structure.
 /// </summary>
 /// <param name="isotile">The isometric tile to convert.</param>
 /// <returns>The converted SpriteInst structure.</returns>
 private SpriteRenderInfo ConvertIsoTileToSpriteInst(IIsoTile isotile)
 {
     return(new SpriteRenderInfo()
     {
         SpriteGroup = SpriteGroupEnum.IsoTileSpriteGroup,
         Index = isotile.Variant.Index,
         DisplayCoords = this.MapWindowBC.FullWindow.CellToWindowRect(new RCIntRectangle(isotile.GetCellMapCoords(new RCIntVector(0, 0)), isotile.CellSize)).Location,
         Section = RCIntRectangle.Undefined
     });
 }
コード例 #9
0
ファイル: IsoDraw.cs プロジェクト: kovacsgabor55/marsara
        /// <summary>
        /// Draws the given isometric tile to the given device context.
        /// </summary>
        public void DrawTile(IIsoTile tile, bool isReplaced, Graphics g)
        {
            RCIntVector screenCoords = TILE_SIZE * (tile.MapCoords + new RCIntVector(1, 16));

            if (!this.tileImages.ContainsKey(tile.Type))
            {
                this.CreateTileImage(tile.Type);
            }

            g.DrawImageUnscaled(this.tileImages[tile.Type], screenCoords.X, screenCoords.Y);
            g.DrawImageUnscaled(isReplaced ? this.gridChangedImage : this.gridImage, screenCoords.X, screenCoords.Y);
        }
コード例 #10
0
ファイル: FogOfWarBC.cs プロジェクト: kovacsgabor55/marsara
 /// <summary>
 /// Adds the given isometric tile and all of its cutting quadratic tiles into the update lists.
 /// </summary>
 /// <param name="isoTile">The isometric tile to add.</param>
 /// <param name="isoTileUpdateList">The isometric update list.</param>
 /// <param name="quadTileUpdateList">The quadratic update list.</param>
 private void AddIsoTileToUpdate(IIsoTile isoTile, RCSet <IIsoTile> isoTileUpdateList, RCSet <IQuadTile> quadTileUpdateList)
 {
     if (isoTile != null && isoTileUpdateList.Add(isoTile))
     {
         foreach (IQuadTile cuttingQuadTile in isoTile.CuttingQuadTiles)
         {
             if (cuttingQuadTile != null &&
                 (this.fowCacheMatrix.GetFullFowFlagsAtQuadTile(cuttingQuadTile.MapCoords) != FOWTileFlagsEnum.None ||
                  this.fowCacheMatrix.GetPartialFowFlagsAtQuadTile(cuttingQuadTile.MapCoords) != FOWTileFlagsEnum.None))
             {
                 quadTileUpdateList.Add(cuttingQuadTile);
             }
         }
     }
 }
コード例 #11
0
ファイル: IsoTileType.cs プロジェクト: kovacsgabor55/marsara
        /// <see cref="IIsoTileType.GetNumOfVariants"/>
        public int GetNumOfVariants(IIsoTile isoTile)
        {
            if (isoTile == null)
            {
                throw new ArgumentNullException("isoTile");
            }

            foreach (Tuple <List <IsoTileVariant>, IIsoTileCondition> branch in this.variants)
            {
                if (branch.Item2 == null || branch.Item2.Check(isoTile))
                {
                    return(branch.Item1.Count);
                }
            }

            throw new MapException(string.Format("No matching conditional branch found for isometric tile at {0}!", isoTile.MapCoords));
        }
コード例 #12
0
        /// <see cref="IIsoTileCondition.Check"/>
        public bool Check(IIsoTile isoTile)
        {
            if (isoTile == null)
            {
                throw new ArgumentNullException("isoTile");
            }

            IIsoTile neighbour = isoTile.GetNeighbour(this.direction);

            if (neighbour == null)
            {
                return(false);
            }

            if (isoTile.Type.TerrainA != neighbour.Type.TerrainA || isoTile.Type.TerrainB != neighbour.Type.TerrainB)
            {
                return(false);
            }
            return(this.combination == neighbour.Type.Combination);
        }
コード例 #13
0
        /// <see cref="IMapEditorService.DrawTerrain"/>
        public void DrawTerrain(RCIntVector position, string terrainType)
        {
            if (this.scenarioManager.ActiveScenario == null)
            {
                throw new InvalidOperationException("No active scenario!");
            }
            if (position == RCIntVector.Undefined)
            {
                throw new ArgumentNullException("position");
            }
            if (terrainType == null)
            {
                throw new ArgumentNullException("terrainType");
            }

            RCIntVector navCellCoords = this.mapWindowBC.AttachedWindow.WindowToMapCoords(position).Round();
            IIsoTile    isotile       = this.scenarioManager.ActiveScenario.Map.GetCell(navCellCoords).ParentIsoTile;

            IEnumerable <IIsoTile> affectedIsoTiles = this.mapEditor.DrawTerrain(this.scenarioManager.ActiveScenario.Map, isotile,
                                                                                 this.scenarioManager.ActiveScenario.Map.Tileset.GetTerrainType(terrainType));

            foreach (IIsoTile affectedIsoTile in affectedIsoTiles)
            {
                RCNumRectangle isoTileRect = new RCNumRectangle(affectedIsoTile.GetCellMapCoords(new RCIntVector(0, 0)), affectedIsoTile.CellSize)
                                             - new RCNumVector(1, 1) / 2;
                foreach (Entity affectedEntity in this.scenarioManager.ActiveScenario.GetElementsOnMap <Entity>(isoTileRect, MapObjectLayerEnum.AirObjects, MapObjectLayerEnum.GroundObjects))
                {
                    if (affectedEntity.CheckPlacementConstraints(affectedEntity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0)
                    {
                        affectedEntity.DetachFromMap();
                        this.scenarioManager.ActiveScenario.RemoveElementFromScenario(affectedEntity);
                        affectedEntity.Dispose();
                    }
                }
            }
        }
コード例 #14
0
        /// <summary>
        /// Fills up the layers from the base layer up to the target layer.
        /// </summary>
        /// <param name="center">The center of the draw operation.</param>
        /// <param name="targetTerrain">The target terrain of the draw operation.</param>
        /// <param name="baseTerrain">The base layer of the draw operation.</param>
        public void FillLayers(IMapAccess map, IIsoTile center, ITerrainType targetTerrain, ITerrainType baseTerrain)
        {
            /// Find the biggest flood area to be filled.
            FloodArea areaToFill = new FloodArea();

            ITerrainType[] layersToFill = targetTerrain.FindRoute(baseTerrain);
            for (int routeIdx = 0; routeIdx < layersToFill.Length; routeIdx++)
            {
                ITerrainType prevTerrain = routeIdx - 1 >= 0 ? layersToFill[routeIdx - 1] : null;
                if (prevTerrain != null)
                {
                    areaToFill.Enlarge(prevTerrain.TransitionLength + 1);
                }
            }

            /// Fill the appropriate layers
            for (int routeIdx = layersToFill.Length - 1; routeIdx >= 0; routeIdx--)
            {
                /// Fill the current layer at the appropriate area.
                ITerrainType currLayer = layersToFill[routeIdx];
                foreach (FloodItem floodItem in areaToFill)
                {
                    IIsoTile filledTile = map.GetIsoTile(center.MapCoords + floodItem.Coordinates);
                    if (filledTile != null)
                    {
                        if (filledTile.Type.Combination != TerrainCombination.Simple)
                        {
                            /// Mixed tile.
                            if (filledTile.Type.TerrainB == currLayer)
                            {
                                int newCombInt             = (int)filledTile.Type.Combination | (floodItem.Combination != TerrainCombination.Simple ? (int)floodItem.Combination : 0xF);
                                TerrainCombination newComb = newCombInt != 0xF ? (TerrainCombination)newCombInt : TerrainCombination.Simple;
                                if (newComb != filledTile.Type.Combination)
                                {
                                    filledTile.ExchangeType(
                                        newComb == TerrainCombination.Simple ?
                                        map.Tileset.GetIsoTileType(filledTile.Type.TerrainB.Name) :
                                        map.Tileset.GetIsoTileType(filledTile.Type.TerrainA.Name, filledTile.Type.TerrainB.Name, newComb));
                                }
                            }
                            else if (currLayer.IsDescendantOf(filledTile.Type.TerrainB))
                            {
                                throw new MapException("Filling over the topmost layer is not possible!");
                            }
                        }
                        else
                        {
                            /// Simple tile.
                            if (filledTile.Type.TerrainA == currLayer.Parent)
                            {
                                filledTile.ExchangeType(
                                    floodItem.Combination == TerrainCombination.Simple ?
                                    map.Tileset.GetIsoTileType(currLayer.Name) :
                                    map.Tileset.GetIsoTileType(filledTile.Type.TerrainA.Name, currLayer.Name, floodItem.Combination));
                            }
                            else if (currLayer.IsDescendantOf(filledTile.Type.TerrainA))
                            {
                                throw new MapException("Filling over the topmost layer is not possible!");
                            }
                        }
                    }
                }

                if (routeIdx > 0)
                {
                    areaToFill.Reduce();
                }
            }
        }
コード例 #15
0
        /// <summary>
        /// Clears the given layers for a draw operation.
        /// </summary>
        /// <param name="map">Reference to the map.</param>
        /// <param name="center">The center of the draw operation.</param>
        /// <param name="targetTerrain">The target terrain of the draw operation.</param>
        /// <param name="baseTerrain">The base layer of the draw operation.</param>
        /// <param name="layersToClear">The route from the target terrain up to a topmost layer in the terrain tree.</param>
        private void ClearLayers(IMapAccess map, IIsoTile center, ITerrainType targetTerrain, ITerrainType baseTerrain, ITerrainType[] layersToClear)
        {
            /// Find the biggest flood area to be cleared.
            FloodArea    areaToClear        = new FloodArea();
            ITerrainType lastUninjuredLayer = null;

            for (int routeIdx = 0; routeIdx < layersToClear.Length; routeIdx++)
            {
                ITerrainType currTerrain = layersToClear[routeIdx];
                if (lastUninjuredLayer == null)
                {
                    /// We are going downstairs.
                    ITerrainType nextTerrain = layersToClear[routeIdx + 1];
                    if (nextTerrain.Parent == currTerrain)
                    {
                        /// Last uninjured layer found, from now we go upstairs.
                        lastUninjuredLayer = currTerrain;

                        /// Enlarge the clear area by 1 if there was a previous layer along the way downstairs.
                        ITerrainType prevTerrain = routeIdx - 1 >= 0 ? layersToClear[routeIdx - 1] : null;
                        if (prevTerrain != null)
                        {
                            areaToClear.Enlarge(1);
                        }
                    }
                    else
                    {
                        /// Enlarge the clear area by the transition length of the previous layer if there
                        /// was a previous layer along the way downstairs.
                        ITerrainType prevTerrain = routeIdx - 1 >= 0 ? layersToClear[routeIdx - 1] : null;
                        if (prevTerrain != null)
                        {
                            areaToClear.Enlarge(prevTerrain.TransitionLength + 1);
                        }
                    }
                }
                else
                {
                    /// We are going upstairs.
                    ITerrainType prevTerrain = layersToClear[routeIdx - 1];
                    if (prevTerrain != lastUninjuredLayer)
                    {
                        areaToClear.Enlarge(currTerrain.TransitionLength + 1);
                    }
                }
            }

            /// Clear the appropriate layers.
            if (lastUninjuredLayer == null)
            {
                throw new MapException("Last uninjured layer not found for draw terrain operation!");
            }
            for (int routeIdx = layersToClear.Length - 1; routeIdx >= 0; routeIdx--)
            {
                ITerrainType currLayer = layersToClear[routeIdx];
                if (currLayer == lastUninjuredLayer)
                {
                    break;
                }

                /// Clear the current layer at the appropriate area.
                foreach (FloodItem floodItem in areaToClear)
                {
                    IIsoTile clearedTile = map.GetIsoTile(center.MapCoords + floodItem.Coordinates);
                    if (clearedTile != null)
                    {
                        if (clearedTile.Type.Combination != TerrainCombination.Simple)
                        {
                            /// Mixed tile.
                            if (clearedTile.Type.TerrainB.IsDescendantOf(currLayer))
                            {
                                /// Check whether TerrainB will be cleared by another branch or this is an error.
                                if (!layersToClear.Contains(clearedTile.Type.TerrainB))
                                {
                                    continue;
                                }
                                else
                                {
                                    throw new MapException("Clearing non-topmost layer is not possible!");
                                }
                            }
                            if (clearedTile.Type.TerrainB == currLayer)
                            {
                                TerrainCombination newComb = (TerrainCombination)((int)clearedTile.Type.Combination & ~(floodItem.Combination != TerrainCombination.Simple ? (int)floodItem.Combination : 0xF));
                                if (newComb != clearedTile.Type.Combination)
                                {
                                    clearedTile.ExchangeType(
                                        newComb == TerrainCombination.Simple ?
                                        map.Tileset.GetIsoTileType(clearedTile.Type.TerrainA.Name) :
                                        map.Tileset.GetIsoTileType(clearedTile.Type.TerrainA.Name, clearedTile.Type.TerrainB.Name, newComb));
                                }
                            }
                        }
                        else
                        {
                            /// Simple tile.
                            if (clearedTile.Type.TerrainA.IsDescendantOf(currLayer))
                            {
                                /// Check whether TerrainA will be cleared by another branch or this is an error.
                                if (!layersToClear.Contains(clearedTile.Type.TerrainA))
                                {
                                    continue;
                                }
                                else
                                {
                                    throw new MapException("Clearing non-topmost layer is not possible!");
                                }
                            }
                            if (clearedTile.Type.TerrainA == currLayer)
                            {
                                TerrainCombination newComb = (TerrainCombination)(0xF & ~(floodItem.Combination != TerrainCombination.Simple ? (int)floodItem.Combination : 0xF));
                                clearedTile.ExchangeType(
                                    newComb == TerrainCombination.Simple ?
                                    map.Tileset.GetIsoTileType(clearedTile.Type.TerrainA.Parent.Name) :
                                    map.Tileset.GetIsoTileType(clearedTile.Type.TerrainA.Parent.Name, clearedTile.Type.TerrainA.Name, newComb));
                            }
                        }
                    }
                }

                if (routeIdx > 1)
                {
                    areaToClear.Reduce();
                }
            }
        }
コード例 #16
0
        /// <see cref="IMapEditor.DrawTerrain"/>
        public IEnumerable <IIsoTile> DrawTerrain(IMapAccess targetMap, IIsoTile targetTile, ITerrainType terrainType)
        {
            if (targetMap == null)
            {
                throw new ArgumentNullException("targetMap");
            }
            if (targetTile == null)
            {
                throw new ArgumentNullException("targetTile");
            }
            if (terrainType == null)
            {
                throw new ArgumentNullException("terrainType");
            }
            if (targetMap.Tileset != terrainType.Tileset)
            {
                throw new InvalidOperationException("The tileset of the new terrain type must be the same as the tileset of the map!");
            }

            /// Notify the map that the tile exchanging procedure is started.
            targetMap.BeginExchangingTiles();

            /// First we have to search the basis layer of the draw operation.
            ITerrainType baseLayer = terrainType;
            FloodArea    floodArea = new FloodArea();

            while (!this.CheckLayer(targetMap, targetTile, baseLayer, floodArea))
            {
                floodArea.Enlarge(baseLayer.TransitionLength + 1);
                baseLayer = baseLayer.Parent;
                if (baseLayer == null)
                {
                    throw new MapException("Basis-layer not found for draw terrain operation!");
                }
            }

            /// Clear the appropriate areas of the map around the target tile of the draw operation.
            foreach (ITerrainType topmostLayer in targetMap.Tileset.TerrainTypes)
            {
                if (topmostLayer.IsDescendantOf(baseLayer) && topmostLayer != terrainType && !topmostLayer.HasChildren)
                {
                    ITerrainType[] layersToClear = terrainType.FindRoute(topmostLayer);
                    this.ClearLayers(targetMap, targetTile, terrainType, baseLayer, layersToClear);
                }
            }

            /// Fill the appropriate areas of the map around the target tile of the draw operation.
            this.FillLayers(targetMap, targetTile, terrainType, baseLayer);

            /// Force regenerating the variant of the draw operation center and its neighbours.
            targetTile.ExchangeType(targetTile.Type);

            /// Remove the terrain objects that are violating the new map terrain.
            IEnumerable <IIsoTile> affectedIsoTiles = targetMap.EndExchangingTiles();

            foreach (IIsoTile affectedIsoTile in affectedIsoTiles)
            {
                foreach (IQuadTile cuttingQuadTile in affectedIsoTile.CuttingQuadTiles)
                {
                    ITerrainObject affectedTerrainObj = cuttingQuadTile.TerrainObject;
                    if (affectedTerrainObj != null && affectedTerrainObj.Type.CheckConstraints(targetMap, affectedTerrainObj.MapCoords).Count != 0)
                    {
                        this.RemoveTerrainObject(targetMap, affectedTerrainObj);
                    }
                }
            }
            return(affectedIsoTiles);
        }