Compare commits

..

1 Commits

Author SHA1 Message Date
Ed
73d0ee0ea1 some shitcode 2024-06-27 19:09:50 +03:00
2935 changed files with 89949 additions and 227935 deletions

View File

@@ -129,7 +129,7 @@ csharp_indent_braces = false
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_cast = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false

7
.github/CODEOWNERS vendored
View File

@@ -55,10 +55,3 @@
#Jezi
/Content.*/Medical @Jezithyr
/Content.*/Body @Jezithyr
# Sloth
/Content.*/Audio @metalgearsloth
/Content.*/Movement @metalgearsloth
/Content.*/NPC @metalgearsloth
/Content.*/Shuttles @metalgearsloth
/Content.*/Weapons @metalgearsloth

View File

@@ -7,11 +7,11 @@
<!-- Зачем нужно это изменение? Прикрепите любые обсуждения или проблемы здесь. Опишите, как это повлияет на текущий баланс игры. -->
## Media
<!--
<!--
PRs which make ingame changes (adding clothing, items, new features, etc) are required to have media attached that showcase the changes.
Small fixes/refactors are exempt.
-->
<!--
<!--
Пулл реквесты, которые несут за собой игровые изменения (добавления одежды, предметов и так далее) требуют чтобы вы прикрепили скриншоты или видеоролики, демонстрирующие эти изменения.
Небольшие исправления не считаются.
-->

8
.github/labeler.yml vendored
View File

@@ -5,17 +5,13 @@
"Changes: Map":
- changed-files:
- any-glob-to-any-file:
- 'Resources/Maps/**/*.yml'
- 'Resources/Prototypes/Maps/**/*.yml'
- 'Resources/Maps/*.yml'
- 'Resources/Prototypes/Maps/*.yml'
"Changes: UI":
- changed-files:
- any-glob-to-any-file: '**/*.xaml*'
"Changes: Shaders":
- changed-files:
- any-glob-to-any-file: '**/*.swsl'
"No C#":
- changed-files:
# Equiv to any-glob-to-all as long as this has one matcher. If ALL changed files are not C# files, then apply label.

View File

@@ -9,6 +9,5 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions-ecosystem/action-add-labels@v1
if: join(github.event.issue.labels) == ''
with:
labels: "Status: Untriaged"

View File

