[Entity] Brig Timers (#15285)
* brigtimer * ok * TextScreen w timer implementation * second commit * working brig timer * signal timers near completion * soon done * removed licenses, fixes noRotation on screens, minor edits * no message * no message * removed my last todos * removed csproj.rej?? * missed a thing with .yml and tests * fix tests * Update base_structureairlocks.yml * timespan type serialize * activation turned into comp * sloth review * Update timer.yml * small changes --------- Co-authored-by: CommieFlowers <rasmus.cedergren@hotmail.com> Co-authored-by: rolfero <45628623+rolfero@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.MachineLinking.UI;
|
||||
|
||||
public sealed class SignalTimerBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
private SignalTimerWindow? _window;
|
||||
|
||||
public SignalTimerBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = new SignalTimerWindow(this);
|
||||
|
||||
if (State != null)
|
||||
UpdateState(State);
|
||||
|
||||
_window.OpenCentered();
|
||||
_window.OnClose += Close;
|
||||
_window.OnCurrentTextChanged += OnTextChanged;
|
||||
_window.OnCurrentDelayMinutesChanged += OnDelayChanged;
|
||||
_window.OnCurrentDelaySecondsChanged += OnDelayChanged;
|
||||
}
|
||||
|
||||
public void OnStartTimer()
|
||||
{
|
||||
SendMessage(new SignalTimerStartMessage());
|
||||
}
|
||||
|
||||
private void OnTextChanged(string newText)
|
||||
{
|
||||
SendMessage(new SignalTimerTextChangedMessage(newText));
|
||||
}
|
||||
|
||||
private void OnDelayChanged(string newDelay)
|
||||
{
|
||||
if (_window == null)
|
||||
return;
|
||||
SendMessage(new SignalTimerDelayChangedMessage(_window.GetDelay()));
|
||||
}
|
||||
|
||||
public TimeSpan GetCurrentTime()
|
||||
{
|
||||
return _gameTiming.CurTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the UI state based on server-sent info
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_window == null || state is not SignalTimerBoundUserInterfaceState cast)
|
||||
return;
|
||||
|
||||
_window.SetCurrentText(cast.CurrentText);
|
||||
_window.SetCurrentDelayMinutes(cast.CurrentDelayMinutes);
|
||||
_window.SetCurrentDelaySeconds(cast.CurrentDelaySeconds);
|
||||
_window.SetShowText(cast.ShowText);
|
||||
_window.SetTriggerTime(cast.TriggerTime);
|
||||
_window.SetTimerStarted(cast.TimerStarted);
|
||||
_window.SetHasAccess(cast.HasAccess);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing) return;
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
17
Content.Client/MachineLinking/UI/SignalTimerWindow.xaml
Normal file
17
Content.Client/MachineLinking/UI/SignalTimerWindow.xaml
Normal file
@@ -0,0 +1,17 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc signal-timer-menu-title}">
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150">
|
||||
<BoxContainer Name="TextEdit" Orientation="Horizontal">
|
||||
<Label Name="CurrentLabel" Text="{Loc signal-timer-menu-label}" />
|
||||
<LineEdit Name="CurrentTextEdit" MinWidth="80" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Name="DelayEdit" Orientation="Horizontal">
|
||||
<Label Name="CurrentDelay" Text="{Loc signal-timer-menu-delay}" />
|
||||
<LineEdit Name="CurrentDelayEditMinutes" MinWidth="32" />
|
||||
<Label Name="Colon" Text=":" />
|
||||
<LineEdit Name="CurrentDelayEditSeconds" MinWidth="32" />
|
||||
<Label Name="DelayInfo" Text=" (mm:ss)" />
|
||||
</BoxContainer>
|
||||
<Button Name="StartTimer" Text="{Loc signal-timer-menu-start}" />
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
192
Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs
Normal file
192
Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Client.TextScreen;
|
||||
|
||||
namespace Content.Client.MachineLinking.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SignalTimerWindow : DefaultWindow
|
||||
{
|
||||
private const int MaxTextLength = 5;
|
||||
|
||||
public event Action<string>? OnCurrentTextChanged;
|
||||
public event Action<string>? OnCurrentDelayMinutesChanged;
|
||||
public event Action<string>? OnCurrentDelaySecondsChanged;
|
||||
|
||||
private readonly SignalTimerBoundUserInterface _owner;
|
||||
|
||||
private TimeSpan? _triggerTime;
|
||||
|
||||
private bool _timerStarted;
|
||||
|
||||
public SignalTimerWindow(SignalTimerBoundUserInterface owner)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
_owner = owner;
|
||||
|
||||
CurrentTextEdit.OnTextChanged += e => OnCurrentTextChange(e.Text);
|
||||
CurrentDelayEditMinutes.OnTextChanged += e => OnCurrentDelayMinutesChange(e.Text);
|
||||
CurrentDelayEditSeconds.OnTextChanged += e => OnCurrentDelaySecondsChange(e.Text);
|
||||
StartTimer.OnPressed += _ => OnStartTimer();
|
||||
}
|
||||
|
||||
public void OnStartTimer()
|
||||
{
|
||||
if (!_timerStarted)
|
||||
{
|
||||
_timerStarted = true;
|
||||
_triggerTime = _owner.GetCurrentTime() + GetDelay();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTimerStarted(false);
|
||||
}
|
||||
_owner.OnStartTimer();
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (!_timerStarted || _triggerTime == null)
|
||||
return;
|
||||
|
||||
if (_owner.GetCurrentTime() < _triggerTime.Value)
|
||||
{
|
||||
StartTimer.Text = TextScreenSystem.TimeToString(_triggerTime.Value - _owner.GetCurrentTime());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTimerStarted(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCurrentTextChange(string text)
|
||||
{
|
||||
if (CurrentTextEdit.Text.Length > MaxTextLength)
|
||||
{
|
||||
CurrentTextEdit.Text = CurrentTextEdit.Text.Remove(MaxTextLength);
|
||||
CurrentTextEdit.CursorPosition = MaxTextLength;
|
||||
}
|
||||
OnCurrentTextChanged?.Invoke(text);
|
||||
}
|
||||
|
||||
public void OnCurrentDelayMinutesChange(string text)
|
||||
{
|
||||
List<char> toRemove = new();
|
||||
|
||||
foreach (var a in text)
|
||||
{
|
||||
if (!char.IsDigit(a))
|
||||
toRemove.Add(a);
|
||||
}
|
||||
|
||||
foreach (var a in toRemove)
|
||||
{
|
||||
CurrentDelayEditMinutes.Text = text.Replace(a.ToString(),"");
|
||||
}
|
||||
|
||||
if (CurrentDelayEditMinutes.Text == "")
|
||||
return;
|
||||
|
||||
while (CurrentDelayEditMinutes.Text[0] == '0' && CurrentDelayEditMinutes.Text.Length > 2)
|
||||
{
|
||||
CurrentDelayEditMinutes.Text = CurrentDelayEditMinutes.Text.Remove(0, 1);
|
||||
}
|
||||
|
||||
if (CurrentDelayEditMinutes.Text.Length > 2)
|
||||
{
|
||||
CurrentDelayEditMinutes.Text = CurrentDelayEditMinutes.Text.Remove(2);
|
||||
}
|
||||
OnCurrentDelayMinutesChanged?.Invoke(CurrentDelayEditMinutes.Text);
|
||||
}
|
||||
|
||||
public void OnCurrentDelaySecondsChange(string text)
|
||||
{
|
||||
List<char> toRemove = new();
|
||||
|
||||
foreach (var a in text)
|
||||
{
|
||||
if (!char.IsDigit(a))
|
||||
toRemove.Add(a);
|
||||
}
|
||||
|
||||
foreach (var a in toRemove)
|
||||
{
|
||||
CurrentDelayEditSeconds.Text = text.Replace(a.ToString(), "");
|
||||
}
|
||||
|
||||
if (CurrentDelayEditSeconds.Text == "")
|
||||
return;
|
||||
|
||||
while (CurrentDelayEditSeconds.Text[0] == '0' && CurrentDelayEditSeconds.Text.Length > 2)
|
||||
{
|
||||
CurrentDelayEditSeconds.Text = CurrentDelayEditSeconds.Text.Remove(0, 1);
|
||||
}
|
||||
|
||||
if (CurrentDelayEditSeconds.Text.Length > 2)
|
||||
{
|
||||
CurrentDelayEditSeconds.Text = CurrentDelayEditSeconds.Text.Remove(2);
|
||||
}
|
||||
OnCurrentDelaySecondsChanged?.Invoke(CurrentDelayEditSeconds.Text);
|
||||
}
|
||||
|
||||
public void SetCurrentText(string text)
|
||||
{
|
||||
CurrentTextEdit.Text = text;
|
||||
}
|
||||
|
||||
public void SetCurrentDelayMinutes(string delay)
|
||||
{
|
||||
CurrentDelayEditMinutes.Text = delay;
|
||||
}
|
||||
|
||||
public void SetCurrentDelaySeconds(string delay)
|
||||
{
|
||||
CurrentDelayEditSeconds.Text = delay;
|
||||
}
|
||||
|
||||
public void SetShowText(bool showTime)
|
||||
{
|
||||
TextEdit.Visible = showTime;
|
||||
}
|
||||
|
||||
public void SetTriggerTime(TimeSpan timeSpan)
|
||||
{
|
||||
_triggerTime = timeSpan;
|
||||
}
|
||||
|
||||
public void SetTimerStarted(bool timerStarted)
|
||||
{
|
||||
_timerStarted = timerStarted;
|
||||
|
||||
if (!timerStarted)
|
||||
StartTimer.Text = Loc.GetString("signal-timer-menu-start");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables fields and buttons if you don't have the access.
|
||||
/// </summary>
|
||||
public void SetHasAccess(bool hasAccess)
|
||||
{
|
||||
CurrentTextEdit.Editable = hasAccess;
|
||||
CurrentDelayEditMinutes.Editable = hasAccess;
|
||||
CurrentDelayEditSeconds.Editable = hasAccess;
|
||||
StartTimer.Disabled = !hasAccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a TimeSpan from the currently entered delay.
|
||||
/// </summary>
|
||||
public TimeSpan GetDelay()
|
||||
{
|
||||
if (!double.TryParse(CurrentDelayEditMinutes.Text, out var minutes))
|
||||
minutes = 0;
|
||||
if (!double.TryParse(CurrentDelayEditSeconds.Text, out var seconds))
|
||||
seconds = 0;
|
||||
return TimeSpan.FromMinutes(minutes) + TimeSpan.FromSeconds(seconds);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user