mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-06-09 10:06:49 +02:00
387 lines
14 KiB
C#
387 lines
14 KiB
C#
using System.Numerics;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Shared.Modular.Suit;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Client.UserInterface.XAML;
|
|
|
|
namespace Content.Client._Wega.ModularSuit.Ui;
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class ModularSuitWindow : BaseWindow
|
|
{
|
|
[Dependency] private IEntityManager _entMan = default!;
|
|
|
|
private Dictionary<NetEntity, ModuleControl> _moduleControls = new();
|
|
private Dictionary<SuitPartType, PartControl> _partControls = new();
|
|
|
|
public event Action<bool>? OnToggleActive;
|
|
public event Action<NetEntity, bool>? OnToggleModule;
|
|
|
|
public ModularSuitWindow()
|
|
{
|
|
RobustXamlLoader.Load(this);
|
|
IoCManager.InjectDependencies(this);
|
|
|
|
CloseButton.OnPressed += _ => Close();
|
|
|
|
ActivateButton.OnToggled += OnActivateToggled;
|
|
|
|
SetupTabs();
|
|
}
|
|
|
|
private void OnActivateToggled(BaseButton.ButtonToggledEventArgs args)
|
|
{
|
|
OnToggleActive?.Invoke(args.Pressed);
|
|
UpdateTheme(args.Pressed);
|
|
}
|
|
|
|
private void SetupTabs()
|
|
{
|
|
Tabs.SetTabTitle(0, Loc.GetString("modsuit-tab-modules"));
|
|
Tabs.SetTabTitle(1, Loc.GetString("modsuit-tab-parts"));
|
|
}
|
|
|
|
public void UpdateState(ModularSuitBoundUserInterfaceState state)
|
|
{
|
|
WearerNameLabel.Text = !string.IsNullOrEmpty(state.WearerName)
|
|
? state.WearerName : Loc.GetString("modsuit-ui-not-worn");
|
|
|
|
if (state.HasCore)
|
|
{
|
|
CoreChargeBar.Value = state.CoreCharge;
|
|
CoreChargeBar.MaxValue = state.MaxCoreCharge;
|
|
CoreChargeLabel.Text = $"{state.CoreCharge:F0}/{state.MaxCoreCharge:F0}";
|
|
}
|
|
else
|
|
{
|
|
CoreChargeBar.Value = 0;
|
|
CoreChargeLabel.Text = Loc.GetString("modsuit-ui-no-core");
|
|
}
|
|
|
|
var powerDrawW = state.TotalPowerDraw;
|
|
|
|
if (powerDrawW > 0 && powerDrawW < 0.01f)
|
|
PowerDrawLabel.Text = Loc.GetString("modsuit-ui-power-draw-value", ("power", "<0.01"));
|
|
else
|
|
PowerDrawLabel.Text = state.InfinityCore
|
|
? Loc.GetString("modsuit-ui-power-draw-error")
|
|
: Loc.GetString("modsuit-ui-power-draw-value", ("power", Math.Round(powerDrawW, 2)));
|
|
|
|
if (state.HasBattery && !state.InfinityCore)
|
|
{
|
|
var batteryPercent = state.BatteryCharge / state.MaxBatteryCharge * 100;
|
|
BatteryChargeBar.Value = batteryPercent;
|
|
BatteryChargeBar.MaxValue = 100;
|
|
BatteryChargeBar.Visible = true;
|
|
|
|
BatteryChargeLabel.Text = $"{state.BatteryCharge:F0}/{state.MaxBatteryCharge:F0}";
|
|
BatteryChargeLabel.Visible = true;
|
|
BatteryStatusLabel.Visible = false;
|
|
|
|
if (powerDrawW > 0)
|
|
{
|
|
var coreRemainingSec = state.CoreCharge / powerDrawW;
|
|
var batteryRemainingSec = state.BatteryCharge / powerDrawW;
|
|
var totalRemainingSec = coreRemainingSec + batteryRemainingSec;
|
|
|
|
if (totalRemainingSec < 60)
|
|
{
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-critical", ("seconds", (int)totalRemainingSec));
|
|
}
|
|
else if (totalRemainingSec < 3600)
|
|
{
|
|
var minutes = (int)(totalRemainingSec / 60);
|
|
var seconds = (int)(totalRemainingSec % 60);
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-minutes", ("minutes", minutes), ("seconds", seconds));
|
|
}
|
|
else
|
|
{
|
|
var hours = (int)(totalRemainingSec / 3600);
|
|
var minutes = (int)((totalRemainingSec % 3600) / 60);
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-hours", ("hours", hours), ("minutes", minutes));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-infinite");
|
|
}
|
|
}
|
|
else if (state.InfinityCore)
|
|
{
|
|
BatteryChargeBar.Visible = false;
|
|
BatteryChargeLabel.Visible = false;
|
|
BatteryStatusLabel.Text = Loc.GetString("modsuit-ui-infinity-core");
|
|
BatteryStatusLabel.FontColorOverride = Color.FromHex("#f04c4c");
|
|
BatteryStatusLabel.Visible = true;
|
|
|
|
PowerDrawLabel.Text = Loc.GetString("modsuit-ui-power-draw-error");
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-infinite");
|
|
}
|
|
else
|
|
{
|
|
BatteryChargeBar.Visible = false;
|
|
BatteryChargeLabel.Visible = false;
|
|
BatteryStatusLabel.Text = Loc.GetString("modsuit-ui-no-battery");
|
|
BatteryStatusLabel.FontColorOverride = Color.FromHex("#ffaa33");
|
|
BatteryStatusLabel.Visible = true;
|
|
|
|
if (powerDrawW > 0 && state.CoreCharge > 0)
|
|
{
|
|
var remainingSec = state.CoreCharge / powerDrawW;
|
|
|
|
if (remainingSec < 60)
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-critical", ("seconds", (int)remainingSec));
|
|
else if (remainingSec < 3600)
|
|
{
|
|
var minutes = (int)(remainingSec / 60);
|
|
var seconds = (int)(remainingSec % 60);
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-minutes", ("minutes", minutes), ("seconds", seconds))
|
|
+ $" {Loc.GetString("modsuit-ui-time-core")}";
|
|
}
|
|
else
|
|
{
|
|
var hours = (int)(remainingSec / 3600);
|
|
var minutes = (int)((remainingSec % 3600) / 60);
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-hours", ("hours", hours), ("minutes", minutes))
|
|
+ $" {Loc.GetString("modsuit-ui-time-core")}";
|
|
}
|
|
}
|
|
else if (state.CoreCharge <= 0)
|
|
{
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-depleted");
|
|
}
|
|
else
|
|
{
|
|
RemainingTimeLabel.Text = Loc.GetString("modsuit-ui-time-infinite");
|
|
}
|
|
}
|
|
|
|
ActivateButton.Pressed = state.Active;
|
|
ActivateButton.Text = state.Active
|
|
? Loc.GetString("modsuit-ui-deactivate")
|
|
: Loc.GetString("modsuit-ui-activate");
|
|
|
|
ActivateButton.Disabled = !state.HasCore || state.CoreCharge <= 0;
|
|
|
|
UpdateTheme(state.Active);
|
|
|
|
UpdateModules(state.Modules);
|
|
UpdateParts(state.Parts);
|
|
}
|
|
|
|
private void UpdateTheme(bool active)
|
|
{
|
|
var color = active ? Color.FromHex("#4cc9f0") : Color.FromHex("#a8a8a8");
|
|
ContentsContainer.Modulate = color.WithAlpha(0.9f);
|
|
}
|
|
|
|
private void UpdateModules(List<SuitModuleEntry> modules)
|
|
{
|
|
ModulesCountLabel.Text = modules.Count.ToString();
|
|
ModulesContainer.Children.Clear();
|
|
_moduleControls.Clear();
|
|
|
|
if (modules.Count == 0)
|
|
{
|
|
var emptyLabel = new Label
|
|
{
|
|
Text = Loc.GetString("modsuit-ui-no-modules"),
|
|
HorizontalAlignment = HAlignment.Center,
|
|
VerticalAlignment = VAlignment.Center,
|
|
FontColorOverride = Color.FromHex("#8ecae6"),
|
|
Margin = new Thickness(0, 20)
|
|
};
|
|
ModulesContainer.AddChild(emptyLabel);
|
|
return;
|
|
}
|
|
|
|
foreach (var module in modules)
|
|
{
|
|
var control = new ModuleControl(module, _entMan);
|
|
control.OnToggle += active => OnToggleModule?.Invoke(module.ModuleUid, active);
|
|
ModulesContainer.AddChild(control);
|
|
_moduleControls[module.ModuleUid] = control;
|
|
}
|
|
}
|
|
|
|
private void UpdateParts(List<SuitPartEntry> parts)
|
|
{
|
|
PartsCountLabel.Text = parts.Count.ToString();
|
|
PartsContainer.Children.Clear();
|
|
_partControls.Clear();
|
|
|
|
if (parts.Count == 0)
|
|
{
|
|
var emptyLabel = new Label
|
|
{
|
|
Text = Loc.GetString("modsuit-ui-no-parts"),
|
|
HorizontalAlignment = HAlignment.Center,
|
|
VerticalAlignment = VAlignment.Center,
|
|
FontColorOverride = Color.FromHex("#8ecae6"),
|
|
Margin = new Thickness(0, 20)
|
|
};
|
|
PartsContainer.AddChild(emptyLabel);
|
|
return;
|
|
}
|
|
|
|
foreach (var part in parts)
|
|
{
|
|
var control = new PartControl(part, _entMan);
|
|
PartsContainer.AddChild(control);
|
|
_partControls[part.PartType] = control;
|
|
}
|
|
}
|
|
|
|
protected override DragMode GetDragModeFor(Vector2 relativeMousePos) => DragMode.Move;
|
|
}
|
|
|
|
public sealed class ModuleControl : PanelContainer
|
|
{
|
|
private readonly CheckBox? _toggleButton;
|
|
public event Action<bool>? OnToggle;
|
|
|
|
public ModuleControl(SuitModuleEntry module, IEntityManager entMan)
|
|
{
|
|
HorizontalExpand = true;
|
|
MinHeight = 48;
|
|
Margin = new Thickness(0, 2);
|
|
|
|
PanelOverride = new StyleBoxFlat
|
|
{
|
|
BackgroundColor = Color.FromHex("#1e2b3c"),
|
|
BorderColor = module.IsPermanent
|
|
? Color.FromHex("#f04c4c")
|
|
: (module.IsActive || !module.CanBeDisabled
|
|
? Color.FromHex("#4cc9f0")
|
|
: Color.FromHex("#3a4a5a")),
|
|
BorderThickness = new Thickness(1),
|
|
ContentMarginBottomOverride = 4,
|
|
ContentMarginLeftOverride = 6,
|
|
ContentMarginRightOverride = 6,
|
|
ContentMarginTopOverride = 4
|
|
};
|
|
|
|
var container = new BoxContainer
|
|
{
|
|
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
|
HorizontalExpand = true,
|
|
VerticalAlignment = VAlignment.Center
|
|
};
|
|
|
|
var view = new SpriteView
|
|
{
|
|
OverrideDirection = Direction.South,
|
|
Scale = new Vector2(2, 2),
|
|
MinSize = new Vector2(32, 32),
|
|
Margin = new Thickness(0, 0, 8, 0),
|
|
VerticalAlignment = VAlignment.Center
|
|
};
|
|
view.SetEntity(entMan.GetEntity(module.ModuleUid));
|
|
container.AddChild(view);
|
|
|
|
var infoContainer = new BoxContainer
|
|
{
|
|
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
|
HorizontalExpand = true,
|
|
SeparationOverride = 2
|
|
};
|
|
|
|
var nameLabel = new Label
|
|
{
|
|
Text = $"{module.Name} #{module.ModuleId}",
|
|
FontColorOverride = module.IsActive ? Color.FromHex("#ffffff") : Color.FromHex("#a8a8a8"),
|
|
HorizontalExpand = true
|
|
};
|
|
infoContainer.AddChild(nameLabel);
|
|
|
|
var powerText = module.PowerUsage > 0
|
|
? Loc.GetString("modsuit-ui-power-usage", ("power", Math.Round(module.PowerUsage, 3)))
|
|
: Loc.GetString("modsuit-ui-no-power-usage");
|
|
|
|
if (module.PowerInstanceUsage > 0)
|
|
{
|
|
powerText += $"\n{Loc.GetString("modsuit-ui-power-instance-usage", ("power", Math.Round(module.PowerInstanceUsage, 3)))}";
|
|
}
|
|
|
|
var powerLabel = new Label
|
|
{
|
|
Text = powerText,
|
|
FontColorOverride = Color.FromHex("#aaccff"),
|
|
HorizontalExpand = true
|
|
};
|
|
powerLabel.AddStyleClass(StyleClass.LabelSubText);
|
|
infoContainer.AddChild(powerLabel);
|
|
|
|
container.AddChild(infoContainer);
|
|
|
|
if (module.CanBeDisabled)
|
|
{
|
|
_toggleButton = new CheckBox
|
|
{
|
|
Pressed = module.IsActive,
|
|
MinSize = new Vector2(40, 0),
|
|
VerticalAlignment = VAlignment.Center,
|
|
Margin = new Thickness(8, 0, 0, 0)
|
|
};
|
|
_toggleButton.OnToggled += args => OnToggle?.Invoke(args.Pressed);
|
|
container.AddChild(_toggleButton);
|
|
}
|
|
|
|
AddChild(container);
|
|
}
|
|
}
|
|
|
|
public sealed class PartControl : PanelContainer
|
|
{
|
|
public PartControl(SuitPartEntry part, IEntityManager entMan)
|
|
{
|
|
HorizontalExpand = true;
|
|
MinHeight = 48;
|
|
Margin = new Thickness(0, 2);
|
|
|
|
PanelOverride = new StyleBoxFlat
|
|
{
|
|
BackgroundColor = Color.FromHex("#1e2b3c"),
|
|
BorderColor = Color.FromHex("#ffaa33"),
|
|
BorderThickness = new Thickness(1),
|
|
ContentMarginBottomOverride = 4,
|
|
ContentMarginLeftOverride = 6,
|
|
ContentMarginRightOverride = 6,
|
|
ContentMarginTopOverride = 4
|
|
};
|
|
|
|
var container = new BoxContainer
|
|
{
|
|
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
|
HorizontalExpand = true,
|
|
VerticalAlignment = VAlignment.Center
|
|
};
|
|
|
|
var view = new SpriteView
|
|
{
|
|
OverrideDirection = Direction.South,
|
|
Scale = new Vector2(2, 2),
|
|
MinSize = new Vector2(32, 32),
|
|
Margin = new Thickness(0, 0, 8, 0),
|
|
VerticalAlignment = VAlignment.Center
|
|
};
|
|
view.SetEntity(entMan.GetEntity(part.PartUid));
|
|
container.AddChild(view);
|
|
|
|
var partName = Loc.GetString($"modsuit-part-{part.PartType.ToString().ToLower()}");
|
|
var nameLabel = new Label
|
|
{
|
|
Text = partName,
|
|
FontColorOverride = Color.FromHex("#ffffff"),
|
|
HorizontalExpand = true,
|
|
VerticalAlignment = VAlignment.Center
|
|
};
|
|
container.AddChild(nameLabel);
|
|
|
|
AddChild(container);
|
|
}
|
|
}
|