Microwave UX enhancements (#24547)

* Facelift Microwave UI

Includes new background light in UI, Uses predictive input, UI now properly disables buttons when microwave is active

* Microwave now shows Elapsed time

* Fixed bad formatting

* Added new term for "BottomMargin"

* Change yellow color

* Update StyleNano.cs

just spacing fixed

* Cook time countdown now detached from server


Instead of the server constantly sending out messages for the cook countdown, it is now predicted client side using TimeSpan

* Update MicrowaveMenu.xaml

forgot to re-add item space
This commit is contained in:
James Simonson
2024-02-14 06:16:00 +08:00
committed by GitHub
parent 40823416f0
commit 25f73f6406
8 changed files with 241 additions and 92 deletions

View File

@@ -4,6 +4,7 @@ using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
namespace Content.Client.Kitchen.UI
{
@@ -18,6 +19,9 @@ namespace Content.Client.Kitchen.UI
[ViewVariables]
private readonly Dictionary<int, ReagentQuantity> _reagents = new();
[Dependency] private readonly IGameTiming _gameTiming = default!;
public MicrowaveUpdateUserInterfaceState currentState = default!;
private IEntityManager _entManager;
@@ -26,23 +30,47 @@ namespace Content.Client.Kitchen.UI
_entManager = IoCManager.Resolve<IEntityManager>();
}
public TimeSpan GetCurrentTime()
{
return _gameTiming.CurTime;
}
protected override void Open()
{
base.Open();
_menu = new MicrowaveMenu(this);
_menu.OpenCentered();
_menu.OnClose += Close;
_menu.StartButton.OnPressed += _ => SendMessage(new MicrowaveStartCookMessage());
_menu.EjectButton.OnPressed += _ => SendMessage(new MicrowaveEjectMessage());
_menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage());
_menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage());
_menu.IngredientsList.OnItemSelected += args =>
{
SendMessage(new MicrowaveEjectSolidIndexedMessage(EntMan.GetNetEntity(_solids[args.ItemIndex])));
SendPredictedMessage(new MicrowaveEjectSolidIndexedMessage(EntMan.GetNetEntity(_solids[args.ItemIndex])));
};
_menu.OnCookTimeSelected += (args, buttonIndex) =>
{
var actualButton = (MicrowaveMenu.MicrowaveCookTimeButton) args.Button;
SendMessage(new MicrowaveSelectCookTimeMessage(buttonIndex, actualButton.CookTime));
var selectedCookTime = (uint) 0;
if (args.Button is MicrowaveMenu.MicrowaveCookTimeButton microwaveCookTimeButton)
{
// args.Button is a MicrowaveCookTimeButton
var actualButton = (MicrowaveMenu.MicrowaveCookTimeButton) args.Button;
selectedCookTime = actualButton.CookTime == 0 ? 0 : actualButton.CookTime;
// SendMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime / 5, actualButton.CookTime));
SendPredictedMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime / 5, actualButton.CookTime));
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
("time", selectedCookTime));
}
else
{
// args.Button is a normal button aka instant cook button
SendPredictedMessage(new MicrowaveSelectCookTimeMessage((int) selectedCookTime, 0));
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
("time", Loc.GetString("microwave-menu-instant-button")));
}
};
}
@@ -67,20 +95,47 @@ namespace Content.Client.Kitchen.UI
return;
}
_menu?.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy);
_menu?.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0);
currentState = cState;
// TODO move this to a component state and ensure the net ids.
RefreshContentsDisplay(_entManager.GetEntityArray(cState.ContainedSolids));
if (_menu == null) return;
var currentlySelectedTimeButton = (Button) _menu.CookTimeButtonVbox.GetChild(cState.ActiveButtonIndex);
currentlySelectedTimeButton.Pressed = true;
//Set the cook time info label
var cookTime = cState.ActiveButtonIndex == 0
? Loc.GetString("microwave-menu-instant-button")
: cState.CurrentCookTime.ToString();
_menu.CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
("time", cookTime));
_menu.StartButton.Disabled = cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0;
_menu.EjectButton.Disabled = cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0;
//Set the correct button active button
if (cState.ActiveButtonIndex == 0)
{
_menu.InstantCookButton.Pressed = true;
}
else
{
var currentlySelectedTimeButton = (Button) _menu.CookTimeButtonVbox.GetChild(cState.ActiveButtonIndex - 1);
currentlySelectedTimeButton.Pressed = true;
}
//Set the "micowave light" ui color to indicate if the microwave is busy or not
if (cState.IsMicrowaveBusy && cState.ContainedSolids.Length > 0)
{
_menu.IngredientsPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#947300") };
}
else
{
_menu.IngredientsPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#1B1B1E") };
}
}
private void RefreshContentsDisplay(EntityUid[] containedSolids)

