mirror of
https://gitlab.acidiclight.dev/sociallydistant/sociallydistant.git
synced 2025-01-22 17:41:49 -05:00
Port Main Menu
This commit is contained in:
parent
711096b258
commit
3b0c3a2f09
9 changed files with 344 additions and 13 deletions
|
@ -328,6 +328,9 @@ public sealed class GuiManager : IFontFamilyProvider
|
|||
|
||||
foreach (Widget widget in CollapseChildren())
|
||||
{
|
||||
if (!widget.IsVisible)
|
||||
continue;
|
||||
|
||||
if (widget is not IMouseHandler)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -804,7 +804,7 @@ public class TextWidget : Widget
|
|||
);
|
||||
}
|
||||
|
||||
private class MarkupData
|
||||
private struct MarkupData
|
||||
{
|
||||
public int Length;
|
||||
public Color? ColorOverride;
|
||||
|
|
|
@ -19,6 +19,8 @@ public partial class Widget
|
|||
private Point previousAvailableSize;
|
||||
private Visibility visibility;
|
||||
|
||||
public bool IsVisible => this.Visibility == Visibility.Visible && (Parent == null || Parent.IsVisible);
|
||||
|
||||
public Visibility Visibility
|
||||
{
|
||||
get => visibility;
|
||||
|
|
|
@ -34,6 +34,27 @@ namespace SociallyDistant.Core.Core
|
|||
|
||||
public static readonly string PlayerHomeId = "player";
|
||||
|
||||
public static string CreateFormattedDataMarkup(Dictionary<string, string> data)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
var isFirst = true;
|
||||
foreach (string key in data.Keys)
|
||||
{
|
||||
if (!isFirst)
|
||||
builder.AppendLine();
|
||||
|
||||
isFirst = false;
|
||||
|
||||
builder.Append("<color=#858585>");
|
||||
builder.Append(key);
|
||||
builder.Append(":</color> ");
|
||||
builder.Append(data[key]);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static string GetDayOfWeek(DayOfWeek day)
|
||||
{
|
||||
return day switch
|
||||
|
|
|
@ -17,6 +17,7 @@ using SociallyDistant.Core.UI;
|
|||
using SociallyDistant.Player;
|
||||
using SociallyDistant.UI.Common;
|
||||
using SociallyDistant.UI.InfoWidgets;
|
||||
using SociallyDistant.UI.MainMenu;
|
||||
using SociallyDistant.UI.Settings;
|
||||
using SociallyDistant.UI.Shell;
|
||||
using SociallyDistant.UI.Windowing;
|
||||
|
@ -26,7 +27,7 @@ namespace SociallyDistant.UI;
|
|||
public class GuiController : GameComponent,
|
||||
IShellContext
|
||||
{
|
||||
private readonly IGameContext context;
|
||||
private readonly SociallyDistantGame context;
|
||||
private readonly NotificationManager notificationManager;
|
||||
private readonly FlexPanel mainPanel = new();
|
||||
private readonly StatusBar statusBar;
|
||||
|
@ -45,7 +46,7 @@ public class GuiController : GameComponent,
|
|||
public StatusBar StatusBar => statusBar;
|
||||
public IGameContext Context => context;
|
||||
|
||||
public GuiController(IGameContext game, PlayerManager playerManager) : base(game.GameInstance)
|
||||
internal GuiController(SociallyDistantGame game, PlayerManager playerManager) : base(game.GameInstance)
|
||||
{
|
||||
this.context = game;
|
||||
|
||||
|
@ -100,22 +101,34 @@ public class GuiController : GameComponent,
|
|||
private void OnGameModeChanged(GameMode gameMode)
|
||||
{
|
||||
trayModel.UpdateGameMode(gameMode);
|
||||
|
||||
if (gameMode == GameMode.OnDesktop)
|
||||
{
|
||||
this.desktop = new Desktop(desktopController);
|
||||
this.mainBox.Content = desktop;
|
||||
mainBox.Content = null;
|
||||
|
||||
desktopController.Login();
|
||||
desktopController.InfoPanelController.ShowClock = true;
|
||||
}
|
||||
else
|
||||
if (gameMode != GameMode.OnDesktop)
|
||||
{
|
||||
desktopController.InfoPanelController.ShowClock = false;
|
||||
desktopController.Logout();
|
||||
mainBox.Content = null;
|
||||
desktop?.Dispose();
|
||||
}
|
||||
|
||||
switch (gameMode)
|
||||
{
|
||||
case GameMode.OnDesktop:
|
||||
{
|
||||
this.desktop = new Desktop(desktopController);
|
||||
this.mainBox.Content = desktop;
|
||||
|
||||
desktopController.Login();
|
||||
desktopController.InfoPanelController.ShowClock = true;
|
||||
break;
|
||||
}
|
||||
case GameMode.AtLoginScreen:
|
||||
{
|
||||
var menu = new LoginScreen(context);
|
||||
mainBox.Content = menu;
|
||||
menu.Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(GameTime gameTime)
|
||||
|
|
38
src/SociallyDistant/UI/MainMenu/LoginListADapter.cs
Normal file
38
src/SociallyDistant/UI/MainMenu/LoginListADapter.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using AcidicGUI.ListAdapters;
|
||||
using AcidicGUI.Widgets;
|
||||
using SociallyDistant.Core.Modules;
|
||||
|
||||
namespace SociallyDistant.UI.MainMenu;
|
||||
|
||||
public sealed class LoginListADapter : ListAdapter<ScrollView, LoginUserViewHolder>
|
||||
{
|
||||
private readonly DataHelper<IGameData> gameData;
|
||||
|
||||
public event Action<IGameData>? OnShowUser;
|
||||
|
||||
public LoginListADapter()
|
||||
{
|
||||
gameData = new DataHelper<IGameData>(this);
|
||||
}
|
||||
|
||||
public void SetUsers(IEnumerable<IGameData> source)
|
||||
{
|
||||
gameData.SetItems(source);
|
||||
}
|
||||
|
||||
protected override LoginUserViewHolder CreateViewHolder(int itemIndex, Box rootWidget)
|
||||
{
|
||||
return new LoginUserViewHolder(itemIndex, rootWidget);
|
||||
}
|
||||
|
||||
protected override void UpdateView(LoginUserViewHolder viewHolder)
|
||||
{
|
||||
viewHolder.UpdateView(gameData[viewHolder.ItemIndex]);
|
||||
viewHolder.Callback = ShowUser;
|
||||
}
|
||||
|
||||
private void ShowUser(IGameData user)
|
||||
{
|
||||
OnShowUser?.Invoke(user);
|
||||
}
|
||||
}
|
167
src/SociallyDistant/UI/MainMenu/LoginScreen.cs
Normal file
167
src/SociallyDistant/UI/MainMenu/LoginScreen.cs
Normal file
|
@ -0,0 +1,167 @@
|
|||
using System.Globalization;
|
||||
using AcidicGUI.Layout;
|
||||
using AcidicGUI.TextRendering;
|
||||
using AcidicGUI.Widgets;
|
||||
using Microsoft.Xna.Framework;
|
||||
using SociallyDistant.Core.Core;
|
||||
using SociallyDistant.Core.Modules;
|
||||
using SociallyDistant.Core.Shell;
|
||||
using SociallyDistant.Core.UI.Common;
|
||||
using SociallyDistant.Core.UI.Effects;
|
||||
using SociallyDistant.Core.UI.VisualStyles;
|
||||
|
||||
namespace SociallyDistant.UI.MainMenu;
|
||||
|
||||
public class LoginScreen : Widget
|
||||
{
|
||||
private readonly SociallyDistantGame game;
|
||||
private readonly OverlayWidget overlay = new();
|
||||
private readonly StackPanel versionArea = new();
|
||||
private readonly StackPanel mainArea = new();
|
||||
private readonly TextWidget versionText = new();
|
||||
private readonly StackPanel usersArea = new();
|
||||
private readonly Image gameLogo = new();
|
||||
private readonly TextWidget title = new();
|
||||
private readonly TextWidget prompt = new();
|
||||
private readonly Box userBox = new();
|
||||
private readonly TextButton createNewUserButton = new();
|
||||
private readonly StackPanel currentUserStack = new();
|
||||
private readonly Avatar currentUserAvatar = new();
|
||||
private readonly TextWidget currentUserName = new();
|
||||
private readonly TextWidget currentUserInfo = new();
|
||||
private readonly TextButton loginButtonn = new();
|
||||
private readonly TextButton switchUserButton = new();
|
||||
private readonly ToolbarIcon userOptionsButton = new();
|
||||
private readonly StackPanel currentUserInfoStack = new();
|
||||
private readonly LoginListADapter usersList = new();
|
||||
private readonly WrapPanel userOptionsArea = new();
|
||||
private IGameData? currentProfile;
|
||||
|
||||
internal LoginScreen(SociallyDistantGame game)
|
||||
{
|
||||
currentUserInfo.UseMarkup = true;
|
||||
currentUserInfo.WordWrapping = true;
|
||||
|
||||
userOptionsArea.Direction = Direction.Horizontal;
|
||||
userOptionsArea.SpacingX = 3;
|
||||
userOptionsArea.Padding = new Padding(0, 3, 0, 0);
|
||||
|
||||
currentUserName.FontWeight = FontWeight.Bold;
|
||||
currentUserAvatar.AvatarSize = 72;
|
||||
|
||||
currentUserStack.Direction = Direction.Horizontal;
|
||||
createNewUserButton.Text = "Create New User";
|
||||
switchUserButton.Text = "Switch User";
|
||||
loginButtonn.Text = "Log in";
|
||||
userOptionsButton.Icon = MaterialIcons.Settings;
|
||||
|
||||
title.FontSize = 36;
|
||||
prompt.FontSize = 20;
|
||||
|
||||
this.game = game;
|
||||
|
||||
overlay.Padding = 16;
|
||||
|
||||
versionText.UseMarkup = true;
|
||||
|
||||
versionArea.VerticalAlignment = VerticalAlignment.Bottom;
|
||||
versionArea.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
|
||||
mainArea.VerticalAlignment = VerticalAlignment.Middle;
|
||||
mainArea.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
|
||||
usersArea.MaximumSize = new Point(391, 320);
|
||||
usersArea.MinimumSize = new Point(391, 0);
|
||||
usersArea.SetCustomProperty(WidgetBackgrounds.Overlay);
|
||||
usersArea.Margin = 12;
|
||||
|
||||
|
||||
|
||||
Children.Add(overlay);
|
||||
overlay.ChildWidgets.Add(versionArea);
|
||||
overlay.ChildWidgets.Add(mainArea);
|
||||
versionArea.ChildWidgets.Add(gameLogo);
|
||||
versionArea.ChildWidgets.Add(versionText);
|
||||
mainArea.ChildWidgets.Add(title);
|
||||
mainArea.ChildWidgets.Add(prompt);
|
||||
mainArea.ChildWidgets.Add(usersArea);
|
||||
usersArea.ChildWidgets.Add(currentUserStack);
|
||||
usersArea.ChildWidgets.Add(usersList);
|
||||
mainArea.ChildWidgets.Add(switchUserButton);
|
||||
mainArea.ChildWidgets.Add(createNewUserButton);
|
||||
currentUserStack.ChildWidgets.Add(currentUserAvatar);
|
||||
currentUserStack.ChildWidgets.Add(currentUserInfoStack);
|
||||
currentUserInfoStack.ChildWidgets.Add(currentUserName);
|
||||
currentUserInfoStack.ChildWidgets.Add(currentUserInfo);
|
||||
currentUserInfoStack.ChildWidgets.Add(userOptionsArea);
|
||||
userOptionsArea.ChildWidgets.Add(loginButtonn);
|
||||
userOptionsArea.ChildWidgets.Add(userOptionsButton);
|
||||
|
||||
switchUserButton.ClickCallback = SwitchUser;
|
||||
createNewUserButton.ClickCallback = CreateNewUser;
|
||||
loginButtonn.ClickCallback = LogIn;
|
||||
}
|
||||
|
||||
private async void LogIn()
|
||||
{
|
||||
if (currentProfile == null)
|
||||
return;
|
||||
|
||||
await game.StartGame(currentProfile);
|
||||
}
|
||||
|
||||
private void SwitchUser()
|
||||
{
|
||||
currentProfile = null;
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private async void CreateNewUser()
|
||||
{
|
||||
await game.StartCharacterCreator();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
this.RenderEffect = BackgroundBlurWidgetEffect.GetEffect(game);
|
||||
usersArea.RenderEffect = BackgroundBlurWidgetEffect.GetEffect(game);
|
||||
versionText.Text = $"version <b>{Application.Instance.Version}</b>";
|
||||
|
||||
usersList.OnShowUser += ShowUser;
|
||||
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
if (currentProfile != null)
|
||||
{
|
||||
currentUserStack.Visibility = Visibility.Visible;
|
||||
switchUserButton.Visibility = Visibility.Visible;
|
||||
createNewUserButton.Visibility = Visibility.Collapsed;
|
||||
usersList.Visibility = Visibility.Collapsed;
|
||||
|
||||
currentUserName.Text = currentProfile.PlayerInfo.Name;
|
||||
|
||||
currentUserInfo.Text = SociallyDistantUtility.CreateFormattedDataMarkup(new Dictionary<string, string>() { { "Last played", currentProfile.PlayerInfo.LastPlayed.ToString(CultureInfo.CurrentCulture) }, { "Mission", currentProfile.PlayerInfo.Comment } });
|
||||
}
|
||||
else
|
||||
{
|
||||
usersList.SetUsers(game.ContentManager.GetContentOfType<IGameData>().OrderByDescending(x => x.PlayerInfo.LastPlayed));
|
||||
|
||||
title.Text = "Welcome";
|
||||
prompt.Text = "Please log in.";
|
||||
|
||||
currentUserStack.Visibility = Visibility.Collapsed;
|
||||
switchUserButton.Visibility = Visibility.Collapsed;
|
||||
createNewUserButton.Visibility = Visibility.Visible;
|
||||
usersList.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowUser(IGameData user)
|
||||
{
|
||||
this.currentProfile = user;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
61
src/SociallyDistant/UI/MainMenu/LoginUserView.cs
Normal file
61
src/SociallyDistant/UI/MainMenu/LoginUserView.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System.Globalization;
|
||||
using AcidicGUI.CustomProperties;
|
||||
using AcidicGUI.Layout;
|
||||
using AcidicGUI.TextRendering;
|
||||
using AcidicGUI.Widgets;
|
||||
using SociallyDistant.Core.Core;
|
||||
using SociallyDistant.Core.Modules;
|
||||
using SociallyDistant.Core.UI.Common;
|
||||
|
||||
namespace SociallyDistant.UI.MainMenu;
|
||||
|
||||
public sealed class LoginUserView : Widget
|
||||
{
|
||||
private readonly ListItem listItem = new();
|
||||
private readonly FlexPanel root = new();
|
||||
private readonly Avatar avatar = new();
|
||||
private readonly StackPanel textStack = new();
|
||||
private readonly TextWidget name = new();
|
||||
private readonly TextWidget info = new();
|
||||
|
||||
private IGameData? gameData;
|
||||
|
||||
public Action<IGameData>? Callback { get; set; }
|
||||
|
||||
public LoginUserView()
|
||||
{
|
||||
root.Direction = Direction.Horizontal;
|
||||
root.Spacing = 6;
|
||||
|
||||
name.FontWeight = FontWeight.Bold;
|
||||
|
||||
Children.Add(listItem);
|
||||
listItem.Content = root;
|
||||
root.ChildWidgets.Add(avatar);
|
||||
root.ChildWidgets.Add(textStack);
|
||||
textStack.ChildWidgets.Add(name);
|
||||
textStack.ChildWidgets.Add(info);
|
||||
|
||||
info.WordWrapping = true;
|
||||
info.UseMarkup = true;
|
||||
|
||||
listItem.ClickCallback = OnClick;
|
||||
avatar.AvatarSize = 48;
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
if (gameData == null)
|
||||
return;
|
||||
|
||||
this.Callback?.Invoke(gameData);
|
||||
}
|
||||
|
||||
public void UpdateView(IGameData user)
|
||||
{
|
||||
this.gameData = user;
|
||||
|
||||
name.Text = user.PlayerInfo.Name;
|
||||
info.Text = SociallyDistantUtility.CreateFormattedDataMarkup(new Dictionary<string, string>() { { "Last played", user.PlayerInfo.LastPlayed.ToString(CultureInfo.CurrentCulture) }, { "Mission", user.PlayerInfo.Comment } });
|
||||
}
|
||||
}
|
26
src/SociallyDistant/UI/MainMenu/LoginUserViewHolder.cs
Normal file
26
src/SociallyDistant/UI/MainMenu/LoginUserViewHolder.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using AcidicGUI.ListAdapters;
|
||||
using AcidicGUI.Widgets;
|
||||
using SociallyDistant.Core.Modules;
|
||||
|
||||
namespace SociallyDistant.UI.MainMenu;
|
||||
|
||||
public sealed class LoginUserViewHolder : ViewHolder
|
||||
{
|
||||
private readonly LoginUserView view = new();
|
||||
|
||||
public Action<IGameData>? Callback
|
||||
{
|
||||
get => view.Callback;
|
||||
set => view.Callback = value;
|
||||
}
|
||||
|
||||
public LoginUserViewHolder(int itemIndex, Box root) : base(itemIndex, root)
|
||||
{
|
||||
root.Content = view;
|
||||
}
|
||||
|
||||
public void UpdateView(IGameData user)
|
||||
{
|
||||
view.UpdateView(user);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue