/// <summary> /// Shows a dialog to add a new terrain patch to the world map. /// </summary> /// <param name="sender">The object that raised the event.</param> /// <param name="e">The event arguments.</param> private void AddNewPatchToolStripMenuItem_Click(object sender, EventArgs e) { Helper.EnsureDirectories(); AddNewPatchDialog addPatchForm = new AddNewPatchDialog(this.editorRenderWindow.Engine.CurrentCamera.Target, this.editorRenderWindow.Engine.Terrain.CurrentHeightLevel); if (addPatchForm.ShowDialog() == DialogResult.OK) { TerrainPatch tp = new TerrainPatch(addPatchForm.PatchCoordinates, addPatchForm.DefaultHeight, addPatchForm.DefaultTerrainType); string destinationFilename = Helper.GetPatchFileName(tp.PatchId); if (File.Exists(destinationFilename)) { if (MessageBox.Show("Are you sure you want to overwrite?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, this.RightToLeft == RightToLeft.Yes ? MessageBoxOptions.RtlReading : 0) == DialogResult.Yes) { File.WriteAllBytes(destinationFilename, tp.ToByteArray()); this.editorRenderWindow.Engine.Terrain.ForcePatchReload(addPatchForm.PatchCoordinates); } } else { File.WriteAllBytes(destinationFilename, tp.ToByteArray()); } } }
/// <summary> /// Generates a terrain patch from an array of bytes; returns null if the data is invalid. /// </summary> /// <param name="data">The array of bytes to generate the patch from.</param> /// <returns>See summary.</returns> public static TerrainPatch FromByteArray(byte[] data) { if (data == null) { return null; } else { ReadOnlyCollection<Season> seasons = SeasonExtensions.GetSeasons(); BinaryReader reader = new BinaryReader(new MemoryStream(data)); try { // Read the patch ID int x = reader.ReadInt32(); int y = reader.ReadInt32(); int z = reader.ReadInt32(); // Create a patch object TerrainPatch patch = new TerrainPatch(new Point3D(x, y, z)); // Read the array of heights for (int i = 0; i < patch.vertexHeightsArray.Length; i++) { patch.vertexHeightsArray[i] = reader.ReadSingle(); } // Read terrain types for all seasons for (int j = 0; j < seasons.Count; j++) { // Read the array of textures for (int i = 0; i < patch.vertexTexturesArray[j].Length; i++) { patch.vertexTexturesArray[(int)seasons[j]][i] = (TerrainType)reader.ReadInt16(); } } // Read the number of fluids short countFluids = reader.ReadInt16(); // Read all the fluids for (int i = 0; i < countFluids; i++) { // Create a new fluid object to store on the patch Fluid fluid = new Fluid(patch.PatchId); // Read fluid properties for all seasons for (int j = 0; j < seasons.Count; j++) { // Read the vertices Vector3 southWest = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector3 southEast = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector3 northWest = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Vector3 northEast = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); // Read the fluid type short fluidType = reader.ReadInt16(); // Read the fluid flow direction short flowDirection = reader.ReadInt16(); // Read the fluid flow speed float flowSpeed = reader.ReadSingle(); // Copy the read variables into the properties of the fluid object fluid.SetPoint(seasons[j], FluidVertex.Southwest, southWest); fluid.SetPoint(seasons[j], FluidVertex.Southeast, southEast); fluid.SetPoint(seasons[j], FluidVertex.Northwest, northWest); fluid.SetPoint(seasons[j], FluidVertex.Northeast, northEast); fluid.SetFluidType(seasons[j], (FluidType)fluidType); fluid.SetFlowDirection(seasons[j], (FluidFlowDirection)flowDirection); fluid.SetFlowSpeed(seasons[j], flowSpeed); } // Add the fluid to the patch patch.Fluids.Add(fluid); } return patch; } catch (EndOfStreamException) { return null; } catch (IOException) { return null; } finally { reader.Close(); } } }
/// <summary> /// Creates a new instance of the TerrainPatch class using all the properties /// of an existing TerrainPatch but with a different patch ID. /// </summary> /// <param name="patchId">The ID of the terrain patch.</param> /// <param name="terrainPatch">The terrain patch whose properties to use.</param> /// <returns>See summary.</returns> public static TerrainPatch FromExisting(Point3D patchId, TerrainPatch terrainPatch) { TerrainPatch pat = terrainPatch.Clone() as TerrainPatch; pat.PatchId = patchId; return pat; }
/// <summary> /// Draws the specified terrain patch using the specified graphics context. /// </summary> /// <param name="terrainPatch">The terrain patch to draw.</param> /// <param name="lowestPatchID">The lowest terrain patch ID that will be needed to draw the map.</param> /// <param name="bitmapSize">The height of the finished world map, in pixels.</param> /// <param name="g">The graphics context to draw in.</param> /// <param name="textured">Whether the map should be drawn textured.</param> /// <param name="season">The season to draw the map in.</param> /// <param name="hideBase"> /// Whether to draw undefined for non-base season /// instead of showing the base season terrain. /// </param> private static void DrawTerrainPatch(TerrainPatch terrainPatch, Point3D lowestPatchID, Size bitmapSize, Graphics g, bool textured, Season season, bool hideBase) { for (int x = 0; x < TerrainPatch.PatchSize; x++) { for (int y = 0; y < TerrainPatch.PatchSize; y++) { // Get the patch local point and screen point Vector2 localPoint = new Vector2(x, y); Xna.Point screen = WorldMap.ProjectScreenPoint(lowestPatchID, CoordinateConverter.LocalToWorld(terrainPatch.PatchId, new Xna.Point(x, y)), bitmapSize); // Initially set the draw color to that of the terrain Color drawColor = WorldMap.GetDrawColor(terrainPatch.GetTerrainTypeDataForSeason(localPoint, season, hideBase), x, y, textured); // Store the heighest terrain height so far float highestHeight = terrainPatch.GetExactElevation(localPoint); // Loop through all the fluids for (int i = 0; i < terrainPatch.Fluids.Count; i++) { // If the fluid contains the local point, check its height if (terrainPatch.Fluids[i].ContainsPoint(season, localPoint)) { // If the fluid's height is higher than the highest height (initially, the terrain's) if (terrainPatch.Fluids[i].GetExactHeight(season, localPoint) > highestHeight) { // Set the highest height to this fluid's, and set the draw color to this fluid's highestHeight = terrainPatch.Fluids[i].GetExactHeight(season, localPoint); drawColor = WorldMap.GetDrawColor(terrainPatch.Fluids[i].GetFluidType(season), x, y, textured); } } } g.FillRectangle(new SolidBrush(drawColor), screen.X, screen.Y, 1, 1); } } }