using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Myra; using Myra.Graphics2D.Brushes; using Myra.Graphics2D.TextureAtlases; using Myra.Graphics2D.UI; using Myra.Graphics2D.UI.File; using Newtonsoft.Json; using System.Collections.Generic; using System.IO; using System.Linq; using System; using System.Collections.Concurrent; using Sledgemapper.Shared.Entities; using Refit; using System.Net.Http; namespace Sledgemapper { public class Sledgemapper : Game { private GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; private Tile _selectedTile = new Tile { X = 1, Y = 1 }; private Tile _hoveredTile = new Tile { X = 1, Y = 1 }; private Wall _selectedWall = new Wall { X = 1, Y = 1 }; private Overlay _selectedOverlay = new Overlay { X = 1, Y = 1 }; private int _tileSize = 30; private HubConnection connection; private readonly Desktop _desktop; private string _currentTileId = ""; private string _currentWallId = ""; private string _currentOverlayId = ""; private InsertMode _insertMode; private string _session; private KeyboardState oldState; private MouseState oldMouseState; private Vector3 _viewportCenter = new Vector3(0, 0, 0); private SpriteFont font; private Dictionary _fonts; private SessionData _sessionData; private IMapApi _api; public Sledgemapper() { _graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; _desktop = new Desktop(); MyraEnvironment.Game = this; _sessionData = new SessionData(); IsFixedTimeStep = false; } protected override void Initialize() { // TODO: Add your initialization logic here IsMouseVisible = true; Window.AllowUserResizing = true; Players = new List(); connection = new HubConnectionBuilder() // .WithAutomaticReconnect() .WithUrl("http://localhost:5000/SledgemapperHub") // .WithUrl("http://hub.michelescandura.com:5000/SledgemapperHub") .Build(); var httpClientHandler = new HttpClientHandler(); //if (myConfigurationService.VerifySslCertificate == false) //{ httpClientHandler.ServerCertificateCustomValidationCallback = (message, certificate, chain, sslPolicyErrors) => true; //} _api = RestService.For( new HttpClient(httpClientHandler) { BaseAddress = new Uri ("http://localhost:5000") } ); connection.On("UpdateMap", (map) => { _sessionData.Map = map.Map; _sessionData.Walls = map.Walls; _sessionData.Overlays = map.Overlays; }); connection.On("PlayerUpdate", (player) => { var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); if (p != null) { p.Position = player.Position; } }); connection.On("DeleteTile", (tile) => { _sessionData.Map.Remove(tile.ToString(), out var rtile); }); connection.On("DeleteWall", (tile) => { _sessionData.Walls.Remove(tile.ToString(), out var rtile); }); connection.On("DeleteOverlay", (tile) => { _sessionData.Overlays.Remove(tile.ToString(), out var rtile); }); connection.On("NewTile", (tile) => { _sessionData.Map.Remove(tile.ToString(), out var rtile); _sessionData.Map.TryAdd(tile.ToString(), tile); }); connection.On("NewWall", (tile) => { _sessionData.Walls.Remove(tile.ToString(), out var rtile); _sessionData.Walls.TryAdd(tile.ToString(), tile); }); connection.On("NewOverlay", (tile) => { _sessionData.Overlays.Remove(tile.ToString(), out var rtile); _sessionData.Overlays.TryAdd(tile.ToString(), tile); }); connection.On("NewPlayer", (player) => { var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); if (p is null) { Players.Add(player); } else { p.Color = player.Color; p.Position = player.Position; } }); base.Initialize(); } public List Players { get; set; } private HorizontalMenu BuildMenu() { var menu = new HorizontalMenu(); var menuFile = new MenuItem("_file", "File"); var menuFileLoad = new MenuItem("_file_load", "Load"); var menuFileSave = new MenuItem("_file_save", "Save"); var menuConnect = new MenuItem("_connect", "Connect"); var menuConnectNew = new MenuItem("_connect_new", "New"); var menuConnectJoin = new MenuItem("_connect_join", "Join"); var menuConnectSync = new MenuItem("_connect_sync", "Sync"); menuConnectSync.Selected += async (s, e) => { await connection?.InvokeAsync("Sync", _session, _sessionData); }; menuFileLoad.Selected += (s, e) => { FileDialog dialog = new FileDialog(FileDialogMode.OpenFile) { Filter = "*.map" //Folder = @"D:\Temp" }; dialog.Closed += (s, a) => { if (!dialog.Result) { // "Cancel" or Escape return; } using (StreamReader file = File.OpenText(dialog.FilePath)) { JsonSerializer serializer = new JsonSerializer(); _sessionData = (SessionData)serializer.Deserialize(file, typeof(SessionData)); } // "Ok" or Enter // ... }; dialog.ShowModal(_desktop); }; menuFileSave.Selected += (s, e) => { FileDialog dialog = new FileDialog(FileDialogMode.SaveFile) { Filter = "*.map" //Folder = @"D:\Temp" }; dialog.Closed += (s, a) => { if (!dialog.Result) { // "Cancel" or Escape return; } using (StreamWriter file = File.CreateText(dialog.FilePath)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(file, _sessionData); } // "Ok" or Enter // ... }; dialog.ShowModal(_desktop); }; menuConnectNew.Selected += (s, e) => { Window window = new Window { Title = "New mapping session" }; var content = new VerticalStackPanel(); var grid = new Grid { Width = 200, ShowGridLines = false, ColumnSpacing = 8, RowSpacing = 3, }; // Set partitioning configuration grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto)); grid.ColumnsProportions.Add(new Proportion(ProportionType.Fill)); grid.RowsProportions.Add(new Proportion(ProportionType.Auto)); grid.RowsProportions.Add(new Proportion(ProportionType.Auto)); var sessionNameLabel = new Label { Text = "Session Name:" }; var initialsLabel = new Label { Text = "Initials:", GridRow = 1 }; var textbox = new TextBox { GridColumn = 1 }; var initialsTextbox = new TextBox { GridColumn = 1, GridRow = 1 }; TextButton button = new TextButton { Text = "Start", HorizontalAlignment = HorizontalAlignment.Center }; grid.Widgets.Add(textbox); grid.Widgets.Add(initialsTextbox); grid.Widgets.Add(sessionNameLabel); grid.Widgets.Add(initialsLabel); content.Widgets.Add(grid); button.Click += async (s, e) => { if (string.IsNullOrWhiteSpace(textbox.Text)) { return; } if (connection.State != HubConnectionState.Connected) { await connection.StartAsync(); } var successful = false; try { var session = await connection?.InvokeAsync("NewSession", textbox.Text, initialsTextbox.Text); if (session != null) { Players = session.Players; } successful = session != null; } catch (Exception ex) { } if (successful) { _session = textbox.Text; window.Close(); } }; content.Widgets.Add(button); window.Content = content; window.Closed += (s, a) => { // Called when window is closed }; window.ShowModal(_desktop); }; menuConnectJoin.Selected += (s, e) => { Window window = new Window { Title = "Join mapping session" }; var content = new VerticalStackPanel(); var grid = new Grid { Width = 200, ShowGridLines = false, ColumnSpacing = 8, RowSpacing = 3, }; // Set partitioning configuration grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto)); grid.ColumnsProportions.Add(new Proportion(ProportionType.Fill)); grid.RowsProportions.Add(new Proportion(ProportionType.Auto)); grid.RowsProportions.Add(new Proportion(ProportionType.Auto)); var sessionNameLabel = new Label { Text = "Session Name:" }; var initialsLabel = new Label { Text = "Initials:", GridRow = 1 }; var textbox = new TextBox { GridColumn = 1 }; var initialsTextbox = new TextBox { GridColumn = 1, GridRow = 1 }; TextButton button = new TextButton { Text = "Start", HorizontalAlignment = HorizontalAlignment.Center }; grid.Widgets.Add(textbox); grid.Widgets.Add(initialsTextbox); grid.Widgets.Add(sessionNameLabel); grid.Widgets.Add(initialsLabel); content.Widgets.Add(grid); // var content = new VerticalStackPanel(); // var textbox = new TextBox(); // TextButton button = new TextButton // { // Text = "Start", // HorizontalAlignment = HorizontalAlignment.Center // }; button.Click += async (s, e) => { if (string.IsNullOrWhiteSpace(textbox.Text)) { return; } if (connection.State != HubConnectionState.Connected) { await connection.StartAsync(); } var successful = false; try { var result = await connection?.InvokeAsync("JoinSession", textbox.Text, initialsTextbox.Text); if (result != null) { _sessionData.Map = result.Map; _sessionData.Walls = result.Walls; _sessionData.Overlays = result.Overlays; Players = result.Players; } successful = result != null; ; } catch { } if (successful) { _session = textbox.Text; window.Close(); } }; //content.Widgets.Add(textbox); content.Widgets.Add(button); window.Content = content; window.Closed += (s, a) => { // Called when window is closed }; window.ShowModal(_desktop); }; menuConnect.Items.Add(menuConnectNew); menuConnect.Items.Add(menuConnectJoin); menuConnect.Items.Add(menuConnectSync); menu.Items.Add(menuConnect); menuFile.Items.Add(menuFileLoad); menuFile.Items.Add(menuFileSave); menu.Items.Add(menuFile); menu.Items.Add(menuConnect); return menu; } protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); MyraEnvironment.Game = this; var mainPanel = new VerticalStackPanel(); var menu = BuildMenu(); mainPanel.Widgets.Add(menu); var sidePanel = new VerticalStackPanel { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h"), Background = new SolidBrush(Color.DarkGray) }; var tileScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; var tileGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; tileScrollView.Content = tileGrid; sidePanel.Widgets.Add(tileScrollView); var wallScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; var wallGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; wallScrollView.Content = wallGrid; sidePanel.Widgets.Add(wallScrollView); var overlayScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; var overlayGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; overlayScrollView.Content = overlayGrid; sidePanel.Widgets.Add(overlayScrollView); mainPanel.Widgets.Add(sidePanel); var tilesFolderContent = Content.LoadContentFolder("tiles"); var indexX = 0; var indexY = 0; foreach (var item in tilesFolderContent) { var tileButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; tileButton.Click += (s, e) => { _currentTileId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); ClearSelection(overlayGrid); ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); _insertMode = InsertMode.Tile; }; tileGrid.Widgets.Add(tileButton); indexY++; if (indexY == 4) { indexY = 0; indexX++; } } var wallsFolderContent = Content.LoadContentFolder("walls"); indexX = 0; indexY = 0; foreach (var item in wallsFolderContent) { var wallButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; wallButton.Click += (s, e) => { _currentWallId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); ClearSelection(overlayGrid); ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); _insertMode = InsertMode.Wall; }; wallGrid.Widgets.Add(wallButton); indexY++; if (indexY == 4) { indexY = 0; indexX++; } } var overlayFolderContent = Content.LoadContentFolder("overlays"); indexX = 0; indexY = 0; foreach (var item in overlayFolderContent) { var overlayButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; overlayButton.Click += (s, e) => { _currentOverlayId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); ClearSelection(overlayGrid); ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); _insertMode = InsertMode.Overlay; }; overlayGrid.Widgets.Add(overlayButton); indexY++; if (indexY == 4) { indexY = 0; indexX++; } } _fonts = Content.LoadContentFolder("fonts"); // Add it to the desktop // _desktop = new Desktop(); _desktop.Root = mainPanel; // TODO: use this.Content to load your game content here } bool _draw; protected override void Update(GameTime gameTime) { // if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) // Exit(); KeyboardState newState = Keyboard.GetState(); // TODO: Add your update logic here if (IsActive && GraphicsDevice.Viewport.Bounds.Contains(Mouse.GetState().Position) && !_desktop.IsMouseOverGUI && !_desktop.HasModalWidget) { var mouseState = Mouse.GetState(); var screenPosition = new Point((mouseState.Position.X - (int)_viewportCenter.X), (mouseState.Position.Y - (int)_viewportCenter.Y)); _hoveredTile.X = screenPosition.X / _tileSize; _hoveredTile.Y = screenPosition.Y / _tileSize; if (screenPosition.X < 0) { _hoveredTile.X--; } if (screenPosition.Y < 0) { _hoveredTile.Y--; } if (_insertMode == InsertMode.Wall) { SelectClosestWall(screenPosition); } if (_insertMode == InsertMode.Overlay) { SelectOverlay(screenPosition); } if (mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton != oldMouseState.LeftButton) { _selectedTile.X = _hoveredTile.X; _selectedTile.Y = _hoveredTile.Y; connection?.SendAsync("UpdatePosition", _session, _selectedTile); } if (newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && ((mouseState.LeftButton != oldMouseState.LeftButton) || (_selectedTile.X != _hoveredTile.X && _selectedTile.Y != _hoveredTile.Y))) { switch (_insertMode) { case InsertMode.Tile: _selectedTile.X = _hoveredTile.X; _selectedTile.Y = _hoveredTile.Y; connection?.SendAsync("UpdatePosition", _session, _selectedTile); SetTile(_currentTileId); break; case InsertMode.Wall: SetWall(_currentWallId); break; case InsertMode.Overlay: SetOverlay(_currentOverlayId); break; } } if (!newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == oldMouseState.LeftButton) { _viewportCenter = new Vector3(_viewportCenter.X + mouseState.Position.X - oldMouseState.Position.X, _viewportCenter.Y + mouseState.Position.Y - oldMouseState.Position.Y, 0); } if (newState.IsKeyDown(Keys.LeftControl) && mouseState.ScrollWheelValue != oldMouseState.ScrollWheelValue) { if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue) { _tileSize = System.Math.Min(120, _tileSize + 10); } else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue) { _tileSize = System.Math.Max(10, _tileSize - 10); } } oldMouseState = mouseState; } if (newState.IsKeyDown(Keys.Delete)) { switch (_insertMode) { case InsertMode.Tile: _selectedTile.X = _hoveredTile.X; _selectedTile.Y = _hoveredTile.Y; DeleteTile(); break; case InsertMode.Wall: DeleteWall(); break; case InsertMode.Overlay: DeleteOverlay(); break; } } foreach (var key in newState.GetPressedKeys()) { switch (key) { case Keys.Left: if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left)) { _selectedTile.X--; } break; case Keys.Right: if (oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right)) { _selectedTile.X++; } break; case Keys.Up: if (oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up)) { _selectedTile.Y--; } break; case Keys.Down: if (oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down)) { _selectedTile.Y++; } break; } connection?.SendAsync("UpdatePosition", _session, _selectedTile); } oldState = newState; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { if (_spriteBatch is null) { return; } GraphicsDevice.Clear(Color.DarkGray); var sessionData = _sessionData; // TODO: Add your drawing code here var visibleTilesX = GraphicsDevice.Viewport.Width / _tileSize + 1; var visibleTilesY = GraphicsDevice.Viewport.Height / _tileSize + 1; _spriteBatch.Begin(transformMatrix: Matrix.CreateTranslation(_viewportCenter)); for (var i = -1; i < visibleTilesX + 2; i++) { var posX1 = i * _tileSize - _viewportCenter.X; var posY1 = -_viewportCenter.Y; posX1 = posX1 - posX1 % _tileSize; posY1 = posY1 - posY1 % _tileSize; var posX2 = i * _tileSize - _viewportCenter.X; var posY2 = GraphicsDevice.Viewport.Height - _viewportCenter.Y; posX2 = posX2 - posX2 % _tileSize; posY2 = posY2 - posY2 % _tileSize; _spriteBatch.DrawLine( posX1, posY1, posX2, posY2, Color.Black); } for (var i = -1; i < visibleTilesY + 2; i++) { var posX1 = -_viewportCenter.X; var posY1 = i * _tileSize - _viewportCenter.Y; posX1 = posX1 - posX1 % _tileSize; posY1 = posY1 - posY1 % _tileSize; var posX2 = GraphicsDevice.Viewport.Width - _viewportCenter.X; var posY2 = i * _tileSize - _viewportCenter.Y; posX2 = posX2 - posX2 % _tileSize; posY2 = posY2 - posY2 % _tileSize; _spriteBatch.DrawLine(posX1, posY1, posX2, posY2, Color.Black); } foreach (var tile in sessionData.Map.Values) { var content = Content.Load($"tiles/{tile.ID}"); var destinationRectangle = new Rectangle(tile.X * _tileSize, tile.Y * _tileSize, _tileSize, _tileSize); var posX = tile.X * _tileSize + _tileSize / 2f; var posY = tile.Y * _tileSize + _tileSize / 2f; _spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 1) / content.Width, SpriteEffects.None, 0); } foreach (var wall in sessionData.Walls.Values) { var content = Content.Load($"walls/{wall.ID}"); var scale = _tileSize / (float)content.Height; var offset = scale * content.Width / 2f; var posX = wall.X * _tileSize; var posY = wall.Y * _tileSize; if (wall.Rotation == 1) { posX -= (int)offset; } else if (wall.Rotation == 0) { posY += (int)offset; } // _spriteBatch.Draw(content, new Vector2(posX, posY),null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(offset, 0), scale, SpriteEffects.None, 0); _spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(0, 0), scale, SpriteEffects.None, 0); } foreach (var tile in sessionData.Overlays.Values) { var content = Content.Load($"overlays/{tile.ID}"); // System.Console.WriteLine(tile.Rotation); if (tile.Intersection) { var posX = tile.X * _tileSize; var posY = tile.Y * _tileSize; _spriteBatch.Draw(content, new Vector2(posX, posY), null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0); } else { var posX = tile.X * _tileSize + _tileSize / 2f; var posY = tile.Y * _tileSize + _tileSize / 2f; _spriteBatch.Draw(content, new Vector2(posX, posY), null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0); } } if (string.IsNullOrWhiteSpace(_session)) { _spriteBatch.DrawRectangle(new Rectangle(_selectedTile.X * _tileSize, _selectedTile.Y * _tileSize, _tileSize - 1, _tileSize - 1), Color.Red, 2); } foreach (var player in Players.Copy>()) { var hexs = player.Color.Split(2).ToArray(); var color = new Color(int.Parse(hexs[0], System.Globalization.NumberStyles.HexNumber), int.Parse(hexs[1], System.Globalization.NumberStyles.HexNumber), int.Parse(hexs[2], System.Globalization.NumberStyles.HexNumber)); _spriteBatch.DrawRectangle(new Rectangle(player.Position.X * _tileSize, player.Position.Y * _tileSize, _tileSize - 1, _tileSize - 1), color, 2); var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _tileSize).Value ?? _fonts.Last().Value; var fscale = (float)_tileSize / ((float)ffont.LineSpacing * 2); _spriteBatch.DrawString(ffont, player.Initials, new Vector2(player.Position.X * _tileSize + 2, player.Position.Y * _tileSize + _tileSize - 2 - ffont.LineSpacing * fscale), color, 0, Vector2.Zero, fscale, SpriteEffects.None, 0); } var startWall = new Vector2(_selectedWall.X * _tileSize, _selectedWall.Y * _tileSize); if (_insertMode == InsertMode.Wall) { _spriteBatch.DrawLine(startWall, _tileSize, MathHelper.ToRadians(90 * _selectedWall.Rotation), Color.Red, 2); } var overlay = new Vector2(_selectedOverlay.X * _tileSize, _selectedOverlay.Y * _tileSize); if (_insertMode == InsertMode.Overlay) { if (_selectedOverlay.Intersection) { _spriteBatch.DrawCircle(overlay, _tileSize / 3, 100, Color.Red, 2); } } _spriteBatch.End(); _desktop?.Render(); base.Draw(gameTime); } private void ClearSelection(Grid grid) { foreach (var widget in grid.Widgets) { widget.Border = null; } } private float Sign(Point p1, Point p2, Point p3) { return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y); } private bool PointInTri(Point pt, Point v1, Point v2, Point v3) { bool b1, b2, b3; b1 = Sign(pt, v1, v2) < 0.0f; b2 = Sign(pt, v2, v3) < 0.0f; b3 = Sign(pt, v3, v1) < 0.0f; return ((b1 == b2) && (b2 == b3)); } private void SelectClosestWall(Point mousePosition) { var topLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize); var bottomLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize + _tileSize); var topRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize); var bottomRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize + _tileSize); var center = new Point(_hoveredTile.X * _tileSize + _tileSize / 2, _hoveredTile.Y * _tileSize + _tileSize / 2); var leftWall = PointInTri(mousePosition, topLeft, center, bottomLeft); var rightWall = PointInTri(mousePosition, topRight, bottomRight, center); var topWall = PointInTri(mousePosition, topLeft, topRight, center); var bottomtWall = PointInTri(mousePosition, bottomLeft, center, bottomRight); if (leftWall) { _selectedWall.X = _hoveredTile.X; _selectedWall.Y = _hoveredTile.Y; _selectedWall.Rotation = 1; } else if (rightWall) { _selectedWall.X = _hoveredTile.X + 1; _selectedWall.Y = _hoveredTile.Y; _selectedWall.Rotation = 1; } else if (topWall) { _selectedWall.X = _hoveredTile.X; _selectedWall.Y = _hoveredTile.Y; _selectedWall.Rotation = 0; } else if (bottomtWall) { _selectedWall.X = _hoveredTile.X; _selectedWall.Y = _hoveredTile.Y + 1; _selectedWall.Rotation = 0; } } private void SelectOverlay(Point mousePosition) { _selectedOverlay.X = _hoveredTile.X; _selectedOverlay.Y = _hoveredTile.Y; var q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2); var s = System.Math.Sqrt(q1 + q2); if (s < _tileSize / 3) { _selectedOverlay.Intersection = true; return; } q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); // var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2); s = System.Math.Sqrt(q1 + q2); if (s < _tileSize / 3) { _selectedOverlay.X = _selectedOverlay.X + 1; _selectedOverlay.Intersection = true; return; } //q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); s = System.Math.Sqrt(q1 + q2); if (s < _tileSize / 3) { _selectedOverlay.X = _selectedOverlay.X + 1; _selectedOverlay.Y = _selectedOverlay.Y + 1; _selectedOverlay.Intersection = true; return; } q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); s = System.Math.Sqrt(q1 + q2); if (s < _tileSize / 3) { _selectedOverlay.X = _selectedOverlay.X; _selectedOverlay.Y = _selectedOverlay.Y + 1; _selectedOverlay.Intersection = true; return; } _selectedOverlay.Intersection = false; } private void SetTile(string tileId) { var tileExist = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var rtile); if (tileExist) { var get = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var tile); _sessionData.Map.TryRemove(tile.ToString(), out var rrtile); if (tile.ID == tileId) { var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId, Rotation = (tile.Rotation + 1) % 4 }; _sessionData.Map.TryAdd(newTile.ToString(), newTile); _api.NewTile(newTile, _session); //connection?.InvokeAsync("NewTile", _session, newTile); } else { var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId }; _sessionData.Map.TryAdd(newTile.ToString(), newTile); _api.NewTile(newTile, _session); // connection?.InvokeAsync("NewTile", _session, newTile); } } else { var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId }; _sessionData.Map.TryAdd(newTile.ToString(), newTile); _api.NewTile(newTile, _session); // connection?.InvokeAsync("NewTile", _session, newTile); } } private void SetOverlay(string tileId) { var overlayExist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var tile); if (overlayExist) { var exist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var overlay); _sessionData.Overlays.TryRemove(tile.ToString(), out var rrtile); if (overlay.ID == tileId) { var newOverlay = new Overlay { X = overlay.X, Y = overlay.Y, ID = tileId, Intersection = overlay.Intersection, Rotation = (overlay.Rotation + 1) % 4 }; _sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay); connection?.InvokeAsync("NewOverlay", _session, newOverlay); } else { var newOverlay = new Overlay { X = _selectedOverlay.X, Y = _selectedOverlay.Y, ID = tileId, Intersection = _selectedOverlay.Intersection }; _sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay); connection?.InvokeAsync("NewOverlay", _session, newOverlay); } } else { var newOverlay = new Overlay { X = _selectedOverlay.X, Y = _selectedOverlay.Y, ID = tileId, Intersection = _selectedOverlay.Intersection }; _sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay); connection?.InvokeAsync("NewOverlay", _session, newOverlay); } } private void DeleteWall() { var tileExist = _sessionData.Walls.TryGetValue(_selectedWall.ToString(), out var wall); if (tileExist) { //var wall = _sessionData.Walls.First(m => m.X == _selectedWall.X && m.Y == _selectedWall.Y && m.Rotation == _selectedWall.Rotation); //var index = _sessionData.Walls.IndexOf(wall); _sessionData.Walls.TryRemove(wall.ToString(), out var rwall); connection?.InvokeAsync("DeleteWall", _session, wall); } } private void DeleteOverlay() { var tileExist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var overlay); if (tileExist) { //var wall = _sessionData.Overlays.First(m => m.X == _selectedOverlay.X && m.Y == _selectedOverlay.Y && m.Intersection == _selectedOverlay.Intersection); //var index = _sessionData.Overlays.IndexOf(wall); _sessionData.Overlays.TryRemove(overlay.ToString(), out var roverlay); connection?.InvokeAsync("DeleteOverlay", _session, overlay); } } private void DeleteTile() { var tileExist = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var tile); if (tileExist) { // var tile = _sessionData.Map.First(m => m.X == _selectedTile.X && m.Y == _selectedTile.Y); // var index = _sessionData.Map.IndexOf(tile); _sessionData.Map.TryRemove(tile.ToString(), out var rtile); connection?.InvokeAsync("DeleteTile", _session, tile); } } private void SetWall(string wallId) { var tileExist = _sessionData.Walls.TryGetValue(_selectedWall.ToString(), out var wall); if (tileExist) { // var wall = _sessionData.Walls.First(m => m.X == _selectedWall.X && m.Y == _selectedWall.Y && m.Rotation == _selectedWall.Rotation); // var index = _sessionData.Walls.IndexOf(wall); _sessionData.Walls.TryRemove(wall.ToString(), out var rwall); var newWall = new Wall { X = _selectedWall.X, Y = _selectedWall.Y, ID = wallId, Rotation = _selectedWall.Rotation }; _sessionData.Walls.TryAdd(newWall.ToString(), newWall); connection?.InvokeAsync("NewWall", _session, newWall); } else { var newWall = new Wall { X = _selectedWall.X, Y = _selectedWall.Y, ID = wallId, Rotation = _selectedWall.Rotation }; _sessionData.Walls.TryAdd(newWall.ToString(), newWall); connection?.InvokeAsync("NewWall", _session, newWall); //connection?.InvokeAsync("SendMessage", $"{_selectedTile.X}:{_selectedTile.Y}", tileId.ToString(), _session); } } } }