перенос файлов клиента из папки White в _White

This commit is contained in:
Remuchi
2024-01-28 17:32:55 +07:00
parent c80b10a688
commit 21dbccfec9
139 changed files with 345 additions and 434 deletions

View File

@@ -0,0 +1,63 @@
using Content.Shared.White.Medical.BodyScanner;
using JetBrains.Annotations;
namespace Content.Client._White.Medical.BodyScanner
{
[UsedImplicitly]
public sealed class BodyScannerConsoleBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private BodyScannerConsoleWindow? _window;
public BodyScannerConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new BodyScannerConsoleWindow();
_window.OnClose += Close;
_window.OpenCentered();
_window.OnScanButtonPressed += () => StartScanning();
_window.OnPrintButtonPressed += () => StartPrinting();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
switch(state)
{
case BodyScannerConsoleBoundUserInterfaceState msg:
_window?.UpdateUserInterface(msg);
break;
}
}
public void StartScanning()
{
SendMessage(new BodyScannerStartScanningMessage());
}
public void StartPrinting()
{
SendMessage(new BodyScannerStartPrintingMessage());
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
if (_window != null)
_window.OnClose -= Close;
_window?.Dispose();
}
}
}

View File

@@ -0,0 +1,165 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.Pinpointer.UI"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'body-scanner-console-window-title'}"
MinSize="830 670">
<BoxContainer Orientation="Vertical">
<BoxContainer Name="MainContainer"
Margin="4 0"
Orientation="Vertical"
Visible="False">
<BoxContainer Orientation="Vertical">
<!-- Entity name -->
<controls:StripeBack>
<Label Name="EntityNameLabel" Text="{Loc 'body-scanner-console-window-no-data'}" StyleClasses="LabelBig" Align="Center"/>
</controls:StripeBack>
<!-- Main box -->
<BoxContainer Orientation="Horizontal">
<!-- First column -->
<BoxContainer Orientation="Vertical" MinSize="300 490">
<GridContainer Columns="2">
<Label Text="{Loc 'body-scanner-console-window-current-alive-status-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="AliveStatusLabel" Text="{Loc 'body-scanner-console-window-no-data'}" Margin="4 0 0 0"/>
<Label Text="{Loc 'body-scanner-console-window-temperature-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="TemperatureLabel" Text="{Loc 'body-scanner-console-window-no-data'}" Margin="4 0 0 0"/>
<Label Text="{Loc 'body-scanner-console-window-entity-blood-level-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="BloodLevelLabel" Text="{Loc 'body-scanner-console-window-no-data'}" Margin="4 0 0 0"/>
<Label Text="{Loc 'body-scanner-console-window-entity-damage-total-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="TotalDamageLabel" Text="{Loc 'body-scanner-console-window-no-data'}" Margin="4 0 0 0"/>
</GridContainer>
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 5"/>
<GridContainer Name="DamageGroupsContainer" Columns="2"/>
</BoxContainer>
<!-- Second column -->
<customControls:VSeparator StyleClasses="LowDivider" Margin="5 0"/>
<BoxContainer Orientation="Vertical" MinSize="255 485">
<GridContainer Columns="2">
<!-- Temperature -->
<BoxContainer Orientation="Vertical" Margin="4 0 4 4">
<Label Text="{Loc 'body-scanner-console-window-temperature-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="CurrentTemperature"/>
<Label Name="HeatDamageThreshold"/>
<Label Name="ColdDamageThreshold"/>
</BoxContainer>
<!-- Saturation -->
<BoxContainer Orientation="Vertical" Margin="4 0 4 4">
<Label Text="{Loc 'body-scanner-console-window-saturation-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="CurrentSaturation"/>
<Label Name="MinimumSaturation"/>
<Label Name="MaximumSaturation"/>
</BoxContainer>
<!-- Thirst -->
<BoxContainer Orientation="Vertical" Margin="4">
<Label Text="{Loc 'body-scanner-console-window-thirst-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="CurrentThirst"/>
<Label Name="CurrentThirstStatus"/>
<Label Name="CurrentThirstThreshold"/>
</BoxContainer>
<!-- Hunger -->
<BoxContainer Orientation="Vertical" Margin="4">
<Label Text="{Loc 'body-scanner-console-window-hunger-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="CurrentHunger"/>
<Label Name="CurrentHungerStatus"/>
<Label Name="CurrentHungerThreshold"/>
</BoxContainer>
</GridContainer>
<!-- Blood solution-->
<BoxContainer Orientation="Vertical" Margin="4">
<Label Text="{Loc 'body-scanner-console-window-blood-solutions-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="BloodSolutionVolume"/>
<PanelContainer VerticalExpand="True" MinSize="0 100">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
</PanelContainer.PanelOverride>
<ScrollContainer HorizontalExpand="True" MinSize="0 100">
<BoxContainer Name="BloodSolutionElements" Orientation="Vertical" Margin="4" HorizontalExpand="True"/>
</ScrollContainer>
</PanelContainer>
</BoxContainer>
<!-- Chemical solution-->
<BoxContainer Orientation="Vertical" Margin="4">
<Label Text="{Loc 'body-scanner-console-window-chemical-solutions-group-text'}" StyleClasses="StatusFieldTitle"/>
<Label Name="ChemicalSolutionVolume"/>
<PanelContainer VerticalExpand="True" MinSize="0 100">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
</PanelContainer.PanelOverride>
<ScrollContainer HorizontalExpand="True" MinSize="0 100">
<BoxContainer Name="ChemicalSolutionElements" Orientation="Vertical" Margin="4" HorizontalExpand="True"/>
</ScrollContainer>
</PanelContainer>
</BoxContainer>
</BoxContainer>
<!-- Third column -->
<customControls:VSeparator StyleClasses="LowDivider" Margin="5 0"/>
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<ProgressBar Name="HealthBar" HorizontalAlignment="Center" VerticalAlignment="Center" MinValue="0" MaxValue="1" MinSize="200 20" Margin="10"/>
<PanelContainer Margin="10 0 0 0" StyleClasses="Inset" VerticalAlignment="Center" >
<SpriteView Name="EntityView" OverrideDirection="South" Scale="8 8" />
</PanelContainer>
</BoxContainer>
</BoxContainer>
<!-- Main panel bottom row -->
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 5"/>
<BoxContainer Orientation="Horizontal">
<Label Name="Mind" Margin="5 0 0 0"/>
<customControls:VSeparator StyleClasses="LowDivider" Margin="10 0"/>
<Label Name="DNA"/>
<customControls:VSeparator StyleClasses="LowDivider" Margin="10 0"/>
<Label Name="Fingerprint"/>
</BoxContainer>
</BoxContainer>
<!-- Bottom row -->
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 5"/>
<BoxContainer Orientation="Horizontal">
<Button Name="PrintButton" TextAlign="Center" MinSize="150 25" Margin="0 0 10 5" Text="{Loc 'body-scanner-console-window-print-button'}"/>
<Button Name="ScanButton" TextAlign="Center" MinSize="150 25" Margin="0 0 10 5" Text="{Loc 'body-scanner-console-window-scan-button'}"/>
<Label Name="StatusText"/>
</BoxContainer>
</BoxContainer>
<BoxContainer Name="NoDataContainer"
VerticalExpand="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="4 0"
Orientation="Vertical">
<TextureRect Stretch="KeepAspectCentered"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TexturePath="/Textures/White/Interface/BodyScanner/body_scanner_logo.svg.160dpi.png"
Margin="10"/>
<ProgressBar Name="NoDataScanProgressBar"
HorizontalAlignment="Center"
MinValue="0" MaxValue="1"
MinSize="400 75"
Margin="10"/>
<Button Name="NoDataScanButton"
HorizontalAlignment="Center"
TextAlign="Center"
MinSize="250 50"
Margin="10"
Text="{Loc 'body-scanner-console-window-scan-button'}"/>
<Label Name="NoDataStatusLabel"
Text=" "
HorizontalAlignment="Center"
StyleClasses="LabelBig"
Margin="10"/>
</BoxContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical" VerticalAlignment="Bottom">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'body-scanner-console-window-flavor-bottom-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'body-scanner-console-window-flavor-bottom-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>
</controls:FancyWindow>