View File

@@ -1,73 +1,113 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'microwave-menu-title'}"
SetSize="512 256"
MinSize="512 256">
<BoxContainer Orientation="Horizontal">
<ItemList Name="IngredientsList"
Access="Public"
VerticalExpand="True"
HorizontalExpand="True"
SelectMode="Button"
SizeFlagsStretchRatio="2"
MinSize="100 128">
<!-- Ingredients are added here by code -->
</ItemList>
<BoxContainer Orientation="Vertical"
MinWidth="176"
VerticalExpand="True"
HorizontalExpand="True">
<BoxContainer Orientation="Vertical"
Align="Center"
SizeFlagsStretchRatio="3">
<Button Name="StartButton"
Access="Public"
Text="{Loc 'microwave-menu-start-button'}"
TextAlign="Center" />
<Button Name="EjectButton"
Access="Public"
Text="{Loc 'microwave-menu-eject-all-text'}"
ToolTip="{Loc 'microwave-menu-eject-all-tooltip'}"
TextAlign="Center" />
</BoxContainer>
<Control MinSize="0 15" />
<PanelContainer VerticalExpand="True"
HorizontalExpand="True">
<PanelContainer VerticalExpand="True"
ModulateSelfOverride="#FF0000"
MinSize="100 128">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#00000080" />
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical">
<PanelContainer>
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#80808032" />
</PanelContainer.PanelOverride>
<Label Name="CookTimeInfoLabel"
Access="Public"
Align="Center"
Modulate="#FFFFFF"
VAlign="Center" />
</PanelContainer>
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="CookTimeButtonVbox"
Access="Public"
Orientation="Vertical"
VerticalExpand="True"
Align="Center">
<!-- Cook time buttons are added here by code -->
</BoxContainer>
</ScrollContainer>
</BoxContainer>
</PanelContainer>
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:style="clr-namespace:Content.Client.Stylesheets"
Title="{Loc 'microwave-menu-title'}"
MinWidth="512"
MinSize="512 256">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" >
<PanelContainer
Name="IngredientsPanel"
Access="Public"
MinSize="300 128"
Margin="5 5">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
</PanelContainer.PanelOverride>
<ItemList
Name="IngredientsList"
Access="Public"
Margin="5 5"
VerticalExpand="True"
HorizontalExpand="True"
StyleClasses="transparentBackgroundItemList"
SelectMode="Button"
SizeFlagsStretchRatio="3"
ItemSeparation="5"
MinSize="100 128">
<!-- Ingredients are added here by code -->
</ItemList>
</PanelContainer>
<BoxContainer
Orientation="Vertical"
MinWidth="170"
Margin="10 10"
VerticalExpand="True"
HorizontalExpand="True">
<PanelContainer
VerticalExpand="True"
HorizontalExpand="True">
<PanelContainer
VerticalExpand="True"
ModulateSelfOverride="#FF0000"
MinSize="100 128">
<BoxContainer Orientation="Vertical">
<Label
Name="CookTimeInfoLabel"
Access="Public"
Align="Center"
Modulate="#FFFFFF"
VAlign="Center" />
<BoxContainer Orientation="Vertical">
<Button
Name="InstantCookButton"
Access="Public"
Text="{Loc 'microwave-menu-instant-button'}"
StyleClasses="OpenLeft"
ToggleMode="True"
Margin="0 0 2 0"
TextAlign="Center" />
<GridContainer
Name="CookTimeButtonVbox"
HSeparationOverride="1"
VSeparationOverride="1"
HorizontalExpand="True"
Columns="3"
Margin="0"
Access="Public">
<!-- Cook time buttons are added here by code -->
</GridContainer>
<BoxContainer
Orientation="Vertical"
Align="Center"
SizeFlagsStretchRatio="3">
<Control MinSize="0 15" />
<Button
Name="StartButton"
Access="Public"
Text="{Loc 'microwave-menu-start-button'}"
StyleClasses="ButtonColorGreen"
TextAlign="Center" />
<Button
Name="EjectButton"
Access="Public"
Text="{Loc 'microwave-menu-eject-all-text'}"
ToolTip="{Loc 'microwave-menu-eject-all-tooltip'}"
StyleClasses="ButtonColorRed"
TextAlign="Center" />
</BoxContainer>
</BoxContainer>
</BoxContainer>
</PanelContainer>
</PanelContainer>
</BoxContainer>
</BoxContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'microwave-menu-footer-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'microwave-menu-footer-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered" VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
</BoxContainer>
<PanelContainer Name="DisableCookingPanelOverlay"
MouseFilter="Stop">
<PanelContainer Name="DisableCookingPanelOverlay" MouseFilter="Stop">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#00000099" />
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E66" />
</PanelContainer.PanelOverride>
</PanelContainer>
</DefaultWindow>
</controls:FancyWindow>

