/// <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(); } } }
/// <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(); } } }