View File

@@ -0,0 +1,169 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.White.Medical.BodyScanner;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client._White.Medical.BodyScanner
{
[GenerateTypedNameReferences]
public sealed partial class BodyScannerConsoleWindow : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public event Action? OnScanButtonPressed;
public event Action? OnPrintButtonPressed;
public BodyScannerConsoleWindow()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
ScanButton.OnPressed += _ => OnScanButtonPressed?.Invoke();
NoDataScanButton.OnPressed += _ => OnScanButtonPressed?.Invoke();
PrintButton.OnPressed += _ => OnPrintButtonPressed?.Invoke();
}
public void UpdateUserInterface(BodyScannerConsoleBoundUserInterfaceState state)
{
MainContainer.Visible = state.TargetEntityUid != null && !state.Scanning;
NoDataContainer.Visible = !MainContainer.Visible;
NoDataStatusLabel.Text = state.Scanning ? Loc.GetString("body-scanner-console-window-status-scanning") : " ";
ScanButton.Disabled = !state.CanScan;
PrintButton.Disabled = !state.CanPrint;
NoDataScanButton.Disabled = !state.CanScan;
NoDataScanProgressBar.Value = 1 - (float) (state.ScanTimeRemaining / state.ScanTotalTime);
if (state.Scanning)
return;
EntityNameLabel.Text = state.EntityName;
// First column
TemperatureLabel.Text = $"{state.CurrentTemperature - 273f:F1} \u00B0C";
BloodLevelLabel.Text = $"{state.BloodSolution.FillFraction * 100:F1} %";
TotalDamageLabel.Text = state.TotalDamage.ToString();
AliveStatusLabel.Text = state.CurrentState switch
{
Shared.Mobs.MobState.Alive => Loc.GetString("body-scanner-console-window-current-alive-status-alive-text"),
Shared.Mobs.MobState.Critical => Loc.GetString("body-scanner-console-window-current-alive-status-critical-text"),
Shared.Mobs.MobState.Dead => Loc.GetString("body-scanner-console-window-current-alive-status-dead-text"),
_ => Loc.GetString("body-scanner-console-window-no-data")
};
HashSet<string> shownTypes = new();
var protos = IoCManager.Resolve<IPrototypeManager>();
IReadOnlyDictionary<string, FixedPoint2> damagePerGroup = state.DamagePerGroup;
IReadOnlyDictionary<string, FixedPoint2> damagePerType = state.DamageDict;
DamageGroupsContainer.RemoveAllChildren();
// Show the total damage and type breakdown for each damage group.
foreach (var (damageGroupId, damageAmount) in damagePerGroup)
{
var damageGroupTitle = Loc.GetString("health-analyzer-window-damage-group-" + damageGroupId, ("amount", damageAmount));
DamageGroupsContainer.AddChild(new GroupDamageCardComponent(damageGroupTitle, damageGroupId, damagePerType));
}
// Second column.
CurrentTemperature.Text = Loc.GetString("body-scanner-console-window-temperature-current-temperature-text",
("amount", $"{state.CurrentTemperature - 273:f1}"));
HeatDamageThreshold.Text = Loc.GetString("body-scanner-console-window-temperature-heat-damage-threshold-temperature-text",
("amount", $"{state.HeatDamageThreshold - 273:f1}"));
ColdDamageThreshold.Text = Loc.GetString("body-scanner-console-window-temperature-cold-damage-threshold-temperature-text",
("amount", $"{state.ColdDamageThreshold - 273:f1}"));
CurrentSaturation.Text = Loc.GetString("body-scanner-console-window-saturation-current-saturation-text",
("amount", $"{state.Saturation:f1}"));
MinimumSaturation.Text = Loc.GetString("body-scanner-console-window-saturation-maximum-saturation-text",
("amount", $"{state.MinSaturation:f1}"));
MaximumSaturation.Text = Loc.GetString("body-scanner-console-window-saturation-minimum-saturation-text",
("amount", $"{state.MaxSaturation:f1}"));
CurrentThirst.Text = Loc.GetString("body-scanner-console-window-thirst-current-thirst-text",
("amount", $"{state.CurrentThirst:f1}"));
CurrentThirstStatus.Text = Loc.GetString("body-scanner-console-window-thirst-current-thirst-status-text",
("status", Loc.GetString("body-scanner-console-window-hunger-current-hunger-status-" + state.CurrentThirstThreshold)));
CurrentHunger.Text = Loc.GetString("body-scanner-console-window-hunger-current-hunger-text",
("amount", $"{state.CurrentHunger:f1}"));
CurrentHungerStatus.Text = Loc.GetString("body-scanner-console-window-hunger-current-hunger-status-text",
("status", Loc.GetString("body-scanner-console-window-thirst-current-thirst-status-" + state.CurrentHungerThreshold)));
BloodSolutionVolume.Text = Loc.GetString("body-scanner-console-window-blood-solutions-volume-group-text",
("amount", $"{state.BloodSolution.Volume.Float():f1}"),
("maxAmount", $"{state.BloodSolution.MaxVolume.Float():f1}"),
("temperature", $"{state.BloodSolution.Temperature - 271:f1}"));
BloodSolutionElements.RemoveAllChildren();
state.BloodSolution.Contents.ForEach(x =>
{
_prototypeManager.TryIndex(x.Reagent.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
BloodSolutionElements.AddChild(new Label() { Text = $"{name}: {x.Quantity}", FontColorOverride = Color.LightGray });
});
ChemicalSolutionVolume.Text = Loc.GetString("body-scanner-console-window-chemical-solutions-volume-group-text",
("amount", $"{state.ChemicalSolution.Volume.Float():f1}"),
("maxAmount", $"{state.ChemicalSolution.MaxVolume.Float():f1}"),
("temperature", $"{state.ChemicalSolution.Temperature - 271:f1}"));
ChemicalSolutionElements.RemoveAllChildren();
state.ChemicalSolution.Contents.ForEach(x =>
{
_prototypeManager.TryIndex(x.Reagent.Prototype, out ReagentPrototype? proto);
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
ChemicalSolutionElements.AddChild(new Label() { Text = $"{name}: {x.Quantity}", FontColorOverride = Color.LightGray });
});
// Third column.
HealthBar.Value = 1 - (state.TotalDamage / state.DeadThreshold).Float();
HealthBar.ForegroundStyleBoxOverride = new StyleBoxFlat()
{
BackgroundColor = HealthBar.Value >= 0.5f ?
GetColorLerp(Color.Yellow, Color.Green, (HealthBar.Value - 0.5f) * 2) :
GetColorLerp(Color.Red, Color.Yellow, HealthBar.Value * 2)
};
if (state.TargetEntityUid != null)
EntityView.SetEntity(state.TargetEntityUid.Value);
// Bottom row.
Mind.Text = Loc.GetString("body-scanner-console-window-mind-text",
("value", state.HasMind ? Loc.GetString("body-scanner-console-window-mind-present-text") :
Loc.GetString("body-scanner-console-window-mind-absent-text")));
DNA.Text = Loc.GetString("body-scanner-console-window-dna-text",
("value", $"{state.DNA}"));
Fingerprint.Text = Loc.GetString("body-scanner-console-window-fingerprint-text",
("value", $"{state.Fingerprint}"));
}
/// <summary>
/// Smooth transition from one color to another depending on the percentage.
/// </summary>
/// <param name="startColor"></param>
/// <param name="endColor"></param>
/// <param name="percentage"></param>
/// <returns></returns>
private Color GetColorLerp(Color startColor, Color endColor, float percentage)
{
var r = MathHelper.Lerp(startColor.R, endColor.R, percentage);
var g = MathHelper.Lerp(startColor.G, endColor.G, percentage);
var b = MathHelper.Lerp(startColor.B, endColor.B, percentage);
var a = MathHelper.Lerp(startColor.A, endColor.A, percentage);
return new Color(r, g, b, a);
}
}
}