@@ -41,22 +41,31 @@ jobs:
- name: Package client
run: dotnet run --project Content.Packaging client --no-wipe-release
- name: Upload build artifact
id: artifact-upload-step
uses: actions/upload-artifact@v4
with:
name: build
path: release/*.zip
compression-level: 0
retention-days: 0
- name: Update Build Info
run: Tools/gen_build_info.py
- name: Publish version
run: Tools/publish_github_artifact.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
ARTIFACT_ID: ${{ steps.artifact-upload-step.outputs.artifact-id }}
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}
- name: Shuffle files around
run: |
mkdir "release/${{ github.sha }}"
mv release/*.zip "release/${{ github.sha }}"
- name: Upload files to centcomm
uses: appleboy/scp-action@master
with:
host: centcomm.spacestation14.io
username: wizards-build-push
key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }}
source: "release/${{ github.sha }}"
target: "/home/wizards-build-push/builds_dir/builds/"
strip_components: 1
- name: Update manifest JSON
uses: appleboy/ssh-action@master
with:
host: centcomm.spacestation14.io
username: wizards-build-push
key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }}
script: /home/wizards-build-push/push.ps1 ${{ github.sha }}
- name: Publish changelog (Discord)
run: Tools/actions_changelogs_since_last_run.py
@@ -68,8 +77,3 @@ jobs:
run: Tools/actions_changelog_rss.py
env:
CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }}
- uses: geekyeggo/delete-artifact@v5
if: always()
with:
name: build

View File

@@ -64,3 +64,11 @@ jobs:
- name: Package client
run: dotnet run --project Content.Packaging client --no-wipe-release
- name: Update Build Info
run: Tools/gen_build_info.py
- name: Shuffle files around
run: |
mkdir "release/${{ github.sha }}"
mv release/*.zip "release/${{ github.sha }}"

1
.gitignore vendored
View File

@@ -306,4 +306,3 @@ Resources/MapImages
# Direnv stuff
.direnv/
/Tools/_CP14/LocalizationHelper/last_launch

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"omnisharp.analyzeOpenDocumentsOnly": true,
"dotnet.defaultSolution": "SpaceStation14.sln"
}

View File

@@ -12,18 +12,11 @@ namespace Content.Client.Access.UI;
[GenerateTypedNameReferences]
public sealed partial class AccessLevelControl : GridContainer
{
[Dependency] private readonly ILogManager _logManager = default!;
private ISawmill _sawmill = default!;
public readonly Dictionary<ProtoId<AccessLevelPrototype>, Button> ButtonsList = new();
public AccessLevelControl()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_sawmill = _logManager.GetSawmill("accesslevelcontrol");
}
public void Populate(List<ProtoId<AccessLevelPrototype>> accessLevels, IPrototypeManager prototypeManager)
@@ -32,7 +25,7 @@ public sealed partial class AccessLevelControl : GridContainer
{
if (!prototypeManager.TryIndex(access, out var accessLevel))
{
_sawmill.Error($"Unable to find accesslevel for {access}");
Logger.Error($"Unable to find accesslevel for {access}");
continue;
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Access;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.Containers.ItemSlots;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
using static Content.Shared.Access.Components.AccessOverriderComponent;
@@ -24,28 +23,6 @@ namespace Content.Client.Access.UI
{
base.Open();
_window = this.CreateWindow<AccessOverriderWindow>();
RefreshAccess();
_window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
_window.OnSubmit += SubmitData;
_window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId));
}
public override void OnProtoReload(PrototypesReloadedEventArgs args)
{
base.OnProtoReload(args);
if (!args.WasModified<AccessLevelPrototype>())
return;
RefreshAccess();
if (State != null)
_window?.UpdateState(_prototypeManager, (AccessOverriderBoundUserInterfaceState) State);
}
private void RefreshAccess()
{
List<ProtoId<AccessLevelPrototype>> accessLevels;
if (EntMan.TryGetComponent<AccessOverriderComponent>(Owner, out var accessOverrider))
@@ -53,20 +30,38 @@ namespace Content.Client.Access.UI
accessLevels = accessOverrider.AccessLevels;
accessLevels.Sort();
}
else
{
accessLevels = new List<ProtoId<AccessLevelPrototype>>();
_accessOverriderSystem.Log.Error($"No AccessOverrider component found for {EntMan.ToPrettyString(Owner)}!");
}
_window?.SetAccessLevels(_prototypeManager, accessLevels);
_window = new AccessOverriderWindow(this, _prototypeManager, accessLevels)
{
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName
};
_window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId));
_window.OnClose += Close;
_window.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_window?.Dispose();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
var castState = (AccessOverriderBoundUserInterfaceState) state;
_window?.UpdateState(_prototypeManager, castState);
_window?.UpdateState(castState);
}
public void SubmitData(List<ProtoId<AccessLevelPrototype>> newAccessList)

View File

@@ -13,24 +13,26 @@ namespace Content.Client.Access.UI
[GenerateTypedNameReferences]
public sealed partial class AccessOverriderWindow : DefaultWindow
{
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly AccessOverriderBoundUserInterface _owner;
private readonly Dictionary<string, Button> _accessButtons = new();
public event Action<List<ProtoId<AccessLevelPrototype>>>? OnSubmit;
public AccessOverriderWindow()
public AccessOverriderWindow(AccessOverriderBoundUserInterface owner, IPrototypeManager prototypeManager,
List<ProtoId<AccessLevelPrototype>> accessLevels)
{
RobustXamlLoader.Load(this);
}
IoCManager.InjectDependencies(this);
var logMill = _logManager.GetSawmill(SharedAccessOverriderSystem.Sawmill);
public void SetAccessLevels(IPrototypeManager protoManager, List<ProtoId<AccessLevelPrototype>> accessLevels)
{
_accessButtons.Clear();
AccessLevelGrid.DisposeAllChildren();
_owner = owner;
foreach (var access in accessLevels)
{
if (!protoManager.TryIndex(access, out var accessLevel))
if (!prototypeManager.TryIndex(access, out var accessLevel))
{
logMill.Error($"Unable to find accesslevel for {access}");
continue;
}
@@ -42,16 +44,11 @@ namespace Content.Client.Access.UI
AccessLevelGrid.AddChild(newButton);
_accessButtons.Add(accessLevel.ID, newButton);
newButton.OnPressed += _ =>
{
OnSubmit?.Invoke(
// Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
_accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId<AccessLevelPrototype>(x.Key)).ToList());
};
newButton.OnPressed += _ => SubmitData();
}
}
public void UpdateState(IPrototypeManager protoManager, AccessOverriderBoundUserInterfaceState state)
public void UpdateState(AccessOverriderBoundUserInterfaceState state)
{
PrivilegedIdLabel.Text = state.PrivilegedIdName;
PrivilegedIdButton.Text = state.IsPrivilegedIdPresent
@@ -69,11 +66,11 @@ namespace Content.Client.Access.UI
if (state.MissingPrivilegesList != null && state.MissingPrivilegesList.Any())
{
var missingPrivileges = new List<string>();
List<string> missingPrivileges = new List<string>();
foreach (string tag in state.MissingPrivilegesList)
{
var privilege = Loc.GetString(protoManager.Index<AccessLevelPrototype>(tag)?.Name ?? "generic-unknown");
string privilege = Loc.GetString(_prototypeManager.Index<AccessLevelPrototype>(tag)?.Name ?? "generic-unknown");
missingPrivileges.Add(privilege);
}
@@ -93,5 +90,13 @@ namespace Content.Client.Access.UI
}
}
}
private void SubmitData()
{
_owner.SubmitData(
// Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
_accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId<AccessLevelPrototype>(x.Key)).ToList());
}
}
}

View File

@@ -1,7 +1,6 @@
using Content.Shared.Access.Systems;
using Content.Shared.StatusIcon;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
namespace Content.Client.Access.UI
@@ -21,11 +20,16 @@ namespace Content.Client.Access.UI
{
base.Open();
_window = this.CreateWindow<AgentIDCardWindow>();
_window?.Dispose();
_window = new AgentIDCardWindow(this);
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.OnNameChanged += OnNameChanged;
_window.OnJobChanged += OnJobChanged;
_window.OnJobIconChanged += OnJobIconChanged;
}
private void OnNameChanged(string newName)
@@ -57,5 +61,14 @@ namespace Content.Client.Access.UI
_window.SetCurrentJob(cast.CurrentJob);
_window.SetAllowedIcons(cast.Icons, cast.CurrentJobIconId);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_window?.Dispose();
}
}
}

View File

@@ -17,19 +17,19 @@ namespace Content.Client.Access.UI
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
private readonly SpriteSystem _spriteSystem;
private readonly AgentIDCardBoundUserInterface _bui;
private const int JobIconColumnCount = 10;
public event Action<string>? OnNameChanged;
public event Action<string>? OnJobChanged;
public event Action<ProtoId<StatusIconPrototype>>? OnJobIconChanged;
public AgentIDCardWindow()
public AgentIDCardWindow(AgentIDCardBoundUserInterface bui)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
_bui = bui;
NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text);
NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text);
@@ -67,7 +67,7 @@ namespace Content.Client.Access.UI
};
// Generate buttons textures
var jobIconTexture = new TextureRect
TextureRect jobIconTexture = new TextureRect
{
Texture = _spriteSystem.Frame0(jobIcon.Icon),
TextureScale = new Vector2(2.5f, 2.5f),
@@ -75,7 +75,7 @@ namespace Content.Client.Access.UI
};
jobIconButton.AddChild(jobIconTexture);
jobIconButton.OnPressed += _ => OnJobIconChanged?.Invoke(jobIcon.ID);
jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId);
IconGrid.AddChild(jobIconButton);
if (jobIconId.Equals(currentJobIconId))

View File

@@ -107,7 +107,7 @@ namespace Content.Client.Actions
UpdateAction(uid, component);
}
public override void UpdateAction(EntityUid? actionId, BaseActionComponent? action = null)
protected override void UpdateAction(EntityUid? actionId, BaseActionComponent? action = null)
{
if (!ResolveActionData(actionId, ref action))
return;

View File

@@ -1,4 +1,4 @@
using Content.Client.Stylesheets;
using Content.Client.Stylesheets;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -77,12 +77,9 @@ namespace Content.Client.Actions.UI
MaxWidth = TooltipTextMaxWidth,
StyleClasses = {StyleNano.StyleClassTooltipActionRequirements}
};
if (!FormattedMessage.TryFromMarkup("[color=#635c5c]" + requires + "[/color]", out var markup))
return;
requiresLabel.SetMessage(markup);
requiresLabel.SetMessage(FormattedMessage.FromMarkup("[color=#635c5c]" +
requires +
"[/color]"));
vbox.AddChild(requiresLabel);
}
}
@@ -100,11 +97,8 @@ namespace Content.Client.Actions.UI
if (timeLeft > TimeSpan.Zero)
{
var duration = Cooldown.Value.End - Cooldown.Value.Start;
if (!FormattedMessage.TryFromMarkup($"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]", out var markup))
return;
_cooldownLabel.SetMessage(markup);
_cooldownLabel.SetMessage(FormattedMessage.FromMarkup(
$"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]"));
_cooldownLabel.Visible = true;
}
else

View File

@@ -3,57 +3,38 @@ using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI;
[GenerateTypedNameReferences]
public sealed partial class AdminMenuWindow : DefaultWindow
namespace Content.Client.Administration.UI
{
public event Action? OnDisposed;
public AdminMenuWindow()
[GenerateTypedNameReferences]
public sealed partial class AdminMenuWindow : DefaultWindow
{
MinSize = new Vector2(650, 250);
Title = Loc.GetString("admin-menu-title");
RobustXamlLoader.Load(this);
MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Adminbus, Loc.GetString("admin-menu-adminbus-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Atmos, Loc.GetString("admin-menu-atmos-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Round, Loc.GetString("admin-menu-round-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Server, Loc.GetString("admin-menu-server-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.PanicBunker, Loc.GetString("admin-menu-panic-bunker-tab"));
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
MasterTabContainer.SetTabTitle((int) TabIndex.BabyJail, Loc.GetString("admin-menu-baby-jail-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Players, Loc.GetString("admin-menu-players-tab"));
MasterTabContainer.SetTabTitle((int) TabIndex.Objects, Loc.GetString("admin-menu-objects-tab"));
MasterTabContainer.OnTabChanged += OnTabChanged;
}
public event Action? OnDisposed;
private void OnTabChanged(int tabIndex)
{
var tabEnum = (TabIndex)tabIndex;
if (tabEnum == TabIndex.Objects)
ObjectsTabControl.RefreshObjectList();
}
public AdminMenuWindow()
{
MinSize = new Vector2(650, 250);
Title = Loc.GetString("admin-menu-title");
RobustXamlLoader.Load(this);
MasterTabContainer.SetTabTitle(0, Loc.GetString("admin-menu-admin-tab"));
MasterTabContainer.SetTabTitle(1, Loc.GetString("admin-menu-adminbus-tab"));
MasterTabContainer.SetTabTitle(2, Loc.GetString("admin-menu-atmos-tab"));
MasterTabContainer.SetTabTitle(3, Loc.GetString("admin-menu-round-tab"));
MasterTabContainer.SetTabTitle(4, Loc.GetString("admin-menu-server-tab"));
MasterTabContainer.SetTabTitle(5, Loc.GetString("admin-menu-panic-bunker-tab"));
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
MasterTabContainer.SetTabTitle(6, Loc.GetString("admin-menu-baby-jail-tab"));
MasterTabContainer.SetTabTitle(7, Loc.GetString("admin-menu-players-tab"));
MasterTabContainer.SetTabTitle(8, Loc.GetString("admin-menu-objects-tab"));
}
protected override void Dispose(bool disposing)
{
OnDisposed?.Invoke();
base.Dispose(disposing);
OnDisposed = null;
}
private enum TabIndex
{
Admin = 0,
Adminbus,
Atmos,
Round,
Server,
PanicBunker,
BabyJail,
Players,
Objects,
protected override void Dispose(bool disposing)
{
OnDisposed?.Invoke();
base.Dispose(disposing);
OnDisposed = null;
}
}
}

View File

@@ -5,7 +5,7 @@
<LineEdit Name="FilterLineEdit"
MinSize="100 0"
HorizontalExpand="True"
PlaceHolder="{Loc player-list-filter}"/>
PlaceHolder="{Loc Filter}"/>
<PanelContainer Name="BackgroundPanel"
VerticalExpand="True"
HorizontalExpand="True">

View File

@@ -1,10 +1,10 @@
<Popup xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
<PanelContainer>
<PanelContainer StyleClasses="BackgroundDark">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BorderThickness="2" BorderColor="#18181B" BackgroundColor="#25252a"/>
<gfx:StyleBoxFlat BorderThickness="1" BorderColor="#18181B"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical" Margin="4 4 4 4">
<BoxContainer Orientation="Vertical">
<Label Name="PlayerNameLabel"/>
<Label Name="IdLabel"/>
<Label Name="TypeLabel"/>

View File

@@ -4,7 +4,7 @@
Title="{Loc admin-player-actions-window-title}" MinSize="425 272">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-player-actions-reason}" MinWidth="100" />
<Label Text="{Loc Reason}" MinWidth="100" />
<Control MinWidth="50" />
<LineEdit Name="ReasonLine" MinWidth="100" HorizontalExpand="True" />
</BoxContainer>

View File

@@ -1,9 +1,9 @@
<DefaultWindow
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc admin-ui-teleport}" MinSize="425 230">
Title="{Loc Teleport}" MinSize="425 230">
<BoxContainer Orientation="Vertical">
<cc:PlayerListControl Name="PlayerList" />
<Button Name="SubmitButton" Text="{Loc admin-ui-teleport}" />
<Button Name="SubmitButton" Text="{Loc Teleport}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -1,33 +1,33 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc admin-ui-blueprint-load}">
xmlns="https://spacestation14.io" Title="{Loc Load Blueprint}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-blueprint-map}" MinSize="100 0" />
<Label Text="{Loc Map}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="MapOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-blueprint-path}" MinSize="100 0" />
<Label Text="{Loc Path}" MinSize="100 0" />
<Control MinSize="50 0" />
<LineEdit Name="MapPath" MinSize="200 0" HorizontalExpand="True" Text="/Maps/" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-blueprint-x}" MinSize="100 0" />
<Label Text="{Loc X}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="XCoordinate" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-blueprint-y}" MinSize="100 0" />
<Label Text="{Loc Y}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="YCoordinate" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-blueprint-rotation}" MinSize="100 0" />
<Label Text="{Loc Rotation}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="RotationSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc admin-ui-blueprint-load}" />
<Button Name="TeleportButton" Text="{Loc admin-ui-blueprint-teleport}" />
<Button Name="ResetButton" Text="{Loc admin-ui-blueprint-reset}"></Button>
<Button Name="SubmitButton" Text="{Loc Load Blueprint}" />
<Button Name="TeleportButton" Text="{Loc Teleport to}" />
<Button Name="ResetButton" Text="{Loc Reset to default}"></Button>
</BoxContainer>
</DefaultWindow>

View File

@@ -1,11 +1,11 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-add}">
xmlns="https://spacestation14.io" Title="{Loc Add Atmos}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-add}" />
<Button Name="SubmitButton" Text="{Loc Add Atmos}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -35,7 +35,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
while (query.MoveNext(out var uid, out var grid))
{
_data.Add((uid, grid));
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
}
GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id);

View File

@@ -1,31 +1,31 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-add-gas}">
xmlns="https://spacestation14.io" Title="{Loc Add Gas}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-tile-x}" MinSize="100 0" />
<Label Text="{Loc TileX}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-tile-y}" MinSize="100 0" />
<Label Text="{Loc TileY}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-gas}" MinSize="100 0" />
<Label Text="{Loc Gas}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-gas-amount}" MinSize="100 0" />
<Label Text="{Loc Amount}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-add-gas}" />
<Button Name="SubmitButton" Text="{Loc Add Gas}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -33,7 +33,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
_gridData.Add(entManager.GetNetEntity(uid));
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString("admin-ui-atmos-grid-current") : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
}
GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id);

View File

@@ -6,10 +6,10 @@
Margin="4"
MinSize="50 50">
<GridContainer Columns="4">
<cc:UICommandButton Text="{Loc admin-ui-atmos-add}" Command="addatmos" WindowType="{x:Type at:AddAtmosWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-add-gas}" Command="addgas" WindowType="{x:Type at:AddGasWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-fill-gas}" Command="fillgas" WindowType="{x:Type at:FillGasWindow}" />
<cc:UICommandButton Text="{Loc admin-ui-atmos-set-temperature}" Command="settemp"
<cc:UICommandButton Text="{Loc Add Atmos}" Command="addatmos" WindowType="{x:Type at:AddAtmosWindow}" />
<cc:UICommandButton Text="{Loc Add Gas}" Command="addgas" WindowType="{x:Type at:AddGasWindow}" />
<cc:UICommandButton Text="{Loc Fill Gas}" Command="fillgas" WindowType="{x:Type at:FillGasWindow}" />
<cc:UICommandButton Text="{Loc Set Temperature}" Command="settemp"
WindowType="{x:Type at:SetTemperatureWindow}" />
</GridContainer>
</Control>

View File

@@ -1,21 +1,21 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-fill-gas}">
xmlns="https://spacestation14.io" Title="{Loc Fill Gas}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-gas}" MinSize="100 0" />
<Label Text="{Loc Gas}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GasOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-gas-amount}" MinSize="100 0" />
<Label Text="{Loc Amount}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="AmountSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-fill-gas}" />
<Button Name="SubmitButton" Text="{Loc Fill Gas}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -36,7 +36,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
{
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
_gridData.Add(entManager.GetNetEntity(uid));
}

View File

@@ -1,26 +1,26 @@
<DefaultWindow
xmlns="https://spacestation14.io" Title="{Loc admin-ui-atmos-set-temperature}">
xmlns="https://spacestation14.io" Title="{Loc Set Temperature}">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-grid}" MinSize="100 0" />
<Label Text="{Loc Grid}" MinSize="100 0" />
<Control MinSize="50 0" />
<OptionButton Name="GridOptions" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-tile-x}" MinSize="100 0" />
<Label Text="{Loc TileX}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileXSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-tile-y}" MinSize="100 0" />
<Label Text="{Loc TileY}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TileYSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc admin-ui-atmos-temperature}" MinSize="100 0" />
<Label Text="{Loc Temperature}" MinSize="100 0" />
<Control MinSize="50 0" />
<SpinBox Name="TemperatureSpin" MinSize="100 0" HorizontalExpand="True" />
</BoxContainer>
<Button Name="SubmitButton" Text="{Loc admin-ui-atmos-set-temperature}" />
<Button Name="SubmitButton" Text="{Loc Set Temperature}" />
</BoxContainer>
</DefaultWindow>

View File

@@ -32,7 +32,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab
{
var player = playerManager.LocalEntity;
var playerGrid = entManager.GetComponentOrNull<TransformComponent>(player)?.GridUid;
GridOptions.AddItem($"{uid} {(playerGrid == uid ? Loc.GetString($"admin-ui-atmos-grid-current") : "")}");
GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}");
_data.Add(entManager.GetNetEntity(uid));
}

View File

@@ -4,17 +4,18 @@
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc object-tab-object-type}" />
<OptionButton Name="ObjectTypeOptions" HorizontalAlignment="Left" />
<LineEdit Name="SearchLineEdit" PlaceHolder="{Loc object-tab-object-search}" HorizontalExpand="True"
SizeFlagsStretchRatio="1" />
<Button Name="RefreshListButton" Text="{Loc object-tab-refresh-button}" ToggleMode="False" />
<Label HorizontalExpand="True" SizeFlagsStretchRatio="0.50"
Text="{Loc Object type:}" />
<LineEdit Name="SearchLineEdit" PlaceHolder="{Loc Search...}" HorizontalExpand="True" SizeFlagsStretchRatio="1"/>
<OptionButton Name="ObjectTypeOptions" HorizontalExpand="True" SizeFlagsStretchRatio="0.25"/>
</BoxContainer>
<cc:HSeparator />
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
</BoxContainer>
<cc:HSeparator/>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<ot:ObjectsTabHeader Name="ListHeader" />
<cc:HSeparator />
<co:SearchListContainer Name="SearchList" Access="Public" VerticalExpand="True" />
<ot:ObjectsTabHeader Name="ListHeader"/>
<cc:HSeparator/>
<co:SearchListContainer Name="SearchList" Access="Public" VerticalExpand="True"/>
</BoxContainer>
</BoxContainer>
</Control>

View File

@@ -3,7 +3,6 @@ using Content.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
@@ -14,16 +13,20 @@ namespace Content.Client.Administration.UI.Tabs.ObjectsTab;
public sealed partial class ObjectsTab : Control
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly List<ObjectsTabEntry> _objects = new();
private readonly List<ObjectsTabSelection> _selections = new();
private bool _ascending = false; // Set to false for descending order by default
private ObjectsTabHeader.Header _headerClicked = ObjectsTabHeader.Header.ObjectName;
private readonly Color _altColor = Color.FromHex("#292B38");
private readonly Color _defaultColor = Color.FromHex("#2F2F3B");
private bool _ascending;
private ObjectsTabHeader.Header _headerClicked = ObjectsTabHeader.Header.ObjectName;
private readonly List<ObjectsTabSelection> _selections = [];
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
private readonly TimeSpan _updateFrequency = TimeSpan.FromSeconds(2);
private TimeSpan _nextUpdate;
public ObjectsTab()
{
RobustXamlLoader.Load(this);
@@ -35,25 +38,40 @@ public sealed partial class ObjectsTab : Control
RefreshObjectList(_selections[ev.Id]);
};
foreach (var type in Enum.GetValues<ObjectsTabSelection>())
foreach (var type in Enum.GetValues(typeof(ObjectsTabSelection)))
{
_selections.Add(type);
ObjectTypeOptions.AddItem(GetLocalizedEnumValue(type));
_selections.Add((ObjectsTabSelection)type!);
ObjectTypeOptions.AddItem(Enum.GetName((ObjectsTabSelection)type)!);
}
ListHeader.OnHeaderClicked += HeaderClicked;
SearchList.SearchBar = SearchLineEdit;
SearchList.GenerateItem += GenerateButton;
SearchList.DataFilterCondition += DataFilterCondition;
SearchList.ItemKeyBindDown += (args, data) => OnEntryKeyBindDown?.Invoke(args, data);
RefreshListButton.OnPressed += _ => RefreshObjectList();
RefreshObjectList();
// Set initial selection and refresh the list to apply the initial sort order
var defaultSelection = ObjectsTabSelection.Grids;
ObjectTypeOptions.SelectId((int) defaultSelection);
RefreshObjectList(defaultSelection);
ObjectTypeOptions.SelectId((int)defaultSelection); // Set the default selection
RefreshObjectList(defaultSelection); // Refresh the list with the default selection
// Initialize the next update time
_nextUpdate = TimeSpan.Zero;
}
public void RefreshObjectList()
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_timing.CurTime < _nextUpdate)
return;
_nextUpdate = _timing.CurTime + _updateFrequency;
RefreshObjectList();
}
private void RefreshObjectList()
{
RefreshObjectList(_selections[ObjectTypeOptions.SelectedId]);
}
@@ -83,7 +101,6 @@ public sealed partial class ObjectsTab : Control
{
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
}
break;
}
default:
@@ -94,18 +111,14 @@ public sealed partial class ObjectsTab : Control
{
var valueA = GetComparableValue(a, _headerClicked);
var valueB = GetComparableValue(b, _headerClicked);
return _ascending
? Comparer<object>.Default.Compare(valueA, valueB)
: Comparer<object>.Default.Compare(valueB, valueA);
return _ascending ? Comparer<object>.Default.Compare(valueA, valueB) : Comparer<object>.Default.Compare(valueB, valueA);
});
var listData = new List<ObjectsListData>();
for (var index = 0; index < entities.Count; index++)
for (int index = 0; index < entities.Count; index++)
{
var info = entities[index];
listData.Add(new ObjectsListData(info,
$"{info.Name} {info.Entity}",
index % 2 == 0 ? _altColor : _defaultColor));
listData.Add(new ObjectsListData(info, $"{info.Name} {info.Entity}", index % 2 == 0 ? _altColor : _defaultColor));
}
SearchList.PopulateList(listData);
@@ -116,11 +129,10 @@ public sealed partial class ObjectsTab : Control
if (data is not ObjectsListData { Info: var info, BackgroundColor: var backgroundColor })
return;
var entry = new ObjectsTabEntry(info.Name,
info.Entity,
new StyleBoxFlat { BackgroundColor = backgroundColor });
var entry = new ObjectsTabEntry(info.Name, info.Entity, new StyleBoxFlat { BackgroundColor = backgroundColor });
button.ToolTip = $"{info.Name}, {info.Entity}";
button.OnKeyBindDown += args => OnEntryKeyBindDown?.Invoke(args, data);
button.AddChild(entry);
}
@@ -142,7 +154,7 @@ public sealed partial class ObjectsTab : Control
{
ObjectsTabHeader.Header.ObjectName => entity.Name,
ObjectsTabHeader.Header.EntityID => entity.Entity.ToString(),
_ => entity.Name,
_ => entity.Name
};
}
@@ -162,17 +174,6 @@ public sealed partial class ObjectsTab : Control
RefreshObjectList();
}
private string GetLocalizedEnumValue(ObjectsTabSelection selection)
{
return selection switch
{
ObjectsTabSelection.Grids => Loc.GetString("object-tab-object-type-grids"),
ObjectsTabSelection.Maps => Loc.GetString("object-tab-object-type-maps"),
ObjectsTabSelection.Stations => Loc.GetString("object-tab-object-type-stations"),
_ => throw new ArgumentOutOfRangeException(nameof(selection), selection, null),
};
}
private enum ObjectsTabSelection
{
Grids,
@@ -181,5 +182,4 @@ public sealed partial class ObjectsTab : Control
}
}
public record ObjectsListData((string Name, NetEntity Entity) Info, string FilteringString, Color BackgroundColor)
: ListData;
public record ObjectsListData((string Name, NetEntity Entity) Info, string FilteringString, Color BackgroundColor) : ListData;

View File

@@ -4,7 +4,7 @@
xmlns:co="clr-namespace:Content.Client.UserInterface.Controls">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Name="PlayerCount" HorizontalExpand="True" Text="{Loc player-tab-player-count}" />
<Label Name="PlayerCount" HorizontalExpand="True" Text="{Loc Player Count}" />
<LineEdit Name="SearchLineEdit" HorizontalExpand="True"
PlaceHolder="{Loc player-tab-filter-line-edit-placeholder}" />
<Button Name="ShowDisconnectedButton" HorizontalExpand="True"

View File

@@ -109,7 +109,7 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
{
_players = players;
PlayerCount.Text = Loc.GetString("player-tab-player-count", ("count", _playerMan.PlayerCount));
PlayerCount.Text = $"Players: {_playerMan.PlayerCount}";
var filteredPlayers = players.Where(info => _showDisconnected || info.Connected).ToList();

View File

@@ -5,9 +5,9 @@
MinSize="50 50">
<GridContainer
Columns="3">
<cc:CommandButton Command="startround" Text="{Loc administration-ui-round-tab-start-round}" />
<cc:CommandButton Command="endround" Text="{Loc administration-ui-round-tab-end-round}" />
<cc:CommandButton Command="restartround" Text="{Loc administration-ui-round-tab-restart-round}" />
<cc:CommandButton Command="startround" Text="{Loc Start Round}" />
<cc:CommandButton Command="endround" Text="{Loc End Round}" />
<cc:CommandButton Command="restartround" Text="{Loc Restart Round}" />
<cc:CommandButton Command="restartroundnow" Text="{Loc administration-ui-round-tab-restart-round-now}" />
</GridContainer>
</Control>

View File

@@ -1,6 +1,5 @@
using Content.Shared.Ame.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Ame.UI
{
@@ -17,8 +16,9 @@ namespace Content.Client.Ame.UI
{
base.Open();
_window = this.CreateWindow<AmeWindow>();
_window.OnAmeButton += ButtonPressed;
_window = new AmeWindow(this);
_window.OnClose += Close;
_window.OpenCentered();
}
/// <summary>
@@ -40,5 +40,15 @@ namespace Content.Client.Ame.UI
{
SendMessage(new UiButtonPressedMessage(button));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -1,4 +1,3 @@
using System.Linq;
using Content.Client.UserInterface;
using Content.Shared.Ame.Components;
using Robust.Client.AutoGenerated;
@@ -10,17 +9,15 @@ namespace Content.Client.Ame.UI
[GenerateTypedNameReferences]
public sealed partial class AmeWindow : DefaultWindow
{
public event Action<UiButton>? OnAmeButton;
public AmeWindow()
public AmeWindow(AmeControllerBoundUserInterface ui)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
EjectButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.Eject);
ToggleInjection.OnPressed += _ => OnAmeButton?.Invoke(UiButton.ToggleInjection);
IncreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.IncreaseFuel);
DecreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.DecreaseFuel);
EjectButton.OnPressed += _ => ui.ButtonPressed(UiButton.Eject);
ToggleInjection.OnPressed += _ => ui.ButtonPressed(UiButton.ToggleInjection);
IncreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.IncreaseFuel);
DecreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.DecreaseFuel);
}
/// <summary>
@@ -32,7 +29,7 @@ namespace Content.Client.Ame.UI
var castState = (AmeControllerBoundUserInterfaceState) state;
// Disable all buttons if not powered
if (Contents.Children.Any())
if (Contents.Children != null)
{
ButtonHelpers.SetButtonDisabledRecursive(Contents, !castState.HasPower);
EjectButton.Disabled = false;
@@ -68,8 +65,8 @@ namespace Content.Client.Ame.UI
CoreCount.Text = $"{castState.CoreCount}";
InjectionAmount.Text = $"{castState.InjectionAmount}";
// format power statistics to pretty numbers
CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply:N1}";
TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply:N1}";
CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply.ToString("N1")}";
TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply.ToString("N1")}";
}
}
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Anomaly;
using Content.Shared.Gravity;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Anomaly.Ui;
@@ -19,8 +18,10 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface
{
base.Open();
_window = this.CreateWindow<AnomalyGeneratorWindow>();
_window.SetEntity(Owner);
_window = new(Owner);
_window.OpenCentered();
_window.OnClose += Close;
_window.OnGenerateButtonPressed += () =>
{
@@ -36,5 +37,18 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface
return;
_window?.UpdateState(msg);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
public void SetPowerSwitch(bool on)
{
SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on));
}
}

View File

@@ -18,21 +18,17 @@ public sealed partial class AnomalyGeneratorWindow : FancyWindow
public Action? OnGenerateButtonPressed;
public AnomalyGeneratorWindow()
public AnomalyGeneratorWindow(EntityUid gen)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
EntityView.SetEntity(gen);
EntityView.SpriteOffset = false;
GenerateButton.OnPressed += _ => OnGenerateButtonPressed?.Invoke();
}
public void SetEntity(EntityUid uid)
{
EntityView.SetEntity(uid);
}
public void UpdateState(AnomalyGeneratorUserInterfaceState state)
{
_cooldownEnd = state.CooldownEndTime;

View File

@@ -28,6 +28,8 @@ namespace Content.Client.Arcade
private static readonly Vector2 BlockSize = new(15, 15);
private readonly BlockGameBoundUserInterface _owner;
private readonly PanelContainer _mainPanel;
private readonly BoxContainer _gameRootContainer;
@@ -56,11 +58,10 @@ namespace Content.Client.Arcade
private bool _isPlayer = false;
private bool _gameOver = false;
public event Action<BlockGamePlayerAction>? OnAction;
public BlockGameMenu()
public BlockGameMenu(BlockGameBoundUserInterface owner)
{
Title = Loc.GetString("blockgame-menu-title");
_owner = owner;
MinSize = SetSize = new Vector2(410, 490);
@@ -175,7 +176,7 @@ namespace Content.Client.Arcade
};
_newGameButton.OnPressed += (e) =>
{
OnAction?.Invoke(BlockGamePlayerAction.NewGame);
_owner.SendAction(BlockGamePlayerAction.NewGame);
};
pauseMenuContainer.AddChild(_newGameButton);
pauseMenuContainer.AddChild(new Control { MinSize = new Vector2(1, 10) });
@@ -185,10 +186,7 @@ namespace Content.Client.Arcade
Text = Loc.GetString("blockgame-menu-button-scoreboard"),
TextAlign = Label.AlignMode.Center
};
_scoreBoardButton.OnPressed += (e) =>
{
OnAction?.Invoke(BlockGamePlayerAction.ShowHighscores);
};
_scoreBoardButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.ShowHighscores);
pauseMenuContainer.AddChild(_scoreBoardButton);
_unpauseButtonMargin = new Control { MinSize = new Vector2(1, 10), Visible = false };
pauseMenuContainer.AddChild(_unpauseButtonMargin);
@@ -201,7 +199,7 @@ namespace Content.Client.Arcade
};
_unpauseButton.OnPressed += (e) =>
{
OnAction?.Invoke(BlockGamePlayerAction.Unpause);
_owner.SendAction(BlockGamePlayerAction.Unpause);
};
pauseMenuContainer.AddChild(_unpauseButton);
@@ -259,7 +257,7 @@ namespace Content.Client.Arcade
};
_finalNewGameButton.OnPressed += (e) =>
{
OnAction?.Invoke(BlockGamePlayerAction.NewGame);
_owner.SendAction(BlockGamePlayerAction.NewGame);
};
gameOverMenuContainer.AddChild(_finalNewGameButton);
@@ -329,10 +327,7 @@ namespace Content.Client.Arcade
Text = Loc.GetString("blockgame-menu-button-back"),
TextAlign = Label.AlignMode.Center
};
_highscoreBackButton.OnPressed += (e) =>
{
OnAction?.Invoke(BlockGamePlayerAction.Pause);
};
_highscoreBackButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.Pause);
menuContainer.AddChild(_highscoreBackButton);
menuInnerPanel.AddChild(menuContainer);
@@ -380,7 +375,7 @@ namespace Content.Client.Arcade
{
PanelOverride = back,
HorizontalExpand = true,
SizeFlagsStretchRatio = 34.25f
SizeFlagsStretchRatio = 60
};
var backgroundPanel = new PanelContainer
{
@@ -478,7 +473,7 @@ namespace Content.Client.Arcade
private void TryPause()
{
OnAction?.Invoke(BlockGamePlayerAction.Pause);
_owner.SendAction(BlockGamePlayerAction.Pause);
}
public void SetStarted()
@@ -581,19 +576,19 @@ namespace Content.Client.Arcade
return;
else if (args.Function == ContentKeyFunctions.ArcadeLeft)
OnAction?.Invoke(BlockGamePlayerAction.StartLeft);
_owner.SendAction(BlockGamePlayerAction.StartLeft);
else if (args.Function == ContentKeyFunctions.ArcadeRight)
OnAction?.Invoke(BlockGamePlayerAction.StartRight);
_owner.SendAction(BlockGamePlayerAction.StartRight);
else if (args.Function == ContentKeyFunctions.ArcadeUp)
OnAction?.Invoke(BlockGamePlayerAction.Rotate);
_owner.SendAction(BlockGamePlayerAction.Rotate);
else if (args.Function == ContentKeyFunctions.Arcade3)
OnAction?.Invoke(BlockGamePlayerAction.CounterRotate);
_owner.SendAction(BlockGamePlayerAction.CounterRotate);
else if (args.Function == ContentKeyFunctions.ArcadeDown)
OnAction?.Invoke(BlockGamePlayerAction.SoftdropStart);
_owner.SendAction(BlockGamePlayerAction.SoftdropStart);
else if (args.Function == ContentKeyFunctions.Arcade2)
OnAction?.Invoke(BlockGamePlayerAction.Hold);
_owner.SendAction(BlockGamePlayerAction.Hold);
else if (args.Function == ContentKeyFunctions.Arcade1)
OnAction?.Invoke(BlockGamePlayerAction.Harddrop);
_owner.SendAction(BlockGamePlayerAction.Harddrop);
}
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
@@ -604,11 +599,11 @@ namespace Content.Client.Arcade
return;
else if (args.Function == ContentKeyFunctions.ArcadeLeft)
OnAction?.Invoke(BlockGamePlayerAction.EndLeft);
_owner.SendAction(BlockGamePlayerAction.EndLeft);
else if (args.Function == ContentKeyFunctions.ArcadeRight)
OnAction?.Invoke(BlockGamePlayerAction.EndRight);
_owner.SendAction(BlockGamePlayerAction.EndRight);
else if (args.Function == ContentKeyFunctions.ArcadeDown)
OnAction?.Invoke(BlockGamePlayerAction.SoftdropEnd);
_owner.SendAction(BlockGamePlayerAction.SoftdropEnd);
}
public void UpdateNextBlock(BlockGameBlock[] blocks)

View File

@@ -8,6 +8,8 @@ namespace Content.Client.Arcade
{
public sealed class SpaceVillainArcadeMenu : DefaultWindow
{
public SpaceVillainArcadeBoundUserInterface Owner { get; set; }
private readonly Label _enemyNameLabel;
private readonly Label _playerInfoLabel;
private readonly Label _enemyInfoLabel;
@@ -15,13 +17,11 @@ namespace Content.Client.Arcade
private readonly Label _enemyActionLabel;
private readonly Button[] _gameButtons = new Button[3]; //used to disable/enable all game buttons
public event Action<SharedSpaceVillainArcadeComponent.PlayerAction>? OnPlayerAction;
public SpaceVillainArcadeMenu()
public SpaceVillainArcadeMenu(SpaceVillainArcadeBoundUserInterface owner)
{
MinSize = SetSize = new Vector2(300, 225);
Title = Loc.GetString("spacevillain-menu-title");
Owner = owner;
var grid = new GridContainer { Columns = 1 };
@@ -47,43 +47,32 @@ namespace Content.Client.Arcade
grid.AddChild(_enemyActionLabel);
var buttonGrid = new GridContainer { Columns = 3 };
_gameButtons[0] = new Button()
_gameButtons[0] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Attack)
{
Text = Loc.GetString("spacevillain-menu-button-attack")
};
_gameButtons[0].OnPressed +=
_ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Attack);
buttonGrid.AddChild(_gameButtons[0]);
_gameButtons[1] = new Button()
_gameButtons[1] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Heal)
{
Text = Loc.GetString("spacevillain-menu-button-heal")
};
_gameButtons[1].OnPressed +=
_ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Heal);
buttonGrid.AddChild(_gameButtons[1]);
_gameButtons[2] = new Button()
_gameButtons[2] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Recharge)
{
Text = Loc.GetString("spacevillain-menu-button-recharge")
};
_gameButtons[2].OnPressed +=
_ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Recharge);
buttonGrid.AddChild(_gameButtons[2]);
centerContainer = new CenterContainer();
centerContainer.AddChild(buttonGrid);
grid.AddChild(centerContainer);
var newGame = new Button()
var newGame = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.NewGame)
{
Text = Loc.GetString("spacevillain-menu-button-new-game")
};
newGame.OnPressed += _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.NewGame);
grid.AddChild(newGame);
Contents.AddChild(grid);
@@ -110,5 +99,23 @@ namespace Content.Client.Arcade
_playerActionLabel.Text = message.PlayerActionMessage;
_enemyActionLabel.Text = message.EnemyActionMessage;
}
private sealed class ActionButton : Button
{
private readonly SpaceVillainArcadeBoundUserInterface _owner;
private readonly SharedSpaceVillainArcadeComponent.PlayerAction _playerAction;
public ActionButton(SpaceVillainArcadeBoundUserInterface owner, SharedSpaceVillainArcadeComponent.PlayerAction playerAction)
{
_owner = owner;
_playerAction = playerAction;
OnPressed += Clicked;
}
private void Clicked(ButtonEventArgs e)
{
_owner.SendAction(_playerAction);
}
}
}
}

View File

@@ -1,6 +1,5 @@
using Content.Shared.Arcade;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Arcade.UI;
@@ -16,8 +15,9 @@ public sealed class BlockGameBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<BlockGameMenu>();
_menu.OnAction += SendAction;
_menu = new BlockGameMenu(this);
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)

View File

@@ -1,5 +1,4 @@
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;
using static Content.Shared.Arcade.SharedSpaceVillainArcadeComponent;
@@ -10,6 +9,8 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
{
[ViewVariables] private SpaceVillainArcadeMenu? _menu;
//public SharedSpaceVillainArcadeComponent SpaceVillainArcade;
public SpaceVillainArcadeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
SendAction(PlayerAction.RequestData);
@@ -24,8 +25,10 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<SpaceVillainArcadeMenu>();
_menu.OnPlayerAction += SendAction;
_menu = new SpaceVillainArcadeMenu(this);
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
@@ -33,4 +36,12 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
if (message is SpaceVillainArcadeDataUpdateMessage msg)
_menu?.UpdateInfo(msg);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_menu?.Dispose();
}
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
@@ -21,9 +20,16 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
{
base.Open();
_window = this.CreateWindow<AirAlarmWindow>();
_window.SetEntity(Owner);
_window = new AirAlarmWindow(this);
if (State != null)
{
UpdateState(State);
}
_window.OpenCentered();
_window.OnClose += Close;
_window.AtmosDeviceDataChanged += OnDeviceDataChanged;
_window.AtmosDeviceDataCopied += OnDeviceDataCopied;
_window.AtmosAlarmThresholdChanged += OnThresholdChanged;

View File

@@ -47,7 +47,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
private CheckBox _autoMode => AutoModeCheckBox;
public AirAlarmWindow()
public AirAlarmWindow(BoundUserInterface owner)
{
RobustXamlLoader.Load(this);
@@ -95,11 +95,8 @@ public sealed partial class AirAlarmWindow : FancyWindow
_sensors.Clear();
ResyncAllRequested!.Invoke();
};
}
public void SetEntity(EntityUid uid)
{
EntityView.SetEntity(uid);
EntityView.SetEntity(owner.Owner);
}
public void UpdateState(AirAlarmUIState state)

View File

@@ -1,7 +1,6 @@
using Content.Shared.Atmos.Piping.Binary.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
{
@@ -22,8 +21,14 @@ namespace Content.Client.Atmos.UI
{
base.Open();
_window = this.CreateWindow<GasCanisterWindow>();
_window = new GasCanisterWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ReleaseValveCloseButtonPressed += OnReleaseValveClosePressed;
_window.ReleaseValveOpenButtonPressed += OnReleaseValveOpenPressed;
_window.ReleasePressureSet += OnReleasePressureSet;

View File

@@ -3,7 +3,6 @@ using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Trinary.Components;
using Content.Shared.Localizations;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
{
@@ -29,8 +28,14 @@ namespace Content.Client.Atmos.UI
var atmosSystem = EntMan.System<AtmosphereSystem>();
_window = this.CreateWindow<GasFilterWindow>();
_window.PopulateGasList(atmosSystem.Gases);
_window = new GasFilterWindow(atmosSystem.Gases);
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.FilterTransferRateChanged += OnFilterTransferRatePressed;

View File

@@ -26,9 +26,10 @@ namespace Content.Client.Atmos.UI
public event Action<string>? FilterTransferRateChanged;
public event Action? SelectGasPressed;
public GasFilterWindow()
public GasFilterWindow(IEnumerable<GasPrototype> gases)
{
RobustXamlLoader.Load(this);
PopulateGasList(gases);
ToggleStatusButton.OnPressed += _ => SetFilterStatus(!FilterStatus);
ToggleStatusButton.OnPressed += _ => ToggleStatusButtonPressed?.Invoke();
@@ -72,7 +73,7 @@ namespace Content.Client.Atmos.UI
SelectGasButton.Disabled = true;
}
public void PopulateGasList(IEnumerable<GasPrototype> gases)
private void PopulateGasList(IEnumerable<GasPrototype> gases)
{
GasList.Add(new ItemList.Item(GasList)
{
@@ -80,7 +81,7 @@ namespace Content.Client.Atmos.UI
Text = Loc.GetString("comp-gas-filter-ui-filter-gas-none")
});
foreach (var gas in gases)
foreach (GasPrototype gas in gases)
{
var gasName = Loc.GetString(gas.Name);
GasList.Add(GetGasItem(gas.ID, gasName, GasList));

View File

@@ -2,7 +2,7 @@ using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Trinary.Components;
using Content.Shared.Localizations;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
using Robust.Client.GameObjects;
namespace Content.Client.Atmos.UI
{
@@ -26,7 +26,14 @@ namespace Content.Client.Atmos.UI
{
base.Open();
_window = this.CreateWindow<GasMixerWindow>();
_window = new GasMixerWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.MixerOutputPressureChanged += OnMixerOutputPressurePressed;
@@ -76,5 +83,12 @@ namespace Content.Client.Atmos.UI
_window.SetOutputPressure(cast.OutputPressure);
_window.SetNodePercentages(cast.NodeOne);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Localizations;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
{
@@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI
{
base.Open();
_window = this.CreateWindow<GasPressurePumpWindow>();
_window = new GasPressurePumpWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.PumpOutputPressureChanged += OnPumpOutputPressurePressed;
@@ -61,5 +67,12 @@ namespace Content.Client.Atmos.UI
_window.SetPumpStatus(cast.Enabled);
_window.SetOutputPressure(cast.OutputPressure);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -2,7 +2,6 @@
using Content.Shared.Atmos.Piping.Unary.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
{
@@ -32,7 +31,14 @@ namespace Content.Client.Atmos.UI
{
base.Open();
_window = this.CreateWindow<GasThermomachineWindow>();
_window = new GasThermomachineWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
_window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value);
@@ -85,5 +91,12 @@ namespace Content.Client.Atmos.UI
true => Loc.GetString("comp-gas-thermomachine-ui-title-heater")
};
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Localizations;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Atmos.UI
{
@@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI
{
base.Open();
_window = this.CreateWindow<GasVolumePumpWindow>();
_window = new GasVolumePumpWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
_window.PumpTransferRateChanged += OnPumpTransferRatePressed;
@@ -58,9 +64,16 @@ namespace Content.Client.Atmos.UI
if (_window == null || state is not GasVolumePumpBoundUserInterfaceState cast)
return;
_window.Title = cast.PumpLabel;
_window.Title = (cast.PumpLabel);
_window.SetPumpStatus(cast.Enabled);
_window.SetTransferRate(cast.TransferRate);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -1,6 +1,5 @@
using Content.Shared.Atmos.Piping.Portable.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
namespace Content.Client.Atmos.UI;
@@ -22,7 +21,14 @@ public sealed class SpaceHeaterBoundUserInterface : BoundUserInterface
{
base.Open();
_window = this.CreateWindow<SpaceHeaterWindow>();
_window = new SpaceHeaterWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
_window.IncreaseTempRange.OnPressed += _ => OnTemperatureRangeChanged(_window.TemperatureChangeDelta);

View File

@@ -54,7 +54,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var resource = GetSoundOrFallback(value, CCVars.UIClickSound.DefaultValue);
var resource = _cache.GetResource<AudioResource>(value);
var source =
_audioManager.CreateAudioSource(resource);
@@ -77,7 +77,7 @@ public sealed class AudioUIController : UIController
{
if (!string.IsNullOrEmpty(value))
{
var hoverResource = GetSoundOrFallback(value, CCVars.UIHoverSound.DefaultValue);
var hoverResource = _cache.GetResource<AudioResource>(value);
var hoverSource =
_audioManager.CreateAudioSource(hoverResource);
@@ -95,12 +95,4 @@ public sealed class AudioUIController : UIController
UIManager.SetHoverSound(null);
}
}
private AudioResource GetSoundOrFallback(string path, string fallback)
{
if (!_cache.TryGetResource(path, out AudioResource? resource))
return _cache.GetResource<AudioResource>(fallback);
return resource;
}
}

View File

@@ -4,7 +4,6 @@ using Content.Shared.Audio;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Content.Shared.Random;
using Content.Shared.Random.Rules;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
@@ -117,7 +116,6 @@ public sealed partial class ContentAudioSystem
private void OnRoundEndMessage(RoundEndMessageEvent ev)
{
OnRoundEndMessageAmbientLoop(); //CP14
// If scoreboard shows then just stop the music
_ambientMusicStream = _audio.Stop(_ambientMusicStream);
_nextAudio = TimeSpan.FromMinutes(3);

View File

@@ -1,122 +0,0 @@
using System.Linq;
using Content.Client.Gameplay;
using Content.Shared.Audio;
using Content.Shared.CCVar;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
namespace Content.Client.Audio;
public sealed partial class ContentAudioSystem
{
private const float AmbientLoopFadeInTime = 1f;
private const float AmbientLoopFadeOutTime = 4f;
private Dictionary<CP14AmbientLoopPrototype, EntityUid> _loopStreams = new();
private TimeSpan _nextUpdateTime = TimeSpan.Zero;
private readonly TimeSpan _updateFrequency = TimeSpan.FromSeconds(1f);
private void CP14InitializeAmbientLoops()
{
Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChangedAmbientMusic, true);
}
private void AmbienceCVarChangedAmbientMusic(float obj)
{
_volumeSlider = SharedAudioSystem.GainToVolume(obj);
foreach (var loop in _loopStreams)
{
_audio.SetVolume(loop.Value, loop.Key.Sound.Params.Volume + _volumeSlider);
}
}
private void OnRoundEndMessageAmbientLoop()
{
foreach (var loop in _loopStreams)
{
StopAmbientLoop(loop.Key);
}
}
private void CP14UpdateAmbientLoops()
{
if (_timing.CurTime <= _nextUpdateTime)
return;
_nextUpdateTime = _timing.CurTime + _updateFrequency;
if (_state.CurrentState is not GameplayState)
return;
var requiredLoops = GetAmbientLoops();
foreach (var loop in _loopStreams)
{
if (!requiredLoops.Contains(loop.Key)) //If ambient is playing and it shouldn't, stop it.
StopAmbientLoop(loop.Key);
}
foreach (var loop in requiredLoops)
{
if (!_loopStreams.ContainsKey(loop)) //If it's not playing, but should, run it
StartAmbientLoop(loop);
}
}
private void StartAmbientLoop(CP14AmbientLoopPrototype proto)
{
if (_loopStreams.ContainsKey(proto))
return;
var newLoop = _audio.PlayGlobal(
proto.Sound,
Filter.Local(),
false,
AudioParams.Default
.WithLoop(true)
.WithVolume(proto.Sound.Params.Volume + _volumeSlider)
.WithPlayOffset(_random.NextFloat(0f, 100f)));
_loopStreams.Add(proto, newLoop.Value.Entity);
FadeIn(newLoop.Value.Entity, newLoop.Value.Component, AmbientLoopFadeInTime);
}
private void StopAmbientLoop(CP14AmbientLoopPrototype proto)
{
if (!_loopStreams.TryGetValue(proto, out var audioEntity))
return;
FadeOut(audioEntity, duration: AmbientLoopFadeOutTime);
_loopStreams.Remove(proto);
}
/// <summary>
/// Checks the player's environment, and returns a list of all ambients that should currently be playing around the player
/// </summary>
/// <returns></returns>
private List<CP14AmbientLoopPrototype> GetAmbientLoops()
{
List<CP14AmbientLoopPrototype> list = new();
var player = _player.LocalEntity;
if (player == null)
return list;
var ambientLoops = _proto.EnumeratePrototypes<CP14AmbientLoopPrototype>().ToList();
foreach (var loop in ambientLoops)
{
if (_rules.IsTrue(player.Value, _proto.Index(loop.Rules)))
{
list.Add(loop);
}
}
return list;
}
}

View File

@@ -29,14 +29,13 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem
public const float AmbientMusicMultiplier = 3f;
public const float LobbyMultiplier = 3f;
public const float InterfaceMultiplier = 2f;
public override void Initialize()
{
base.Initialize();
UpdatesOutsidePrediction = true;
InitializeAmbientMusic();
CP14InitializeAmbientLoops(); //CP14 ambient loops
InitializeLobbyMusic();
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
}
@@ -83,7 +82,6 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem
return;
UpdateAmbientMusic();
CP14UpdateAmbientLoops(); //CP14
UpdateLobbyMusic();
UpdateFades(frameTime);
}

View File

@@ -1,7 +1,8 @@
using Content.Shared.Audio.Jukebox;
using Robust.Client.Audio;
using Robust.Client.UserInterface;
using Robust.Client.Player;
using Robust.Shared.Audio.Components;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Client.Audio.Jukebox;
@@ -22,7 +23,9 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<JukeboxMenu>();
_menu = new JukeboxMenu();
_menu.OnClose += Close;
_menu.OpenCentered();
_menu.OnPlayPressed += args =>
{
@@ -97,5 +100,19 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface
SendMessage(new JukeboxSetTimeMessage(sentTime));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
if (_menu == null)
return;
_menu.OnClose -= Close;
_menu.Dispose();
_menu = null;
}
}

View File

@@ -1,4 +1,3 @@
using Content.Client.BarSign.Ui;
using Content.Shared.BarSign;
using Content.Shared.Power;
using Robust.Client.GameObjects;
@@ -9,7 +8,6 @@ namespace Content.Client.BarSign;
public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
public override void Initialize()
{
@@ -19,9 +17,6 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args)
{
if (_ui.TryGetOpenUi<BarSignBoundUserInterface>(uid, BarSignUiKey.Key, out var bui))
bui.Update(component.Current);
UpdateAppearance(uid, component);
}
@@ -39,9 +34,9 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
if (powered
&& sign.Current != null
&& _prototypeManager.TryIndex(sign.Current, out var proto))
&& _prototypeManager.TryIndex(sign.Current, out BarSignPrototype? proto))
{
sprite.LayerSetSprite(0, proto.Icon);
sprite.LayerSetState(0, proto.Icon);
sprite.LayerSetShader(0, "unshaded");
}
else

View File

@@ -1,50 +0,0 @@
using System.Linq;
using Content.Shared.BarSign;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
namespace Content.Client.BarSign.Ui;
[UsedImplicitly]
public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
private BarSignMenu? _menu;
protected override void Open()
{
base.Open();
var sign = EntMan.GetComponentOrNull<BarSignComponent>(Owner)?.Current is { } current
? _prototype.Index(current)
: null;
var allSigns = Shared.BarSign.BarSignSystem.GetAllBarSigns(_prototype)
.OrderBy(p => Loc.GetString(p.Name))
.ToList();
_menu = new(sign, allSigns);
_menu.OnSignSelected += id =>
{
SendMessage(new SetBarSignMessage(id));
};
_menu.OnClose += Close;
_menu.OpenCentered();
}
public void Update(ProtoId<BarSignPrototype>? sign)
{
if (_prototype.TryIndex(sign, out var signPrototype))
_menu?.UpdateState(signPrototype);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -1,19 +0,0 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'barsign-ui-menu'}"
MinSize="280 180"
SetSize="280 180">
<BoxContainer VerticalExpand="True" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 5 10 10">
<BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center">
<Label Text="{Loc 'barsign-ui-set-label'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="30 0"/>
<customControls:HSeparator Margin="0 0 0 5"/>
</BoxContainer>
<OptionButton Name="SignOptions" HorizontalAlignment="Center" VerticalAlignment="Center" MinSize="175 60" Margin="0 0 0 20"/>
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -1,50 +0,0 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.BarSign;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.BarSign.Ui;
[GenerateTypedNameReferences]
public sealed partial class BarSignMenu : FancyWindow
{
private string? _currentId;
private readonly List<BarSignPrototype> _cachedPrototypes = new();
public event Action<string>? OnSignSelected;
public BarSignMenu(BarSignPrototype? currentSign, List<BarSignPrototype> signs)
{
RobustXamlLoader.Load(this);
_currentId = currentSign?.ID;
_cachedPrototypes.Clear();
_cachedPrototypes = signs;
foreach (var proto in _cachedPrototypes)
{
SignOptions.AddItem(Loc.GetString(proto.Name));
}
SignOptions.OnItemSelected += idx =>
{
OnSignSelected?.Invoke(_cachedPrototypes[idx.Id].ID);
SignOptions.SelectId(idx.Id);
};
if (currentSign != null)
{
var idx = _cachedPrototypes.IndexOf(currentSign);
SignOptions.TrySelectId(idx);
}
}
public void UpdateState(BarSignPrototype newSign)
{
if (_currentId != null && newSign.ID == _currentId)
return;
_currentId = newSign.ID;
var idx = _cachedPrototypes.IndexOf(newSign);
SignOptions.TrySelectId(idx);
}
}

View File

@@ -1,6 +1,5 @@
using Content.Shared.Bed.Cryostorage;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Bed.Cryostorage;
@@ -18,7 +17,9 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<CryostorageMenu>();
_menu = new();
_menu.OnClose += Close;
_menu.SlotRemoveButtonPressed += (ent, slot) =>
{
@@ -29,6 +30,8 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
{
SendMessage(new CryostorageRemoveItemBuiMessage(ent, hand, CryostorageRemoveItemBuiMessage.RemovalType.Hand));
};
_menu.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -42,4 +45,12 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
break;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -1,7 +1,6 @@
using Content.Client.Cargo.UI;
using Content.Shared.Cargo.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Cargo.BUI;
@@ -19,7 +18,9 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<CargoBountyMenu>();
_menu = new();
_menu.OnClose += Close;
_menu.OnLabelButtonPressed += id =>
{
@@ -30,6 +31,8 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
{
SendMessage(new BountySkipMessage(id));
};
_menu.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState message)
@@ -41,4 +44,14 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
_menu?.UpdateEntries(state.Bounties, state.UntilNextSkip);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}

View File

@@ -2,7 +2,6 @@ using Content.Client.Cargo.UI;
using Content.Shared.Cargo.BUI;
using Content.Shared.Cargo.Events;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Cargo.BUI;
@@ -19,9 +18,21 @@ public sealed class CargoPalletConsoleBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<CargoPalletMenu>();
_menu = new CargoPalletMenu();
_menu.AppraiseRequested += OnAppraisal;
_menu.SellRequested += OnSell;
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_menu?.Dispose();
}
}
private void OnAppraisal()

View File

@@ -2,7 +2,6 @@ using Content.Client.Cargo.UI;
using Content.Shared.Cargo.BUI;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
namespace Content.Client.Cargo.BUI;
@@ -10,8 +9,6 @@ namespace Content.Client.Cargo.BUI;
[UsedImplicitly]
public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[ViewVariables]
private CargoShuttleMenu? _menu;
@@ -22,7 +19,24 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<CargoShuttleMenu>();
var collection = IoCManager.Instance;
if (collection == null)
return;
_menu = new CargoShuttleMenu(collection.Resolve<IPrototypeManager>(), collection.Resolve<IEntitySystemManager>().GetEntitySystem<SpriteSystem>());
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_menu?.Dispose();
}
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -31,6 +45,6 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
if (state is not CargoShuttleConsoleBoundUserInterfaceState cargoState) return;
_menu?.SetAccountName(cargoState.AccountName);
_menu?.SetShuttleName(cargoState.ShuttleName);
_menu?.SetOrders(EntMan.System<SpriteSystem>(), _protoManager, cargoState.Orders);
_menu?.SetOrders(cargoState.Orders);
}
}

View File

@@ -12,9 +12,14 @@ namespace Content.Client.Cargo.UI
[GenerateTypedNameReferences]
public sealed partial class CargoShuttleMenu : FancyWindow
{
public CargoShuttleMenu()
private readonly IPrototypeManager _protoManager;
private readonly SpriteSystem _spriteSystem;
public CargoShuttleMenu(IPrototypeManager protoManager, SpriteSystem spriteSystem)
{
RobustXamlLoader.Load(this);
_protoManager = protoManager;
_spriteSystem = spriteSystem;
Title = Loc.GetString("cargo-shuttle-console-menu-title");
}
@@ -28,19 +33,19 @@ namespace Content.Client.Cargo.UI
ShuttleNameLabel.Text = name;
}
public void SetOrders(SpriteSystem sprites, IPrototypeManager protoManager, List<CargoOrderData> orders)
public void SetOrders(List<CargoOrderData> orders)
{
Orders.DisposeAllChildren();
foreach (var order in orders)
{
var product = protoManager.Index<EntityPrototype>(order.ProductId);
var product = _protoManager.Index<EntityPrototype>(order.ProductId);
var productName = product.Name;
var row = new CargoOrderRow
{
Order = order,
Icon = { Texture = sprites.Frame0(product) },
Icon = { Texture = _spriteSystem.Frame0(product) },
ProductName =
{
Text = Loc.GetString(

View File

@@ -31,7 +31,7 @@ public sealed partial class NewsReaderUiFragment : BoxContainer
Author.Visible = true;
PageName.Text = article.Title;
PageText.SetMarkupPermissive(article.Content);
PageText.SetMarkup(article.Content);
PageNum.Text = $"{targetNum}/{totalNum}";

View File

@@ -65,13 +65,14 @@ public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem
{
if (_isClientTyping == isClientTyping)
return;
_isClientTyping = isClientTyping;
// check if player controls any entity.
// check if player controls any pawn
if (_playerManager.LocalEntity == null)
return;
_isClientTyping = isClientTyping;
RaisePredictiveEvent(new TypingChangedEvent(isClientTyping));
// send a networked event to server
RaiseNetworkEvent(new TypingChangedEvent(isClientTyping));
}
private void OnShowTypingChanged(bool showTyping)

View File

@@ -2,36 +2,21 @@
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;
using Content.Shared.Inventory;
namespace Content.Client.Chat.TypingIndicator;
public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem<TypingIndicatorComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
var currentTypingIndicator = component.TypingIndicatorPrototype;
var evt = new BeforeShowTypingIndicatorEvent();
if (TryComp<InventoryComponent>(uid, out var inventoryComp))
_inventory.RelayEvent((uid, inventoryComp), ref evt);
var overrideIndicator = evt.GetMostRecentIndicator();
if (overrideIndicator != null)
currentTypingIndicator = overrideIndicator.Value;
if (!_prototypeManager.TryIndex(currentTypingIndicator, out var proto))
if (!_prototypeManager.TryIndex<TypingIndicatorPrototype>(component.Prototype, out var proto))
{
Log.Error($"Unknown typing indicator id: {component.TypingIndicatorPrototype}");
Log.Error($"Unknown typing indicator id: {component.Prototype}");
return;
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Chemistry;
using Content.Shared.Containers.ItemSlots;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Chemistry.UI
{
@@ -28,8 +27,13 @@ namespace Content.Client.Chemistry.UI
base.Open();
// Setup window layout/elements
_window = this.CreateWindow<ChemMasterWindow>();
_window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
_window = new ChemMasterWindow
{
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
};
_window.OpenCentered();
_window.OnClose += Close;
// Setup static button actions.
_window.InputEjectButton.OnPressed += _ => SendMessage(
@@ -71,5 +75,15 @@ namespace Content.Client.Chemistry.UI
_window?.UpdateState(castState); // Update window state
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -3,7 +3,6 @@ using Content.Shared.Chemistry;
using Content.Shared.Containers.ItemSlots;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Chemistry.UI
{
@@ -16,6 +15,9 @@ namespace Content.Client.Chemistry.UI
[ViewVariables]
private ReagentDispenserWindow? _window;
[ViewVariables]
private ReagentDispenserBoundUserInterfaceState? _lastState;
public ReagentDispenserBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
@@ -30,9 +32,14 @@ namespace Content.Client.Chemistry.UI
base.Open();
// Setup window layout/elements
_window = this.CreateWindow<ReagentDispenserWindow>();
_window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
_window.HelpGuidebookIds = EntMan.GetComponent<GuideHelpComponent>(Owner).Guides;
_window = new()
{
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
HelpGuidebookIds = EntMan.GetComponent<GuideHelpComponent>(Owner).Guides
};
_window.OpenCentered();
_window.OnClose += Close;
// Setup static button actions.
_window.EjectButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName));
@@ -56,7 +63,19 @@ namespace Content.Client.Chemistry.UI
base.UpdateState(state);
var castState = (ReagentDispenserBoundUserInterfaceState) state;
_lastState = castState;
_window?.UpdateState(castState); //Update window state
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Chemistry;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Chemistry.UI
{
@@ -19,7 +18,7 @@ namespace Content.Client.Chemistry.UI
protected override void Open()
{
base.Open();
_window = this.CreateWindow<TransferAmountWindow>();
_window = new TransferAmountWindow();
_window.ApplyButton.OnPressed += _ =>
{
@@ -29,6 +28,15 @@ namespace Content.Client.Chemistry.UI
_window.Close();
}
};
_window.OnClose += Close;
_window.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -48,7 +48,7 @@ namespace Content.Client.Clickable
Angle cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero;
// First we get `localPos`, the clicked location in the sprite-coordinate frame.
var entityXform = Matrix3Helpers.CreateInverseTransform(spritePos, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var entityXform = Matrix3Helpers.CreateInverseTransform(transform.WorldPosition, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var localPos = Vector2.Transform(Vector2.Transform(worldPos, entityXform), invSpriteMatrix);
// Check explicitly defined click-able bounds
@@ -58,11 +58,8 @@ namespace Content.Client.Clickable
// Next check each individual sprite layer using automatically computed click maps.
foreach (var spriteLayer in sprite.AllLayers)
{
// TODO: Move this to a system and also use SpriteSystem.IsVisible instead.
if (!spriteLayer.Visible || spriteLayer is not Layer layer || layer.CopyToShaderParameters != null)
{
if (!spriteLayer.Visible || spriteLayer is not Layer layer)
continue;
}
// Check the layer's texture, if it has one
if (layer.Texture != null)

View File

@@ -1,26 +0,0 @@
using Content.Shared.Clock;
using Robust.Client.GameObjects;
namespace Content.Client.Clock;
public sealed class ClockSystem : SharedClockSystem
{
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<ClockComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out var comp, out var sprite))
{
if (!sprite.LayerMapTryGet(ClockVisualLayers.HourHand, out var hourLayer) ||
!sprite.LayerMapTryGet(ClockVisualLayers.MinuteHand, out var minuteLayer))
continue;
var time = GetClockTime((uid, comp));
var hourState = $"{comp.HoursBase}{time.Hours % 12}";
var minuteState = $"{comp.MinutesBase}{time.Minutes / 5}";
sprite.LayerSetState(hourLayer, hourState);
sprite.LayerSetState(minuteLayer, minuteState);
}
}
}

View File

@@ -1,7 +1,6 @@
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Content.Shared.Cloning.CloningConsole;
using Robust.Client.UserInterface;
namespace Content.Client.CloningConsole.UI
{
@@ -18,11 +17,13 @@ namespace Content.Client.CloningConsole.UI
protected override void Open()
{
base.Open();
_window = this.CreateWindow<CloningConsoleWindow>();
_window.Title = Loc.GetString("cloning-console-window-title");
_window = new CloningConsoleWindow
{
Title = Loc.GetString("cloning-console-window-title")
};
_window.OnClose += Close;
_window.CloneButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
_window.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -31,5 +32,19 @@ namespace Content.Client.CloningConsole.UI
_window?.Populate((CloningConsoleBoundUserInterfaceState) state);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
if (_window != null)
{
_window.OnClose -= Close;
_window.CloneButton.OnPressed -= _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
}
_window?.Dispose();
}
}
}

View File

@@ -1,12 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using Content.Client.DisplacementMap;
using Content.Client.Inventory;
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.DisplacementMap;
using Content.Shared.Humanoid;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
@@ -59,7 +57,6 @@ public sealed class ClientClothingSystem : ClothingSystem
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
public override void Initialize()
{
@@ -74,14 +71,15 @@ public sealed class ClientClothingSystem : ClothingSystem
private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref AppearanceChangeEvent args)
{
// May need to update displacement maps if the sex changed. Also required to properly set the stencil on init
// May need to update jumpsuit stencils if the sex changed. Also required to properly set the stencil on init
if (args.Sprite == null)
return;
var enumerator = _inventorySystem.GetSlotEnumerator((uid, component));
while (enumerator.NextItem(out var item, out var slot))
if (_inventorySystem.TryGetSlotEntity(uid, Jumpsuit, out var suit, component)
&& TryComp(suit, out ClothingComponent? clothing))
{
RenderEquipment(uid, item, slot.Name, component);
SetGenderedMask(uid, args.Sprite, clothing);
return;
}
// No clothing equipped -> make sure the layer is hidden, though this should already be handled by on-unequip.
@@ -188,6 +186,14 @@ public sealed class ClientClothingSystem : ClothingSystem
private void OnDidUnequip(EntityUid uid, SpriteComponent component, DidUnequipEvent args)
{
// Hide jumpsuit mask layer.
if (args.Slot == Jumpsuit
&& TryComp(uid, out SpriteComponent? sprite)
&& sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var maskLayer))
{
sprite.LayerSetVisible(maskLayer, false);
}
if (!TryComp(uid, out InventorySlotsComponent? inventorySlots))
return;
@@ -232,6 +238,9 @@ public sealed class ClientClothingSystem : ClothingSystem
return;
}
if (slot == Jumpsuit)
SetGenderedMask(equipee, sprite, clothingComponent);
if (!_inventorySystem.TryGetSlot(equipee, slot, out var slotDef, inventory))
return;
@@ -263,25 +272,7 @@ public sealed class ClientClothingSystem : ClothingSystem
// temporary, until layer draw depths get added. Basically: a layer with the key "slot" is being used as a
// bookmark to determine where in the list of layers we should insert the clothing layers.
bool slotLayerExists = sprite.LayerMapTryGet(slot, out var index);
// Select displacement maps
var displacementData = inventory.Displacements.GetValueOrDefault(slot); //Default unsexed map
var equipeeSex = CompOrNull<HumanoidAppearanceComponent>(equipee)?.Sex;
if (equipeeSex != null)
{
switch (equipeeSex)
{
case Sex.Male:
if (inventory.MaleDisplacements.Count > 0)
displacementData = inventory.MaleDisplacements.GetValueOrDefault(slot);
break;
case Sex.Female:
if (inventory.FemaleDisplacements.Count > 0)
displacementData = inventory.FemaleDisplacements.GetValueOrDefault(slot);
break;
}
}
var displacementData = inventory.Displacements.GetValueOrDefault(slot);
// add the new layers
foreach (var (key, layerData) in ev.Layers)
@@ -308,7 +299,7 @@ public sealed class ClientClothingSystem : ClothingSystem
index = sprite.LayerMapReserveBlank(key);
if (sprite[index] is not Layer layer)
continue;
return;
// In case no RSI is given, use the item's base RSI as a default. This cuts down on a lot of unnecessary yaml entries.
if (layerData.RsiPath == null
@@ -319,19 +310,78 @@ public sealed class ClientClothingSystem : ClothingSystem
layer.SetRsi(clothingSprite.BaseRSI);
}
// Another "temporary" fix for clothing stencil masks.
// Sprite layer redactor when
// Sprite "redactor" just a week away.
if (slot == Jumpsuit)
layerData.Shader ??= "StencilDraw";
sprite.LayerSetData(index, layerData);
layer.Offset += slotDef.Offset;
if (displacementData is not null)
if (displacementData != null)
{
//Checking that the state is not tied to the current race. In this case we don't need to use the displacement maps.
if (layerData.State is not null && inventory.SpeciesId is not null && layerData.State.EndsWith(inventory.SpeciesId))
continue;
if (displacementData.ShaderOverride != null)
sprite.LayerSetShader(index, displacementData.ShaderOverride);
_displacement.TryAddDisplacement(displacementData, sprite, index, key, revealedLayers);
var displacementKey = $"{key}-displacement";
if (!revealedLayers.Add(displacementKey))
{
Log.Warning($"Duplicate key for clothing visuals DISPLACEMENT: {displacementKey}.");
continue;
}
var displacementLayer = _serialization.CreateCopy(displacementData.Layer, notNullableOverride: true);
displacementLayer.CopyToShaderParameters!.LayerKey = key;
// Add before main layer for this item.
sprite.AddLayer(displacementLayer, index);
sprite.LayerMapSet(displacementKey, index);
revealedLayers.Add(displacementKey);
}
}
RaiseLocalEvent(equipment, new EquipmentVisualsUpdatedEvent(equipee, slot, revealedLayers), true);
}
/// <summary>
/// Sets a sprite's gendered mask based on gender (obviously).
/// </summary>
/// <param name="sprite">Sprite to modify</param>
/// <param name="humanoid">Humanoid, to get gender from</param>
/// <param name="clothing">Clothing component, to get mask sprite type</param>
private void SetGenderedMask(EntityUid uid, SpriteComponent sprite, ClothingComponent clothing)
{
if (!sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer))
return;
ClothingMask mask;
string prefix;
switch (CompOrNull<HumanoidAppearanceComponent>(uid)?.Sex)
{
case Sex.Male:
mask = clothing.MaleMask;
prefix = "male_";
break;
case Sex.Female:
mask = clothing.FemaleMask;
prefix = "female_";
break;
default:
mask = clothing.UnisexMask;
prefix = "unisex_";
break;
}
sprite.LayerSetState(layer, mask switch
{
ClothingMask.NoMask => $"{prefix}none",
ClothingMask.UniformTop => $"{prefix}top",
_ => $"{prefix}full",
});
sprite.LayerSetVisible(layer, true);
}
}

View File

@@ -2,7 +2,6 @@
using Content.Shared.Clothing.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.Clothing.UI;
@@ -23,8 +22,10 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
{
base.Open();
_menu = this.CreateWindow<ChameleonMenu>();
_menu = new ChameleonMenu();
_menu.OnClose += Close;
_menu.OnIdSelected += OnIdSelected;
_menu.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -41,4 +42,15 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
{
SendMessage(new ChameleonPrototypeSelectedMessage(selectedId));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_menu?.Close();
_menu = null;
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using System.Numerics;
using Content.Client.Clothing.Systems;
using Content.Client.Stylesheets;
@@ -74,9 +74,13 @@ public sealed partial class ChameleonMenu : DefaultWindow
};
button.OnPressed += _ => OnIdSelected?.Invoke(id);
Grid.AddChild(button);
var entityPrototypeView = new EntityPrototypeView();
button.AddChild(entityPrototypeView);
entityPrototypeView.SetPrototype(proto);
var texture = _sprite.GetPrototypeIcon(proto);
button.AddChild(new TextureRect
{
Stretch = TextureRect.StretchMode.KeepAspectCentered,
Texture = texture.Default
});
}
}

View File

@@ -20,7 +20,7 @@ public sealed class ZoomCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
Vector2 zoom;
if (args.Length is not (1 or 2 or 3))
if (args.Length is not (1 or 2))
{
shell.WriteLine(Help);
return;
@@ -57,18 +57,11 @@ public sealed class ZoomCommand : LocalizedCommands
}
}
var scalePvs = true;
if (args.Length == 3 && !bool.TryParse(args[2], out scalePvs))
{
shell.WriteError(LocalizationManager.GetString("cmd-parse-failure-bool", ("arg", args[2])));
return;
}
var player = _playerManager.LocalSession?.AttachedEntity;
if (_entityManager.TryGetComponent<ContentEyeComponent>(player, out var content))
{
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, scalePvs, content);
_entityManager.System<ContentEyeSystem>().RequestZoom(player.Value, zoom, true, content);
return;
}

View File

@@ -1,7 +1,6 @@
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Communications;
using Robust.Client.UserInterface;
using Robust.Shared.Configuration;
using Robust.Shared.Timing;
@@ -9,11 +8,34 @@ namespace Content.Client.Communications.UI
{
public sealed class CommunicationsConsoleBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[ViewVariables]
private CommunicationsConsoleMenu? _menu;
[ViewVariables]
public bool CanAnnounce { get; private set; }
[ViewVariables]
public bool CanBroadcast { get; private set; }
[ViewVariables]
public bool CanCall { get; private set; }
[ViewVariables]
public bool CountdownStarted { get; private set; }
[ViewVariables]
public bool AlertLevelSelectable { get; private set; }
[ViewVariables]
public string CurrentLevel { get; private set; } = default!;
[ViewVariables]
private TimeSpan? _expectedCountdownTime;
public int Countdown => _expectedCountdownTime == null ? 0 : Math.Max((int) _expectedCountdownTime.Value.Subtract(_gameTiming.CurTime).TotalSeconds, 0);
public CommunicationsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
@@ -22,25 +44,23 @@ namespace Content.Client.Communications.UI
{
base.Open();
_menu = this.CreateWindow<CommunicationsConsoleMenu>();
_menu.OnAnnounce += AnnounceButtonPressed;
_menu.OnBroadcast += BroadcastButtonPressed;
_menu.OnAlertLevel += AlertLevelSelected;
_menu.OnEmergencyLevel += EmergencyShuttleButtonPressed;
_menu = new CommunicationsConsoleMenu(this);
_menu.OnClose += Close;
_menu.OpenCentered();
}
public void AlertLevelSelected(string level)
{
if (_menu!.AlertLevelSelectable)
if (AlertLevelSelectable)
{
_menu.CurrentLevel = level;
CurrentLevel = level;
SendMessage(new CommunicationsConsoleSelectAlertLevelMessage(level));
}
}
public void EmergencyShuttleButtonPressed()
{
if (_menu!.CountdownStarted)
if (CountdownStarted)
RecallShuttle();
else
CallShuttle();
@@ -75,23 +95,31 @@ namespace Content.Client.Communications.UI
if (state is not CommunicationsConsoleInterfaceState commsState)
return;
CanAnnounce = commsState.CanAnnounce;
CanBroadcast = commsState.CanBroadcast;
CanCall = commsState.CanCall;
_expectedCountdownTime = commsState.ExpectedCountdownEnd;
CountdownStarted = commsState.CountdownStarted;
AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0;
CurrentLevel = commsState.CurrentAlert;
if (_menu != null)
{
_menu.CanAnnounce = commsState.CanAnnounce;
_menu.CanBroadcast = commsState.CanBroadcast;
_menu.CanCall = commsState.CanCall;
_menu.CountdownStarted = commsState.CountdownStarted;
_menu.AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0;
_menu.CurrentLevel = commsState.CurrentAlert;
_menu.CountdownEnd = commsState.ExpectedCountdownEnd;
_menu.UpdateCountdown();
_menu.UpdateAlertLevels(commsState.AlertLevels, _menu.CurrentLevel);
_menu.AlertLevelButton.Disabled = !_menu.AlertLevelSelectable;
_menu.EmergencyShuttleButton.Disabled = !_menu.CanCall;
_menu.AnnounceButton.Disabled = !_menu.CanAnnounce;
_menu.BroadcastButton.Disabled = !_menu.CanBroadcast;
_menu.UpdateAlertLevels(commsState.AlertLevels, CurrentLevel);
_menu.AlertLevelButton.Disabled = !AlertLevelSelectable;
_menu.EmergencyShuttleButton.Disabled = !CanCall;
_menu.AnnounceButton.Disabled = !CanAnnounce;
_menu.BroadcastButton.Disabled = !CanBroadcast;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_menu?.Dispose();
}
}
}

View File

@@ -1,40 +1,31 @@
using System.Globalization;
using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Controls;
using System.Threading;
using Content.Shared.CCVar;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Timer = Robust.Shared.Timing.Timer;
namespace Content.Client.Communications.UI
{
[GenerateTypedNameReferences]
public sealed partial class CommunicationsConsoleMenu : FancyWindow
{
private CommunicationsConsoleBoundUserInterface Owner { get; set; }
private readonly CancellationTokenSource _timerCancelTokenSource = new();
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ILocalizationManager _loc = default!;
public bool CanAnnounce;
public bool CanBroadcast;
public bool CanCall;
public bool AlertLevelSelectable;
public bool CountdownStarted;
public string CurrentLevel = string.Empty;
public TimeSpan? CountdownEnd;
public event Action? OnEmergencyLevel;
public event Action<string>? OnAlertLevel;
public event Action<string>? OnAnnounce;
public event Action<string>? OnBroadcast;
public CommunicationsConsoleMenu()
public CommunicationsConsoleMenu(CommunicationsConsoleBoundUserInterface owner)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
MessageInput.Placeholder = new Rope.Leaf(_loc.GetString("comms-console-menu-announcement-placeholder"));
Owner = owner;
var loc = IoCManager.Resolve<ILocalizationManager>();
MessageInput.Placeholder = new Rope.Leaf(loc.GetString("comms-console-menu-announcement-placeholder"));
var maxAnnounceLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength);
MessageInput.OnTextChanged += (args) =>
@@ -46,38 +37,33 @@ namespace Content.Client.Communications.UI
}
else
{
AnnounceButton.Disabled = !CanAnnounce;
AnnounceButton.Disabled = !owner.CanAnnounce;
AnnounceButton.ToolTip = null;
}
};
AnnounceButton.OnPressed += _ => OnAnnounce?.Invoke(Rope.Collapse(MessageInput.TextRope));
AnnounceButton.Disabled = !CanAnnounce;
AnnounceButton.OnPressed += (_) => Owner.AnnounceButtonPressed(Rope.Collapse(MessageInput.TextRope));
AnnounceButton.Disabled = !owner.CanAnnounce;
BroadcastButton.OnPressed += _ => OnBroadcast?.Invoke(Rope.Collapse(MessageInput.TextRope));
BroadcastButton.Disabled = !CanBroadcast;
BroadcastButton.OnPressed += (_) => Owner.BroadcastButtonPressed(Rope.Collapse(MessageInput.TextRope));
BroadcastButton.Disabled = !owner.CanBroadcast;
AlertLevelButton.OnItemSelected += args =>
{
var metadata = AlertLevelButton.GetItemMetadata(args.Id);
if (metadata != null && metadata is string cast)
{
OnAlertLevel?.Invoke(cast);
Owner.AlertLevelSelected(cast);
}
};
AlertLevelButton.Disabled = !owner.AlertLevelSelectable;
EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed();
EmergencyShuttleButton.Disabled = !owner.CanCall;
AlertLevelButton.Disabled = !AlertLevelSelectable;
EmergencyShuttleButton.OnPressed += _ => OnEmergencyLevel?.Invoke();
EmergencyShuttleButton.Disabled = !CanCall;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateCountdown();
Timer.SpawnRepeating(1000, UpdateCountdown, _timerCancelTokenSource.Token);
}
// The current alert could make levels unselectable, so we need to ensure that the UI reacts properly.
@@ -119,19 +105,30 @@ namespace Content.Client.Communications.UI
public void UpdateCountdown()
{
if (!CountdownStarted)
if (!Owner.CountdownStarted)
{
CountdownLabel.SetMessage(string.Empty);
CountdownLabel.SetMessage("");
EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-call-shuttle");
return;
}
var diff = MathHelper.Max((CountdownEnd - _timing.CurTime) ?? TimeSpan.Zero, TimeSpan.Zero);
EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-recall-shuttle");
var infoText = Loc.GetString($"comms-console-menu-time-remaining",
("time", diff.TotalSeconds.ToString(CultureInfo.CurrentCulture)));
CountdownLabel.SetMessage(infoText);
CountdownLabel.SetMessage($"Time remaining\n{Owner.Countdown.ToString()}s");
}
public override void Close()
{
base.Close();
_timerCancelTokenSource.Cancel();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_timerCancelTokenSource.Cancel();
}
}
}

View File

@@ -1,5 +1,4 @@
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
namespace Content.Client.Computer
@@ -20,8 +19,10 @@ namespace Content.Client.Computer
{
base.Open();
_window = this.CreateWindow<TWindow>();
_window = (TWindow) _dynamicTypeFactory.CreateInstance(typeof(TWindow));
_window.SetupComputerWindow(this);
_window.OnClose += Close;
_window.OpenCentered();
}
// Alas, this constructor has to be copied to the subclass. :(
@@ -41,6 +42,16 @@ namespace Content.Client.Computer
_window.UpdateState((TState) state);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
{
_window?.ReceiveMessage(message);

View File

@@ -1,6 +1,5 @@
using System.Text.RegularExpressions;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using static Content.Shared.Configurable.ConfigurationComponent;
namespace Content.Client.Configurable.UI
@@ -10,6 +9,9 @@ namespace Content.Client.Configurable.UI
[ViewVariables]
private ConfigurationMenu? _menu;
[ViewVariables]
public Regex? Validation { get; internal set; }
public ConfigurationBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
@@ -17,8 +19,10 @@ namespace Content.Client.Configurable.UI
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<ConfigurationMenu>();
_menu.OnConfiguration += SendConfiguration;
_menu = new ConfigurationMenu(this);
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -26,7 +30,9 @@ namespace Content.Client.Configurable.UI
base.UpdateState(state);
if (state is not ConfigurationBoundUserInterfaceState configurationState)
{
return;
}
_menu?.Populate(configurationState);
}
@@ -35,12 +41,9 @@ namespace Content.Client.Configurable.UI
{
base.ReceiveMessage(message);
if (_menu == null)
return;
if (message is ValidationUpdateMessage msg)
{
_menu.Validation = new Regex(msg.ValidationString, RegexOptions.Compiled);
Validation = new Regex(msg.ValidationString, RegexOptions.Compiled);
}
}
@@ -48,5 +51,16 @@ namespace Content.Client.Configurable.UI
{
SendMessage(new ConfigurationUpdatedMessage(config));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && _menu != null)
{
_menu.OnClose -= Close;
_menu.Close();
}
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Numerics;
using System.Text.RegularExpressions;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
@@ -14,25 +13,23 @@ namespace Content.Client.Configurable.UI
{
public sealed class ConfigurationMenu : DefaultWindow
{
public ConfigurationBoundUserInterface Owner { get; }
private readonly BoxContainer _column;
private readonly BoxContainer _row;
private readonly List<(string name, LineEdit input)> _inputs;
[ViewVariables]
public Regex? Validation { get; internal set; }
public event Action<Dictionary<string, string>>? OnConfiguration;
public ConfigurationMenu()
public ConfigurationMenu(ConfigurationBoundUserInterface owner)
{
MinSize = SetSize = new Vector2(300, 250);
Owner = owner;
_inputs = new List<(string name, LineEdit input)>();
Title = Loc.GetString("configuration-menu-device-title");
var baseContainer = new BoxContainer
BoxContainer baseContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
@@ -119,13 +116,14 @@ namespace Content.Client.Configurable.UI
private void OnConfirm(ButtonEventArgs args)
{
var config = GenerateDictionary(_inputs, "Text");
OnConfiguration?.Invoke(config);
Owner.SendConfiguration(config);
Close();
}
private bool Validate(string value)
{
return Validation?.IsMatch(value) != false;
return Owner.Validation == null || Owner.Validation.IsMatch(value);
}
private Dictionary<string, string> GenerateDictionary(IEnumerable<(string name, LineEdit input)> inputs, string propertyName)

View File

@@ -26,6 +26,7 @@ namespace Content.Client.Construction
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
@@ -47,11 +48,11 @@ namespace Content.Client.Construction
CommandBinds.Builder
.Bind(ContentKeyFunctions.OpenCraftingMenu,
new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction: true))
new PointerInputCmdHandler(HandleOpenCraftingMenu, outsidePrediction:true))
.Bind(EngineKeyFunctions.Use,
new PointerInputCmdHandler(HandleUse, outsidePrediction: true))
.Bind(ContentKeyFunctions.EditorFlipObject,
new PointerInputCmdHandler(HandleFlip, outsidePrediction: true))
new PointerInputCmdHandler(HandleFlip, outsidePrediction:true))
.Register<ConstructionSystem>();
SubscribeLocalEvent<ConstructionGhostComponent, ExaminedEvent>(HandleConstructionGhostExamined);
@@ -195,7 +196,7 @@ namespace Content.Client.Construction
if (GhostPresent(loc))
return false;
var predicate = GetPredicate(prototype.CanBuildInImpassable, _transformSystem.ToMapCoordinates(loc));
var predicate = GetPredicate(prototype.CanBuildInImpassable, loc.ToMap(EntityManager, _transformSystem));
if (!_examineSystem.InRangeUnOccluded(user, loc, 20f, predicate: predicate))
return false;

View File

@@ -1,33 +1,29 @@
<DefaultWindow xmlns="https://spacestation14.io">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4" Margin="0 0 5 0">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 0 0 5">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
<OptionButton Name="OptionCategories" Access="Public" MinSize="130 0"/>
<OptionButton Name="Category" Access="Public" MinSize="130 0"/>
</BoxContainer>
<ItemList Name="Recipes" Access="Public" SelectMode="Single" VerticalExpand="True"/>
</BoxContainer>
<Control MinSize="10 0"/>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
<Button Name="FavoriteButton" Visible="false" HorizontalExpand="False"
HorizontalAlignment="Right" Margin="0 0 0 15"/>
<Control>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="0 0 0 5">
<BoxContainer Orientation="Horizontal" Align="Center">
<TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep" Margin="0 0 10 0"/>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="TargetName"/>
<RichTextLabel Name="TargetDesc"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Align="Center">
<TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep"/>
<Control MinSize="10 0"/>
<BoxContainer Orientation="Vertical">
<RichTextLabel Name="TargetName"/>
<RichTextLabel Name="TargetDesc"/>
</BoxContainer>
</BoxContainer>
</Control>
<ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True" Margin="0 0 0 5"/>
<ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True"/>
<BoxContainer Orientation="Vertical">
<Button Name="BuildButton" Disabled="True" ToggleMode="True"
VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
<Button Name="BuildButton" Disabled="True" ToggleMode="True" VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
<BoxContainer Orientation="Horizontal" VerticalExpand="True" SizeFlagsStretchRatio="0.5">
<Button Name="EraseButton" ToggleMode="True"
HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
<Button Name="EraseButton" ToggleMode="True" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
<Button Name="ClearButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"/>
</BoxContainer>
</BoxContainer>

View File

@@ -22,7 +22,7 @@ namespace Content.Client.Construction.UI
// It isn't optimal to expose UI controls like this, but the UI control design is
// questionable so it can't be helped.
string[] Categories { get; set; }
OptionButton OptionCategories { get; }
OptionButton Category { get; }
bool EraseButtonPressed { get; set; }
bool BuildButtonPressed { get; set; }
@@ -32,13 +32,12 @@ namespace Content.Client.Construction.UI
event EventHandler<(string search, string catagory)> PopulateRecipes;
event EventHandler<ItemList.Item?> RecipeSelected;
event EventHandler RecipeFavorited;
event EventHandler<bool> BuildButtonToggled;
event EventHandler<bool> EraseButtonToggled;
event EventHandler ClearAllGhosts;
void ClearRecipeInfo();
void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem, bool isFavorite);
void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem);
void ResetPlacement();
#region Window Control
@@ -85,12 +84,10 @@ namespace Content.Client.Construction.UI
Recipes.OnItemSelected += obj => RecipeSelected?.Invoke(this, obj.ItemList[obj.ItemIndex]);
Recipes.OnItemDeselected += _ => RecipeSelected?.Invoke(this, null);
SearchBar.OnTextChanged += _ =>
PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[OptionCategories.SelectedId]));
OptionCategories.OnItemSelected += obj =>
SearchBar.OnTextChanged += _ => PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[Category.SelectedId]));
Category.OnItemSelected += obj =>
{
OptionCategories.SelectId(obj.Id);
SearchBar.SetText(string.Empty);
Category.SelectId(obj.Id);
PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[obj.Id]));
};
@@ -100,14 +97,12 @@ namespace Content.Client.Construction.UI
ClearButton.OnPressed += _ => ClearAllGhosts?.Invoke(this, EventArgs.Empty);
EraseButton.Text = Loc.GetString("construction-menu-eraser-mode");
EraseButton.OnToggled += args => EraseButtonToggled?.Invoke(this, args.Pressed);
FavoriteButton.OnPressed += args => RecipeFavorited?.Invoke(this, EventArgs.Empty);
}
public event EventHandler? ClearAllGhosts;
public event EventHandler<(string search, string catagory)>? PopulateRecipes;
public event EventHandler<ItemList.Item?>? RecipeSelected;
public event EventHandler? RecipeFavorited;
public event EventHandler<bool>? BuildButtonToggled;
public event EventHandler<bool>? EraseButtonToggled;
@@ -117,17 +112,13 @@ namespace Content.Client.Construction.UI
EraseButton.Pressed = false;
}
public void SetRecipeInfo(
string name, string description, Texture iconTexture, bool isItem, bool isFavorite)
public void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem)
{
BuildButton.Disabled = false;
BuildButton.Text = Loc.GetString(isItem ? "construction-menu-place-ghost" : "construction-menu-craft");
TargetName.SetMessage(name);
TargetDesc.SetMessage(description);
TargetTexture.Texture = iconTexture;
FavoriteButton.Visible = true;
FavoriteButton.Text = Loc.GetString(
isFavorite ? "construction-add-favorite-button" : "construction-remove-from-favorite-button");
}
public void ClearRecipeInfo()
@@ -136,7 +127,6 @@ namespace Content.Client.Construction.UI
TargetName.SetMessage(string.Empty);
TargetDesc.SetMessage(string.Empty);
TargetTexture.Texture = null;
FavoriteButton.Visible = false;
RecipeStepList.Clear();
}
}

View File

@@ -36,10 +36,7 @@ namespace Content.Client.Construction.UI
private ConstructionSystem? _constructionSystem;
private ConstructionPrototype? _selected;
private List<ConstructionPrototype> _favoritedRecipes = [];
private string _selectedCategory = string.Empty;
private string _favoriteCatName = "construction-category-favorites";
private string _forAllCategoryName = "construction-category-all";
private bool CraftingAvailable
{
get => _uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.Visible;
@@ -68,7 +65,7 @@ namespace Content.Client.Construction.UI
else
_constructionView.OpenCentered();
if (_selected != null)
if(_selected != null)
PopulateInfo(_selected);
}
else
@@ -108,10 +105,9 @@ namespace Content.Client.Construction.UI
_constructionView.EraseButtonPressed = b;
};
_constructionView.RecipeFavorited += (_, _) => OnViewFavoriteRecipe();
PopulateCategories();
OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
}
public void OnHudCraftingButtonToggled(ButtonToggledEventArgs args)
@@ -158,13 +154,6 @@ namespace Content.Client.Construction.UI
recipesList.Clear();
var recipes = new List<ConstructionPrototype>();
var isEmptyCategory = string.IsNullOrEmpty(category) || category == _forAllCategoryName;
if (isEmptyCategory)
_selectedCategory = string.Empty;
else
_selectedCategory = category;
foreach (var recipe in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
{
if (recipe.Hide)
@@ -184,19 +173,10 @@ namespace Content.Client.Construction.UI
continue;
}
if (!isEmptyCategory)
if (!string.IsNullOrEmpty(category) && category != "construction-category-all")
{
if (category == _favoriteCatName)
{
if (!_favoritedRecipes.Contains(recipe))
{
continue;
}
}
else if (recipe.Category != category)
{
if (recipe.Category != category)
continue;
}
}
recipes.Add(recipe);
@@ -212,10 +192,13 @@ namespace Content.Client.Construction.UI
// There is apparently no way to set which
}
private void PopulateCategories(string? selectCategory = null)
private void PopulateCategories()
{
var uniqueCategories = new HashSet<string>();
// hard-coded to show all recipes
uniqueCategories.Add("construction-category-all");
foreach (var prototype in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
{
var category = prototype.Category;
@@ -224,49 +207,25 @@ namespace Content.Client.Construction.UI
uniqueCategories.Add(category);
}
var isFavorites = _favoritedRecipes.Count > 0;
var categoriesArray = new string[isFavorites ? uniqueCategories.Count + 2 : uniqueCategories.Count + 1];
_constructionView.Category.Clear();
// hard-coded to show all recipes
var idx = 0;
categoriesArray[idx++] = _forAllCategoryName;
var array = uniqueCategories.OrderBy(Loc.GetString).ToArray();
Array.Sort(array);
// hard-coded to show favorites if it need
if (isFavorites)
for (var i = 0; i < array.Length; i++)
{
categoriesArray[idx++] = _favoriteCatName;
var category = array[i];
_constructionView.Category.AddItem(Loc.GetString(category), i);
}
var sortedProtoCategories = uniqueCategories.OrderBy(Loc.GetString);
foreach (var cat in sortedProtoCategories)
{
categoriesArray[idx++] = cat;
}
_constructionView.OptionCategories.Clear();
for (var i = 0; i < categoriesArray.Length; i++)
{
_constructionView.OptionCategories.AddItem(Loc.GetString(categoriesArray[i]), i);
if (!string.IsNullOrEmpty(selectCategory) && selectCategory == categoriesArray[i])
_constructionView.OptionCategories.SelectId(i);
}
_constructionView.Categories = categoriesArray;
_constructionView.Categories = array;
}
private void PopulateInfo(ConstructionPrototype prototype)
{
var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
_constructionView.ClearRecipeInfo();
_constructionView.SetRecipeInfo(
prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon),
prototype.Type != ConstructionType.Item,
!_favoritedRecipes.Contains(prototype));
_constructionView.SetRecipeInfo(prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon), prototype.Type != ConstructionType.Item);
var stepList = _constructionView.RecipeStepList;
GenerateStepList(prototype, stepList);
@@ -284,7 +243,7 @@ namespace Content.Client.Construction.UI
var text = entry.Arguments != null
? Loc.GetString(entry.Localization, entry.Arguments) : Loc.GetString(entry.Localization);
if (entry.EntryNumber is { } number)
if (entry.EntryNumber is {} number)
{
text = Loc.GetString("construction-presenter-step-wrapper",
("step-number", number), ("text", text));
@@ -376,26 +335,6 @@ namespace Content.Client.Construction.UI
if (args.System is ConstructionSystem) SystemBindingChanged(null);
}
private void OnViewFavoriteRecipe()
{
if (_selected is not ConstructionPrototype recipe)
return;
if (!_favoritedRecipes.Remove(_selected))
_favoritedRecipes.Add(_selected);
if (_selectedCategory == _favoriteCatName)
{
if (_favoritedRecipes.Count > 0)
OnViewPopulateRecipes(_constructionView, (string.Empty, _favoriteCatName));
else
OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
}
PopulateInfo(_selected);
PopulateCategories(_selectedCategory);
}
private void SystemBindingChanged(ConstructionSystem? newSystem)
{
if (newSystem is null)

View File

@@ -1,6 +1,5 @@
using Content.Shared.Construction.Components;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Construction.UI
{
@@ -18,8 +17,8 @@ namespace Content.Client.Construction.UI
{
base.Open();
_menu = this.CreateWindow<FlatpackCreatorMenu>();
_menu.SetEntity(Owner);
_menu = new FlatpackCreatorMenu(Owner);
_menu.OnClose += Close;
_menu.PackButtonPressed += () =>
{
@@ -28,5 +27,14 @@ namespace Content.Client.Construction.UI
_menu.OpenCentered();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Dispose();
}
}
}

View File

@@ -24,7 +24,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
private readonly FlatpackSystem _flatpack;
private readonly MaterialStorageSystem _materialStorage;
private EntityUid _owner;
private readonly EntityUid _owner;
[ValidatePrototypeId<EntityPrototype>]
public const string NoBoardEffectId = "FlatpackerNoBoardEffect";
@@ -33,7 +33,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
public event Action? PackButtonPressed;
public FlatpackCreatorMenu()
public FlatpackCreatorMenu(EntityUid uid)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
@@ -42,15 +42,12 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
_flatpack = _entityManager.System<FlatpackSystem>();
_materialStorage = _entityManager.System<MaterialStorageSystem>();
_owner = uid;
PackButton.OnPressed += _ => PackButtonPressed?.Invoke();
InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board"));
}
public void SetEntity(EntityUid uid)
{
_owner = uid;
MaterialStorageControl.SetOwner(uid);
InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board"));
}
protected override void FrameUpdate(FrameEventArgs args)

View File

@@ -170,7 +170,7 @@ namespace Content.Client.ContextMenu.UI
if (_combatMode.IsInCombatMode(args.Session?.AttachedEntity))
return false;
var coords = _xform.ToMapCoordinates(args.Coordinates);
var coords = args.Coordinates.ToMap(_entityManager, _xform);
if (_verbSystem.TryGetEntityMenuEntities(coords, out var entities))
OpenRootMenu(entities);

View File

@@ -2,15 +2,12 @@
using Content.Shared.Crayon;
using Content.Shared.Decals;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
namespace Content.Client.Crayon.UI
{
public sealed class CrayonBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[ViewVariables]
private CrayonWindow? _menu;
@@ -21,29 +18,15 @@ namespace Content.Client.Crayon.UI
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<CrayonWindow>();
_menu.OnColorSelected += SelectColor;
_menu.OnSelected += Select;
PopulateCrayons();
_menu = new CrayonWindow(this);
_menu.OnClose += Close;
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var crayonDecals = prototypeManager.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("crayon"));
_menu.Populate(crayonDecals);
_menu.OpenCenteredLeft();
}
private void PopulateCrayons()
{
var crayonDecals = _protoManager.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("crayon"));
_menu?.Populate(crayonDecals);
}
public override void OnProtoReload(PrototypesReloadedEventArgs args)
{
base.OnProtoReload(args);
if (!args.WasModified<DecalPrototype>())
return;
PopulateCrayons();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
@@ -60,5 +43,16 @@ namespace Content.Client.Crayon.UI
{
SendMessage(new CrayonColorMessage(color));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_menu?.Close();
_menu = null;
}
}
}
}

View File

@@ -18,17 +18,18 @@ namespace Content.Client.Crayon.UI
[GenerateTypedNameReferences]
public sealed partial class CrayonWindow : DefaultWindow
{
public CrayonBoundUserInterface Owner { get; }
private Dictionary<string, Texture>? _decals;
private string? _selected;
private Color _color;
public event Action<Color>? OnColorSelected;
public event Action<string>? OnSelected;
public CrayonWindow()
public CrayonWindow(CrayonBoundUserInterface owner)
{
RobustXamlLoader.Load(this);
Owner = owner;
Search.OnTextChanged += _ => RefreshList();
ColorSelector.OnColorChanged += SelectColor;
}
@@ -37,16 +38,16 @@ namespace Content.Client.Crayon.UI
{
_color = color;
OnColorSelected?.Invoke(color);
Owner.SelectColor(color);
RefreshList();
}
private void RefreshList()
{
// Clear
Grid.DisposeAllChildren();
if (_decals == null)
return;
Grid.RemoveAllChildren();
if (_decals == null) return;
var filter = Search.Text;
foreach (var (decal, tex) in _decals)
@@ -88,8 +89,8 @@ namespace Content.Client.Crayon.UI
{
if (obj.Button.Name == null) return;
Owner.Select(obj.Button.Name);
_selected = obj.Button.Name;
OnSelected?.Invoke(_selected);
RefreshList();
}

View File

@@ -1,28 +1,23 @@
using Content.Client.Administration.Managers;
using Content.Client.Administration.Managers;
using Content.Shared.CCVar;
using Robust.Client;
using Robust.Client.UserInterface;
using Robust.Shared.Configuration;
namespace Content.Client.DebugMon;
/// <summary>
/// This handles preventing certain debug monitors from being usable by non-admins.
/// This handles preventing certain debug monitors from appearing.
/// </summary>
internal sealed class DebugMonitorManager
public sealed class DebugMonitorSystem : EntitySystem
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IClientAdminManager _admin = default!;
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
[Dependency] private readonly IBaseClient _baseClient = default!;
public void FrameUpdate()
public override void FrameUpdate(float frameTime)
{
if (_baseClient.RunLevel == ClientRunLevel.InGame
&& !_admin.IsActive()
&& _cfg.GetCVar(CCVars.DebugCoordinatesAdminOnly))
{
if (!_admin.IsActive() && _cfg.GetCVar(CCVars.DebugCoordinatesAdminOnly))
_userInterface.DebugMonitors.SetMonitor(DebugMonitor.Coords, false);
}
}
}

View File

@@ -1,65 +0,0 @@
using Content.Shared.DisplacementMap;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Serialization.Manager;
namespace Content.Client.DisplacementMap;
public sealed class DisplacementMapSystem : EntitySystem
{
[Dependency] private readonly ISerializationManager _serialization = default!;
public bool TryAddDisplacement(DisplacementData data, SpriteComponent sprite, int index, string key, HashSet<string> revealedLayers)
{
if (data.ShaderOverride != null)
sprite.LayerSetShader(index, data.ShaderOverride);
var displacementKey = $"{key}-displacement";
if (!revealedLayers.Add(displacementKey))
{
Log.Warning($"Duplicate key for DISPLACEMENT: {displacementKey}.");
return false;
}
//allows you not to write it every time in the YML
foreach (var pair in data.SizeMaps)
{
pair.Value.CopyToShaderParameters??= new()
{
LayerKey = "dummy",
ParameterTexture = "displacementMap",
ParameterUV = "displacementUV",
};
}
if (!data.SizeMaps.ContainsKey(32))
{
Log.Error($"DISPLACEMENT: {displacementKey} don't have 32x32 default displacement map");
return false;
}
// We choose a displacement map from the possible ones, matching the size with the original layer size.
// If there is no such a map, we use a standard 32 by 32 one
var displacementDataLayer = data.SizeMaps[EyeManager.PixelsPerMeter];
var actualRSI = sprite.LayerGetActualRSI(index);
if (actualRSI is not null)
{
if (actualRSI.Size.X != actualRSI.Size.Y)
Log.Warning($"DISPLACEMENT: {displacementKey} has a resolution that is not 1:1, things can look crooked");
var layerSize = actualRSI.Size.X;
if (data.SizeMaps.ContainsKey(layerSize))
displacementDataLayer = data.SizeMaps[layerSize];
}
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
displacementLayer.CopyToShaderParameters!.LayerKey = key;
sprite.AddLayer(displacementLayer, index);
sprite.LayerMapSet(displacementKey, index);
revealedLayers.Add(displacementKey);
return true;
}
}

View File

@@ -1,6 +1,5 @@
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using static Content.Shared.Disposal.Components.SharedDisposalRouterComponent;
namespace Content.Client.Disposal.UI
@@ -22,16 +21,20 @@ namespace Content.Client.Disposal.UI
{
base.Open();
_window = this.CreateWindow<DisposalRouterWindow>();
_window = new DisposalRouterWindow();
_window.OpenCentered();
_window.OnClose += Close;
_window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
_window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
}
private void ButtonPressed(UiAction action, string tag)
{
SendMessage(new UiActionMessage(action, tag));
Close();
_window?.Close();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -45,5 +48,18 @@ namespace Content.Client.Disposal.UI
_window?.UpdateState(cast);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -1,6 +1,5 @@
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using static Content.Shared.Disposal.Components.SharedDisposalTaggerComponent;
namespace Content.Client.Disposal.UI
@@ -22,17 +21,20 @@ namespace Content.Client.Disposal.UI
{
base.Open();
_window = this.CreateWindow<DisposalTaggerWindow>();
_window = new DisposalTaggerWindow();
_window.OpenCentered();
_window.OnClose += Close;
_window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
_window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
}
private void ButtonPressed(UiAction action, string tag)
{
// TODO: This looks copy-pasted with the other mailing stuff...
SendMessage(new UiActionMessage(action, tag));
Close();
_window?.Close();
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -46,5 +48,18 @@ namespace Content.Client.Disposal.UI
_window?.UpdateState(cast);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More