/// <summary> /// Initializes the terrain objects of the map. /// </summary> /// <param name="terrainObjListPackage">The package that contains the terrain object informations.</param> /// <param name="map">Reference to the map.</param> private void LoadTerrainObjects(RCPackage terrainObjListPackage, IMapAccess map) { /// TODO: Avoid this downcast! MapAccess mapObj = map as MapAccess; if (mapObj == null) { throw new ArgumentException("The given map cannot be handled by the MapEditor!", "map"); } string[] terrainObjIndexTable = terrainObjListPackage.ReadStringArray(0); byte[] terrainObjInfoBytes = terrainObjListPackage.ReadByteArray(1); int offset = 0; while (offset < terrainObjInfoBytes.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(terrainObjInfoBytes, offset, terrainObjInfoBytes.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new MapException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == MapFileFormat.TERRAINOBJ) { RCIntVector quadCoords = new RCIntVector(package.ReadShort(0), package.ReadShort(1)); ITerrainObjectType terrainObjType = this.mapStructure.Tileset.GetTerrainObjectType(terrainObjIndexTable[package.ReadByte(2)]); /// TODO: Might be better to create the TerrainObject with a factory? ITerrainObject newObj = new TerrainObject(map, terrainObjType, quadCoords); foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets) { changeset.Apply(newObj); } mapObj.AttachTerrainObject(newObj); } } /// Check the constraints of the terrain objects. List <ITerrainObject> terrainObjects = new List <ITerrainObject>(map.TerrainObjects); foreach (ITerrainObject terrainObj in terrainObjects) { mapObj.DetachTerrainObject(terrainObj); if (terrainObj.Type.CheckConstraints(map, terrainObj.MapCoords).Count != 0) { throw new MapException(string.Format("Terrain object at {0} is voilating the tileset constraints!", terrainObj.MapCoords)); } if (terrainObj.Type.CheckTerrainObjectIntersections(map, terrainObj.MapCoords).Count != 0) { throw new MapException(string.Format("Terrain object at {0} intersects other terrain objects!", terrainObj.MapCoords)); } mapObj.AttachTerrainObject(terrainObj); } }
/// <summary> /// Constructs a terrain object. /// </summary> /// <param name="map">The map that this terrain object belongs to.</param> /// <param name="type">The type of this terrain object.</param> /// <param name="mapCoords">The coordinates of the top-left quadratic tile of this terrain object.</param> public TerrainObject(IMapAccess map, ITerrainObjectType type, RCIntVector mapCoords) { if (map == null) { throw new ArgumentNullException("map"); } if (type == null) { throw new ArgumentNullException("type"); } if (mapCoords == RCIntVector.Undefined) { throw new ArgumentNullException("type"); } if (type.Tileset != map.Tileset) { throw new MapException("Tileset of the TerrainObjectType and tileset of the map are not the same!"); } this.mapCoords = mapCoords; this.type = type; this.parentMap = map; this.cells = new Cell[this.type.QuadraticSize.X * MapStructure.NAVCELL_PER_QUAD, this.type.QuadraticSize.Y * MapStructure.NAVCELL_PER_QUAD]; this.quadTiles = new QuadTile[this.type.QuadraticSize.X, this.type.QuadraticSize.Y]; /// Set the references to the appropriate quadratic tiles and cells. for (int quadX = 0; quadX < this.type.QuadraticSize.X; quadX++) { for (int quadY = 0; quadY < this.type.QuadraticSize.Y; quadY++) { RCIntVector relQuadCoords = new RCIntVector(quadX, quadY); if (!this.type.IsExcluded(relQuadCoords)) { IQuadTile currQuadTile = this.parentMap.GetQuadTile(this.mapCoords + relQuadCoords); this.quadTiles[quadX, quadY] = currQuadTile; for (int navX = 0; navX < MapStructure.NAVCELL_PER_QUAD; navX++) { for (int navY = 0; navY < MapStructure.NAVCELL_PER_QUAD; navY++) { RCIntVector relNavCoords = relQuadCoords * MapStructure.NAVCELL_PER_QUAD + new RCIntVector(navX, navY); this.cells[relNavCoords.X, relNavCoords.Y] = currQuadTile.GetCell(new RCIntVector(navX, navY)); } } } } } /// TODO: Apply the cell data changesets! /// TODO: Attach this TerrainObject to the map! }
/// <see cref="IMapEditorService.PlaceTerrainObject"/> public bool PlaceTerrainObject(RCIntVector position, string terrainObject) { if (this.scenarioManager.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } if (position == RCIntVector.Undefined) { throw new ArgumentNullException("position"); } if (terrainObject == null) { throw new ArgumentNullException("terrainObject"); } ITerrainObjectType terrainObjType = this.scenarioManager.ActiveScenario.Map.Tileset.GetTerrainObjectType(terrainObject); RCIntVector navCellCoords = this.mapWindowBC.AttachedWindow.WindowToMapCoords(position).Round(); IQuadTile quadTileAtPos = this.scenarioManager.ActiveScenario.Map.GetCell(navCellCoords).ParentQuadTile; RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - terrainObjType.QuadraticSize / 2; ITerrainObject placedTerrainObject = null; if (topLeftQuadCoords.X >= 0 && topLeftQuadCoords.Y >= 0 && topLeftQuadCoords.X < this.scenarioManager.ActiveScenario.Map.Size.X && topLeftQuadCoords.Y < this.scenarioManager.ActiveScenario.Map.Size.Y) { IQuadTile targetQuadTile = this.scenarioManager.ActiveScenario.Map.GetQuadTile(topLeftQuadCoords); placedTerrainObject = this.mapEditor.PlaceTerrainObject(this.scenarioManager.ActiveScenario.Map, targetQuadTile, terrainObjType); } if (placedTerrainObject != null) { RCNumRectangle terrObjRect = new RCNumRectangle(this.scenarioManager.ActiveScenario.Map.GetQuadTile(placedTerrainObject.MapCoords).GetCell(new RCIntVector(0, 0)).MapCoords, placedTerrainObject.CellSize) - new RCNumVector(1, 1) / 2; foreach (Entity affectedEntity in this.scenarioManager.ActiveScenario.GetElementsOnMap <Entity>(terrObjRect, 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(); } } } return(placedTerrainObject != null); }
/// <see cref="IMapEditor.PlaceTerrainObject"/> public ITerrainObject PlaceTerrainObject(IMapAccess targetMap, IQuadTile targetTile, ITerrainObjectType type) { if (targetMap == null) { throw new ArgumentNullException("targetMap"); } if (targetTile == null) { throw new ArgumentNullException("targetTile"); } if (type == null) { throw new ArgumentNullException("type"); } if (targetMap.Tileset != type.Tileset) { throw new InvalidOperationException("The tileset of the terrain object type must be the same as the tileset of the map!"); } /// TODO: Avoid this downcast! MapAccess targetMapObj = targetMap as MapAccess; if (targetMapObj == null) { throw new ArgumentException("The given map cannot be handled by the MapEditor!", "targetMap"); } if (type.CheckConstraints(targetMap, targetTile.MapCoords).Count != 0) { return(null); } if (type.CheckTerrainObjectIntersections(targetMap, targetTile.MapCoords).Count != 0) { return(null); } /// TODO: Might be better to create the TerrainObject with a factory? ITerrainObject newObj = new TerrainObject(targetMap, type, targetTile.MapCoords); foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets) { changeset.Apply(newObj); } targetMapObj.AttachTerrainObject(newObj); return(newObj); }