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 Sledgemapper.Shared.Entities; using Sledgemapper.UI; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace Sledgemapper { public class Sledgemapper : Game { private readonly CommunicationManager _communicationManager; private readonly State _state; private readonly GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; private readonly Desktop _desktop; private KeyboardState oldState; private MouseState oldMouseState; private Vector3 _viewportCenter = new(0, 0, 0); private bool _isDraggin; private Dictionary _fonts; private readonly Session _sessionData; private AuthenticateResponse _authResponse; private MainWidget _mainWidget; private bool _showCellNumbers; public Sledgemapper() { _graphics = new GraphicsDeviceManager(this); _graphics.GraphicsProfile = GraphicsProfile.Reach; _graphics.PreferMultiSampling = false; Content.RootDirectory = "Content"; _desktop = new Desktop(); MyraEnvironment.Game = this; _sessionData = new Session(); IsFixedTimeStep = false; _communicationManager = new CommunicationManager(_sessionData); _communicationManager.Connection.Reconnected += OnHubReconnected; _communicationManager.Connection.Reconnecting += OnHubReconnecting; _communicationManager.Connection.Closed += OnHubDisconnected; _state = new State(); } private async Task OnHubDisconnected(Exception arg) { _mainWidget.lblConnectionStatus.Text = "Disconnected"; } private async Task OnHubReconnecting(Exception arg) { _mainWidget.lblConnectionStatus.Text = "Reconnecting"; } private async Task OnHubReconnected(string arg) { _mainWidget.lblConnectionStatus.Text = "Connected"; } protected override void Initialize() { IsMouseVisible = true; Window.AllowUserResizing = true; base.Initialize(); } private void AddItemToToolGrid(Grid grid, EventHandler eventAction, string folder) { var tilesFolderContent = Content.LoadContentFolder(folder); 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 += eventAction; grid.Widgets.Add(tileButton); indexY++; if (indexY == 4) { indexY = 0; indexX++; } } } protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); MyraEnvironment.Game = this; _mainWidget = new MainWidget(); _mainWidget.MenuConnectSync.Selected += OnMenuConnectSyncSelected; _mainWidget.MenuFileLoad.Selected += OnMenuFileLoadSelected; _mainWidget.MenuFileSave.Selected += OnMenuFileSaveSelected; _mainWidget.MenuConnectLogin.Selected += OnMenuConnectLoginSelected; _mainWidget.MenuConnectNew.Selected += OnMenuConnectNewSelected; _mainWidget.MenuConnectJoin.Selected += OnMenuConnectJoinSelected; _mainWidget.MenuConnectUpload.Selected += OnMenuConnectUploadSelected; _mainWidget.MenuViewCenterOnSelection.Selected += OnMenuViewCenterOnSelectionSelected; _mainWidget.MenuViewShowCellNUmbers.Selected += OnMenuViewShowCellNUmbersSelected; _mainWidget.MenuConnectNew.Enabled = false; _mainWidget.MenuConnectJoin.Enabled = false; _mainWidget.MenuConnectSync.Enabled = false; _mainWidget.MenuConnectUpload.Enabled = false; AddItemToToolGrid(_mainWidget.GridTiles, OnTileButtonClicked, "tiles"); AddItemToToolGrid(_mainWidget.GridWalls, OnWallButtonClicked, "walls"); AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, "overlays"); _fonts = Content.LoadContentFolder("fonts"); _desktop.Root = _mainWidget; } private void OnMenuViewShowCellNUmbersSelected(object sender, EventArgs e) { _showCellNumbers = !_showCellNumbers; } private void OnMenuViewCenterOnSelectionSelected(object sender, EventArgs e) { CenterOnSelectedTile(); } protected override void Update(GameTime gameTime) { KeyboardState newState = Keyboard.GetState(); 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); _state.HoveredTile.X = screenPosition.X / _state.TileSize; _state.HoveredTile.Y = screenPosition.Y / _state.TileSize; if (screenPosition.X < 0) { _state.HoveredTile.X--; } if (screenPosition.Y < 0) { _state.HoveredTile.Y--; } if (_state.InsertMode == InsertMode.Wall) { _state.SelectClosestWall(screenPosition); } if (_state.InsertMode == InsertMode.Overlay) { _state.SelectOverlay(screenPosition); } // if (newState.IsKeyDown(Keys.LeftControl) && newState.IsKeyDown(Keys.C) && !oldState.IsKeyDown(Keys.C)) // { // CenterOnSelectedTile(); // } 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 (mouseState.Position != oldMouseState.Position) { _isDraggin = true; } } if (mouseState.LeftButton == ButtonState.Released && mouseState.LeftButton != oldMouseState.LeftButton) { if (_isDraggin) { _isDraggin = false; } else { _state.SelectedTile.X = _state.HoveredTile.X; _state.SelectedTile.Y = _state.HoveredTile.Y; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _sessionData.SessionId, _state.SelectedTile); } } if (newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && ((mouseState.LeftButton != oldMouseState.LeftButton) || (_state.SelectedTile.X != _state.HoveredTile.X && _state.SelectedTile.Y != _state.HoveredTile.Y))) { switch (_state.InsertMode) { case InsertMode.Tile: _state.SelectedTile.X = _state.HoveredTile.X; _state.SelectedTile.Y = _state.HoveredTile.Y; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _sessionData.SessionId, _state.SelectedTile); _sessionData.NewTile(_state.SelectedTile, _state.CurrentTileId); break; case InsertMode.Wall: _sessionData.NewWall(_state.SelectedWall, _state.CurrentWallId); break; case InsertMode.Overlay: _sessionData.NewOverlay(_state.SelectedOverlay, _state.CurrentOverlayId); break; } } if (newState.IsKeyDown(Keys.LeftControl) && mouseState.ScrollWheelValue != oldMouseState.ScrollWheelValue) { // var center = new Point(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2); var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, Window.ClientBounds.Height / 2 - _state.TileSize / 2); var tx = (center.X - (int)_viewportCenter.X) / _state.TileSize; var ty = (center.Y - (int)_viewportCenter.Y) / _state.TileSize; if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue) { _state.TileSize = Math.Min(120, _state.TileSize + 10); } else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue) { _state.TileSize = Math.Max(10, _state.TileSize - 10); } CenterOnTile(tx, ty); } oldMouseState = mouseState; } if (newState.IsKeyDown(Keys.Delete)) { switch (_state.InsertMode) { case InsertMode.Tile: _state.SelectedTile.X = _state.HoveredTile.X; _state.SelectedTile.Y = _state.HoveredTile.Y; _sessionData.DeleteTile(_state.SelectedTile); break; case InsertMode.Wall: _sessionData.DeleteWall(_state.SelectedWall); break; case InsertMode.Overlay: _sessionData.DeleteOverlay(_state.SelectedOverlay); break; } } foreach (var key in newState.GetPressedKeys()) { switch (key) { case Keys.Left: if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left)) { _state.SelectedTile.X--; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state.SelectedTile); } break; case Keys.Right: if (oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right)) { _state.SelectedTile.X++; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state.SelectedTile); } break; case Keys.Up: if (oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up)) { _state.SelectedTile.Y--; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state.SelectedTile); } break; case Keys.Down: if (oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down)) { _state.SelectedTile.Y++; _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state.SelectedTile); } break; } } oldState = newState; base.Update(gameTime); } private void CenterOnSelectedTile() { CenterOnTile(_state.SelectedTile.X, _state.SelectedTile.Y); } private void CenterOnTile(int x, int y) { var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, Window.ClientBounds.Height / 2 - _state.TileSize / 2); var dx = center.X - x * _state.TileSize - _viewportCenter.X; var dy = center.Y - y * _state.TileSize - _viewportCenter.Y; _viewportCenter.X += dx; _viewportCenter.Y += dy; } protected override void Draw(GameTime gameTime) { if (_spriteBatch is null) { return; } GraphicsDevice.Clear(Color.LightGray); var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1; var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1; _spriteBatch.Begin(transformMatrix: Matrix.CreateTranslation(_viewportCenter)); DrawGrid(visibleTilesX, visibleTilesY); DrawTiles(); DrawWalls(); DrawOverlays(); if (string.IsNullOrWhiteSpace(_sessionData.SessionName)) { _spriteBatch.DrawRectangle(new Rectangle((_state.SelectedTile.X * _state.TileSize) - 2, (_state.SelectedTile.Y * _state.TileSize) - 2, _state.TileSize + 3, _state.TileSize + 3), Color.Red, 2); } DrawPlayers(); var startWall = new Vector2(_state.SelectedWall.X * _state.TileSize, _state.SelectedWall.Y * _state.TileSize); if (_state.InsertMode == InsertMode.Wall) { _spriteBatch.DrawLine(startWall, _state.TileSize, MathHelper.ToRadians(90 * _state.SelectedWall.Rotation), Color.Red, 2); } var overlay = new Vector2(_state.SelectedOverlay.X * _state.TileSize, _state.SelectedOverlay.Y * _state.TileSize); if (_state.InsertMode == InsertMode.Overlay && _state.SelectedOverlay.Intersection) { _spriteBatch.DrawCircle(overlay, _state.TileSize / 3f, 100, Color.Red, 2); } _spriteBatch.End(); try { _desktop?.Render(); } catch { System.Console.WriteLine("Desktop render error"); } base.Draw(gameTime); } private void DrawGrid(int visibleTilesX, int visibleTilesY) { for (var i = -1; i < visibleTilesX + 2; i++) { var posX1 = i * _state.TileSize - _viewportCenter.X; var posY1 = -_viewportCenter.Y; posX1 -= posX1 % _state.TileSize; posY1 -= posY1 % _state.TileSize; var posX2 = i * _state.TileSize - _viewportCenter.X; var posY2 = GraphicsDevice.Viewport.Height - _viewportCenter.Y; posX2 -= posX2 % _state.TileSize; posY2 -= posY2 % _state.TileSize; _spriteBatch.DrawLine( posX1, posY1, posX2, posY2, Color.GhostWhite); } for (var i = -1; i < visibleTilesY + 2; i++) { var posX1 = -_viewportCenter.X; var posY1 = i * _state.TileSize - _viewportCenter.Y; posX1 -= posX1 % _state.TileSize; posY1 -= posY1 % _state.TileSize; var posX2 = GraphicsDevice.Viewport.Width - _viewportCenter.X; var posY2 = i * _state.TileSize - _viewportCenter.Y; posX2 -= posX2 % _state.TileSize; posY2 -= posY2 % _state.TileSize; _spriteBatch.DrawLine(posX1, posY1, posX2, posY2, Color.GhostWhite); } if (_showCellNumbers && _state.TileSize >= 30) { var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 8).Value ?? _fonts.Last().Value; var fscale = 1f; for (var i = -1; i < visibleTilesX + 2; i++) { for (var j = -1; j < visibleTilesY + 2; j++) { var screenPosition = new Point(i * _state.TileSize - (int)_viewportCenter.X, j * _state.TileSize - (int)_viewportCenter.Y); var x = screenPosition.X / _state.TileSize; var y = screenPosition.Y / _state.TileSize; _spriteBatch.DrawString(ffont, $"{x}:{y}", new Vector2( x * _state.TileSize + 2, y * _state.TileSize + 2 ), Color.Black, 0, Vector2.Zero, fscale, SpriteEffects.None, 0); } } } } private void DrawOverlays() { foreach (var tile in _sessionData.Overlays.Values) { var content = Content.Load($"overlays/{tile.ID}"); if (tile.Intersection) { var posX = tile.X * _state.TileSize; var posY = tile.Y * _state.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)_state.TileSize - 10) / content.Width, SpriteEffects.None, 0); } else { var posX = tile.X * _state.TileSize + _state.TileSize / 2f; var posY = tile.Y * _state.TileSize + _state.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)_state.TileSize - 10) / content.Width, SpriteEffects.None, 0); } } } private void DrawPlayers() { foreach (var player in _sessionData.Players.Copy()) { var hexs = player.Color.TrimStart('#').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 * _state.TileSize, player.Position.Y * _state.TileSize, _state.TileSize - 1, _state.TileSize - 1), color, 2); var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize).Value ?? _fonts.Last().Value; var fscale = _state.TileSize / ((float)ffont.LineSpacing * 2); _spriteBatch.DrawString(ffont, player.Initials, new Vector2(player.Position.X * _state.TileSize + 2, player.Position.Y * _state.TileSize + _state.TileSize - 2 - ffont.LineSpacing * fscale), color, 0, Vector2.Zero, fscale, SpriteEffects.None, 0); } } private void DrawTiles() { foreach (var tile in _sessionData.Map.Values) { var content = Content.Load($"tiles/{tile.ID}"); var posX = tile.X * _state.TileSize + _state.TileSize / 2f; var posY = tile.Y * _state.TileSize + _state.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)_state.TileSize - 1) / content.Width, SpriteEffects.None, 0); } } private void DrawWalls() { foreach (var wall in _sessionData.Walls.Values) { var content = Content.Load($"walls/{wall.ID}"); var scale = _state.TileSize / (float)content.Height; var offset = scale * content.Width / 2f; var posX = wall.X * _state.TileSize; var posY = wall.Y * _state.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(0, 0), scale, SpriteEffects.None, 0); } } private async void OnButtonJoinSessionClicked(object sender, EventArgs e) { Container container = ((TextButton)sender).Parent; while (!(container is Window)) { container = container.Parent; } var localWindow = (Window)container; var localContent = localWindow.Content as SessionWindow; var isValid = ValidateTextbox(localContent.TxtSession); if (!isValid) { return; } if (_communicationManager.Connection.State != HubConnectionState.Connected) { _mainWidget.lblConnectionStatus.Text = "Connecting"; await _communicationManager.Connection.StartAsync(); UpdateConnectionState(_communicationManager.Connection); } var successful = false; try { var result = await _communicationManager.Connection?.InvokeAsync("JoinSession", localContent.TxtSession.Text); if (result != null) { _sessionData.Map = result.Map; _sessionData.Walls = result.Walls; _sessionData.Overlays = result.Overlays; _sessionData.MapEntityAdded -= OnMapEntityAdded; _sessionData.MapEntityDeleted -= OnMapEntityDeleted; _sessionData.MapEntityAdded += OnMapEntityAdded; _sessionData.MapEntityDeleted += OnMapEntityDeleted; _sessionData.SessionId = result.SessionId; _sessionData.SessionName = result.SessionName; } successful = result != null; } catch (Exception ex) { Console.WriteLine(ex.Message); } if (successful) { _sessionData.SessionName = localContent.TxtSession.Text; _mainWidget.lblSessionName.Text = _sessionData.SessionName; localWindow.Close(); } } private async void OnButtonNewSessionClicked(object sender, EventArgs e) { Container container = ((TextButton)sender).Parent; while (!(container is Window)) { container = container.Parent; } var localWindow = (Window)container; var localContent = localWindow.Content as SessionWindow; var isValid = ValidateTextbox(localContent.TxtSession); if (!isValid) { return; } if (_communicationManager.Connection.State != HubConnectionState.Connected) { _mainWidget.lblConnectionStatus.Text = "Connecting"; await _communicationManager.Connection.StartAsync(); UpdateConnectionState(_communicationManager.Connection); } var successful = false; try { var result = await _communicationManager.Api.NewSession(localContent.TxtSession.Text); if (result) { _sessionData.SessionName = localContent.TxtSession.Text; _sessionData.MapEntityAdded -= OnMapEntityAdded; _sessionData.MapEntityDeleted -= OnMapEntityDeleted; _sessionData.MapEntityAdded += OnMapEntityAdded; _sessionData.MapEntityDeleted += OnMapEntityDeleted; } successful = result; var result2 = await _communicationManager.Connection?.InvokeAsync("JoinSession", localContent.TxtSession.Text); _sessionData.SessionId = result2.SessionId; _sessionData.SessionName = localContent.TxtSession.Text; } catch (Exception ex) { Console.WriteLine(ex.Message); } if (successful) { _sessionData.SessionName = localContent.TxtSession.Text; _communicationManager.SessionData.Map = _sessionData.Map; _communicationManager.SessionData.Overlays = _sessionData.Overlays; _communicationManager.SessionData.Walls = _sessionData.Walls; _mainWidget.lblSessionName.Text = _sessionData.SessionName; localWindow.Close(); } } private void UpdateConnectionState(HubConnection connection) { switch (connection.State) { case HubConnectionState.Connected: _mainWidget.lblConnectionStatus.Text = "Connected"; break; case HubConnectionState.Connecting: _mainWidget.lblConnectionStatus.Text = "Connecting"; break; case HubConnectionState.Disconnected: _mainWidget.lblConnectionStatus.Text = "Disconnected"; break; case HubConnectionState.Reconnecting: _mainWidget.lblConnectionStatus.Text = "Reconnecting"; break; } } private async void OnButtonLoginClick(object sender, EventArgs e) { var button = ((TextButton)sender); Container container = button.Parent; while (!(container is Window)) { container = container.Parent; } var localWindow = (Window)container; var localContent = localWindow.Content as LoginRegisterWindow; if (!button.Enabled) { return; } var isValid = true; isValid &= ValidateTextbox(localContent.TxtEmail); isValid &= ValidateTextbox(localContent.TxtPassword); if (!isValid) { localContent.LblLoginError.Text = "Username or password is not valid"; localContent.LblLoginError.Visible = true; return; } var successful = false; try { button.Text = "Wait..."; localContent.LblLoginError.Text = ""; localContent.LblLoginError.Visible = false; _authResponse = await _communicationManager.Login(new AuthenticateModel { Username = localContent.TxtEmail.Text, Password = localContent.TxtPassword.Text }); successful = _authResponse != null; } catch (Refit.ApiException refitException) { localContent.LblLoginError.Text = refitException.Content; localContent.LblLoginError.Visible = true; } catch (Exception ex) { localContent.LblLoginError.Text = "Can't connect to the server"; localContent.LblLoginError.Visible = true; } finally { button.Enabled = true; button.Text = "Login"; } if (successful) { _mainWidget.MenuConnectNew.Enabled = true; _mainWidget.MenuConnectJoin.Enabled = true; _mainWidget.MenuConnectSync.Enabled = true; _mainWidget.MenuConnectUpload.Enabled = true; _mainWidget.lblUsername.Text = $"{_authResponse.Username} - {_authResponse.Initials}"; localWindow.Close(); } } private async void OnButtonRegisterClick(object sender, EventArgs e) { var button = ((TextButton)sender); Container container = button.Parent; while (!(container is Window)) { container = container.Parent; } var localWindow = (Window)container; var localContent = localWindow.Content as LoginRegisterWindow; if (!button.Enabled) { return; } var isValid = true; isValid &= ValidateTextbox(localContent.TxtEmail); isValid &= ValidateTextbox(localContent.TxtPassword); isValid &= ValidateTextbox(localContent.TxtFirstname); isValid &= ValidateTextbox(localContent.TxtLastname); isValid &= ValidateTextbox(localContent.TxtInitials); if (!isValid) { localContent.LblLoginError.Text = "Please complete all the fields"; localContent.LblLoginError.Visible = true; return; } var successful = false; try { button.Text = "Wait..."; localContent.LblLoginError.Text = ""; localContent.LblLoginError.Visible = false; var result = await _communicationManager.Register(new RegisterModel { Username = localContent.TxtEmail.Text, Password = localContent.TxtPassword.Text, FirstName = localContent.TxtFirstname.Text, LastName = localContent.TxtLastname.Text, Initials = localContent.TxtInitials.Text }); if (result.IsSuccessStatusCode) { _authResponse = await _communicationManager.Login(new AuthenticateModel { Username = localContent.TxtEmail.Text, Password = localContent.TxtPassword.Text }); successful = true; } else { localContent.LblLoginError.Text = result.ReasonPhrase; localContent.LblLoginError.Visible = true; } } catch (Refit.ApiException refitException) { localContent.LblLoginError.Text = refitException.Content; localContent.LblLoginError.Visible = true; } catch (Exception ex) { localContent.LblLoginError.Text = "Can't connect to the server"; localContent.LblLoginError.Visible = true; } finally { button.Enabled = true; button.Text = "Register"; } if (successful) { _mainWidget.MenuConnectNew.Enabled = true; _mainWidget.MenuConnectJoin.Enabled = true; _mainWidget.MenuConnectSync.Enabled = true; _mainWidget.MenuConnectUpload.Enabled = true; _mainWidget.lblUsername.Text = $"{_authResponse.Username} - {_authResponse.Initials}"; localWindow.Close(); } } private void OnOverlayButtonClicked(object sender, EventArgs e) { _state.CurrentOverlayId = ((ImageButton)sender).Id; _mainWidget.ClearSelection(); ((ImageButton)sender).Border = new SolidBrush(Color.Red); ((ImageButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2); _state.InsertMode = InsertMode.Overlay; } private void OnTileButtonClicked(object sender, EventArgs e) { _state.CurrentTileId = ((ImageButton)sender).Id; _mainWidget.ClearSelection(); ((ImageButton)sender).Border = new SolidBrush(Color.Red); ((ImageButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2); _state.InsertMode = InsertMode.Tile; } private void OnWallButtonClicked(object sender, EventArgs e) { _state.CurrentWallId = ((ImageButton)sender).Id; _mainWidget.ClearSelection(); ((ImageButton)sender).Border = new SolidBrush(Color.Red); ((ImageButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2); _state.InsertMode = InsertMode.Wall; } private void OnMenuConnectJoinSelected(object sender, EventArgs e) { if (!((MenuItem)sender).Enabled) { return; } Window window = new() { Title = "Join mapping session" }; var content = new SessionWindow(); content.BtnLogin.Text = "Join"; content.BtnLogin.Click += OnButtonJoinSessionClicked; window.Content = content; window.ShowModal(_desktop); } private void OnMenuConnectLoginSelected(object sender, EventArgs e) { Window window = new() { Title = "Login" }; var content = new LoginRegisterWindow(); content.RdoLogin.IsPressed = true; content.RdoLogin.Click += (s, e) => { content.TxtFirstname.Visible = false; content.TxtLastname.Visible = false; content.TxtInitials.Visible = false; content.LblFirstname.Visible = false; content.LblLastname.Visible = false; content.LblInitials.Visible = false; content.BtnLogin.Visible = true; content.BtnRegister.Visible = false; window.Title = "Login"; }; content.RdoRegister.Click += (s, e) => { content.TxtFirstname.Visible = true; content.TxtLastname.Visible = true; content.TxtInitials.Visible = true; content.LblFirstname.Visible = true; content.LblLastname.Visible = true; content.LblInitials.Visible = true; content.BtnLogin.Visible = false; content.BtnRegister.Visible = true; window.Title = "Register"; }; content.BtnRegister.Click += OnButtonRegisterClick; content.BtnLogin.Click += OnButtonLoginClick; window.Content = content; window.ShowModal(_desktop); } private async void OnMenuConnectSyncSelected(object sender, EventArgs e) { if (!((MenuItem)sender).Enabled) { return; } var serverMap = await _communicationManager.Api.Session(_sessionData.SessionName); _sessionData.Overlays = serverMap.Overlays; _sessionData.Map = serverMap.Map; _sessionData.Walls = serverMap.Walls; } private async void OnMenuConnectUploadSelected(object sender, EventArgs e) { if (!((MenuItem)sender).Enabled) { return; } await _communicationManager.Api.SaveSnapshot(_sessionData, _sessionData.SessionName); } private void OnMenuConnectNewSelected(object sender, EventArgs e) { if (!((MenuItem)sender).Enabled) { return; } Window window = new() { Title = "New mapping session" }; var content = new SessionWindow(); content.BtnLogin.Text = "Join"; content.BtnLogin.Click += OnButtonNewSessionClicked; window.Content = content; window.ShowModal(_desktop); } private void OnMenuFileSaveSelected(object sender, EventArgs e) { FileDialog dialog = new(FileDialogMode.SaveFile) { Filter = "*.map" }; dialog.Closed += (s, a) => { if (!dialog.Result) { return; } using StreamWriter file = File.CreateText(dialog.FilePath); JsonSerializer serializer = new(); serializer.Serialize(file, _sessionData); }; dialog.ShowModal(_desktop); } private void OnMenuFileLoadSelected(object sender, EventArgs e) { var dialog = new FileDialog(FileDialogMode.OpenFile) { Filter = "*.map" }; dialog.Closed += (s, a) => { if (!dialog.Result) { return; } using StreamReader file = File.OpenText(dialog.FilePath); JsonSerializer serializer = new(); var loadData = (Session)serializer.Deserialize(file, typeof(Session)); _sessionData.Map = loadData.Map; _sessionData.Overlays = loadData.Overlays; _sessionData.Walls = loadData.Walls; }; dialog.ShowModal(_desktop); } private void OnMapEntityAdded(object sender, MapEntityAddedEventArgs e) { _communicationManager.Enqueue(e.MapEntity, TileAction.Add); } private void OnMapEntityDeleted(object sender, MapEntityDeletedEventArgs e) { _communicationManager.Enqueue(e.MapEntity, TileAction.Delete); } private bool ValidateTextbox(TextBox textBox) { var valid = !string.IsNullOrWhiteSpace(textBox.Text); if (!valid) { textBox.Background = new SolidBrush(Color.Red); } else { textBox.Background = new SolidBrush(new Color(51, 51, 51)); ; } return valid; } } }