View File

@@ -1,14 +1,13 @@
using System;
using Robust.Client.AutoGenerated;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
using Robust.Shared.Timing;
namespace Content.Client.Kitchen.UI
{
[GenerateTypedNameReferences]
public sealed partial class MicrowaveMenu : DefaultWindow
public sealed partial class MicrowaveMenu : FancyWindow
{
public sealed class MicrowaveCookTimeButton : Button
{
@@ -17,28 +16,43 @@ namespace Content.Client.Kitchen.UI
public event Action<BaseButton.ButtonEventArgs, int>? OnCookTimeSelected;
private ButtonGroup CookTimeButtonGroup { get; }
public ButtonGroup CookTimeButtonGroup { get; }
private readonly MicrowaveBoundUserInterface _owner;
public MicrowaveMenu(MicrowaveBoundUserInterface owner)
{
RobustXamlLoader.Load(this);
CookTimeButtonGroup = new ButtonGroup();
InstantCookButton.Group = CookTimeButtonGroup;
_owner = owner;
InstantCookButton.OnPressed += args =>
{
OnCookTimeSelected?.Invoke(args, 0);
};
for (var i = 0; i <= 30; i += 5)
for (var i = 1; i <= 6; i++)
{
var newButton = new MicrowaveCookTimeButton
{
Text = i == 0 ? Loc.GetString("microwave-menu-instant-button") : i.ToString(),
CookTime = (uint) i,
Text = (i * 5).ToString(),
TextAlign = Label.AlignMode.Center,
ToggleMode = true,
CookTime = (uint) (i * 5),
Group = CookTimeButtonGroup,
HorizontalExpand = true,
};
CookTimeButtonVbox.AddChild(newButton);
newButton.OnToggled += args =>
if (i == 4)
{
OnCookTimeSelected?.Invoke(args, newButton.GetPositionInParent());
newButton.StyleClasses.Add("OpenRight");
}
else
{
newButton.StyleClasses.Add("OpenBoth");
}
CookTimeButtonVbox.AddChild(newButton);
newButton.OnPressed += args =>
{
OnCookTimeSelected?.Invoke(args, i);
};
}
}
@@ -47,5 +61,18 @@ namespace Content.Client.Kitchen.UI
{
DisableCookingPanelOverlay.Visible = shouldDisable;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if(!_owner.currentState.IsMicrowaveBusy)
return;
if(_owner.currentState.CurrentCookTimeEnd > _owner.GetCurrentTime())
{
CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
("time",_owner.currentState.CurrentCookTimeEnd.Subtract(_owner.GetCurrentTime()).Seconds));
}
}
}
}

View File

