private string DebugTileString(Point position) { if (position.X < 0 || position.Y < 0 || position.X >= Map.Width || position.Y >= Map.Height) { return("(nothing)"); } string str = ""; foreach (Tile.MapLayer layer in Tile.CachedAllMapLayers) { TileMetadata metadata = Map.GetMetadata(layer, position.X, position.Y); str += layer + " - " + "\"" + Map[layer, position.X, position.Y].Name(metadata, Map.Info.Environment) + "\" " + "(id '" + Map[layer, position.X, position.Y].ID + "') " + " metadata: "; if (metadata == null || metadata.Count == 0) { str += "(none)"; } else { foreach (KeyValuePair <string, string> pair in metadata) { str += "\n " + pair.Key + ": " + pair.Value; } } str += "\n"; } return(str); }
public override void Draw(Engine.Game game, Point mapPos, Map map, TileMetadata metadata, Map.Environment environment, Color?color = null) { game.Batch.Texture( new Vector2(mapPos.X * 16, mapPos.Y * 16), Template.TextureForDirection(game, Direction.Down), color.HasValue ? color.Value : Color.White); }
public void MoveSelection(Keys key) { Coords curCoords = Tiles[SelectedTileIndex].DrawCoords; TileMetadata destinationTile = null; if (key == Keys.NumPad2) { destinationTile = Tiles .Where(t => t.DrawCoords != null && t.DrawCoords.X == curCoords.X && t.DrawCoords.Y > curCoords.Y) .OrderBy(t => t.DrawCoords.Y).FirstOrDefault(); } if (key == Keys.NumPad4) { destinationTile = Tiles .Where(t => t.DrawCoords != null && t.DrawCoords.Y == curCoords.Y && t.DrawCoords.X < curCoords.X) .OrderByDescending(t => t.DrawCoords.X).FirstOrDefault(); } if (key == Keys.NumPad6) { destinationTile = Tiles .Where(t => t.DrawCoords != null && t.DrawCoords.Y == curCoords.Y && t.DrawCoords.X > curCoords.X) .OrderBy(t => t.DrawCoords.X).FirstOrDefault(); } if (key == Keys.NumPad8) { destinationTile = Tiles .Where(t => t.DrawCoords != null && t.DrawCoords.X == curCoords.X && t.DrawCoords.Y < curCoords.Y) .OrderByDescending(t => t.DrawCoords.Y).FirstOrDefault(); } if (destinationTile != null) { SelectedTileIndex = Tiles.FindIndex(t => t == destinationTile); } }
private static TileMetadata GenerateTile(string path) { var fn = Path.GetFileNameWithoutExtension(path); var match = Pattern.Match(fn ?? ""); if (!match.Success) { Debug.LogError("Failed to match tile data: " + fn); return(null); } var level = int.Parse(match.Groups[1].Value); var x = int.Parse(match.Groups[2].Value); var y = int.Parse(match.Groups[3].Value); var meshfile = Path.GetFileName(path); // todo: support for multiple textures per mesh var texturefile = $"L{level}_{x}_{y}_0.jpg"; var bundlefile = $"tile_{level}_{x}_{y}.bundle"; var data = new TileMetadata { Level = level, X = x, Y = y, MeshFile = meshfile, TextureFile = texturefile, BundleFile = bundlefile }; return(data); }
private void ParseTileList() { string file = SidebarWindow.sett.path + @"\Cache\Tiles.list"; if (Directory.Exists(SidebarWindow.sett.path + @"\Cache") && File.Exists(file)) { FileInfo f = new FileInfo(SidebarWindow.sett.path + @"\Cache\Tiles.list"); if (Math.Abs(DateTime.Now.Day - f.LastAccessTime.Day) > 3) { f.Delete(); ParseTileList(); return; } TileListManifest manifest; using (StreamReader reader = new StreamReader(file)) { XmlSerializer deserializer = new XmlSerializer(typeof(TileListManifest)); manifest = (TileListManifest)deserializer.Deserialize(reader); } for (int i = 0; i < manifest.Tiles.Length; i++) { TileMetadata metadata = manifest.Tiles[i]; LibraryItem item = new LibraryItem() { Id = metadata.Id, Header = metadata.Name, Developer = metadata.Developer, Icon = manifest.Provider.IconBaseUrl + metadata.Icon, Link = manifest.Provider.PackageBaseUrl + metadata.DownloadUrl, Description = metadata.Description, Version = metadata.Version, }; item.MouseLeftButtonDown += new MouseButtonEventHandler(item_MouseLeftButtonDown); item.MouseDoubleClick += new MouseButtonEventHandler(item_MouseDoubleClick); DownTilesPanel.Children.Add(item); } DownTilesCaption.Text = string.Format( (string)Application.Current.TryFindResource("DownloadableTiles"), DownTilesPanel.Children.Count); ItemsCount.Text = string.Format( (string)Application.Current.TryFindResource("ElementsCount"), DownTilesPanel.Children.Count); } }
public string CurrentTileForegroundColor() { string val = "y"; try { TileMetadata tileInfo = Tiles[SelectedTileIndex]; val = tileInfo.ForegroundColor; } catch (Exception ex) { Log($"(Error) Failed to retrieve selected tile foreground color [{ex}]"); } return(val); }
private void FinalizeEdit() { TileMetadata newAttribs = new TileMetadata(); foreach (TileAttributeEditor editor in _editors) { if (!editor.IsDefaultValue) { newAttribs[editor.Name] = editor.ValueAsString; } editor.Dispose(); } BaseState.Map.SetMetadata(Layer, SelectedTile.X, SelectedTile.Y, newAttribs); _editors = null; SelectedTile = new Point(-1, -1); if (BaseState.Buttons.ContainsKey("exit-edit-button")) { BaseState.Buttons.Remove("exit-edit-button"); } }
public static void GetTilesetTileDimensions(int sheetNum, out int x, out int y) { if (tileData[sheetNum] == null) { tileData[sheetNum] = new TileMetadata(); tileData[sheetNum].Load(Paths.CachedGFXPath + "Tile\\Tiles" + sheetNum + ".tile"); } x = Graphics.TextureManager.tileData[sheetNum].Size.Width / Graphics.TextureManager.TILE_SIZE; y = Graphics.TextureManager.tileData[sheetNum].Size.Height / Graphics.TextureManager.TILE_SIZE; }
public static Texture GetTile(int sheetNum, Maps.Loc2D tileLoc) { try { if (tileData[sheetNum] == null) { tileData[sheetNum] = new TileMetadata(); tileData[sheetNum].Load(Paths.CachedGFXPath + "Tile\\Tiles" + sheetNum + ".tile"); } int tileNum = (tileData[sheetNum].Size.Width / TILE_SIZE) * tileLoc.Y + tileLoc.X; Texture cacheSheet = tileCache.Get(sheetNum + "-" + tileLoc.X + "-" + tileLoc.Y); if (cacheSheet != null) return cacheSheet; if (sheetNum > -1 && sheetNum < TOTAL_TILE_SHEETS && tileNum > -1 && tileNum < tileData[sheetNum].TotalTiles) { Texture sheet = new Texture(); byte[] tileBytes = new byte[tileData[sheetNum].TileSizes[tileNum]]; using (FileStream stream = new FileStream(Paths.CachedGFXPath + "Tile\\Tiles" + sheetNum + ".tile", FileMode.Open, FileAccess.Read, FileShare.Read)) { // Seek to the location of the tile stream.Seek(tileData[sheetNum].GetTilePosition(tileNum), SeekOrigin.Begin); stream.Read(tileBytes, 0, tileBytes.Length); } using (MemoryStream tileStream = new MemoryStream(tileBytes)) { sheet.LoadPixelsFromBytes(tileStream); sheet.LoadTextureFromPixels32(); } tileCache.Add(sheetNum + "-" + tileLoc.X + "-" + tileLoc.Y, sheet); return sheet; } } catch (Exception ex) { Logs.Logger.LogError(new Exception("Error retrieving tile " + tileLoc.X + ", " + tileLoc.Y + " from Tileset #" + sheetNum + "\n", ex)); } tileCache.Add(sheetNum + "-" + tileLoc.X + "-" + tileLoc.Y, ErrorTexture); return ErrorTexture; }
public override void Draw(SpriteBatch batch, Vector2 screenSize) { batch.SamplerState = SamplerState.PointWrap; if (SelectedTile != new Point(-1, -1)) { batch.Rectangle(new Rectangle(0, 0, screenSize.ToPoint().X, screenSize.ToPoint().Y), Color.Black * 0.6f); string tileName = BaseState.Map[Layer, SelectedTile.X, SelectedTile.Y].Name(BaseState.Map.GetMetadata(Layer, SelectedTile.X, SelectedTile.Y), BaseState.Map.Info.Environment); string str = "\"" + tileName + "\" (" + SelectedTile.X + ", " + SelectedTile.Y + ")"; Vector2 measure = Game.DefaultFonts.Bold.Measure(15, str); batch.Text(FontStyle.Bold, 15, str, new Vector2(screenSize.X / 2 - measure.X / 2, screenSize.Y / 2 - 300 / 2), Color.White); } if (!BaseState.IsPointObscured(Input.MousePosition) && SelectedTile == new Point(-1, -1)) { if (BaseState.Map[Layer, HoveredTile.X, HoveredTile.Y].ID == "") { return; } batch.Transform = BaseState.Camera.Transform; bool canCurrentTileHaveMetadata = BaseState.Map[Layer, HoveredTile.X, HoveredTile.Y].HasEditableAttributes; TileMetadata attribs = BaseState.Map.GetMetadata(Layer, HoveredTile.X, HoveredTile.Y); batch.Outline(new Rectangle(HoveredTile.X * 16, HoveredTile.Y * 16, 16, 16), canCurrentTileHaveMetadata ? Color.White * 0.6f : Color.DarkRed * 0.6f, 1, false); batch.Reset(); string tileName = BaseState.Map[Layer, HoveredTile.X, HoveredTile.Y].Name(BaseState.Map.GetMetadata(Layer, HoveredTile.X, HoveredTile.Y), BaseState.Map.Info.Environment); string str = ""; if (canCurrentTileHaveMetadata) { if (attribs == null) { str = "Edit \"" + tileName + "\" (" + HoveredTile.X + ", " + HoveredTile.Y + ") [0.00 KB, no attributes set]"; } else { int size = 0; foreach (KeyValuePair <string, string> pair in attribs) { size += pair.Key.Length * 2; size += pair.Value.Length * 2; } str = "Edit \"" + tileName + "\" (" + HoveredTile.X + ", " + HoveredTile.Y + ") [" + (size / (double)1024).ToString("0.00") + " KB @ slot " + BaseState.Map.GetMetadataSlot(Layer, HoveredTile.X, HoveredTile.Y) + "]"; } } else { str = "No attributes exist for \"" + tileName + "\""; } Vector2 pos = new Vector2(HoveredTile.X * 16, HoveredTile.Y * 16) * BaseState.Camera.Zoom + BaseState.Camera.Translation - new Vector2(0, 12 * BaseState.Camera.Zoom); if (pos.X < 5 * BaseState.Camera.Zoom) { pos.X = 5 * BaseState.Camera.Zoom; } if (pos.Y < 5 * BaseState.Camera.Zoom) { pos.Y = 5 * BaseState.Camera.Zoom; pos.X += 3 * BaseState.Camera.Zoom; } batch.Text( SpriteBatch.FontStyle.MonoBold, (uint)(8 * BaseState.Camera.Zoom), str, pos, canCurrentTileHaveMetadata ? Color.White * 0.6f : Color.DarkRed * 0.6f); } }
public override void Update(double deltaTime, double totalTime, long count) { BaseState.Buttons["layer-terrain"].Active = Layer == Tile.MapLayer.Terrain; BaseState.Buttons["layer-decoration"].Active = Layer == Tile.MapLayer.Decoration; BaseState.Buttons["layer-npc"].Active = Layer == Tile.MapLayer.NPC; BaseState.Buttons["layer-control"].Active = Layer == Tile.MapLayer.Control; BaseState.Buttons["layer-terrain"].Disabled = SelectedTile != new Point(-1, -1); BaseState.Buttons["layer-decoration"].Disabled = SelectedTile != new Point(-1, -1); BaseState.Buttons["layer-npc"].Disabled = SelectedTile != new Point(-1, -1); BaseState.Buttons["layer-control"].Disabled = SelectedTile != new Point(-1, -1); if (Game.Input.KeyPressed(Keys.T) && SelectedTile == new Point(-1, -1)) { MapEditorTileEditState state = new MapEditorTileEditState(); state.Layer = Layer; BaseState.CurrentState = state; return; } if (Game.Input.MousePressed(MouseButton.Left) && !BaseState.IsPointObscured(Input.MousePosition) && SelectedTile == new Point(-1, -1)) { bool canCurrentTileHaveMetadata = BaseState.Map[Layer, HoveredTile.X, HoveredTile.Y].HasEditableAttributes; if (canCurrentTileHaveMetadata) { SelectedTile = HoveredTile; TileMetadata attribs = BaseState.Map.GetMetadata(Layer, SelectedTile.X, SelectedTile.Y); int currentY = Game.GraphicsDevice.Viewport.Bounds.Height / 2 - 300 / 2 + 30; _editors = BaseState.Map[Layer, SelectedTile.X, SelectedTile.Y].AttributeEditors(BaseState, ref currentY); if (attribs != null) { foreach (TileAttributeEditor editor in _editors) { if (attribs.IsKeySet(editor.Name)) { editor.ValueFromExistingTile(attribs[editor.Name]); } } } BaseState.Buttons.Add("exit-edit-button", new Button() { Text = "Finish editing", Font = Game.DefaultFonts.Bold, Position = new TweenedVector2(Game, Vector2.Zero), Clicked = (btn) => { FinalizeEdit(); } }); } } if (BaseState.Buttons.ContainsKey("exit-edit-button")) { BaseState.Buttons["exit-edit-button"].Position. TweenTo(new Vector2( Game.GraphicsDevice.Viewport.Bounds.Width / 2 - BaseState.Buttons["exit-edit-button"].Rectangle.Width / 2, Game.GraphicsDevice.Viewport.Bounds.Height / 2 + 300 / 2 - 32), TweenEaseType.Linear, 0); } Vector2 offset = new Vector2( Game.GraphicsDevice.Viewport.Bounds.Width - _lastBounds.Width, Game.GraphicsDevice.Viewport.Bounds.Height - _lastBounds.Height) / 2; foreach (KeyValuePair <string, Button> pair in BaseState.Buttons) { if (pair.Key.StartsWith("editor-")) { pair.Value.Position.TweenTo(pair.Value.Position + offset, TweenEaseType.Linear, 0); } } foreach (KeyValuePair <string, SelectionMenu> pair in BaseState.SelectionMenus) { if (pair.Key.StartsWith("editor-")) { pair.Value.Rectangle.TweenTo(new Rectangle( pair.Value.Rectangle.Value.X + (int)offset.X, pair.Value.Rectangle.Value.Y + (int)offset.Y, 0, 0), TweenEaseType.Linear, 0); } } foreach (KeyValuePair <string, TextField> pair in BaseState.TextFields) { if (pair.Key.StartsWith("editor-")) { pair.Value.Position.TweenTo(pair.Value.Position + offset, TweenEaseType.Linear, 0); } } foreach (KeyValuePair <string, ScrollableTextField> pair in BaseState.ScrollableTextFields) { if (pair.Key.StartsWith("editor-")) { pair.Value.Area.TweenTo(new Rectangle( pair.Value.Area.Value.X + (int)offset.X, pair.Value.Area.Value.Y + (int)offset.Y, pair.Value.Area.Value.Width, pair.Value.Area.Value.Height), TweenEaseType.Linear, 0); } } foreach (KeyValuePair <string, ChoiceField> pair in BaseState.ChoiceFields) { if (pair.Key.StartsWith("editor-")) { pair.Value.Position.TweenTo(pair.Value.Position + offset, TweenEaseType.Linear, 0); } } _lastBounds = Game.GraphicsDevice.Viewport.Bounds; }
public override void Draw(SpriteBatch batch, Vector2 screenSize) { batch.UseSmartRound = false; batch.Transform = Camera.Transform; batch.SamplerState = SamplerState.PointWrap; Vector2 scissorPos = Vector2.Transform(Vector2.Zero, Camera.Transform); batch.Scissor = new Rectangle((int)scissorPos.X, (int)scissorPos.Y, (int)(Map.Width * 16 * Camera.Zoom.Value), (int)(Map.Height * 16 * Camera.Zoom.Value)); foreach (Tile.MapLayer layer in Tile.CachedAllMapLayers) { Rectangle area = new Rectangle( (int)-(Camera.Translation.X / Camera.Zoom.Value), (int)-(Camera.Translation.Y / Camera.Zoom.Value), (int)(screenSize.X / Math.Floor(Camera.Zoom.Value)), (int)(screenSize.Y / Math.Floor(Camera.Zoom.Value))); if (layer == Tile.MapLayer.Control) { bool shouldDraw = false; if (CurrentState.GetType() == typeof(MapEditorTileEditState) && (CurrentState as MapEditorTileEditState).Layer == Tile.MapLayer.Control) { shouldDraw = true; } if (CurrentState.GetType() == typeof(MapEditorEditAttributesState) && (CurrentState as MapEditorEditAttributesState).Layer == Tile.MapLayer.Control) { shouldDraw = true; } if (!shouldDraw) { break; } } if (layer == Tile.MapLayer.Control) { batch.Rectangle(area, Color.Black * 0.4f); } Map.Draw(layer, Game, area); } batch.Scissor = null; batch.Outline(new Rectangle(0, 0, Map.Width * 16, Map.Height * 16), Color.White, 1, false); //batch.Texture(new Vector2(64, 64), Assets.Get<Texture2D>("textures/buildings/mine_soviet.png"), Color.White); batch.Reset(); if (_dataOperation == DataOperation.None) { CurrentState.Draw(batch, screenSize); string str = "Map Editor\n" + "Name: \"" + Map.Info.Name + "\"\n" + "Size: " + Map.Width + "x" + Map.Height + "\n" + "[PLACEHOLDER PLACEHOLDER PLACEHOLDER]"; Vector2 measure = Game.DefaultFonts.Bold.Measure(15, str); batch.Rectangle(new Rectangle(10, (int)_topTextY, (int)(measure.X + 20), (int)(measure.Y + 20)), Color.Black * (MathHelper.Clamp(_topTextFade, 0, 1) * 0.85f)); str = str.Replace("[PLACEHOLDER PLACEHOLDER PLACEHOLDER]", CurrentHelpText) .Replace("Map Editor\n", ""); int size = Map.Width * Map.Height * 4; int x, y; foreach (Tile.MapLayer layer in Tile.CachedAllMapLayers) { for (x = 0; x < Map.Width; x++) { for (y = 0; y < Map.Height; y++) { TileMetadata meta = Map.GetMetadata(layer, x, y); if (meta != null && meta.HasValuesSet) { foreach (KeyValuePair <string, string> pair in meta) { size += (pair.Key.Length + pair.Value.Length) * 2; } } } } } batch.Text(SpriteBatch.FontStyle.Bold, 15, "AoD Map Editor (" + (size / (double)1024).ToString("0.00") + " KB)", new Vector2(20, (int)_topTextY + 10), Color.White * MathHelper.Clamp(_topTextFade, 0, 1)); batch.Text(SpriteBatch.FontStyle.Bold, 15, str, new Vector2(20, (int)_topTextY + 10 + (15 * 1.25f)), Color.White * (MathHelper.Clamp(_topTextFade, 0, 1) * 0.8f)); foreach (Button button in Buttons.Values) { button.Draw(Game); } foreach (SelectionMenu menu in SelectionMenus.Values) { menu.Draw(Game); } foreach (TextField field in TextFields.Values) { field.Draw(Game); } foreach (ScrollableTextField field in ScrollableTextFields.Values) { field.Draw(Game); } foreach (ChoiceField field in ChoiceFields.Values) { field.Draw(Game); } } batch.Rectangle(new Rectangle(0, 0, (int)screenSize.X, (int)screenSize.Y), Color.Black * _fade); if (_dataOperation != DataOperation.None) { string text = "Saving map..."; if (_dataOperation == DataOperation.Loading) { text = "Loading map..."; } Vector2 measure = Game.DefaultFonts.Bold.Measure(32, text); float alpha = 0.6f; alpha = MathHelper.Clamp(alpha + (float)Math.Sin(Game.Time * 10f) * 0.05f, 0, 1); batch.Rectangle(new Rectangle(0, 0, (int)screenSize.X, (int)screenSize.Y), Color.Black * alpha); batch.Text(FontStyle.Bold, 32, text, screenSize / 2 - measure / 2, Color.White); } batch.UseSmartRound = true; }
public override void Update(double deltaTime, double totalTime, long count) { /* TODO if(Game.Input.KeyPressed(Keys.E)) * { * _lastSelection = Menu.Selected; * Menu.Selected = 0; * } * * if(Game.Input.KeyReleased(Keys.E)) * { * Menu.Selected = _lastSelection; * _lastSelection = -1; * } */ if (Game.Input.KeyPressed(Keys.T) && !Menu.IsHovered) { MapEditorEditAttributesState state = new MapEditorEditAttributesState(); state.Layer = Layer; BaseState.CurrentState = state; return; } Menu.Disabled = !Menu.IsHovered && (_eraseMode || Game.Input.Key(Keys.E)); BaseState.Buttons["tool-paintone"].Active = _tool == EditTool.PaintOne; BaseState.Buttons["tool-rectangle"].Active = _tool == EditTool.PaintRectangle; BaseState.Buttons["eraser"].Active = _eraseMode || Game.Input.Key(Keys.E); BaseState.Buttons["layer-terrain"].Active = Layer == Tile.MapLayer.Terrain; BaseState.Buttons["layer-decoration"].Active = Layer == Tile.MapLayer.Decoration; BaseState.Buttons["layer-npc"].Active = Layer == Tile.MapLayer.NPC; BaseState.Buttons["layer-control"].Active = Layer == Tile.MapLayer.Control; if (BaseState.Buttons["tool-paintone"].Position.IsComplete) { float alpha = 1.0f; if (Menu.IsHovered) { alpha = 0.0f; } BaseState.Buttons["tool-paintone"].Alpha = MathHelper.Lerp(BaseState.Buttons["tool-paintone"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["tool-rectangle"].Alpha = MathHelper.Lerp(BaseState.Buttons["tool-rectangle"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["eraser"].Alpha = MathHelper.Lerp(BaseState.Buttons["eraser"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["layer-terrain"].Alpha = MathHelper.Lerp(BaseState.Buttons["layer-terrain"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["layer-decoration"].Alpha = MathHelper.Lerp(BaseState.Buttons["layer-decoration"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["layer-npc"].Alpha = MathHelper.Lerp(BaseState.Buttons["layer-npc"].Alpha, alpha, (float)deltaTime * 25f); BaseState.Buttons["layer-control"].Alpha = MathHelper.Lerp(BaseState.Buttons["layer-control"].Alpha, alpha, (float)deltaTime * 25f); } if (!BaseState.IsPointObscured(Input.MousePosition)) { if (Input.MousePressed(MouseButton.Middle) && !Input.Mouse(MouseButton.Left)) { _tool = _tool == EditTool.PaintOne ? EditTool.PaintRectangle : EditTool.PaintOne; } if (Input.KeyPressed(Keys.R) && !_eraseMode && !Game.Input.Key(Keys.E)) { string flip = Input.Key(Keys.LeftShift) ? "flip-v" : "flip-h"; Tile tile = BaseState.Map[Menu.SelectedTile.Layer, SelectedTile.X, SelectedTile.Y]; TileMetadata meta = BaseState.Map.GetMetadata(Menu.SelectedTile.Layer, SelectedTile.X, SelectedTile.Y); int currentY = 0; // TODO: make it easier to call this function without removing menus TileAttributeEditor[] editors = tile.AttributeEditors(BaseState, ref currentY); if (editors != null) { foreach (TileAttributeEditor editor in editors) { if (editor.Name == flip) { bool enable = !(meta != null && meta.IsKeySet(flip) && meta[flip] == "True"); if (enable) { if (meta == null) { meta = new TileMetadata(); } meta[flip] = "True"; BaseState.Map.SetMetadata(Menu.SelectedTile.Layer, SelectedTile.X, SelectedTile.Y, meta); } else { meta[flip] = ""; } } editor.Dispose(); } } } switch (_tool) { case EditTool.PaintOne: if (Input.Mouse(MouseButton.Left)) { BaseState.Map[_eraseMode || Game.Input.Key(Keys.E) ? Layer : Menu.SelectedTile.Layer, SelectedTile.X, SelectedTile.Y] = _eraseMode || Game.Input.Key(Keys.E) ? Tile.Find("", Layer) : Menu.SelectedTile; } break; case EditTool.PaintRectangle: if (Input.MousePressed(MouseButton.Left)) { _startingTile = SelectedTile; } if (Input.MouseReleased(MouseButton.Left)) { for (int x = _rectangleToolRect.X; x <= _rectangleToolRect.X + _rectangleToolRect.Width; x++) { for (int y = _rectangleToolRect.Y; y <= _rectangleToolRect.Y + _rectangleToolRect.Height; y++) { BaseState.Map[_eraseMode || Game.Input.Key(Keys.E) ? Layer : Menu.SelectedTile.Layer, x, y] = _eraseMode || Game.Input.Key(Keys.E) ? Tile.Find("", Layer) : Menu.SelectedTile; } } _startingTile = new Point(-1, -1); } break; } } Menu.MaxHeight = Game.GraphicsDevice.Viewport.Bounds.Height / 2; Menu.Update(Game); }
public MapTreeNode(MapTreeNode parent, TileMetadata data) : base(parent, data.Level, data.X, data.Y) { Data = data; }
/// <summary> /// Generates raster tiles using the Pegasus API and stores them in the data ocean. /// The source is either a DXF file or a GeoTIFF file. /// </summary> /// <param name="fileName">The path and file name of the source file</param> /// <param name="createExecutionMessage">The details of tile generation for Pegasus</param> /// <param name="customHeaders"></param> /// <returns>Metadata for the generated tiles including the zoom range</returns> private async Task <TileMetadata> GenerateTiles(string fileName, CreateExecutionMessage createExecutionMessage, IHeaderDictionary customHeaders, Action <IHeaderDictionary> setJobIdAction) { Log.LogDebug($"Pegasus execution: {JsonConvert.SerializeObject(createExecutionMessage)}"); TileMetadata metadata = null; //Delete any old tiles. To avoid 2 traversals just try the delete anyway without checking for existence. await DeleteTiles(fileName, customHeaders); //In DataOcean this is actually a multifile not a folder string tileFolderFullName = new DataOceanFileUtil(fileName).GeneratedTilesFolder; //Get the parent folder id var parts = tileFolderFullName.Split(DataOceanUtil.PathSeparator); var tileFolderName = parts[parts.Length - 1]; var parentPath = tileFolderFullName.Substring(0, tileFolderFullName.Length - tileFolderName.Length - 1); var parentId = await dataOceanClient.GetFolderId(parentPath, customHeaders); //Set common parameters createExecutionMessage.Execution.Parameters.ParentId = parentId; createExecutionMessage.Execution.Parameters.Name = tileFolderName; createExecutionMessage.Execution.Parameters.TileOrder = TILE_ORDER; createExecutionMessage.Execution.Parameters.MultiFile = "true"; createExecutionMessage.Execution.Parameters.Public = "false"; const string baseRoute = "/api/executions"; var payload = JsonConvert.SerializeObject(createExecutionMessage); PegasusExecutionResult executionResult; using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(payload))) { executionResult = await gracefulClient.ExecuteRequest <PegasusExecutionResult>($"{pegasusBaseUrl}{baseRoute}", ms, customHeaders, HttpMethod.Post); } if (executionResult == null) { throw new ServiceException(HttpStatusCode.InternalServerError, new ContractExecutionResult(ContractExecutionStatesEnum.InternalProcessingError, $"Failed to create execution for {fileName}")); } setJobIdAction?.Invoke(new HeaderDictionary { { PEGASUS_LOG_JOBID_KEY, executionResult.Execution.Id.ToString() } }); //2. Start the execution Log.LogDebug($"Starting execution for {fileName}"); var executionRoute = $"{baseRoute}/{executionResult.Execution.Id}"; var startExecutionRoute = $"{executionRoute}/start"; var startResult = await gracefulClient.ExecuteRequest <PegasusExecutionAttemptResult>($"{pegasusBaseUrl}{startExecutionRoute}", null, customHeaders, HttpMethod.Post); if (startResult == null) { throw new ServiceException(HttpStatusCode.InternalServerError, new ContractExecutionResult(ContractExecutionStatesEnum.InternalProcessingError, $"Failed to start execution for {fileName}")); } //3. Monitor status of execution until done Log.LogDebug($"Monitoring execution status for {fileName}"); var endJob = DateTime.Now + TimeSpan.FromMinutes(executionTimeout); var done = false; var success = true; while (!done && DateTime.Now <= endJob) { if (executionWaitInterval > 0) { await Task.Delay(executionWaitInterval); } var policyResult = await Policy .Handle <Exception>() .WaitAndRetryAsync( 3, attempt => TimeSpan.FromMilliseconds(1000), (exception, calculatedWaitDuration) => { Log.LogError(exception, $"PollyAsync: Failed attempt to query Pegasus. Jobid {executionResult.Execution.Id.ToString()}"); }) .ExecuteAndCaptureAsync(async() => { Log.LogDebug($"Executing monitoring request for {fileName} and jobid {executionResult.Execution.Id.ToString()}"); executionResult = await gracefulClient.ExecuteRequest <PegasusExecutionResult>($"{pegasusBaseUrl}{executionRoute}", null, customHeaders, HttpMethod.Get); var status = executionResult.Execution.ExecutionStatus; success = string.Compare(status, ExecutionStatus.FINISHED, StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(status, ExecutionStatus.SUCCEEDED, StringComparison.OrdinalIgnoreCase) == 0; if (string.Compare(status, ExecutionStatus.FAILED, StringComparison.OrdinalIgnoreCase) == 0) { //Try to retrieve why it failed var jobEventsStream = await gracefulClient.ExecuteRequestAsStreamContent($"{pegasusBaseUrl}{executionRoute}/events", HttpMethod.Get, customHeaders); if (jobEventsStream != null) { var jobEvents = await jobEventsStream.ReadAsStringAsync(); Log.LogError($"Pegasus job {executionResult.Execution.Id} failed to execute with the events: {jobEvents}"); setJobIdAction?.Invoke(new HeaderDictionary { { PEGASUS_LOG_EVENTS_KEY, jobEvents } }); } else { Log.LogDebug($"Unable to resolve jobEventsStream for execution id {executionResult.Execution.Id}"); } } done = success || string.Compare(status, ExecutionStatus.FAILED, StringComparison.OrdinalIgnoreCase) == 0; setJobIdAction?.Invoke(new HeaderDictionary { { PEGASUS_LOG_RESULT_KEY, status } }); Log.LogDebug($"Execution status {status} for {fileName} and jobid {executionResult.Execution.Id.ToString()}"); }); if (policyResult.FinalException != null) { Log.LogCritical(policyResult.FinalException, $"TileGeneration PollyAsync: {GetType().FullName} failed with exception for jobid {executionResult.Execution.Id.ToString()}: "); throw policyResult.FinalException; } } if (!done) { Log.LogInformation($"{nameof(GenerateTiles)} timed out: {fileName}"); } else if (!success) { Log.LogInformation($"{nameof(GenerateTiles)} failed: {fileName}"); throw new ServiceException(HttpStatusCode.InternalServerError, new ContractExecutionResult(ContractExecutionStatesEnum.InternalProcessingError, $"Failed to generate tiles for {fileName}")); } if (success) { /* * Can't delete as not mutable * * //4. Delete the execution * Log.LogDebug($"Deleting execution for {dxfFileName}"); * await gracefulClient.ExecuteRequest($"{pegasusBaseUrl}{executionRoute}", null, customHeaders, HttpMethod.Delete, null, 0, false); */ //5. Get the zoom range from the tile metadata file var metadataFileName = new DataOceanFileUtil(fileName).TilesMetadataFileName; Log.LogDebug($"Getting tiles metadata for {metadataFileName}"); var stream = await dataOceanClient.GetFile(metadataFileName, customHeaders); using (var sr = new StreamReader(stream)) using (var jtr = new JsonTextReader(sr)) { metadata = new JsonSerializer().Deserialize <TileMetadata>(jtr); } } Log.LogInformation($"{nameof(GenerateTiles)}: returning {(metadata == null ? "null" : JsonConvert.SerializeObject(metadata))}"); return(metadata); }