View File

@@ -0,0 +1,14 @@
<Control xmlns="https://spacestation14.io"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
<PanelContainer MinSize="120 100" Margin="1">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BorderColor="#777777" BorderThickness="1"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical">
<Label Name="DamageGroupTitle" Align="Center" Margin="5" StyleClasses="StatusFieldTitle"/>
<customControls:HSeparator Margin="5 0"/>
<BoxContainer Name="DamageLabelsContainer" Orientation="Vertical" Margin="5"/>
</BoxContainer>
</PanelContainer>
</Control>

View File

@@ -0,0 +1,102 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client._White.Medical.BodyScanner
{
[GenerateTypedNameReferences]
public sealed partial class GroupDamageCardComponent : Control
{
public GroupDamageCardComponent(string title, string damageGroupID, IReadOnlyDictionary<string, FixedPoint2> damagePerType)
{
RobustXamlLoader.Load(this);
DamageGroupTitle.Text = title;
HashSet<string> shownTypes = new();
var protos = IoCManager.Resolve<IPrototypeManager>();
var group = protos.Index<DamageGroupPrototype>(damageGroupID);
// Show the damage for each type in that group.
foreach (var type in group.DamageTypes)
{
if (damagePerType.TryGetValue(type, out var typeAmount))
{
// If damage types are allowed to belong to more than one damage group, they may appear twice here. Mark them as duplicate.
if (!shownTypes.Contains(type))
{
shownTypes.Add(type);
Label damagePerTypeLabel = new()
{
Text = Loc.GetString("health-analyzer-window-damage-type-" + type, ("amount", typeAmount)),
};
SetColorLabel(damagePerTypeLabel, typeAmount.Float());
DamageLabelsContainer.AddChild(damagePerTypeLabel);
}
}
}
}
/// <summary>
/// Sets the color of a label depending on the damage.
/// </summary>
/// <param name="label"></param>
/// <param name="damage"></param>
private void SetColorLabel(Label label, float damage)
{
var startColor = Color.White;
var critColor = Color.Yellow;
var endColor = Color.Red;
var startDamage = 0f;
var critDamage = 30f;
var endDamage = 100f;
if (damage <= startDamage)
{
label.FontColorOverride = startColor;
}
else if (damage >= endDamage)
{
label.FontColorOverride = endColor;
}
else if (damage >= startDamage && damage <= critDamage)
{
// We need a number from 0 to 100.
damage *= 100f / (critDamage - startDamage);
label.FontColorOverride = GetColorLerp(startColor, critColor, damage);
}
else if (damage >= critDamage && damage <= endDamage)
{
// We need a number from 0 to 100.
damage *= 100f / (endDamage - critDamage);
label.FontColorOverride = GetColorLerp(critColor, endColor, damage);
}
}
/// <summary>
/// Smooth transition from one color to another depending on the percentage.
/// </summary>
/// <param name="startColor"></param>
/// <param name="endColor"></param>
/// <param name="percentage"></param>
/// <returns></returns>
private Color GetColorLerp(Color startColor, Color endColor, float percentage)
{
var t = percentage / 100f;
var r = MathHelper.Lerp(startColor.R, endColor.R, t);
var g = MathHelper.Lerp(startColor.G, endColor.G, t);
var b = MathHelper.Lerp(startColor.B, endColor.B, t);
var a = MathHelper.Lerp(startColor.A, endColor.A, t);
return new Color(r, g, b, a);
}
}
}