@@ -998,6 +998,18 @@ namespace Content.Client.Stylesheets
itemListBackgroundSelected)
}),
new StyleRule(new SelectorElement(typeof(ItemList), new[] {"transparentBackgroundItemList"}, null, null), new[]
{
new StyleProperty(ItemList.StylePropertyBackground,
new StyleBoxFlat {BackgroundColor = Color.Transparent}),
new StyleProperty(ItemList.StylePropertyItemBackground,
itemListItemBackground),
new StyleProperty(ItemList.StylePropertyDisabledItemBackground,
itemListItemBackgroundDisabled),
new StyleProperty(ItemList.StylePropertySelectedItemBackground,
itemListBackgroundSelected)
}),
// Tree
new StyleRule(new SelectorElement(typeof(Tree), null, null, null), new[]
{

View File

@@ -56,6 +56,12 @@ namespace Content.Server.Kitchen.Components
[DataField("currentCookTimerTime"), ViewVariables(VVAccess.ReadWrite)]
public uint CurrentCookTimerTime = 0;
/// <summary>
/// Tracks the elapsed time of the current cook timer.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan CurrentCookTimeEnd = TimeSpan.Zero;
/// <summary>
/// The maximum number of seconds a microwave can be set to.
/// This is currently only used for validation and the client does not check this.

View File

@@ -369,7 +369,8 @@ namespace Content.Server.Kitchen.EntitySystems
GetNetEntityArray(component.Storage.ContainedEntities.ToArray()),
HasComp<ActiveMicrowaveComponent>(uid),
component.CurrentCookTimeButtonIndex,
component.CurrentCookTimerTime
component.CurrentCookTimerTime,
component.CurrentCookTimeEnd
));
}
@@ -492,6 +493,7 @@ namespace Content.Server.Kitchen.EntitySystems
activeComp.CookTimeRemaining = component.CurrentCookTimerTime * component.CookTimeMultiplier;
activeComp.TotalTime = component.CurrentCookTimerTime; //this doesn't scale so that we can have the "actual" time
activeComp.PortionedRecipe = portionedRecipe;
component.CurrentCookTimeEnd = _gameTiming.CurTime + TimeSpan.FromSeconds(component.CurrentCookTimerTime);
if (malfunctioning)
activeComp.MalfunctionTime = _gameTiming.CurTime + TimeSpan.FromSeconds(component.MalfunctionInterval);
UpdateUserInterfaceState(uid, component);
@@ -557,7 +559,7 @@ namespace Content.Server.Kitchen.EntitySystems
active.CookTimeRemaining -= frameTime;
RollMalfunction((uid, active,microwave));
RollMalfunction((uid, active, microwave));
//check if there's still cook time left
if (active.CookTimeRemaining > 0)
@@ -580,6 +582,7 @@ namespace Content.Server.Kitchen.EntitySystems
}
_container.EmptyContainer(microwave.Storage);
microwave.CurrentCookTimeEnd = TimeSpan.Zero;
UpdateUserInterfaceState(uid, microwave);
_audio.PlayPvs(microwave.FoodDoneSound, uid);
StopCooking((uid, microwave));
@@ -617,6 +620,7 @@ namespace Content.Server.Kitchen.EntitySystems
ent.Comp.CurrentCookTimeButtonIndex = args.ButtonIndex;
ent.Comp.CurrentCookTimerTime = args.NewCookTime;
ent.Comp.CurrentCookTimeEnd = TimeSpan.Zero;
_audio.PlayPvs(ent.Comp.ClickSound, ent, AudioParams.Default.WithVolume(-2));
UpdateUserInterfaceState(ent, ent.Comp);
}

View File

@@ -54,13 +54,16 @@ namespace Content.Shared.Kitchen.Components
public int ActiveButtonIndex;
public uint CurrentCookTime;
public TimeSpan CurrentCookTimeEnd;
public MicrowaveUpdateUserInterfaceState(NetEntity[] containedSolids,
bool isMicrowaveBusy, int activeButtonIndex, uint currentCookTime)
bool isMicrowaveBusy, int activeButtonIndex, uint currentCookTime, TimeSpan currentCookTimeEnd)
{
ContainedSolids = containedSolids;
IsMicrowaveBusy = isMicrowaveBusy;
ActiveButtonIndex = activeButtonIndex;
CurrentCookTime = currentCookTime;
CurrentCookTimeEnd = currentCookTimeEnd;
}
}

View File

@@ -24,3 +24,5 @@ microwave-menu-start-button = Start
microwave-menu-eject-all-text = Eject All Contents
microwave-menu-eject-all-tooltip = This vaporizes all reagents, but ejects any solids.
microwave-menu-instant-button = INSTANT
microwave-menu-footer-flavor-left = Do not insert any electronic, metallic or living objects.
microwave-menu-footer-flavor-right = v1.5