sledgemapper/Sledgemapper/Sledgemapper.cs

2352 lines
95 KiB
C#

using Exceptionless;
using Exceptionless.Models;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MonoGame.Extended;
using Myra;
using Myra.Graphics2D.Brushes;
using Myra.Graphics2D.TextureAtlases;
using Myra.Graphics2D.UI;
using Myra.Graphics2D.UI.File;
using Myra.Graphics2D.UI.Properties;
using Myra.Utility;
using Newtonsoft.Json;
using Sledgemapper.Shared.Entities;
using Sledgemapper.UI;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
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<string, SpriteFont> _fonts;
private Texture2D _eye;
private Texture2D _location;
private Texture2D _comment;
private readonly Session _sessionData;
private AuthenticateResponse _authResponse;
private RenderTarget2D rendertarget;
private MainWidget _mainWidget;
private bool _showCellNumbers;
private readonly Settings _settings;
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 = true;
TargetElapsedTime = TimeSpan.FromSeconds(1d / 30d);
_communicationManager = new CommunicationManager(_sessionData);
_communicationManager.Connection.Reconnected += OnHubReconnected;
_communicationManager.Connection.Reconnecting += OnHubReconnecting;
_communicationManager.Connection.Closed += OnHubDisconnected;
_state = new State();
_settings = new Settings();
_vector2Pool = ArrayPool<Vector2>.Create();
}
private async Task OnHubDisconnected(Exception arg)
{
ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub disconnected", Type = "SignalR Client Events", Source = _settings.MachineName });
_mainWidget.lblConnectionStatus.Text = "Disconnected";
await Task.Yield();
}
private async Task OnHubReconnecting(Exception arg)
{
ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Reconnecting Hub", Type = "SignalR Client Events", Source = _settings.MachineName });
_mainWidget.lblConnectionStatus.Text = "Reconnecting";
await Task.Yield();
}
private async Task OnHubReconnected(string arg)
{
ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub reconnected", Type = "SignalR Client Events", Source = _settings.MachineName });
_mainWidget.lblConnectionStatus.Text = "Connected";
await Task.Yield();
}
protected override void Initialize()
{
ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Initialize", Type = "AppLifecycle", Source = _settings.MachineName });
IsMouseVisible = true;
Window.AllowUserResizing = true;
Window.ClientSizeChanged += OnClientSizeChanged;
base.Initialize();
}
private void ResetRenderTarget()
{
rendertarget = new RenderTarget2D(GraphicsDevice,
GraphicsDevice.Viewport.Width,
GraphicsDevice.Viewport.Height,
false,
SurfaceFormat.Color,
DepthFormat.None,
0,
RenderTargetUsage.DiscardContents);
}
private void OnClientSizeChanged(object sender, EventArgs e)
{
rendertarget?.Dispose();
try
{
ResetRenderTarget();
}
catch
{
System.Console.WriteLine("rendertarget dispose exception");
}
}
private void AddItemToToolGrid(Grid grid, EventHandler eventAction, Dictionary<string, Texture2D> tilesFolderContent)
{
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++;
}
}
}
private void AddItemToToolGrid(Grid grid, EventHandler eventAction, SpriteSheet spriteSheet, string e = "")
{
var indexX = 0;
var indexY = 0;
//foreach (var item in spriteSheet.index)
grid.Widgets.Clear();
_mainWidget.ScrOverlay.ResetScroll();
foreach (var item in spriteSheet.index.Where(t => String.IsNullOrWhiteSpace(e) || t.Key.ToLower().Contains(e.ToLower())))
{
var tileButton = new ImageButton { Image = new TextureRegion(spriteSheet.Texture, item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 };
tileButton.Click += eventAction;
tileButton.MouseMoved += OnTileButtonTouchEntered;
tileButton.MouseLeft += OnTileButtonTouchLeft;
grid.Widgets.Add(tileButton);
indexY++;
if (indexY == 4)
{
indexY = 0;
indexX++;
}
}
}
private void OnTileButtonTouchLeft(object sender, EventArgs e)
{
_desktop.HideContextMenu();
_lblOverlayName.Visible = false;
}
Label _lblOverlayName;
private void OnTileButtonTouchEntered(object sender, EventArgs e)
{
var mouseState = Mouse.GetState().Position;
mouseState.X += 10;
mouseState.Y += 10;
_lblOverlayName.Visible = true;
_lblOverlayName.Text = ((ImageButton)sender).Id;
_desktop.ShowContextMenu(_lblOverlayName, mouseState);
// _lblOverlayName.true;
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
outlineShader = Content.Load<Effect>("shaders/OutlineShader");
MyraEnvironment.Game = this;
ResetRenderTarget();
_mainWidget = new MainWidget();
_mainWidget.MenuConnectSync.Selected += OnMenuConnectSyncSelected;
_mainWidget.MenuFileLoad.Selected += OnMenuFileLoadSelected;
_mainWidget.MenuFileSave.Selected += OnMenuFileSaveSelected;
_mainWidget.MenuFileSettings.Selected += OneMenuFileSettingsSelected;
_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.MenuViewShowNotes.Selected += OnMenuViewNotesSelected;
_mainWidget.MenuConnectNew.Enabled = false;
_mainWidget.MenuConnectJoin.Enabled = false;
_mainWidget.MenuConnectSync.Enabled = false;
_mainWidget.MenuConnectUpload.Enabled = false;
_mainWidget.BtnToolbarLine.Click += OnBtnToolbarLinClicked;
_mainWidget.BtnToolbarRoom.Click += OnBtnToolbarRoomClicked;
_mainWidget.BtnToolbarDelete.Click += OnBtnToolbarDeleteClicked;
_wallsContent = Content.LoadContentFolder<Texture2D>("walls");
_spriteSheet = new SpriteSheet();
_spriteSheet.LoadContent(Content);
_lblOverlayName = new Label();
_lblOverlayName.Background = new SolidBrush(Color.SlateGray);
_lblOverlayName.Padding = new Myra.Graphics2D.Thickness(4);
AddItemToToolGrid(_mainWidget.GridWalls, OnWallButtonClicked, _wallsContent);
AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet);
_fonts = Content.LoadContentFolder<SpriteFont>("fonts");
_eye = Content.Load<Texture2D>("eye");
_location = Content.Load<Texture2D>("location");
_comment = Content.Load<Texture2D>("comment");
_mainWidget.BtnToolbarLine.Image = new TextureRegion(Content.Load<Texture2D>("icon_line"));
_mainWidget.BtnToolbarRoom.Image = new TextureRegion(Content.Load<Texture2D>("icon_room"));
_mainWidget.BtnToolbarDelete.Image = new TextureRegion(Content.Load<Texture2D>("icon_delete"));
_mainWidget.TxtOverlaySearch.TextChangedByUser += OnTxtOverlaySearchChange;
_desktop.Root = _mainWidget;
_transparentRedRectangle = new Texture2D(GraphicsDevice, 1, 1);
_transparentRedRectangle.SetData(new[] { new Color(Color.Red, 80) });
_whiteRectangle = new Texture2D(GraphicsDevice, 1, 1);
_whiteRectangle.SetData(new[] { Color.White });
}
private void OnTxtOverlaySearchChange(object sender, ValueChangedEventArgs<string> e)
{
// var filteredWidget = _mainWidget.GridOverlays.Widgets.Where(m => m.Id.ToLower().Contains(e.NewValue.ToLower())).ToArray();
// foreach (var w in _mainWidget.GridOverlays.Widgets)
// {
// w.
// w.Visible = false;
// }
// foreach (var w in filteredWidget)
// {
// w.Visible = true;
// }
AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet, e.NewValue);
}
private void OnBtnToolbarDeleteClicked(object sender, EventArgs e)
{
_state.InsertMode = InsertMode.NewDelete;
_mainWidget.ClearSelection();
((ImageTextButton)sender).Border = new SolidBrush(Color.Red);
((ImageTextButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2);
}
private void OnBtnToolbarWallClicked(object sender, EventArgs e)
{
_state.InsertMode = InsertMode.NewWall;
_mainWidget.ClearSelection();
((ImageTextButton)sender).Border = new SolidBrush(Color.Red);
((ImageTextButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2);
}
private void OnBtnToolbarTileClicked(object sender, EventArgs e)
{
_state.InsertMode = InsertMode.NewTile;
_mainWidget.ClearSelection();
((ImageTextButton)sender).Border = new SolidBrush(Color.Red);
((ImageTextButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2);
}
private void OnBtnToolbarRoomClicked(object sender, EventArgs e)
{
_state.InsertMode = InsertMode.NewRoom;
_mainWidget.ClearSelection();
((ImageTextButton)sender).Border = new SolidBrush(Color.Red);
((ImageTextButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2);
}
private void OnBtnToolbarLinClicked(object sender, EventArgs e)
{
_state.InsertMode = InsertMode.NewLine;
_mainWidget.ClearSelection();
((ImageTextButton)sender).Border = new SolidBrush(Color.Red);
((ImageTextButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2);
}
private void OneMenuFileSettingsSelected(object sender, EventArgs e)
{
var propertyGrid = new PropertyGrid
{
Object = _settings,
Width = 350
};
var _windowEditor = new Window
{
Title = "Object Editor",
Content = propertyGrid
};
_windowEditor.ShowModal(_desktop);
}
private void OnMenuViewShowCellNUmbersSelected(object sender, EventArgs e)
{
_showCellNumbers = !_showCellNumbers;
}
private void OnMenuViewCenterOnSelectionSelected(object sender, EventArgs e)
{
CenterOnSelectedTile();
}
private void OnMenuViewNotesSelected(object sender, EventArgs e)
{
Window window = new()
{
Title = "Notes"
};
var content = new NoteList();
for (var i = 0; i < _sessionData.Notes.Values.Count; i++)
{
var note = _sessionData.Notes.Values.ElementAt(i);
var item = new NoteListItem();
item.LblNoteText.Text = $"{note.ToString()} - {note.Text}";
item.BtnNoteCenter.Image = new TextureRegion(_location);
item.BtnNoteView.Image = new TextureRegion(_eye);
item.BtnNoteCenter.Click += (s, e) => { CenterOnTile(note.X, note.Y); };
item.BtnNoteView.Click += (s, e) => { EditNote(note); window.Close(); };
content.StackNotesList.AddChild(item);
}
window.Content = content;
window.ShowModal(_desktop);
}
private void EditNote(Note note)
{
_state.SelectedNote = new Note { X = note.X, Y = note.Y, Text = note.Text };
var noteWindow = new NoteWindow();
Window window = new()
{
Title = $" Note on {note.X}:{note.Y}"
};
noteWindow.NoteText.Text = note.Text;
noteWindow.BtnOk.Click += OnButtonNoteOkClick;
noteWindow.BtnCancel.Click += OnButtonNoteCancelClick;
window.Content = noteWindow;
window.ShowModal(_desktop);
noteWindow.NoteText.SetKeyboardFocus();
}
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 (_state.InsertMode == InsertMode.NewLine || _state.InsertMode == InsertMode.NewRoom || _state.InsertMode == InsertMode.NewDelete)
{
_state.SelectClosestSnapPoint(screenPosition);
}
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 (mouseState.RightButton == ButtonState.Released && mouseState.RightButton != oldMouseState.RightButton)
{
_state.SelectedNote.X = _state.HoveredTile.X;
_state.SelectedNote.Y = _state.HoveredTile.Y;
var popup = new VerticalStackPanel { Padding = new Myra.Graphics2D.Thickness(1), Spacing = 2, Background = new SolidBrush(Color.DarkGray) };
if (!_sessionData.Notes.ContainsKey(_state.SelectedNote.ToString()))
{
var newNoteButton = new TextButton { Text = "New Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left };
newNoteButton.Click += OnContextMenuNewNoteClick;
popup.AddChild(newNoteButton);
}
else
{
_sessionData.Notes.TryGetValue(_state.SelectedNote.ToString(), out var n);
_state.SelectedNote = n;
var viewNoteButton = new TextButton { Text = "View Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left };
var deleteNoteButton = new TextButton { Text = "Delete Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left };
viewNoteButton.Click += OnContextMenuViewNoteClick;
deleteNoteButton.Click += OnContextMenuDeleteNoteClick;
popup.AddChild(viewNoteButton);
popup.AddChild(deleteNoteButton);
}
_desktop.ShowContextMenu(popup, mouseState.Position);
}
if (newState.IsKeyDown(Keys.LeftControl)
&& mouseState.LeftButton == ButtonState.Released
&& mouseState.LeftButton != oldMouseState.LeftButton)
{
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 (_state.InsertMode == InsertMode.NewLine && newState.IsKeyDown(Keys.LeftControl)
&& mouseState.LeftButton == ButtonState.Released
&& mouseState.LeftButton != oldMouseState.LeftButton)
{
if (_state.LineStart is null)
{
_state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index };
}
else
{
var line = new Line
{
Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index },
End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index },
Width = _state.LineWidth
};
_state.LineStart = null;
_state.LineWidth = 1;
_sessionData.NewLine(line);
}
}
if (_state.InsertMode == InsertMode.NewRoom && newState.IsKeyDown(Keys.LeftControl)
&& mouseState.LeftButton == ButtonState.Released
&& mouseState.LeftButton != oldMouseState.LeftButton)
{
if (_state.LineStart is null)
{
_state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index };
}
else
{
var line = new Room
{
Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index },
End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }
};
_state.LineStart = null;
_state.LineWidth = 1;
_sessionData.NewRoom(line);
}
}
if (_state.InsertMode == InsertMode.NewDelete && newState.IsKeyDown(Keys.LeftControl)
&& mouseState.LeftButton == ButtonState.Released
&& mouseState.LeftButton != oldMouseState.LeftButton)
{
if (_state.LineStart is null)
{
_state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index };
}
else
{
var line = new Room
{
Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index },
End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index },
Delete = true
};
_state.LineStart = null;
_state.LineWidth = 1;
_sessionData.NewRoom(line);
}
}
if (_state.InsertMode == InsertMode.NewLine && _state.LineStart != null)
{
if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue)
{
_state.LineWidth += .01f;
}
else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue)
{
_state.LineWidth -= .01f;
}
}
if (newState.IsKeyDown(Keys.LeftControl) && mouseState.ScrollWheelValue != oldMouseState.ScrollWheelValue)
{
var maxTileSize = 500;
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(maxTileSize, _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:
case InsertMode.NewRoom:
case InsertMode.NewLine:
case InsertMode.NewDelete:
_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;
}
var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1;
var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1;
DrawMap();
ApplyShaderToMap();
_spriteBatch.Begin(
transformMatrix: Matrix.CreateTranslation(_viewportCenter),
sortMode: SpriteSortMode.Texture);
DrawTiles();
DrawWalls();
DrawOverlays();
DrawNotes();
DrawGrid(visibleTilesX, visibleTilesY);
DrawPlayerOffline();
DrawPlayers();
DrawSelectedWall();
DrawSelectedIntersection();
DrawLinePreview();
DrawRoomPreview();
_spriteBatch.End();
try
{
_desktop?.Render();
}
catch
{
System.Console.WriteLine("Desktop render error");
}
base.Draw(gameTime);
}
private void DrawRoomPreview()
{
if ((_state.InsertMode == InsertMode.NewRoom || _state.InsertMode == InsertMode.NewDelete) && _state.SelectedSnapPoint != null)
{
var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, _state.SelectedSnapPoint.Y * _state.TileSize);
switch (_state.SelectedSnapPoint.Index)
{
case 1:
break;
case 2:
snapPoint.X += _state.TileSize / 2;
break;
case 3:
snapPoint.Y += _state.TileSize / 2;
break;
case 4:
snapPoint.Y += _state.TileSize / 2;
snapPoint.X += _state.TileSize / 2;
break;
}
_spriteBatch.DrawCircle(snapPoint, _state.TileSize / 6f, 50, Color.Red, 2);
if (_state.LineStart != null)
{
var posX = _state.LineStart.X * _state.TileSize;
var posY = _state.LineStart.Y * _state.TileSize;
var endposX = _state.SelectedSnapPoint.X * _state.TileSize;
var endposY = _state.SelectedSnapPoint.Y * _state.TileSize;
if (_state.InsertMode == InsertMode.NewDelete)
{
var ww = _state.TileSize / _settings.TileDeleteDivider;
if (posX == endposX) { endposX += ww; posX -= ww; }
if (posY == endposY) { endposY += ww; posY -= ww; }
}
switch (_state.LineStart.Index)
{
case 1:
break;
case 2:
posX += _state.TileSize / 2;
break;
case 3:
posY += _state.TileSize / 2;
break;
case 4:
posX += _state.TileSize / 2;
posY += _state.TileSize / 2;
break;
}
switch (_state.SelectedSnapPoint.Index)
{
case 1:
break;
case 2:
endposX += _state.TileSize / 2;
break;
case 3:
endposY += _state.TileSize / 2;
break;
case 4:
endposX += _state.TileSize / 2;
endposY += _state.TileSize / 2;
break;
}
var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 3).Value ?? _fonts.Last().Value;
var fscale = 1.2f;
var width = Math.Abs((endposX - posX));
var height = Math.Abs((posY - endposY));
var tilesWidth = width / (double)_state.TileSize;
var tilesHeight = height / (double)_state.TileSize;
tilesWidth = Math.Round(tilesWidth * 2, MidpointRounding.AwayFromZero) / 2;
tilesHeight = Math.Round(tilesHeight * 2, MidpointRounding.AwayFromZero) / 2;
var xmeasure = ffont.MeasureString($"{tilesWidth}");
var ymeasure = ffont.MeasureString($"{tilesHeight}");
float widthX = 0, widthY = 0, heightX = 0, heightY = 0;
Rectangle area = new Rectangle();
if (posX != endposX && posY != endposY)
{
if ((posX > endposX && posY > endposY) || (posX < endposX && posY < endposY))
{
area = new Rectangle(posX, posY, endposX - posX, endposY - posY);
if (posX > endposX && posY > endposY)
{
widthX = endposX + (width / 2) - xmeasure.X / 2;
widthY = endposY - ymeasure.Y * 1.2f;
heightX = posX + xmeasure.X / 2;
heightY = endposY + (height / 2) - ymeasure.Y / 2;
}
else if (posX < endposX && posY < endposY)
{
widthX = posX + (width / 2) - xmeasure.X / 2;
widthY = posY - ymeasure.Y * 1.2f;
heightX = endposX + xmeasure.X / 2;
heightY = posY + (height / 2) - ymeasure.Y / 2;
}
}
else
{
if (endposY < posY)
{
area = new Rectangle(posX, endposY, endposX - posX, posY - endposY);
widthX = posX + (width / 2) - xmeasure.X / 2;
widthY = endposY - ymeasure.Y * 1.2f;
heightX = endposX + xmeasure.X / 2;
heightY = endposY + (height / 2) - ymeasure.Y / 2;
}
if (endposX < posX)
{
area = new Rectangle(endposX, posY, posX - endposX, endposY - posY);
widthX = endposX + (width / 2) - xmeasure.X / 2;
widthY = posY - ymeasure.Y * 1.2f;
heightX = posX + xmeasure.X / 2;
heightY = posY + (height / 2) - ymeasure.Y / 2;
}
}
_spriteBatch.Draw(_transparentRedRectangle, area, null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 1);
_spriteBatch.DrawString(ffont,
$"{tilesWidth}",
new Vector2(
widthX,
widthY
),
Color.Red,
0,
Vector2.Zero,
fscale,
SpriteEffects.None,
0);
_spriteBatch.DrawString(ffont,
$"{tilesHeight}",
new Vector2(
heightX, heightY
),
Color.Red,
0,
Vector2.Zero,
fscale,
SpriteEffects.None,
0);
}
}
}
}
private void DrawLinePreview()
{
if (_state.InsertMode == InsertMode.NewLine && _state.SelectedSnapPoint != null)
{
var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, _state.SelectedSnapPoint.Y * _state.TileSize);
switch (_state.SelectedSnapPoint.Index)
{
case 1:
break;
case 2:
snapPoint.X += _state.TileSize / 2;
break;
case 3:
snapPoint.Y += _state.TileSize / 2;
break;
case 4:
snapPoint.Y += _state.TileSize / 2;
snapPoint.X += _state.TileSize / 2;
break;
}
_spriteBatch.DrawCircle(snapPoint, _state.TileSize / 5f, 100, Color.Red, 2);
if (_state.LineStart != null)
{
var posX = _state.LineStart.X * _state.TileSize;
var posY = _state.LineStart.Y * _state.TileSize;
var endposX = _state.SelectedSnapPoint.X * _state.TileSize;
var endposY = _state.SelectedSnapPoint.Y * _state.TileSize;
switch (_state.LineStart.Index)
{
case 1:
break;
case 2:
posX += _state.TileSize / 2;
break;
case 3:
posY += _state.TileSize / 2;
break;
case 4:
posX += _state.TileSize / 2;
posY += _state.TileSize / 2;
break;
}
switch (_state.SelectedSnapPoint.Index)
{
case 1:
break;
case 2:
endposX += _state.TileSize / 2;
break;
case 3:
endposY += _state.TileSize / 2;
break;
case 4:
endposX += _state.TileSize / 2;
endposY += _state.TileSize / 2;
break;
}
var l = Math.Sqrt(Math.Pow(posX - endposX, 2) + Math.Pow(posY - endposY, 2));
var angle = Math.Atan2(posY - endposY, endposX - posX);
var angleRad = -(float)angle;
if (l > 0)
{
_spriteBatch.Draw(_transparentRedRectangle, new Rectangle(posX, posY, (int)l, (int)(_state.TileSize * _state.LineWidth)), null, Color.White, angleRad, new Vector2(0, 0), SpriteEffects.None, 1);
}
}
}
}
private void DrawSelectedIntersection()
{
if (_state.InsertMode == InsertMode.Overlay && _state.SelectedOverlay.Intersection)
{
var overlay = new Vector2(_state.SelectedOverlay.X * _state.TileSize, _state.SelectedOverlay.Y * _state.TileSize);
_spriteBatch.DrawCircle(overlay, _state.TileSize / 3f, 100, Color.Red, 2);
}
}
private void DrawSelectedWall()
{
if (_state.InsertMode == InsertMode.Wall)
{
var startWall = new Vector2(_state.SelectedWall.X * _state.TileSize, _state.SelectedWall.Y * _state.TileSize);
_spriteBatch.DrawLine(startWall, _state.TileSize, MathHelper.ToRadians(90 * _state.SelectedWall.Rotation), Color.Red, 2);
}
}
private void DrawPlayerOffline()
{
if (string.IsNullOrWhiteSpace(_sessionData.SessionName))
{
var isoffscreen = IsOffscreen(_state.SelectedTile);
if (isoffscreen)
{
var center = new Point((Window.ClientBounds.Width + 200) / 2 - (int)_viewportCenter.X, Window.ClientBounds.Height / 2 - (int)_viewportCenter.Y);
var cx = center.X / _state.TileSize;
var cy = center.Y / _state.TileSize;
var p1 = new Vector2(cx * _state.TileSize, cy * _state.TileSize);
var p2 = new Vector2(_state.SelectedTile.X * _state.TileSize, _state.SelectedTile.Y * _state.TileSize);
var p3 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, 0 - _viewportCenter.Y);
var p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua1 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, 0 - _viewportCenter.Y);
p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, 0 - _viewportCenter.Y);
var ua2 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, 0 - _viewportCenter.Y);
p4 = new Vector2(200 - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua3 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua4 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
var uas = new float[] { ua1, ua2, ua3, ua4 };
if (uas.Any(u => u > 0 && u < 1))
{
var ua = uas.Where(u => u > 0 && u < 1).Min();
int i = 0;
for (var j = 0; j < 4; j++)
{
if (uas[j] == ua)
{
i = j;
}
}
var x = (p1.X + ua * (p2.X - p1.X));
var y = (p1.Y + ua * (p2.Y - p1.Y));
var v = _vector2Pool.Rent(4);
switch (i)
{
case 0:
v[0] = new Vector2(x, y);
v[1] = new Vector2(x - 20, y + 10);
v[2] = new Vector2(x - 20, y - 10);
v[3] = new Vector2(x, y);
break;
case 1:
v[0] = new Vector2(x, y);
v[1] = new Vector2(x - 10, y + 20);
v[2] = new Vector2(x + 10, y + 20);
v[3] = new Vector2(x, y);
y += 20;
break;
case 2:
x += 0;
v[0] = new Vector2(x, y);
v[1] = new Vector2(x + 20, y + 10);
v[2] = new Vector2(x + 20, y - 10);
v[3] = new Vector2(x, y);
break;
case 3:
y -= 20;
v[0] = new Vector2(x, y);
v[1] = new Vector2(x - 10, y - 20);
v[2] = new Vector2(x + 10, y - 20);
v[3] = new Vector2(x, y);
break;
}
_spriteBatch.DrawPolygon(Vector2.Zero, v, Color.Red, 2);
_vector2Pool.Return(v);
}
}
_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);
}
}
private void ApplyShaderToMap()
{
Vector2 texelSize = new Vector2((float)rendertarget.Width, (float)rendertarget.Height);
outlineShader.Parameters["ImageSize"].SetValue(texelSize);
outlineShader.Parameters["BorderSize"].SetValue((int)(_state.TileSize / 100f * 10f));
outlineShader.Parameters["R"].SetValue(_settings.OverlayTintColor.R / 255.0f);
outlineShader.Parameters["G"].SetValue(_settings.OverlayTintColor.G / 255.0f);
outlineShader.Parameters["B"].SetValue(_settings.OverlayTintColor.B / 255.0f);
GraphicsDevice.Clear(_settings.BackgroundColor);
_spriteBatch.Begin(
effect: outlineShader,
sortMode: SpriteSortMode.Immediate);
_spriteBatch.Draw(rendertarget, Vector2.Zero, null, Color.White);
_spriteBatch.End();
}
private void DrawMap()
{
GraphicsDevice.SetRenderTarget(rendertarget);
GraphicsDevice.Clear(Color.Transparent);
_spriteBatch.Begin(
transformMatrix: Matrix.CreateTranslation(_viewportCenter),
samplerState: SamplerState.PointClamp
);
var items = _sessionData.Lines.Values.Union<BaseMapEntity>(_sessionData.Rooms.Values).OrderBy(t => t.Timestamp).ToArray();
for (var i = 0; i < items.Count(); i++)
{
var item = items.ElementAt(i);
if (IsMapElementOffscreen(item))
{
continue;
}
switch (item)
{
case Line l:
DrawLine(l);
break;
case Room room:
if (room.Delete)
{
DrawDelete(room);
}
else
{
DrawRoom(room);
}
break;
}
}
_spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
}
private bool IsMapElementOffscreen(BaseMapEntity item)
{
SnapPoint start, end;
switch (item)
{
case Line l:
start = l.Start;
end = l.End;
break;
case Room room:
start = room.Start;
end = room.End;
break;
default:
return true;
}
var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1;
var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1;
var screenPositionTopLeft = new Point(200 - _state.TileSize + 0 * _state.TileSize - (int)_viewportCenter.X, 0 * _state.TileSize + _state.TileSize - (int)_viewportCenter.Y);
var screenPositionBottomRight = new Point(visibleTilesX * _state.TileSize - (int)_viewportCenter.X, visibleTilesY * _state.TileSize - 20 - (int)_viewportCenter.Y);
var tileTopLeft = new Point(screenPositionTopLeft.X / _state.TileSize, screenPositionTopLeft.Y / _state.TileSize);
var tileBottomRight = new Point(screenPositionBottomRight.X / _state.TileSize, screenPositionBottomRight.Y / _state.TileSize);
if (start.X < tileTopLeft.X && start.Y < tileTopLeft.Y && start.X > tileBottomRight.X && start.Y > tileBottomRight.Y &&
end.X < tileTopLeft.X && end.Y < tileTopLeft.Y && end.X > tileBottomRight.X && end.Y > tileBottomRight.Y
)
{
return true;
}
return false;
}
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,
_settings.GridColor);
}
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,
_settings.GridColor);
}
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 DrawNotes()
{
if (_state.TileSize < 30)
{
return;
}
for (var i = 0; i < _sessionData.Notes.Values.Count; i++)
{
var note = _sessionData.Notes.Values.ElementAt(i);
_spriteBatch.Draw(
_comment,
new Rectangle(
note.X * _state.TileSize + _state.TileSize - (int)(_state.TileSize / 2) + _state.TileSize / 25,
note.Y * _state.TileSize + _state.TileSize / 8 + _state.TileSize / 25,
(int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136)
), Color.Black * .2f
);
_spriteBatch.Draw(
_comment,
new Rectangle(
note.X * _state.TileSize + _state.TileSize - (int)(_state.TileSize / 2),
note.Y * _state.TileSize + _state.TileSize / 8,
(int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136)
), _settings.NoteColor
);
}
}
private void DrawOverlays()
{
for (var i = 0; i < _sessionData.Overlays.Values.Count; i++)
{
var tile = _sessionData.Overlays.Values.ElementAt(i);
var spriteRec = _spriteSheet.SourceRectangle(tile.ID);
float posX;
float posY;
if (tile.Intersection)
{
posX = tile.X * _state.TileSize;
posY = tile.Y * _state.TileSize;
_spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, Color.Black * .2f, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0);
_spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, _settings.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0);
}
else
{
posX = tile.X * _state.TileSize + _state.TileSize / 2f;
posY = tile.Y * _state.TileSize + _state.TileSize / 2f;
}
_spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, Color.Black * .2f, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0);
_spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, _settings.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0);
}
}
private void DrawPlayers()
{
var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize).Value ?? _fonts.Last().Value;
var fscale = _state.TileSize / ((float)ffont.LineSpacing * 3f);
var playerCells = _sessionData.Players.Select(m => m.Position).Distinct().ToList();
foreach (var cell in playerCells)
{
var playersInCell = _sessionData.Players.Where(m => m.Position == cell).ToList();
var i = 0;
foreach (var player in playersInCell)
{
var color = player.Color.ToColor();
var rectangle = new Rectangle();
var stringPosition = new Vector2();
var measure = ffont.MeasureString(player.Initials);
var maxSize = Math.Max(measure.X, measure.Y);
if (playersInCell.Count == 1)
{
fscale = (_state.TileSize - 2) / maxSize;
rectangle = new Rectangle(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize,
_state.TileSize - 1,
_state.TileSize - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale);
}
else if (playersInCell.Count == 2)
{
fscale = (_state.TileSize / 2 - 2) / maxSize;
if (i == 0)
{
rectangle = new Rectangle(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize,
_state.TileSize / 2 - 1,
_state.TileSize - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale);
}
else
{
rectangle = new Rectangle(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize,
_state.TileSize / 2 - 1,
_state.TileSize - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale);
}
i++;
}
else if (playersInCell.Count >= 3)
{
fscale = (_state.TileSize / 2 - 2) / maxSize;
switch (i)
{
case 0:
rectangle = new Rectangle(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize,
_state.TileSize / 2 - 1,
_state.TileSize / 2 - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize + _state.TileSize / 2 - measure.Y * fscale);
break;
case 1:
rectangle = new Rectangle(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize,
_state.TileSize / 2 - 1,
_state.TileSize / 2 - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize + _state.TileSize / 2 - measure.Y * fscale);
break;
case 2:
rectangle = new Rectangle(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize + _state.TileSize / 2,
_state.TileSize / 2 - 1,
_state.TileSize / 2 - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize,
player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale);
break;
case 3:
default:
rectangle = new Rectangle(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize + _state.TileSize / 2,
_state.TileSize / 2 - 1,
_state.TileSize / 2 - 1);
stringPosition = new Vector2(
player.Position.X * _state.TileSize + _state.TileSize / 2,
player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale);
break;
}
i++;
}
_spriteBatch.DrawRectangle(rectangle, color, 2);
_spriteBatch.DrawString(ffont,
player.Initials,
stringPosition,
color,
0,
Vector2.Zero,
fscale,
SpriteEffects.None,
0);
}
}
foreach (var player in _sessionData.Players)
{
var isOffscreen = IsOffscreen(player.Position);
if (isOffscreen)
{
DrawPlayerPointer(player);
}
}
}
private void DrawPlayerPointer(Player player)
{
var center = new Point((Window.ClientBounds.Width + 200) / 2 - (int)_viewportCenter.X, Window.ClientBounds.Height / 2 - (int)_viewportCenter.Y);
var cx = center.X / _state.TileSize;
var cy = center.Y / _state.TileSize;
var p1 = new Vector2(cx * _state.TileSize, cy * _state.TileSize);
var p2 = new Vector2(player.Position.X * _state.TileSize, player.Position.Y * _state.TileSize);
var p3 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, 0 - _viewportCenter.Y);
var p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua1 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, 0 - _viewportCenter.Y);
p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, 0 - _viewportCenter.Y);
var ua2 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, 0 - _viewportCenter.Y);
p4 = new Vector2(200 - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua3 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
p3 = new Vector2(200 - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
p4 = new Vector2(Window.ClientBounds.Width - _viewportCenter.X, Window.ClientBounds.Height - _viewportCenter.Y);
var ua4 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y));
var uas = new List<float> { ua1, ua2, ua3, ua4 };
if (uas.Any(u => u > 0 && u < 1))
{
var ua = uas.Where(u => u > 0 && u < 1).Min();
var i = uas.IndexOf(ua);
var x = (p1.X + ua * (p2.X - p1.X));
var y = (p1.Y + ua * (p2.Y - p1.Y));
Vector2[] vertexes = new Vector2[0];
switch (i)
{
case 0:
vertexes = new Vector2[] { new Vector2(x, y), new Vector2(x - 20, y + 10), new Vector2(x - 20, y - 10), new Vector2(x, y) };
break;
case 1:
y += 20;
vertexes = new Vector2[] { new Vector2(x, y), new Vector2(x - 10, y + 20), new Vector2(x + 10, y + 20), new Vector2(x, y) };
break;
case 2:
x += 0;
vertexes = new Vector2[] { new Vector2(x, y), new Vector2(x + 20, y + 10), new Vector2(x + 20, y - 10), new Vector2(x, y) };
break;
case 3:
y -= 20;
vertexes = new Vector2[] { new Vector2(x, y), new Vector2(x - 10, y - 20), new Vector2(x + 10, y - 20), new Vector2(x, y) };
break;
}
_spriteBatch.DrawPolygon(Vector2.Zero, vertexes, player.Color.ToColor(), 2);
}
}
ArrayPool<Vector2> _vector2Pool;
private bool IsOffscreen(Tile position)
{
var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1;
var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1;
var screenPositionTopLeft = new Point(200 - _state.TileSize + 0 * _state.TileSize - (int)_viewportCenter.X, 0 * _state.TileSize + _state.TileSize - (int)_viewportCenter.Y);
var screenPositionBottomRight = new Point(visibleTilesX * _state.TileSize - (int)_viewportCenter.X, visibleTilesY * _state.TileSize - 20 - (int)_viewportCenter.Y);
var tileTopLeft = new Point(screenPositionTopLeft.X / _state.TileSize, screenPositionTopLeft.Y / _state.TileSize);
var tileBottomRight = new Point(screenPositionBottomRight.X / _state.TileSize, screenPositionBottomRight.Y / _state.TileSize);
if (position.X < tileTopLeft.X || position.Y < tileTopLeft.Y || position.X > tileBottomRight.X || position.Y > tileBottomRight.Y)
{
return true;
}
return false;
}
private int _borderWidth => (_state.TileSize / 6) % 2 == 0 ? (_state.TileSize / 6) : (_state.TileSize / 6) + 1;
private void DrawTiles()
{
for (var i = 0; i < _sessionData.Map.Values.Count; i++)
{
var tile = _sessionData.Map.Values.ElementAt(i);
var content = Content.Load<Texture2D>($"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) / content.Width, SpriteEffects.None, 0);
}
}
private void DrawLine(Line tile)
{
var posX = tile.Start.X * _state.TileSize;
var posY = tile.Start.Y * _state.TileSize;
var endposX = tile.End.X * _state.TileSize;
var endposY = tile.End.Y * _state.TileSize;
switch (tile.Start.Index)
{
case 1:
break;
case 2:
posX += _state.TileSize / 2;
break;
case 3:
posY += _state.TileSize / 2;
break;
case 4:
posX += _state.TileSize / 2;
posY += _state.TileSize / 2;
break;
}
switch (tile.End.Index)
{
case 1:
break;
case 2:
endposX += _state.TileSize / 2;
break;
case 3:
endposY += _state.TileSize / 2;
break;
case 4:
endposX += _state.TileSize / 2;
endposY += _state.TileSize / 2;
break;
}
var length = (int)Math.Sqrt(Math.Pow(posX - endposX, 2) + Math.Pow(posY - endposY, 2));
var height = (int)(_state.TileSize * tile.Width);
if (length > 0)
{
var angle = Math.Atan2(posY - endposY, endposX - posX);
var angleRad = -(float)angle;
_spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, length, height), null, Color.White, angleRad, new Vector2(0, 0), SpriteEffects.None, 1);
}
}
private void DrawRoom(Room tile)
{
var posX = tile.Start.X * _state.TileSize;
var posY = tile.Start.Y * _state.TileSize;
var endposX = tile.End.X * _state.TileSize;
var endposY = tile.End.Y * _state.TileSize;
switch (tile.Start.Index)
{
case 1:
break;
case 2:
posX += _state.TileSize / 2;
break;
case 3:
posY += _state.TileSize / 2;
break;
case 4:
posX += _state.TileSize / 2;
posY += _state.TileSize / 2;
break;
}
switch (tile.End.Index)
{
case 1:
break;
case 2:
endposX += _state.TileSize / 2;
break;
case 3:
endposY += _state.TileSize / 2;
break;
case 4:
endposX += _state.TileSize / 2;
endposY += _state.TileSize / 2;
break;
}
if (posX != endposX && posY != endposY)
{
if ((posX < endposX && posY < endposY))
{
_spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1);
}
else if ((posX > endposX && posY > endposY))
{
_spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1);
}
else
{
if (endposY < posY)
{
_spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, endposY, endposX - posX, posY - endposY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1);
}
if (endposX < posX)
{
_spriteBatch.Draw(_whiteRectangle, new Rectangle(endposX, posY, posX - endposX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1);
}
}
}
}
Effect outlineShader;
private Texture2D _transparentRedRectangle;
private Texture2D _whiteRectangle;
private Dictionary<string, Texture2D> _wallsContent;
private SpriteSheet _spriteSheet;
private void DrawDelete(Room tile)
{
var posX = tile.Start.X * _state.TileSize;
var posY = tile.Start.Y * _state.TileSize;
var endposX = tile.End.X * _state.TileSize;
var endposY = tile.End.Y * _state.TileSize;
var ww = _state.TileSize / _settings.TileDeleteDivider;
if (posX == endposX) { endposX += ww; posX -= ww; }
if (posY == endposY) { endposY += ww; posY -= ww; }
switch (tile.Start.Index)
{
case 1:
break;
case 2:
posX += _state.TileSize / 2;
break;
case 3:
posY += _state.TileSize / 2;
break;
case 4:
posX += _state.TileSize / 2;
posY += _state.TileSize / 2;
break;
}
switch (tile.End.Index)
{
case 1:
break;
case 2:
endposX += _state.TileSize / 2;
break;
case 3:
endposY += _state.TileSize / 2;
break;
case 4:
endposX += _state.TileSize / 2;
endposY += _state.TileSize / 2;
break;
}
if (posX != endposX && posY != endposY)
{
Rectangle r = new Rectangle();
if ((posX < endposX && posY < endposY))
{
r = new Rectangle(posX, posY, endposX - posX, endposY - posY);
}
else if ((posX > endposX && posY > endposY))
{
r = new Rectangle(posX, posY, endposX - posX, endposY - posY);
}
else
{
if (endposY < posY)
{
r = new Rectangle(posX, endposY, endposX - posX, posY - endposY);
}
if (endposX < posX)
{
r = new Rectangle(endposX, posY, posX - endposX, endposY - posY);
}
}
_spriteBatch.Draw(_whiteRectangle, r, null, Color.Black, 0, Vector2.Zero, SpriteEffects.None, 1);
}
}
private void DrawWalls()
{
for (var i = 0; i < _sessionData.Walls.Values.Count; i++)
{
var wall = _sessionData.Walls.Values.ElementAt(i);
var content = _wallsContent[$"{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<Session>("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;
_mainWidget.MenuConnectSync.Enabled = true;
_mainWidget.MenuConnectUpload.Enabled = true;
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<Session>("JoinSession", localContent.TxtSession.Text);
_sessionData.SessionId = result2.SessionId;
_sessionData.SessionName = localContent.TxtSession.Text;
}
catch (Exception ex)
{
ExceptionlessClient.Default.SubmitException(ex);
}
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;
_mainWidget.MenuConnectSync.Enabled = true;
_mainWidget.MenuConnectUpload.Enabled = true;
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 void OnButtonNoteOkClick(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 NoteWindow;
var note = new Note
{
X = _state.SelectedNote.X,
Y = _state.SelectedNote.Y,
Text = localContent.NoteText.Text
};
_sessionData.NewNote(note);
localWindow.Close();
}
private void OnButtonNoteCancelClick(object sender, EventArgs e)
{
var button = ((TextButton)sender);
Container container = button.Parent;
while (!(container is Window))
{
container = container.Parent;
}
var localWindow = (Window)container;
localWindow.Close();
}
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)
{
ExceptionlessClient.Default.SubmitException(refitException);
localContent.LblLoginError.Text = refitException.Content;
localContent.LblLoginError.Visible = true;
}
catch (Exception ex)
{
ExceptionlessClient.Default.SubmitException(ex);
localContent.LblLoginError.Text = "Can't connect to the server";
localContent.LblLoginError.Visible = true;
Debug.Write(ex);
}
finally
{
button.Enabled = true;
button.Text = "Login";
}
if (successful)
{
_mainWidget.MenuConnectNew.Enabled = true;
_mainWidget.MenuConnectJoin.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)
{
ExceptionlessClient.Default.SubmitException(refitException);
localContent.LblLoginError.Text = refitException.Content;
localContent.LblLoginError.Visible = true;
}
catch (Exception ex)
{
ExceptionlessClient.Default.SubmitException(ex);
localContent.LblLoginError.Text = "Can't connect to the server";
localContent.LblLoginError.Visible = true;
Debug.Write(ex);
}
finally
{
button.Enabled = true;
button.Text = "Register";
}
if (successful)
{
_mainWidget.MenuConnectNew.Enabled = true;
_mainWidget.MenuConnectJoin.Enabled = true;
_mainWidget.lblUsername.Text = $"{_authResponse.Username} - {_authResponse.Initials}";
localWindow.Close();
}
}
private void OnContextMenuNewNoteClick(object sender, EventArgs e)
{
_desktop.HideContextMenu();
var noteWindow = new NoteWindow();
Window window = new()
{
Title = $" Note on {_state.SelectedTile.X}:{_state.SelectedTile.Y}"
};
noteWindow.BtnOk.Click += OnButtonNoteOkClick;
noteWindow.BtnCancel.Click += OnButtonNoteCancelClick;
window.Content = noteWindow;
window.ShowModal(_desktop);
noteWindow.NoteText.SetKeyboardFocus();
}
private void OnContextMenuDeleteNoteClick(object sender, EventArgs e)
{
_desktop.HideContextMenu();
_sessionData.DeleteNote(_state.SelectedNote);
}
private void OnContextMenuViewNoteClick(object sender, EventArgs e)
{
_desktop.HideContextMenu();
EditNote(_state.SelectedNote);
}
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 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);
content.TxtSession.SetKeyboardFocus();
}
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);
content.TxtEmail.SetKeyboardFocus();
}
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;
_sessionData.Notes = serverMap.Notes;
_sessionData.Lines = serverMap.Lines;
_sessionData.Rooms = serverMap.Rooms;
}
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);
content.TxtSession.SetKeyboardFocus();
}
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;
_sessionData.Rooms = loadData.Rooms;
_sessionData.Lines = loadData.Lines;
};
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;
}
}
internal class SpriteSheet
{
internal Texture2D Texture;
internal Dictionary<String, Rectangle> index;
public void LoadContent(ContentManager content)
{
index = content.Load<Dictionary<String, Rectangle>>("spriteIndex");
Texture = content.Load<Texture2D>("sprites");
}
internal Rectangle? SourceRectangle(string spriteName)
{
Rectangle r;
bool hasValue = index.TryGetValue(spriteName, out r);
if (hasValue)
{
return r;
}
else
{
throw new Exception("value doesn't exist");
}
}
}
}