Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Dmitry
2025-05-24 22:35:13 +07:00
1303 changed files with 78913 additions and 46683 deletions

View File

@@ -0,0 +1,54 @@
name: Trailing Whitespace Check
on:
pull_request:
types: [ opened, reopened, synchronize, ready_for_review ]
jobs:
build:
name: Trailing Whitespace Check
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- name: Get changed text files
id: changed-files
uses: tj-actions/changed-files@v46.0.5
with:
files: |
**.cs
**.yml
**.swsl
**.json
**.py
- name: Check for trailing whitespace and EOF newline
env:
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
has_trailing_whitespace=0
has_missing_eof_newline=0
for file in ${ALL_CHANGED_FILES}; do
echo "Checking $file"
# Check for trailing whitespace
if grep -qP '[ \t]+$' "$file"; then
echo "::error file=$file::Trailing whitespace found"
has_trailing_whitespace=1
fi
# Check for missing EOF newline
if [ -f "$file" ] && [ -s "$file" ]; then
last_char=$(tail -c 1 "$file")
if [ "$last_char" != "" ] && [ "$last_char" != $'\n' ]; then
echo "::error file=$file::Missing newline at end of file"
has_missing_eof_newline=1
fi
fi
done
if [ "$has_trailing_whitespace" -eq 1 ] || [ "$has_missing_eof_newline" -eq 1 ]; then
echo "Issues found: trailing whitespace or missing EOF newline."
echo "We recommend using an IDE to prevent this from happening."
exit 1
fi

View File

@@ -29,7 +29,7 @@ namespace Content.Benchmarks;
[CategoriesColumn]
public class ComponentQueryBenchmark
{
public const string Map = "Maps/atlas.yml";
public const string Map = "Maps/saltern.yml";
private TestPair _pair = default!;
private IEntityManager _entMan = default!;

View File

@@ -1,15 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Running;
using Content.IntegrationTests;
using Content.Server.Maps;
#if DEBUG
using BenchmarkDotNet.Configs;
#else
using Robust.Benchmarks.Configs;
#endif
using Robust.Shared.Prototypes;
namespace Content.Benchmarks
{
@@ -22,11 +14,15 @@ namespace Content.Benchmarks
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("\nWARNING: YOU ARE RUNNING A DEBUG BUILD, USE A RELEASE BUILD FOR AN ACCURATE BENCHMARK");
Console.WriteLine("THE DEBUG BUILD IS ONLY GOOD FOR FIXING A CRASHING BENCHMARK\n");
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new DebugInProcessConfig());
var baseConfig = new DebugInProcessConfig();
#else
var config = Environment.GetEnvironmentVariable("ROBUST_BENCHMARKS_ENABLE_SQL") != null ? DefaultSQLConfig.Instance : null;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
var baseConfig = Environment.GetEnvironmentVariable("ROBUST_BENCHMARKS_ENABLE_SQL") != null
? DefaultSQLConfig.Instance
: DefaultConfig.Instance;
#endif
var config = ManualConfig.Create(baseConfig);
config.BuildTimeout = TimeSpan.FromMinutes(5);
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
}
}
}

View File

@@ -0,0 +1,126 @@
#nullable enable
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
namespace Content.Benchmarks;
[Virtual]
public class RaiseEventBenchmark
{
private TestPair _pair = default!;
private BenchSystem _sys = default!;
[GlobalSetup]
public void Setup()
{
ProgramShared.PathOffset = "../../../../";
PoolManager.Startup(typeof(BenchSystem).Assembly);
_pair = PoolManager.GetServerClient().GetAwaiter().GetResult();
var entMan = _pair.Server.EntMan;
_sys = entMan.System<BenchSystem>();
_pair.Server.WaitPost(() =>
{
var uid = entMan.Spawn();
_sys.Ent = new(uid, entMan.GetComponent<TransformComponent>(uid));
_sys.Ent2 = new(_sys.Ent.Owner, _sys.Ent.Comp);
})
.GetAwaiter()
.GetResult();
}
[GlobalCleanup]
public async Task Cleanup()
{
await _pair.DisposeAsync();
PoolManager.Shutdown();
}
[Benchmark(Baseline = true)]
public int RaiseEvent()
{
return _sys.RaiseEvent();
}
[Benchmark]
public int RaiseCompEvent()
{
return _sys.RaiseCompEvent();
}
[Benchmark]
public int RaiseICompEvent()
{
return _sys.RaiseICompEvent();
}
[Benchmark]
public int RaiseCSharpEvent()
{
return _sys.CSharpEvent();
}
public sealed class BenchSystem : EntitySystem
{
public Entity<TransformComponent> Ent;
public Entity<IComponent> Ent2;
public delegate void EntityEventHandler(EntityUid uid, TransformComponent comp, ref BenchEv ev);
public event EntityEventHandler? OnCSharpEvent;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TransformComponent, BenchEv>(OnEvent);
OnCSharpEvent += OnEvent;
}
public int RaiseEvent()
{
var ev = new BenchEv();
RaiseLocalEvent(Ent.Owner, ref ev);
return ev.N;
}
public int RaiseCompEvent()
{
var ev = new BenchEv();
EntityManager.EventBus.RaiseComponentEvent(Ent.Owner, Ent.Comp, ref ev);
return ev.N;
}
public int RaiseICompEvent()
{
// Raise with an IComponent instead of concrete type
var ev = new BenchEv();
EntityManager.EventBus.RaiseComponentEvent(Ent2.Owner, Ent2.Comp, ref ev);
return ev.N;
}
public int CSharpEvent()
{
var ev = new BenchEv();
OnCSharpEvent?.Invoke(Ent.Owner, Ent.Comp, ref ev);
return ev.N;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void OnEvent(EntityUid uid, TransformComponent component, ref BenchEv args)
{
args.N += uid.Id;
}
[ByRefEvent]
public struct BenchEv
{
public int N;
}
}
}

View File

@@ -1,8 +1,10 @@
using Content.Shared.Access;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.CCVar;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.CrewManifest;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using static Content.Shared.Access.Components.IdCardConsoleComponent;
@@ -11,13 +13,21 @@ namespace Content.Client.Access.UI
public sealed class IdCardConsoleBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
private readonly SharedIdCardConsoleSystem _idCardConsoleSystem = default!;
private IdCardConsoleWindow? _window;
// CCVar.
private int _maxNameLength;
private int _maxIdJobLength;
public IdCardConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_idCardConsoleSystem = EntMan.System<SharedIdCardConsoleSystem>();
_maxNameLength =_cfgManager.GetCVar(CCVars.MaxNameLength);
_maxIdJobLength = _cfgManager.GetCVar(CCVars.MaxIdJobLength);
}
protected override void Open()
@@ -66,11 +76,11 @@ namespace Content.Client.Access.UI
public void SubmitData(string newFullName, string newJobTitle, List<ProtoId<AccessLevelPrototype>> newAccessList, string newJobPrototype)
{
if (newFullName.Length > MaxFullNameLength)
newFullName = newFullName[..MaxFullNameLength];
if (newFullName.Length > _maxNameLength)
newFullName = newFullName[.._maxNameLength];
if (newJobTitle.Length > MaxJobTitleLength)
newJobTitle = newJobTitle[..MaxJobTitleLength];
if (newJobTitle.Length > _maxIdJobLength)
newJobTitle = newJobTitle[.._maxIdJobLength];
SendMessage(new WriteToTargetIdMessage(
newFullName,

View File

@@ -1,11 +1,13 @@
using System.Linq;
using Content.Shared.Access;
using Content.Shared.Access.Systems;
using Content.Shared.CCVar;
using Content.Shared.Roles;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using static Content.Shared.Access.Components.IdCardConsoleComponent;
@@ -14,12 +16,17 @@ namespace Content.Client.Access.UI
[GenerateTypedNameReferences]
public sealed partial class IdCardConsoleWindow : DefaultWindow
{
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private readonly ISawmill _logMill = default!;
private readonly IdCardConsoleBoundUserInterface _owner;
// CCVar.
private int _maxNameLength;
private int _maxIdJobLength;
private AccessLevelControl _accessButtons = new();
private readonly List<string> _jobPrototypeIds = new();
@@ -39,7 +46,11 @@ namespace Content.Client.Access.UI
_owner = owner;
_maxNameLength = _cfgManager.GetCVar(CCVars.MaxNameLength);
_maxIdJobLength = _cfgManager.GetCVar(CCVars.MaxIdJobLength);
FullNameLineEdit.OnTextEntered += _ => SubmitData();
FullNameLineEdit.IsValid = s => s.Length <= _maxNameLength;
FullNameLineEdit.OnTextChanged += _ =>
{
FullNameSaveButton.Disabled = FullNameSaveButton.Text == _lastFullName;
@@ -47,6 +58,7 @@ namespace Content.Client.Access.UI
FullNameSaveButton.OnPressed += _ => SubmitData();
JobTitleLineEdit.OnTextEntered += _ => SubmitData();
JobTitleLineEdit.IsValid = s => s.Length <= _maxIdJobLength;
JobTitleLineEdit.OnTextChanged += _ =>
{
JobTitleSaveButton.Disabled = JobTitleLineEdit.Text == _lastJobTitle;

View File

@@ -7,6 +7,8 @@ namespace Content.Client.Administration.Systems;
public sealed class KillSignSystem : EntitySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
SubscribeLocalEvent<KillSignComponent, ComponentStartup>(KillSignAdded);
@@ -18,10 +20,10 @@ public sealed class KillSignSystem : EntitySystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
if (!sprite.LayerMapTryGet(KillSignKey.Key, out var layer))
if (!_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var layer, false))
return;
sprite.RemoveLayer(layer);
_sprite.RemoveLayer((uid, sprite), layer);
}
private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args)
@@ -29,15 +31,15 @@ public sealed class KillSignSystem : EntitySystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
if (sprite.LayerMapTryGet(KillSignKey.Key, out var _))
if (_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var _, false))
return;
var adj = sprite.Bounds.Height / 2 + ((1.0f/32) * 6.0f);
var adj = _sprite.GetLocalBounds((uid, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
sprite.LayerMapSet(KillSignKey.Key, layer);
var layer = _sprite.AddLayer((uid, sprite), new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
_sprite.LayerMapSet((uid, sprite), KillSignKey.Key, layer);
sprite.LayerSetOffset(layer, new Vector2(0.0f, adj));
_sprite.LayerSetOffset((uid, sprite), layer, new Vector2(0.0f, adj));
sprite.LayerSetShader(layer, "unshaded");
}

View File

@@ -19,10 +19,10 @@ namespace Content.Client.Administration.UI.SpawnExplosion;
public sealed partial class SpawnExplosionWindow : DefaultWindow
{
[Dependency] private readonly IClientConsoleHost _conHost = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
private readonly SharedMapSystem _mapSystem;
private readonly SharedTransformSystem _transform = default!;
private readonly SpawnExplosionEui _eui;
@@ -38,6 +38,7 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_mapSystem = _entMan.System<SharedMapSystem>();
_transform = _entMan.System<TransformSystem>();
_eui = eui;
@@ -87,7 +88,7 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow
{
_mapData.Clear();
MapOptions.Clear();
foreach (var map in _mapManager.GetAllMapIds())
foreach (var map in _mapSystem.GetAllMapIds())
{
_mapData.Add(map);
MapOptions.AddItem(map.ToString());

View File

@@ -14,6 +14,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
[UsedImplicitly]
public sealed partial class LoadBlueprintsWindow : DefaultWindow
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public LoadBlueprintsWindow()
{
RobustXamlLoader.Load(this);
@@ -21,9 +24,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
protected override void EnteredTree()
{
var mapManager = IoCManager.Resolve<IMapManager>();
var mapSystem = _entityManager.System<SharedMapSystem>();
foreach (var mapId in mapManager.GetAllMapIds())
foreach (var mapId in mapSystem.GetAllMapIds())
{
MapOptions.AddItem(mapId.ToString(), (int) mapId);
}
@@ -39,21 +42,19 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
private void Reset()
{
var entManager = IoCManager.Resolve<IEntityManager>();
var xformSystem = entManager.System<SharedTransformSystem>();
var playerManager = IoCManager.Resolve<IPlayerManager>();
var player = playerManager.LocalEntity;
var xformSystem = _entityManager.System<SharedTransformSystem>();
var player = _playerManager.LocalEntity;
var currentMap = MapId.Nullspace;
var position = Vector2.Zero;
var rotation = Angle.Zero;
if (entManager.TryGetComponent<TransformComponent>(player, out var xform))
if (_entityManager.TryGetComponent<TransformComponent>(player, out var xform))
{
currentMap = xform.MapID;
position = xformSystem.GetWorldPosition(xform);
if (entManager.TryGetComponent<TransformComponent>(xform.GridUid, out var gridXform))
if (_entityManager.TryGetComponent<TransformComponent>(xform.GridUid, out var gridXform))
{
rotation = xformSystem.GetWorldRotation(gridXform);
}

View File

@@ -8,6 +8,8 @@ namespace Content.Client.AlertLevel;
public sealed class AlertLevelDisplaySystem : EntitySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
@@ -21,26 +23,26 @@ public sealed class AlertLevelDisplaySystem : EntitySystem
{
return;
}
var layer = args.Sprite.LayerMapReserveBlank(AlertLevelDisplay.Layer);
var layer = _sprite.LayerMapReserve((uid, args.Sprite), AlertLevelDisplay.Layer);
if (args.AppearanceData.TryGetValue(AlertLevelDisplay.Powered, out var poweredObject))
{
args.Sprite.LayerSetVisible(layer, poweredObject is true);
_sprite.LayerSetVisible((uid, args.Sprite), layer, poweredObject is true);
}
if (!args.AppearanceData.TryGetValue(AlertLevelDisplay.CurrentLevel, out var level))
{
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
return;
}
if (alertLevelDisplay.AlertVisuals.TryGetValue((string) level, out var visual))
if (alertLevelDisplay.AlertVisuals.TryGetValue((string)level, out var visual))
{
args.Sprite.LayerSetState(layer, visual);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, visual);
}
else
{
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
}
}
}

View File

@@ -15,6 +15,7 @@ public sealed class EntityPickupAnimationSystem : EntitySystem
{
[Dependency] private readonly AnimationPlayerSystem _animations = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly TransformSystem _transform = default!;
public override void Initialize()
@@ -56,8 +57,8 @@ public sealed class EntityPickupAnimationSystem : EntitySystem
}
var sprite = Comp<SpriteComponent>(animatableClone);
sprite.CopyFrom(sprite0);
sprite.Visible = true;
_sprite.CopySprite((uid, sprite0), (animatableClone, sprite));
_sprite.SetVisible((animatableClone, sprite), true);
var animations = Comp<AnimationPlayerComponent>(animatableClone);

View File

@@ -11,6 +11,7 @@ public sealed class AnomalySystem : SharedAnomalySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly FloatingVisualizerSystem _floating = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -49,12 +50,12 @@ public sealed class AnomalySystem : SharedAnomalySystem
if (HasComp<AnomalySupercriticalComponent>(uid))
pulsing = true;
if (!sprite.LayerMapTryGet(AnomalyVisualLayers.Base, out var layer) ||
!sprite.LayerMapTryGet(AnomalyVisualLayers.Animated, out var animatedLayer))
if (!_sprite.LayerMapTryGet((uid, sprite), AnomalyVisualLayers.Base, out var layer, false) ||
!_sprite.LayerMapTryGet((uid, sprite), AnomalyVisualLayers.Animated, out var animatedLayer, false))
return;
sprite.LayerSetVisible(layer, !pulsing);
sprite.LayerSetVisible(animatedLayer, pulsing);
_sprite.LayerSetVisible((uid, sprite), layer, !pulsing);
_sprite.LayerSetVisible((uid, sprite), animatedLayer, pulsing);
}
public override void Update(float frameTime)
@@ -63,16 +64,16 @@ public sealed class AnomalySystem : SharedAnomalySystem
var query = EntityQueryEnumerator<AnomalySupercriticalComponent, SpriteComponent>();
while (query.MoveNext(out var super, out var sprite))
while (query.MoveNext(out var uid, out var super, out var sprite))
{
var completion = 1f - (float) ((super.EndTime - _timing.CurTime) / super.SupercriticalDuration);
var completion = 1f - (float)((super.EndTime - _timing.CurTime) / super.SupercriticalDuration);
var scale = completion * (super.MaxScaleAmount - 1f) + 1f;
sprite.Scale = new Vector2(scale, scale);
_sprite.SetScale((uid, sprite), new Vector2(scale, scale));
var transparency = (byte) (65 * (1f - completion) + 190);
var transparency = (byte)(65 * (1f - completion) + 190);
if (transparency < sprite.Color.AByte)
{
sprite.Color = sprite.Color.WithAlpha(transparency);
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(transparency));
}
}
}
@@ -82,7 +83,7 @@ public sealed class AnomalySystem : SharedAnomalySystem
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
sprite.Scale = Vector2.One;
sprite.Color = sprite.Color.WithAlpha(1f);
_sprite.SetScale((ent.Owner, sprite), Vector2.One);
_sprite.SetColor((ent.Owner, sprite), sprite.Color.WithAlpha(1f));
}
}

View File

@@ -7,6 +7,8 @@ namespace Content.Client.Anomaly.Effects;
public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
SubscribeLocalEvent<InnerBodyAnomalyComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
@@ -21,21 +23,20 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
if (ent.Comp.FallbackSprite is null)
return;
if (!sprite.LayerMapTryGet(ent.Comp.LayerMap, out var index))
index = sprite.LayerMapReserveBlank(ent.Comp.LayerMap);
var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap);
if (TryComp<BodyComponent>(ent, out var body) &&
body.Prototype is not null &&
ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite))
{
sprite.LayerSetSprite(index, speciesSprite);
_sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite);
}
else
{
sprite.LayerSetSprite(index, ent.Comp.FallbackSprite);
_sprite.LayerSetSprite((ent.Owner, sprite), index, ent.Comp.FallbackSprite);
}
sprite.LayerSetVisible(index, true);
_sprite.LayerSetVisible((ent.Owner, sprite), index, true);
sprite.LayerSetShader(index, "unshaded");
}
@@ -44,7 +45,7 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
var index = sprite.LayerMapGet(ent.Comp.LayerMap);
sprite.LayerSetVisible(index, false);
var index = _sprite.LayerMapGet((ent.Owner, sprite), ent.Comp.LayerMap);
_sprite.LayerSetVisible((ent.Owner, sprite), index, false);
}
}

View File

@@ -11,6 +11,7 @@ namespace Content.Client.Atmos.EntitySystems;
public sealed class AtmosPipeAppearanceSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -25,21 +26,22 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
if (!TryComp(uid, out SpriteComponent? sprite))
return;
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
{
sprite.LayerMapReserveBlank(layerKey);
var layer = sprite.LayerMapGet(layerKey);
sprite.LayerSetRSI(layer, component.Sprite.RsiPath);
sprite.LayerSetState(layer, component.Sprite.RsiState);
sprite.LayerSetDirOffset(layer, ToOffset(layerKey));
var layer = _sprite.LayerMapReserve((uid, sprite), layerKey);
_sprite.LayerSetRsi((uid, sprite), layer, component.Sprite.RsiPath);
_sprite.LayerSetRsiState((uid, sprite), layer, component.Sprite.RsiState);
_sprite.LayerSetDirOffset((uid, sprite), layer, ToOffset(layerKey));
}
}
private void HideAllPipeConnection(SpriteComponent sprite)
private void HideAllPipeConnection(Entity<SpriteComponent> entity)
{
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
var sprite = entity.Comp;
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
{
if (!sprite.LayerMapTryGet(layerKey, out var key))
if (!_sprite.LayerMapTryGet(entity.AsNullable(), layerKey, out var key, false))
continue;
var layer = sprite[key];
@@ -61,7 +63,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
if (!_appearance.TryGetData<PipeDirection>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
{
HideAllPipeConnection(args.Sprite);
HideAllPipeConnection((uid, args.Sprite));
return;
}
@@ -71,13 +73,13 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
// transform connected directions to local-coordinates
var connectedDirections = worldConnectedDirections.RotatePipeDirection(-Transform(uid).LocalRotation);
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
{
if (!args.Sprite.LayerMapTryGet(layerKey, out var key))
if (!_sprite.LayerMapTryGet((uid, args.Sprite), layerKey, out var key, false))
continue;
var layer = args.Sprite[key];
var dir = (PipeDirection) layerKey;
var dir = (PipeDirection)layerKey;
var visible = connectedDirections.HasDirection(dir);
layer.Visible &= visible;

View File

@@ -2,6 +2,7 @@ using Content.Client.Atmos.Components;
using Content.Shared.Atmos;
using Robust.Client.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Content.Client.Atmos.EntitySystems;
@@ -31,9 +32,9 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
// Need LayerMapTryGet because Init fails if there's no existing sprite / appearancecomp
// which means in some setups (most frequently no AppearanceComp) the layer never exists.
if (TryComp<SpriteComponent>(uid, out var sprite) &&
sprite.LayerMapTryGet(FireVisualLayers.Fire, out var layer))
SpriteSystem.LayerMapTryGet((uid, sprite), FireVisualLayers.Fire, out var layer, false))
{
sprite.RemoveLayer(layer);
SpriteSystem.RemoveLayer((uid, sprite), layer);
}
}
@@ -42,11 +43,11 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
if (!TryComp<SpriteComponent>(uid, out var sprite) || !TryComp(uid, out AppearanceComponent? appearance))
return;
sprite.LayerMapReserveBlank(FireVisualLayers.Fire);
sprite.LayerSetVisible(FireVisualLayers.Fire, false);
SpriteSystem.LayerMapReserve((uid, sprite), FireVisualLayers.Fire);
SpriteSystem.LayerSetVisible((uid, sprite), FireVisualLayers.Fire, false);
sprite.LayerSetShader(FireVisualLayers.Fire, "unshaded");
if (component.Sprite != null)
sprite.LayerSetRSI(FireVisualLayers.Fire, component.Sprite);
SpriteSystem.LayerSetRsi((uid, sprite), FireVisualLayers.Fire, new ResPath(component.Sprite));
UpdateAppearance(uid, component, sprite, appearance);
}
@@ -59,12 +60,12 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
private void UpdateAppearance(EntityUid uid, FireVisualsComponent component, SpriteComponent sprite, AppearanceComponent appearance)
{
if (!sprite.LayerMapTryGet(FireVisualLayers.Fire, out var index))
if (!SpriteSystem.LayerMapTryGet((uid, sprite), FireVisualLayers.Fire, out var index, false))
return;
AppearanceSystem.TryGetData<bool>(uid, FireVisuals.OnFire, out var onFire, appearance);
AppearanceSystem.TryGetData<float>(uid, FireVisuals.FireStacks, out var fireStacks, appearance);
sprite.LayerSetVisible(index, onFire);
SpriteSystem.LayerSetVisible((uid, sprite), index, onFire);
if (!onFire)
{
@@ -78,9 +79,9 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
}
if (fireStacks > component.FireStackAlternateState && !string.IsNullOrEmpty(component.AlternateState))
sprite.LayerSetState(index, component.AlternateState);
SpriteSystem.LayerSetRsiState((uid, sprite), index, component.AlternateState);
else
sprite.LayerSetState(index, component.NormalState);
SpriteSystem.LayerSetRsiState((uid, sprite), index, component.NormalState);
component.LightEntity ??= Spawn(null, new EntityCoordinates(uid, default));
var light = EnsureComp<PointLightComponent>(component.LightEntity.Value);

View File

@@ -9,7 +9,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
protected override void OnAppearanceChange(EntityUid uid, AtmosAlarmableVisualsComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null || !args.Sprite.LayerMapTryGet(component.LayerMap, out var layer))
if (args.Sprite == null || !SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.LayerMap, out var layer, false))
return;
if (!args.AppearanceData.TryGetValue(PowerDeviceVisuals.Powered, out var poweredObject) ||
@@ -22,8 +22,8 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var visLayer in component.HideOnDepowered)
{
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
if (SpriteSystem.LayerMapTryGet((uid, args.Sprite), visLayer, out var powerVisibilityLayer, false))
SpriteSystem.LayerSetVisible((uid, args.Sprite), powerVisibilityLayer, powered);
}
}
@@ -31,8 +31,8 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
{
foreach (var (setLayer, powerState) in component.SetOnDepowered)
{
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
if (SpriteSystem.LayerMapTryGet((uid, args.Sprite), setLayer, out var setStateLayer, false))
SpriteSystem.LayerSetRsiState((uid, args.Sprite), setStateLayer, new RSI.StateId(powerState));
}
}
@@ -41,7 +41,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
&& powered
&& component.AlarmStates.TryGetValue(alarmType, out var state))
{
args.Sprite.LayerSetState(layer, new RSI.StateId(state));
SpriteSystem.LayerSetRsiState((uid, args.Sprite), layer, new RSI.StateId(state));
}
}
}

View File

@@ -74,7 +74,13 @@
<!-- Mode buttons -->
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'air-alarm-ui-window-mode-label'}" Margin="0 0 2 0" />
<OptionButton Name="CModeButton" HorizontalExpand="True" />
<Control HorizontalExpand="True">
<OptionButton Name="CModeButton" />
<ui:StripeBack Name="CModeSelectLocked">
<RichTextLabel Text="{Loc 'air-alarm-ui-window-mode-select-locked-label'}"
HorizontalAlignment="Center" />
</ui:StripeBack>
</Control>
<CheckBox Name="AutoModeCheckBox" Text="{Loc 'air-alarm-ui-window-auto-mode-label'}" />
</BoxContainer>
</BoxContainer>

View File

@@ -110,6 +110,8 @@ public sealed partial class AirAlarmWindow : FancyWindow
{
UpdateDeviceData(addr, dev);
}
_modes.Visible = !state.PanicWireCut;
CModeSelectLocked.Visible = state.PanicWireCut;
}
public void UpdateModeSelector(AirAlarmMode mode)

View File

@@ -71,6 +71,7 @@ public sealed partial class ScrubberControl : BoxContainer
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
ScrubberDataChanged?.Invoke(_address, _data);
};
_pumpDirection.Disabled = data.AirAlarmPanicWireCut;
_copySettings.OnPressed += _ =>
{
@@ -109,6 +110,7 @@ public sealed partial class ScrubberControl : BoxContainer
_data.PumpDirection = data.PumpDirection;
_pumpDirection.Select((int) _data.PumpDirection);
_pumpDirection.Disabled = data.AirAlarmPanicWireCut;
_data.VolumeRate = data.VolumeRate;
_volumeRate.Value = _data.VolumeRate;

View File

@@ -21,6 +21,7 @@ namespace Content.Client.Atmos.Overlays
{
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
private readonly SharedMapSystem _mapSystem;
private readonly SharedTransformSystem _xformSys;
public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities | OverlaySpace.WorldSpaceBelowWorld;
@@ -51,6 +52,7 @@ namespace Content.Client.Atmos.Overlays
{
_entManager = entManager;
_mapManager = IoCManager.Resolve<IMapManager>();
_mapSystem = entManager.System<SharedMapSystem>();
_xformSys = xformSys;
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
ZIndex = GasOverlayZIndex;
@@ -163,7 +165,7 @@ namespace Content.Client.Atmos.Overlays
xformQuery,
_xformSys);
var mapUid = _mapManager.GetMapEntityId(args.MapId);
var mapUid = _mapSystem.GetMapOrInvalid(args.MapId);
if (_entManager.TryGetComponent<MapAtmosphereComponent>(mapUid, out var atmos))
DrawMapOverlay(drawHandle, args, mapUid, atmos);

View File

@@ -0,0 +1,8 @@
using Content.Shared.Atmos.Piping.Binary.Systems;
namespace Content.Client.Atmos.Piping.Binary.Systems;
public sealed class GasValveSystem : SharedGasValveSystem
{
}

View File

@@ -0,0 +1,29 @@
using Content.Client.Atmos.UI;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Atmos.Piping.Unary.Systems;
namespace Content.Client.Atmos.Piping.Unary.Systems;
public sealed class GasThermoMachineSystem : SharedGasThermoMachineSystem
{
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasThermoMachineComponent, AfterAutoHandleStateEvent>(OnGasAfterState);
}
private void OnGasAfterState(Entity<GasThermoMachineComponent> ent, ref AfterAutoHandleStateEvent args)
{
DirtyUI(ent.Owner, ent.Comp);
}
protected override void DirtyUI(EntityUid uid, GasThermoMachineComponent? thermoMachine, UserInterfaceComponent? ui = null)
{
if (_ui.TryGetOpenUi<GasThermomachineBoundUserInterface>(uid, ThermomachineUiKey.Key, out var bui))
{
bui.Update();
}
}
}

View File

@@ -1,5 +1,8 @@
using Content.Shared.Atmos;
using Content.Client.Power.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Atmos.Piping.Unary.Systems;
using Content.Shared.Power.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
@@ -36,6 +39,8 @@ namespace Content.Client.Atmos.UI
_window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
_window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value);
_window.Entity = Owner;
Update();
}
private void OnToggleStatusButtonPressed()
@@ -43,7 +48,7 @@ namespace Content.Client.Atmos.UI
if (_window is null) return;
_window.SetActive(!_window.Active);
SendMessage(new GasThermomachineToggleMessage());
SendPredictedMessage(new GasThermomachineToggleMessage());
}
private void OnTemperatureChanged(float value)
@@ -60,25 +65,32 @@ namespace Content.Client.Atmos.UI
return;
}
SendMessage(new GasThermomachineChangeTemperatureMessage(actual));
SendPredictedMessage(new GasThermomachineChangeTemperatureMessage(actual));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
public override void Update()
{
base.UpdateState(state);
if (_window == null || state is not GasThermomachineBoundUserInterfaceState cast)
if (_window == null || !EntMan.TryGetComponent(Owner, out GasThermoMachineComponent? thermo))
return;
_minTemp = cast.MinTemperature;
_maxTemp = cast.MaxTemperature;
_isHeater = cast.IsHeater;
var system = EntMan.System<SharedGasThermoMachineSystem>();
_minTemp = thermo.MinTemperature;
_maxTemp = thermo.MaxTemperature;
_isHeater = system.IsHeater(thermo);
_window.SetTemperature(thermo.TargetTemperature);
var receiverSys = EntMan.System<PowerReceiverSystem>();
SharedApcPowerReceiverComponent? receiver = null;
receiverSys.ResolveApc(Owner, ref receiver);
// Also set in frameupdates.
if (receiver != null)
{
_window.SetActive(!receiver.PowerDisabled);
}
_window.SetTemperature(cast.Temperature);
_window.SetActive(cast.Enabled);
_window.Title = _isHeater switch
{
false => Loc.GetString("comp-gas-thermomachine-ui-title-freezer"),

View File

@@ -1,5 +1,6 @@
<DefaultWindow xmlns="https://spacestation14.io"
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
MinSize="300 120" Title="{Loc comp-gas-thermomachine-ui-title-freezer}">
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
@@ -11,4 +12,4 @@
<Label Text="{Loc comp-gas-thermomachine-ui-temperature}"/>
</BoxContainer>
</BoxContainer>
</DefaultWindow>
</controls:FancyWindow>

View File

@@ -1,19 +1,26 @@
using Content.Client.Power.Components;
using Content.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
namespace Content.Client.Atmos.UI;
[GenerateTypedNameReferences]
public sealed partial class GasThermomachineWindow : DefaultWindow
public sealed partial class GasThermomachineWindow : FancyWindow
{
[Dependency] private readonly IEntityManager _entManager = default!;
public bool Active = true;
public FloatSpinBox TemperatureSpinbox;
public EntityUid Entity;
public GasThermomachineWindow()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
SpinboxHBox.AddChild(
@@ -27,12 +34,10 @@ public sealed partial class GasThermomachineWindow : DefaultWindow
if (active)
{
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-enabled");
ToggleStatusButton.Pressed = true;
}
else
{
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-disabled");
ToggleStatusButton.Pressed = false;
}
}
@@ -40,4 +45,14 @@ public sealed partial class GasThermomachineWindow : DefaultWindow
{
TemperatureSpinbox.Value = temperature;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_entManager.TryGetComponent(Entity, out ApcPowerReceiverComponent? receiver))
{
SetActive(!receiver.PowerDisabled);
}
}
}

View File

@@ -2,35 +2,35 @@ using Robust.Client.GameObjects;
using Content.Shared.Atmos.Visuals;
using Content.Client.Power;
namespace Content.Client.Atmos.Visualizers
namespace Content.Client.Atmos.Visualizers;
/// <summary>
/// Controls client-side visuals for portable scrubbers.
/// </summary>
public sealed class PortableScrubberSystem : VisualizerSystem<PortableScrubberVisualsComponent>
{
/// <summary>
/// Controls client-side visuals for portable scrubbers.
/// </summary>
public sealed class PortableScrubberSystem : VisualizerSystem<PortableScrubberVisualsComponent>
protected override void OnAppearanceChange(EntityUid uid, PortableScrubberVisualsComponent component, ref AppearanceChangeEvent args)
{
protected override void OnAppearanceChange(EntityUid uid, PortableScrubberVisualsComponent component, ref AppearanceChangeEvent args)
if (args.Sprite == null)
return;
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsFull, out var isFull, args.Component)
&& AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsRunning, out var isRunning, args.Component))
{
if (args.Sprite == null)
return;
var runningState = isRunning ? component.RunningState : component.IdleState;
SpriteSystem.LayerSetRsiState((uid, args.Sprite), PortableScrubberVisualLayers.IsRunning, runningState);
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsFull, out var isFull, args.Component)
&& AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsRunning, out var isRunning, args.Component))
{
var runningState = isRunning ? component.RunningState : component.IdleState;
args.Sprite.LayerSetState(PortableScrubberVisualLayers.IsRunning, runningState);
var fullState = isFull ? component.FullState : component.ReadyState;
SpriteSystem.LayerSetRsiState((uid, args.Sprite), PowerDeviceVisualLayers.Powered, fullState);
}
var fullState = isFull ? component.FullState : component.ReadyState;
args.Sprite.LayerSetState(PowerDeviceVisualLayers.Powered, fullState);
}
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsDraining, out var isDraining, args.Component))
{
args.Sprite.LayerSetVisible(PortableScrubberVisualLayers.IsDraining, isDraining);
}
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsDraining, out var isDraining, args.Component))
{
SpriteSystem.LayerSetVisible((uid, args.Sprite), PortableScrubberVisualLayers.IsDraining, isDraining);
}
}
}
public enum PortableScrubberVisualLayers : byte
{
IsRunning,

View File

@@ -12,6 +12,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -64,7 +65,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
visualState = JukeboxVisualState.On;
}
UpdateAppearance(uid, visualState, component, sprite);
UpdateAppearance((uid, sprite), visualState, component);
}
private void OnAppearanceChange(EntityUid uid, JukeboxComponent component, ref AppearanceChangeEvent args)
@@ -78,25 +79,25 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
visualState = JukeboxVisualState.On;
}
UpdateAppearance(uid, visualState, component, args.Sprite);
UpdateAppearance((uid, args.Sprite), visualState, component);
}
private void UpdateAppearance(EntityUid uid, JukeboxVisualState visualState, JukeboxComponent component, SpriteComponent sprite)
private void UpdateAppearance(Entity<SpriteComponent> entity, JukeboxVisualState visualState, JukeboxComponent component)
{
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
switch (visualState)
{
case JukeboxVisualState.On:
SetLayerState(JukeboxVisualLayers.Base, component.OnState, sprite);
SetLayerState(JukeboxVisualLayers.Base, component.OnState, entity);
break;
case JukeboxVisualState.Off:
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
break;
case JukeboxVisualState.Select:
PlayAnimation(uid, JukeboxVisualLayers.Base, component.SelectState, 1.0f, sprite);
PlayAnimation(entity.Owner, JukeboxVisualLayers.Base, component.SelectState, 1.0f, entity);
break;
}
}
@@ -109,7 +110,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
if (!_animationPlayer.HasRunningAnimation(uid, state))
{
var animation = GetAnimation(layer, state, animationTime);
sprite.LayerSetVisible(layer, true);
_sprite.LayerSetVisible((uid, sprite), layer, true);
_animationPlayer.Play(uid, animation, state);
}
}
@@ -133,13 +134,13 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
};
}
private void SetLayerState(JukeboxVisualLayers layer, string? state, SpriteComponent sprite)
private void SetLayerState(JukeboxVisualLayers layer, string? state, Entity<SpriteComponent> sprite)
{
if (string.IsNullOrEmpty(state))
return;
sprite.LayerSetVisible(layer, true);
sprite.LayerSetAutoAnimated(layer, true);
sprite.LayerSetState(layer, state);
_sprite.LayerSetVisible(sprite.AsNullable(), layer, true);
_sprite.LayerSetAutoAnimated(sprite.AsNullable(), layer, true);
_sprite.LayerSetRsiState(sprite.AsNullable(), layer, state);
}
}

View File

@@ -41,12 +41,12 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
&& sign.Current != null
&& _prototypeManager.TryIndex(sign.Current, out var proto))
{
sprite.LayerSetSprite(0, proto.Icon);
SpriteSystem.LayerSetSprite((id, sprite), 0, proto.Icon);
sprite.LayerSetShader(0, "unshaded");
}
else
{
sprite.LayerSetState(0, "empty");
SpriteSystem.LayerSetRsiState((id, sprite), 0, "empty");
sprite.LayerSetShader(0, null, null);
}
}

View File

@@ -7,6 +7,8 @@ namespace Content.Client.Beam;
public sealed class BeamSystem : SharedBeamSystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
@@ -21,11 +23,11 @@ public sealed class BeamSystem : SharedBeamSystem
if (TryComp<SpriteComponent>(beam, out var sprites))
{
sprites.Rotation = args.UserAngle;
_sprite.SetRotation((beam, sprites), args.UserAngle);
if (args.BodyState != null)
{
sprites.LayerSetState(0, args.BodyState);
_sprite.LayerSetRsiState((beam, sprites), 0, args.BodyState);
sprites.LayerSetShader(0, args.Shader);
}
}

View File

@@ -0,0 +1,8 @@
using Content.Shared.Bed;
namespace Content.Client.Bed;
public sealed class BedSystem : SharedBedSystem
{
}

View File

@@ -10,7 +10,7 @@ public sealed class StasisBedSystem : VisualizerSystem<StasisBedVisualsComponent
if (args.Sprite != null
&& AppearanceSystem.TryGetData<bool>(uid, StasisBedVisuals.IsOn, out var isOn, args.Component))
{
args.Sprite.LayerSetVisible(StasisBedVisualLayers.IsOn, isOn);
SpriteSystem.LayerSetVisible((uid, args.Sprite), StasisBedVisualLayers.IsOn, isOn);
}
}
}

View File

@@ -1,6 +1,7 @@
using Content.Client.Botany.Components;
using Content.Shared.Botany;
using Robust.Client.GameObjects;
using Robust.Shared.Utility;
namespace Content.Client.Botany;
@@ -17,8 +18,8 @@ public sealed class PlantHolderVisualizerSystem : VisualizerSystem<PlantHolderVi
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
sprite.LayerMapReserveBlank(PlantHolderLayers.Plant);
sprite.LayerSetVisible(PlantHolderLayers.Plant, false);
SpriteSystem.LayerMapReserve((uid, sprite), PlantHolderLayers.Plant);
SpriteSystem.LayerSetVisible((uid, sprite), PlantHolderLayers.Plant, false);
}
protected override void OnAppearanceChange(EntityUid uid, PlantHolderVisualsComponent component, ref AppearanceChangeEvent args)
@@ -31,12 +32,12 @@ public sealed class PlantHolderVisualizerSystem : VisualizerSystem<PlantHolderVi
{
var valid = !string.IsNullOrWhiteSpace(state);
args.Sprite.LayerSetVisible(PlantHolderLayers.Plant, valid);
SpriteSystem.LayerSetVisible((uid, args.Sprite), PlantHolderLayers.Plant, valid);
if (valid)
{
args.Sprite.LayerSetRSI(PlantHolderLayers.Plant, rsi);
args.Sprite.LayerSetState(PlantHolderLayers.Plant, state);
SpriteSystem.LayerSetRsi((uid, args.Sprite), PlantHolderLayers.Plant, new ResPath(rsi));
SpriteSystem.LayerSetRsiState((uid, args.Sprite), PlantHolderLayers.Plant, state);
}
}
}

View File

@@ -15,7 +15,7 @@ public sealed class PotencyVisualsSystem : VisualizerSystem<PotencyVisualsCompon
if (AppearanceSystem.TryGetData<float>(uid, ProduceVisuals.Potency, out var potency, args.Component))
{
var scale = MathHelper.Lerp(component.MinimumScale, component.MaximumScale, potency / 100);
args.Sprite.Scale = new Vector2(scale, scale);
SpriteSystem.SetScale((uid, args.Sprite), new Vector2(scale, scale));
}
}
}

View File

@@ -13,6 +13,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
[Dependency] private readonly RotationVisualizerSystem _rotationVisualizerSystem = default!;
[Dependency] private readonly IEyeManager _eye = default!;
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -69,11 +70,11 @@ internal sealed class BuckleSystem : SharedBuckleSystem
{
// This will only assign if empty, it won't get overwritten by new depth on multiple calls, which do happen easily
buckle.OriginalDrawDepth ??= buckledSprite.DrawDepth;
buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
_sprite.SetDrawDepth((buckledEntity, buckledSprite), strapSprite.DrawDepth - 1);
}
else if (buckle.OriginalDrawDepth.HasValue)
{
buckledSprite.DrawDepth = buckle.OriginalDrawDepth.Value;
_sprite.SetDrawDepth((buckledEntity, buckledSprite), buckle.OriginalDrawDepth.Value);
buckle.OriginalDrawDepth = null;
}
}
@@ -97,7 +98,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
return;
ent.Comp.OriginalDrawDepth ??= buckledSprite.DrawDepth;
buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
_sprite.SetDrawDepth((ent.Owner, buckledSprite), strapSprite.DrawDepth - 1);
}
/// <summary>
@@ -111,7 +112,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
if (!ent.Comp.OriginalDrawDepth.HasValue)
return;
buckledSprite.DrawDepth = ent.Comp.OriginalDrawDepth.Value;
_sprite.SetDrawDepth((ent.Owner, buckledSprite), ent.Comp.OriginalDrawDepth.Value);
ent.Comp.OriginalDrawDepth = null;
}

View File

@@ -13,6 +13,7 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private EntityQuery<BodyComponent> _bodyQuery;
@@ -74,7 +75,7 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
if (!xformQuery.TryGetComponent(ent, out var entTransform) || !TryComp<SpriteComponent>(ent, out var sprite))
continue;
sprite.Offset = new Vector2(0, 1);
_sprite.SetOffset((ent, sprite), new Vector2(0, 1));
_transform.SetParent(ent, entTransform, mob);
}

View File

@@ -138,6 +138,11 @@ namespace Content.Client.Cargo.BUI
AccountName = cState.Name;
if (_menu == null)
return;
_menu.ProductCatalogue = cState.Products;
_menu?.UpdateStation(station);
Populate(cState.Orders);
}

View File

@@ -10,6 +10,7 @@ namespace Content.Client.Cargo.Systems;
public sealed partial class CargoSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private static readonly Animation CargoTelepadBeamAnimation = new()
{
@@ -80,12 +81,12 @@ public sealed partial class CargoSystem
_player.Play((uid, player), CargoTelepadBeamAnimation, TelepadBeamKey);
break;
case CargoTelepadState.Unpowered:
sprite.LayerSetVisible(CargoTelepadLayers.Beam, false);
_sprite.LayerSetVisible((uid, sprite), CargoTelepadLayers.Beam, false);
_player.Stop(uid, player, TelepadBeamKey);
_player.Stop(uid, player, TelepadIdleKey);
break;
default:
sprite.LayerSetVisible(CargoTelepadLayers.Beam, true);
_sprite.LayerSetVisible((uid, sprite), CargoTelepadLayers.Beam, true);
if (_player.HasRunningAnimation(uid, player, TelepadIdleKey) ||
_player.HasRunningAnimation(uid, player, TelepadBeamKey))

View File

@@ -40,6 +40,8 @@ namespace Content.Client.Cargo.UI
private readonly List<string> _categoryStrings = new();
private string? _category;
public List<ProtoId<CargoProductPrototype>> ProductCatalogue = new();
public CargoConsoleMenu(EntityUid owner, IEntityManager entMan, IPrototypeManager protoManager, SpriteSystem spriteSystem)
{
RobustXamlLoader.Load(this);
@@ -113,14 +115,16 @@ namespace Content.Client.Cargo.UI
Categories.SelectId(id);
}
public IEnumerable<CargoProductPrototype> ProductPrototypes
private IEnumerable<CargoProductPrototype> ProductPrototypes
{
get
{
var allowedGroups = _entityManager.GetComponentOrNull<CargoOrderConsoleComponent>(_owner)?.AllowedGroups;
foreach (var cargoPrototype in _protoManager.EnumeratePrototypes<CargoProductPrototype>())
foreach (var cargoPrototypeId in ProductCatalogue)
{
var cargoPrototype = _protoManager.Index(cargoPrototypeId);
if (!allowedGroups?.Contains(cargoPrototype.Group) ?? false)
continue;

View File

@@ -11,6 +11,7 @@ namespace Content.Client.Chasm;
public sealed class ChasmFallingVisualsSystem : EntitySystem
{
[Dependency] private readonly AnimationPlayerSystem _anim = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private readonly string _chasmFallAnimationKey = "chasm_fall";
@@ -46,7 +47,7 @@ public sealed class ChasmFallingVisualsSystem : EntitySystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
sprite.Scale = component.OriginalScale;
_sprite.SetScale((uid, sprite), component.OriginalScale);
if (!TryComp<AnimationPlayerComponent>(uid, out var player))
return;

View File

@@ -63,6 +63,9 @@ public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem
{
base.Update(frameTime);
if (!_time.IsFirstTimePredicted)
return;
// check if client didn't changed chat text box for a long time
if (_isClientTyping)
{

View File

@@ -1,6 +1,5 @@
using Content.Shared.Chat.TypingIndicator;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;
using Content.Shared.Inventory;
@@ -11,7 +10,6 @@ public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem<TypingInd
[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)
@@ -35,24 +33,24 @@ public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem<TypingInd
return;
}
var layerExists = args.Sprite.LayerMapTryGet(TypingIndicatorLayers.Base, out var layer);
var layerExists = SpriteSystem.LayerMapTryGet((uid, args.Sprite), TypingIndicatorLayers.Base, out var layer, false);
if (!layerExists)
layer = args.Sprite.LayerMapReserveBlank(TypingIndicatorLayers.Base);
layer = SpriteSystem.LayerMapReserve((uid, args.Sprite), TypingIndicatorLayers.Base);
args.Sprite.LayerSetRSI(layer, proto.SpritePath);
args.Sprite.LayerSetState(layer, proto.TypingState);
SpriteSystem.LayerSetRsi((uid, args.Sprite), layer, proto.SpritePath);
SpriteSystem.LayerSetRsiState((uid, args.Sprite), layer, proto.TypingState);
args.Sprite.LayerSetShader(layer, proto.Shader);
args.Sprite.LayerSetOffset(layer, proto.Offset);
SpriteSystem.LayerSetOffset((uid, args.Sprite), layer, proto.Offset);
AppearanceSystem.TryGetData<TypingIndicatorState>(uid, TypingIndicatorVisuals.State, out var state);
args.Sprite.LayerSetVisible(layer, state != TypingIndicatorState.None);
SpriteSystem.LayerSetVisible((uid, args.Sprite), layer, state != TypingIndicatorState.None);
switch (state)
{
case TypingIndicatorState.Idle:
args.Sprite.LayerSetState(layer, proto.IdleState);
SpriteSystem.LayerSetRsiState((uid, args.Sprite), layer, proto.IdleState);
break;
case TypingIndicatorState.Typing:
args.Sprite.LayerSetState(layer, proto.TypingState);
SpriteSystem.LayerSetRsiState((uid, args.Sprite), layer, proto.TypingState);
break;
}
}

View File

@@ -5,6 +5,8 @@ namespace Content.Client.Chemistry.EntitySystems;
public sealed class PillSystem : EntitySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
@@ -16,9 +18,9 @@ public sealed class PillSystem : EntitySystem
if (!TryComp(uid, out SpriteComponent? sprite))
return;
if (!sprite.TryGetLayer(0, out var layer))
if (!_sprite.TryGetLayer((uid, sprite), 0, out var layer, false))
return;
layer.SetState($"pill{component.PillType + 1}");
_sprite.LayerSetRsiState(layer, $"pill{component.PillType + 1}");
}
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Chemistry;
using Content.Shared.Storage;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
@@ -9,15 +10,15 @@ namespace Content.Client.Chemistry.UI;
[GenerateTypedNameReferences]
public sealed partial class ReagentCardControl : Control
{
public string StorageSlotId { get; }
public Action<string>? OnPressed;
public Action<string>? OnEjectButtonPressed;
public ItemStorageLocation StorageLocation { get; }
public Action<ItemStorageLocation>? OnPressed;
public Action<ItemStorageLocation>? OnEjectButtonPressed;
public ReagentCardControl(ReagentInventoryItem item)
{
RobustXamlLoader.Load(this);
StorageSlotId = item.StorageSlotId;
StorageLocation = item.StorageLocation;
ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
ReagentNameLabel.Text = item.ReagentLabel;
FillLabel.Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", item.Quantity));;
@@ -26,7 +27,7 @@ public sealed partial class ReagentCardControl : Control
if (item.Quantity == 0.0)
MainButton.Disabled = true;
MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId);
EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId);
MainButton.OnPressed += args => OnPressed?.Invoke(StorageLocation);
EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageLocation);
}
}

View File

@@ -40,8 +40,8 @@ namespace Content.Client.Chemistry.UI
_window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s));
_window.OnDispenseReagentButtonPressed += (id) => SendMessage(new ReagentDispenserDispenseReagentMessage(id));
_window.OnEjectJugButtonPressed += (id) => SendMessage(new ItemSlotButtonPressedEvent(id));
_window.OnDispenseReagentButtonPressed += (location) => SendMessage(new ReagentDispenserDispenseReagentMessage(location));
_window.OnEjectJugButtonPressed += (location) => SendMessage(new ReagentDispenserEjectContainerMessage(location));
}
/// <summary>

View File

@@ -2,6 +2,7 @@ using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Storage;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@@ -18,8 +19,8 @@ namespace Content.Client.Chemistry.UI
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
public event Action<string>? OnDispenseReagentButtonPressed;
public event Action<string>? OnEjectJugButtonPressed;
public event Action<ItemStorageLocation>? OnDispenseReagentButtonPressed;
public event Action<ItemStorageLocation>? OnEjectJugButtonPressed;
/// <summary>
/// Create and initialize the dispenser UI client-side. Creates the basic layout,

View File

@@ -71,7 +71,7 @@ public sealed class FoamVisualizerSystem : VisualizerSystem<FoamVisualsComponent
return;
if (TryComp<SpriteComponent>(uid, out var sprite))
sprite.Visible = false;
SpriteSystem.SetVisible((uid, sprite), false);
}
}

View File

@@ -15,8 +15,8 @@ public sealed class SmokeVisualizerSystem : VisualizerSystem<SmokeVisualsCompone
{
if (args.Sprite == null)
return;
if(!AppearanceSystem.TryGetData<Color>(uid, SmokeVisuals.Color, out var color))
if (!AppearanceSystem.TryGetData<Color>(uid, SmokeVisuals.Color, out var color))
return;
args.Sprite.Color = color;
SpriteSystem.SetColor((uid, args.Sprite), color);
}
}

View File

@@ -49,7 +49,7 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
if (args.Sprite == null)
return;
if (!args.Sprite.LayerMapTryGet(component.Layer, out var fillLayer))
if (!SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.Layer, out var fillLayer, false))
return;
var maxFillLevels = component.MaxFillLevels;
@@ -67,9 +67,9 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
}
if (component.Metamorphic)
{
if (args.Sprite.LayerMapTryGet(component.BaseLayer, out var baseLayer))
if (SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.BaseLayer, out var baseLayer, false))
{
var hasOverlay = args.Sprite.LayerMapTryGet(component.OverlayLayer, out var overlayLayer);
var hasOverlay = SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.OverlayLayer, out var overlayLayer, false);
if (AppearanceSystem.TryGetData<string>(uid, SolutionContainerVisuals.BaseOverride,
out var baseOverride,
@@ -79,35 +79,35 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
if (reagentProto?.MetamorphicSprite is { } sprite)
{
args.Sprite.LayerSetSprite(baseLayer, sprite);
SpriteSystem.LayerSetSprite((uid, args.Sprite), baseLayer, sprite);
if (reagentProto.MetamorphicMaxFillLevels > 0)
{
args.Sprite.LayerSetVisible(fillLayer, true);
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
maxFillLevels = reagentProto.MetamorphicMaxFillLevels;
fillBaseName = reagentProto.MetamorphicFillBaseName;
changeColor = reagentProto.MetamorphicChangeColor;
fillSprite = sprite;
}
else
args.Sprite.LayerSetVisible(fillLayer, false);
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, false);
if (hasOverlay)
args.Sprite.LayerSetVisible(overlayLayer, false);
SpriteSystem.LayerSetVisible((uid, args.Sprite), overlayLayer, false);
}
else
{
args.Sprite.LayerSetVisible(fillLayer, true);
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
if (hasOverlay)
args.Sprite.LayerSetVisible(overlayLayer, true);
SpriteSystem.LayerSetVisible((uid, args.Sprite), overlayLayer, true);
if (component.MetamorphicDefaultSprite != null)
args.Sprite.LayerSetSprite(baseLayer, component.MetamorphicDefaultSprite);
SpriteSystem.LayerSetSprite((uid, args.Sprite), baseLayer, component.MetamorphicDefaultSprite);
}
}
}
}
else
{
args.Sprite.LayerSetVisible(fillLayer, true);
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
}
var closestFillSprite = ContentHelpers.RoundToLevels(fraction, 1, maxFillLevels + 1);
@@ -119,25 +119,25 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
var stateName = fillBaseName + closestFillSprite;
if (fillSprite != null)
args.Sprite.LayerSetSprite(fillLayer, fillSprite);
args.Sprite.LayerSetState(fillLayer, stateName);
SpriteSystem.LayerSetSprite((uid, args.Sprite), fillLayer, fillSprite);
SpriteSystem.LayerSetRsiState((uid, args.Sprite), fillLayer, stateName);
if (changeColor && AppearanceSystem.TryGetData<Color>(uid, SolutionContainerVisuals.Color, out var color, args.Component))
args.Sprite.LayerSetColor(fillLayer, color);
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, color);
else
args.Sprite.LayerSetColor(fillLayer, Color.White);
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, Color.White);
}
else
{
if (component.EmptySpriteName == null)
args.Sprite.LayerSetVisible(fillLayer, false);
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, false);
else
{
args.Sprite.LayerSetState(fillLayer, component.EmptySpriteName);
SpriteSystem.LayerSetRsiState((uid, args.Sprite), fillLayer, component.EmptySpriteName);
if (changeColor)
args.Sprite.LayerSetColor(fillLayer, component.EmptySpriteColor);
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, component.EmptySpriteColor);
else
args.Sprite.LayerSetColor(fillLayer, Color.White);
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, Color.White);
}
}

View File

@@ -52,7 +52,7 @@ public sealed class VaporVisualizerSystem : VisualizerSystem<VaporVisualsCompone
{
if (AppearanceSystem.TryGetData<Color>(uid, VaporVisuals.Color, out var color, args.Component) && args.Sprite != null)
{
args.Sprite.Color = color;
SpriteSystem.SetColor((uid, args.Sprite), color);
}
}
}

View File

@@ -77,10 +77,10 @@ public sealed class ClickableSystem : EntitySystem
drawDepth = sprite.DrawDepth;
renderOrder = sprite.RenderOrder;
var (spritePos, spriteRot) = _transforms.GetWorldPositionRotation(transform);
var spriteBB = sprite.CalculateRotatedBoundingBox(spritePos, spriteRot, eye.Rotation);
var spriteBB = _sprites.CalculateBounds((entity.Owner, sprite), spritePos, spriteRot, eye.Rotation);
bottom = Matrix3Helpers.CreateRotation(eye.Rotation).TransformBox(spriteBB).Bottom;
Matrix3x2.Invert(sprite.GetLocalMatrix(), out var invSpriteMatrix);
Matrix3x2.Invert(sprite.LocalMatrix, out var invSpriteMatrix);
// This should have been the rotation of the sprite relative to the screen, but this is not the case with no-rot or directional sprites.
var relativeRotation = (spriteRot + eye.Rotation).Reduced().FlipPositive();
@@ -107,7 +107,7 @@ public sealed class ClickableSystem : EntitySystem
if (layer.Texture != null)
{
// Convert to image coordinates
var imagePos = (Vector2i) (localPos * EyeManager.PixelsPerMeter * new Vector2(1, -1) + layer.Texture.Size / 2f);
var imagePos = (Vector2i)(localPos * EyeManager.PixelsPerMeter * new Vector2(1, -1) + layer.Texture.Size / 2f);
if (_clickMapManager.IsOccluding(layer.Texture, imagePos))
return true;
@@ -125,7 +125,7 @@ public sealed class ClickableSystem : EntitySystem
var layerLocal = Vector2.Transform(localPos, inverseMatrix);
// Convert to image coordinates
var layerImagePos = (Vector2i) (layerLocal * EyeManager.PixelsPerMeter * new Vector2(1, -1) + rsiState.Size / 2f);
var layerImagePos = (Vector2i)(layerLocal * EyeManager.PixelsPerMeter * new Vector2(1, -1) + rsiState.Size / 2f);
// Next, to get the right click map we need the "direction" of this layer that is actually being used to draw the sprite on the screen.
// This **can** differ from the dir defined before, but can also just be the same.

View File

@@ -5,6 +5,8 @@ namespace Content.Client.Clock;
public sealed class ClockSystem : SharedClockSystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Update(float frameTime)
{
base.Update(frameTime);
@@ -12,15 +14,15 @@ public sealed class ClockSystem : SharedClockSystem
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))
if (!_sprite.LayerMapTryGet((uid, sprite), ClockVisualLayers.HourHand, out var hourLayer, false) ||
!_sprite.LayerMapTryGet((uid, sprite), ClockVisualLayers.MinuteHand, out var minuteLayer, false))
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);
_sprite.LayerSetRsiState((uid, sprite), hourLayer, hourState);
_sprite.LayerSetRsiState((uid, sprite), minuteLayer, minuteState);
}
}
}

View File

@@ -52,6 +52,7 @@ public sealed class ClientClothingSystem : ClothingSystem
[Dependency] private readonly IResourceCache _cache = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -74,10 +75,10 @@ public sealed class ClientClothingSystem : ClothingSystem
UpdateAllSlots(uid, component);
// No clothing equipped -> make sure the layer is hidden, though this should already be handled by on-unequip.
if (args.Sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer))
if (_sprite.LayerMapTryGet((uid, args.Sprite), HumanoidVisualLayers.StencilMask, out var layer, false))
{
DebugTools.Assert(!args.Sprite[layer].Visible);
args.Sprite.LayerSetVisible(layer, false);
_sprite.LayerSetVisible((uid, args.Sprite), layer, false);
}
}
@@ -192,9 +193,9 @@ public sealed class ClientClothingSystem : ClothingSystem
RenderEquipment(uid, item, clothing.InSlot, component, null, clothing);
}
private void OnDidUnequip(EntityUid uid, SpriteComponent component, DidUnequipEvent args)
private void OnDidUnequip(Entity<SpriteComponent> entity, ref DidUnequipEvent args)
{
if (!TryComp(uid, out InventorySlotsComponent? inventorySlots))
if (!TryComp(entity, out InventorySlotsComponent? inventorySlots))
return;
if (!inventorySlots.VisualLayerKeys.TryGetValue(args.Slot, out var revealedLayers))
@@ -204,7 +205,7 @@ public sealed class ClientClothingSystem : ClothingSystem
// may eventually bloat the player with lots of invisible layers.
foreach (var layer in revealedLayers)
{
component.RemoveLayer(layer);
_sprite.RemoveLayer(entity.AsNullable(), layer);
}
revealedLayers.Clear();
}
@@ -247,7 +248,7 @@ public sealed class ClientClothingSystem : ClothingSystem
{
foreach (var key in revealedLayers)
{
sprite.RemoveLayer(key);
_sprite.RemoveLayer((equipee, sprite), key);
}
revealedLayers.Clear();
}
@@ -268,7 +269,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);
var slotLayerExists = _sprite.LayerMapTryGet((equipee, sprite), slot, out var index, false);
// Select displacement maps
var displacementData = inventory.Displacements.GetValueOrDefault(slot); //Default unsexed map
@@ -302,16 +303,16 @@ public sealed class ClientClothingSystem : ClothingSystem
{
index++;
// note that every insertion requires reshuffling & remapping all the existing layers.
sprite.AddBlankLayer(index);
sprite.LayerMapSet(key, index);
_sprite.AddBlankLayer((equipee, sprite), index);
_sprite.LayerMapSet((equipee, sprite), key, index);
if (layerData.Color != null)
sprite.LayerSetColor(key, layerData.Color.Value);
_sprite.LayerSetColor((equipee, sprite), key, layerData.Color.Value);
if (layerData.Scale != null)
sprite.LayerSetScale(key, layerData.Scale.Value);
_sprite.LayerSetScale((equipee, sprite), key, layerData.Scale.Value);
}
else
index = sprite.LayerMapReserveBlank(key);
index = _sprite.LayerMapReserve((equipee, sprite), key);
if (sprite[index] is not Layer layer)
continue;
@@ -322,11 +323,11 @@ public sealed class ClientClothingSystem : ClothingSystem
&& layer.RSI == null
&& TryComp(equipment, out SpriteComponent? clothingSprite))
{
layer.SetRsi(clothingSprite.BaseRSI);
_sprite.LayerSetRsi(layer, clothingSprite.BaseRSI);
}
sprite.LayerSetData(index, layerData);
layer.Offset += slotDef.Offset;
_sprite.LayerSetData((equipee, sprite), index, layerData);
_sprite.LayerSetOffset(layer, layer.Offset + slotDef.Offset);
if (displacementData is not null)
{
@@ -334,7 +335,7 @@ public sealed class ClientClothingSystem : ClothingSystem
if (layerData.State is not null && inventory.SpeciesId is not null && layerData.State.EndsWith(inventory.SpeciesId))
continue;
if (_displacement.TryAddDisplacement(displacementData, sprite, index, key, out var displacementKey))
if (_displacement.TryAddDisplacement(displacementData, (equipee, sprite), index, key, out var displacementKey))
{
revealedLayers.Add(displacementKey);
index++;

View File

@@ -32,7 +32,7 @@ public sealed class FlippableClothingVisualizerSystem : VisualizerSystem<Flippab
if (clothing.MappedLayer == null ||
!AppearanceSystem.TryGetData<bool>(ent, FoldableSystem.FoldedVisuals.State, out var folding) ||
!sprite.LayerMapTryGet(folding ? ent.Comp.FoldingLayer : ent.Comp.UnfoldingLayer, out var idx))
!SpriteSystem.LayerMapTryGet((ent.Owner, sprite), folding ? ent.Comp.FoldingLayer : ent.Comp.UnfoldingLayer, out var idx, false))
return;
// add each layer to the visuals

View File

@@ -12,7 +12,6 @@ namespace Content.Client.Clothing.Systems;
public sealed class ChameleonClothingSystem : SharedChameleonClothingSystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IComponentFactory _factory = default!;
private static readonly SlotFlags[] IgnoredSlots =
{
@@ -48,14 +47,14 @@ public sealed class ChameleonClothingSystem : SharedChameleonClothingSystem
{
base.UpdateSprite(uid, proto);
if (TryComp(uid, out SpriteComponent? sprite)
&& proto.TryGetComponent(out SpriteComponent? otherSprite, _factory))
&& proto.TryGetComponent(out SpriteComponent? otherSprite, Factory))
{
sprite.CopyFrom(otherSprite);
}
// Edgecase for PDAs to include visuals when UI is open
if (TryComp(uid, out PdaBorderColorComponent? borderColor)
&& proto.TryGetComponent(out PdaBorderColorComponent? otherBorderColor, _factory))
&& proto.TryGetComponent(out PdaBorderColorComponent? otherBorderColor, Factory))
{
borderColor.BorderColor = otherBorderColor.BorderColor;
borderColor.AccentHColor = otherBorderColor.AccentHColor;
@@ -89,7 +88,7 @@ public sealed class ChameleonClothingSystem : SharedChameleonClothingSystem
// check if this is valid clothing
if (!IsValidTarget(proto))
continue;
if (!proto.TryGetComponent(out ClothingComponent? item, _factory))
if (!proto.TryGetComponent(out ClothingComponent? item, Factory))
continue;
// sort item by their slot flags

View File

@@ -12,7 +12,6 @@ namespace Content.Client.Clothing.UI;
[UsedImplicitly]
public sealed class ChameleonBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
private readonly ChameleonClothingSystem _chameleon;
private readonly TagSystem _tag;
@@ -49,7 +48,7 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
if (string.IsNullOrEmpty(target) || !_proto.TryIndex(target, out EntityPrototype? proto))
continue;
if (!proto.TryGetComponent(out TagComponent? tag, _factory) || !_tag.HasTag(tag, st.RequiredTag))
if (!proto.TryGetComponent(out TagComponent? tag, EntMan.ComponentFactory) || !_tag.HasTag(tag, st.RequiredTag))
continue;
newTargets.Add(target);

View File

@@ -18,23 +18,19 @@ public sealed class HideMechanismsCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var containerSys = _entityManager.System<SharedContainerSystem>();
var query = _entityManager.AllEntityQueryEnumerator<OrganComponent>();
var spriteSys = _entityManager.System<SpriteSystem>();
var query = _entityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out _))
while (query.MoveNext(out var uid, out _, out var sprite))
{
if (!_entityManager.TryGetComponent(uid, out SpriteComponent? sprite))
{
continue;
}
sprite.ContainerOccluded = false;
spriteSys.SetContainerOccluded((uid, sprite), false);
var tempParent = uid;
while (containerSys.TryGetContainingContainer((tempParent, null, null), out var container))
{
if (!container.ShowContents)
{
sprite.ContainerOccluded = true;
spriteSys.SetContainerOccluded((uid, sprite), true);
break;
}

View File

@@ -16,11 +16,12 @@ public sealed class ShowMechanismsCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var spriteSys = _entManager.System<SpriteSystem>();
var query = _entManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
while (query.MoveNext(out _, out var sprite))
while (query.MoveNext(out var uid, out _, out var sprite))
{
sprite.ContainerOccluded = false;
spriteSys.SetContainerOccluded((uid, sprite), false);
}
}
}

View File

@@ -27,6 +27,7 @@ namespace Content.Client.Construction
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
private readonly Dictionary<int, EntityUid> _ghosts = new();
@@ -293,14 +294,14 @@ namespace Content.Client.Construction
_ghosts.Add(comp.GhostId, ghost.Value);
var sprite = EntityManager.GetComponent<SpriteComponent>(ghost.Value);
sprite.Color = new Color(48, 255, 48, 128);
_sprite.SetColor((ghost.Value, sprite), new Color(48, 255, 48, 128));
if (targetProto.TryGetComponent(out IconComponent? icon, EntityManager.ComponentFactory))
{
sprite.AddBlankLayer(0);
sprite.LayerSetSprite(0, icon.Icon);
_sprite.AddBlankLayer((ghost.Value, sprite), 0);
_sprite.LayerSetSprite((ghost.Value, sprite), 0, icon.Icon);
sprite.LayerSetShader(0, "unshaded");
sprite.LayerSetVisible(0, true);
_sprite.LayerSetVisible((ghost.Value, sprite), 0, true);
}
else if (targetProto.Components.TryGetValue("Sprite", out _))
{
@@ -318,10 +319,10 @@ namespace Content.Client.Construction
state.StateId.Name is null)
continue;
sprite.AddBlankLayer(i);
sprite.LayerSetSprite(i, new SpriteSpecifier.Rsi(rsi.Path, state.StateId.Name));
_sprite.AddBlankLayer((ghost.Value, sprite), i);
_sprite.LayerSetSprite((ghost.Value, sprite), i, new SpriteSpecifier.Rsi(rsi.Path, state.StateId.Name));
sprite.LayerSetShader(i, "unshaded");
sprite.LayerSetVisible(i, true);
_sprite.LayerSetVisible((ghost.Value, sprite), i, true);
}
EntityManager.DeleteEntity(dummy);

View File

@@ -9,6 +9,7 @@ namespace Content.Client.Construction;
public sealed class FlatpackSystem : SharedFlatpackSystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -43,6 +44,6 @@ public sealed class FlatpackSystem : SharedFlatpackSystem
}
if (color != null)
args.Sprite.LayerSetColor(FlatpackVisualLayers.Overlay, color.Value);
_sprite.LayerSetColor((ent.Owner, args.Sprite), FlatpackVisualLayers.Overlay, color.Value);
}
}

View File

@@ -1,5 +1,6 @@
using System.Linq;
using System.Numerics;
using Content.Client.Lobby;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Systems.MenuBar.Widgets;
using Content.Shared.Construction.Prototypes;
@@ -28,6 +29,7 @@ namespace Content.Client.Construction.UI
[Dependency] private readonly IPlacementManager _placementManager = default!;
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
private readonly SpriteSystem _spriteSystem;
private readonly IConstructionMenuView _constructionView;
@@ -116,7 +118,7 @@ namespace Content.Client.Construction.UI
_constructionView.RecipeFavorited += (_, _) => OnViewFavoriteRecipe();
PopulateCategories();
SetFavorites(_preferencesManager.Preferences?.ConstructionFavorites ?? []);
OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
}
@@ -493,10 +495,34 @@ namespace Content.Client.Construction.UI
_favoritedRecipes.Count > 0 ? (string.Empty, FavoriteCatName) : (string.Empty, string.Empty));
}
var newFavorites = new List<ProtoId<ConstructionPrototype>>(_favoritedRecipes.Count);
foreach (var recipe in _favoritedRecipes)
newFavorites.Add(recipe.ID);
_preferencesManager.UpdateConstructionFavorites(newFavorites);
PopulateInfo(_selected);
PopulateCategories(_selectedCategory);
}
public void SetFavorites(IReadOnlyList<ProtoId<ConstructionPrototype>> favorites)
{
_favoritedRecipes.Clear();
foreach (var id in favorites)
{
if (_prototypeManager.TryIndex(id, out ConstructionPrototype? recipe, logError: false))
_favoritedRecipes.Add(recipe);
}
if (_selectedCategory == FavoriteCatName)
{
OnViewPopulateRecipes(_constructionView,
_favoritedRecipes.Count > 0 ? (string.Empty, FavoriteCatName) : (string.Empty, string.Empty));
}
PopulateCategories(_selectedCategory);
}
private void SystemBindingChanged(ConstructionSystem? newSystem)
{
if (newSystem is null)

View File

@@ -4,12 +4,14 @@ using Content.Shared.Cuffs.Components;
using Content.Shared.Humanoid;
using Robust.Client.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Client.Cuffs;
public sealed class CuffableSystem : SharedCuffableSystem
{
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -22,7 +24,7 @@ public sealed class CuffableSystem : SharedCuffableSystem
private void OnCuffableShutdown(EntityUid uid, CuffableComponent component, ComponentShutdown args)
{
if (TryComp<SpriteComponent>(uid, out var sprite))
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false);
_sprite.LayerSetVisible((uid, sprite), HumanoidVisualLayers.Handcuffs, false);
}
private void OnCuffableHandleState(EntityUid uid, CuffableComponent component, ref ComponentHandleState args)
@@ -39,22 +41,22 @@ public sealed class CuffableSystem : SharedCuffableSystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
var cuffed = cuffState.NumHandsCuffed > 0;
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, cuffed);
_sprite.LayerSetVisible((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffed);
// if they are not cuffed, that means that we didn't get a valid color,
// iconstate, or RSI. that also means we don't need to update the sprites.
if (!cuffed)
return;
sprite.LayerSetColor(HumanoidVisualLayers.Handcuffs, cuffState.Color!.Value);
_sprite.LayerSetColor((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffState.Color!.Value);
if (!Equals(component.CurrentRSI, cuffState.RSI) && cuffState.RSI != null) // we don't want to keep loading the same RSI
{
component.CurrentRSI = cuffState.RSI;
sprite.LayerSetState(HumanoidVisualLayers.Handcuffs, cuffState.IconState, component.CurrentRSI);
_sprite.LayerSetRsi((uid, sprite), _sprite.LayerMapGet((uid, sprite), HumanoidVisualLayers.Handcuffs), new ResPath(component.CurrentRSI), cuffState.IconState);
}
else
{
sprite.LayerSetState(HumanoidVisualLayers.Handcuffs, cuffState.IconState);
_sprite.LayerSetRsiState((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffState.IconState);
}
}
}

View File

@@ -228,7 +228,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
// the layer key just doesn't exist, we skip it.
foreach (var key in damageVisComp.TargetLayers)
{
if (!spriteComponent.LayerMapTryGet(key, out var index))
if (!SpriteSystem.LayerMapTryGet((entity, spriteComponent), key, out var index, false))
{
Log.Warning($"Layer at key {key} was invalid for entity {entity}.");
continue;
@@ -253,7 +253,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
foreach (var layer in damageVisComp.TargetLayerMapKeys)
{
var layerCount = spriteComponent.AllLayers.Count();
var index = spriteComponent.LayerMapGet(layer);
var index = SpriteSystem.LayerMapGet((entity, spriteComponent), layer);
// var layerState = spriteComponent.LayerGetState(index).ToString()!;
if (index + 1 != layerCount)
@@ -269,7 +269,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
{
foreach (var (group, sprite) in damageVisComp.DamageOverlayGroups)
{
AddDamageLayerToSprite(spriteComponent,
AddDamageLayerToSprite((entity, spriteComponent),
sprite,
$"{layer}_{group}_{damageVisComp.Thresholds[1]}",
$"{layer}{group}",
@@ -283,7 +283,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
// was taken.
else if (damageVisComp.DamageOverlay != null)
{
AddDamageLayerToSprite(spriteComponent,
AddDamageLayerToSprite((entity, spriteComponent),
damageVisComp.DamageOverlay,
$"{layer}_{damageVisComp.Thresholds[1]}",
$"{layer}trackDamage",
@@ -301,7 +301,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
{
foreach (var (group, sprite) in damageVisComp.DamageOverlayGroups)
{
AddDamageLayerToSprite(spriteComponent,
AddDamageLayerToSprite((entity, spriteComponent),
sprite,
$"DamageOverlay_{group}_{damageVisComp.Thresholds[1]}",
$"DamageOverlay{group}");
@@ -310,7 +310,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
}
else if (damageVisComp.DamageOverlay != null)
{
AddDamageLayerToSprite(spriteComponent,
AddDamageLayerToSprite((entity, spriteComponent),
damageVisComp.DamageOverlay,
$"DamageOverlay_{damageVisComp.Thresholds[1]}",
"DamageOverlay");
@@ -322,16 +322,19 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// <summary>
/// Adds a damage tracking layer to a given sprite component.
/// </summary>
private void AddDamageLayerToSprite(SpriteComponent spriteComponent, DamageVisualizerSprite sprite, string state, string mapKey, int? index = null)
private void AddDamageLayerToSprite(Entity<SpriteComponent?> spriteEnt, DamageVisualizerSprite sprite, string state, string mapKey, int? index = null)
{
var newLayer = spriteComponent.AddLayer(
var newLayer = SpriteSystem.AddLayer(
spriteEnt,
new SpriteSpecifier.Rsi(
new (sprite.Sprite), state
), index);
spriteComponent.LayerMapSet(mapKey, newLayer);
new(sprite.Sprite), state
),
index
);
SpriteSystem.LayerMapSet(spriteEnt, mapKey, newLayer);
if (sprite.Color != null)
spriteComponent.LayerSetColor(newLayer, Color.FromHex(sprite.Color));
spriteComponent.LayerSetVisible(newLayer, false);
SpriteSystem.LayerSetColor(spriteEnt, newLayer, Color.FromHex(sprite.Color));
SpriteSystem.LayerSetVisible(spriteEnt, newLayer, false);
}
protected override void OnAppearanceChange(EntityUid uid, DamageVisualsComponent damageVisComp, ref AppearanceChangeEvent args)
@@ -362,18 +365,18 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
UpdateDisabledLayers(uid, spriteComponent, component, damageVisComp);
if (damageVisComp.Overlay && damageVisComp.DamageOverlayGroups != null && damageVisComp.TargetLayers == null)
CheckOverlayOrdering(spriteComponent, damageVisComp);
CheckOverlayOrdering((uid, spriteComponent), damageVisComp);
if (AppearanceSystem.TryGetData<bool>(uid, DamageVisualizerKeys.ForceUpdate, out var update, component)
&& update)
{
ForceUpdateLayers(damageComponent, spriteComponent, damageVisComp);
ForceUpdateLayers((uid, damageComponent, spriteComponent, damageVisComp));
return;
}
if (damageVisComp.TrackAllDamage)
{
UpdateDamageVisuals(damageComponent, spriteComponent, damageVisComp);
UpdateDamageVisuals((uid, damageComponent, spriteComponent, damageVisComp));
return;
}
@@ -383,7 +386,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
data = new DamageVisualizerGroupData(Comp<DamageableComponent>(uid).DamagePerGroup.Keys.ToList());
}
UpdateDamageVisuals(data.GroupList, damageComponent, spriteComponent, damageVisComp);
UpdateDamageVisuals(data.GroupList, (uid, damageComponent, spriteComponent, damageVisComp));
}
/// <summary>
@@ -406,7 +409,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
damageVisComp.DisabledLayers[layer] = disabled;
if (damageVisComp.TrackAllDamage)
{
spriteComponent.LayerSetVisible($"{layer}trackDamage", !disabled);
SpriteSystem.LayerSetVisible((uid, spriteComponent), $"{layer}trackDamage", !disabled);
continue;
}
@@ -415,7 +418,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
foreach (var damageGroup in damageVisComp.DamageOverlayGroups.Keys)
{
spriteComponent.LayerSetVisible($"{layer}{damageGroup}", !disabled);
SpriteSystem.LayerSetVisible((uid, spriteComponent), $"{layer}{damageGroup}", !disabled);
}
}
}
@@ -427,16 +430,16 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// most layer doesn't match, the sprite
/// layers are recreated and placed on top.
/// </summary>
private void CheckOverlayOrdering(SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp)
private void CheckOverlayOrdering(Entity<SpriteComponent> spriteEnt, DamageVisualsComponent damageVisComp)
{
if (spriteComponent[damageVisComp.TopMostLayerKey] != spriteComponent[spriteComponent.AllLayers.Count() - 1])
if (spriteEnt.Comp[damageVisComp.TopMostLayerKey] != spriteEnt.Comp[spriteEnt.Comp.AllLayers.Count() - 1])
{
if (!damageVisComp.TrackAllDamage && damageVisComp.DamageOverlayGroups != null)
{
foreach (var (damageGroup, sprite) in damageVisComp.DamageOverlayGroups)
{
var threshold = damageVisComp.LastThresholdPerGroup[damageGroup];
ReorderOverlaySprite(spriteComponent,
ReorderOverlaySprite(spriteEnt,
damageVisComp,
sprite,
$"DamageOverlay{damageGroup}",
@@ -446,7 +449,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
}
else if (damageVisComp.TrackAllDamage && damageVisComp.DamageOverlay != null)
{
ReorderOverlaySprite(spriteComponent,
ReorderOverlaySprite(spriteEnt,
damageVisComp,
damageVisComp.DamageOverlay,
$"DamageOverlay",
@@ -456,21 +459,22 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
}
}
private void ReorderOverlaySprite(SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp, DamageVisualizerSprite sprite, string key, string statePrefix, FixedPoint2 threshold)
private void ReorderOverlaySprite(Entity<SpriteComponent> spriteEnt, DamageVisualsComponent damageVisComp, DamageVisualizerSprite sprite, string key, string statePrefix, FixedPoint2 threshold)
{
spriteComponent.LayerMapTryGet(key, out var spriteLayer);
var visibility = spriteComponent[spriteLayer].Visible;
spriteComponent.RemoveLayer(spriteLayer);
SpriteSystem.LayerMapTryGet(spriteEnt.AsNullable(), key, out var spriteLayer, false);
var visibility = spriteEnt.Comp[spriteLayer].Visible;
SpriteSystem.RemoveLayer(spriteEnt.AsNullable(), spriteLayer);
if (threshold == FixedPoint2.Zero) // these should automatically be invisible
threshold = damageVisComp.Thresholds[1];
spriteLayer = spriteComponent.AddLayer(
spriteLayer = SpriteSystem.AddLayer(
spriteEnt.AsNullable(),
new SpriteSpecifier.Rsi(
new (sprite.Sprite),
new(sprite.Sprite),
$"{statePrefix}_{threshold}"
),
spriteLayer);
spriteComponent.LayerMapSet(key, spriteLayer);
spriteComponent.LayerSetVisible(spriteLayer, visibility);
SpriteSystem.LayerMapSet(spriteEnt.AsNullable(), key, spriteLayer);
SpriteSystem.LayerSetVisible(spriteEnt.AsNullable(), spriteLayer, visibility);
// this is somewhat iffy since it constantly reallocates
damageVisComp.TopMostLayerKey = key;
}
@@ -479,8 +483,12 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// Updates damage visuals without tracking
/// any damage groups.
/// </summary>
private void UpdateDamageVisuals(DamageableComponent damageComponent, SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp)
private void UpdateDamageVisuals(Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
{
var damageComponent = entity.Comp1;
var spriteComponent = entity.Comp2;
var damageVisComp = entity.Comp3;
if (!CheckThresholdBoundary(damageComponent.TotalDamage, damageVisComp.LastDamageThreshold, damageVisComp, out var threshold))
return;
@@ -490,12 +498,12 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
{
foreach (var layerMapKey in damageVisComp.TargetLayerMapKeys)
{
UpdateTargetLayer(spriteComponent, damageVisComp, layerMapKey, threshold);
UpdateTargetLayer((entity, spriteComponent), damageVisComp, layerMapKey, threshold);
}
}
else
{
UpdateOverlay(spriteComponent, threshold);
UpdateOverlay((entity, spriteComponent), threshold);
}
}
@@ -504,8 +512,12 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// according to the list of damage groups
/// passed into it.
/// </summary>
private void UpdateDamageVisuals(List<string> delta, DamageableComponent damageComponent, SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp)
private void UpdateDamageVisuals(List<string> delta, Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
{
var damageComponent = entity.Comp1;
var spriteComponent = entity.Comp2;
var damageVisComp = entity.Comp3;
foreach (var damageGroup in delta)
{
if (!damageVisComp.Overlay && damageGroup != damageVisComp.DamageGroup)
@@ -525,12 +537,12 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
{
foreach (var layerMapKey in damageVisComp.TargetLayerMapKeys)
{
UpdateTargetLayer(spriteComponent, damageVisComp, layerMapKey, damageGroup, threshold);
UpdateTargetLayer((entity, spriteComponent, damageVisComp), layerMapKey, damageGroup, threshold);
}
}
else
{
UpdateOverlay(spriteComponent, damageVisComp, damageGroup, threshold);
UpdateOverlay((entity, spriteComponent, damageVisComp), damageGroup, threshold);
}
}
@@ -567,19 +579,21 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// Does different things depending on
/// the configuration of the visualizer.
/// </summary>
private void ForceUpdateLayers(DamageableComponent damageComponent, SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp)
private void ForceUpdateLayers(Entity<DamageableComponent, SpriteComponent, DamageVisualsComponent> entity)
{
var damageVisComp = entity.Comp3;
if (damageVisComp.DamageOverlayGroups != null)
{
UpdateDamageVisuals(damageVisComp.DamageOverlayGroups.Keys.ToList(), damageComponent, spriteComponent, damageVisComp);
UpdateDamageVisuals(damageVisComp.DamageOverlayGroups.Keys.ToList(), entity);
}
else if (damageVisComp.DamageGroup != null)
{
UpdateDamageVisuals(new List<string>(){ damageVisComp.DamageGroup }, damageComponent, spriteComponent, damageVisComp);
UpdateDamageVisuals(new List<string>() { damageVisComp.DamageGroup }, entity);
}
else if (damageVisComp.DamageOverlay != null)
{
UpdateDamageVisuals(damageComponent, spriteComponent, damageVisComp);
UpdateDamageVisuals(entity);
}
}
@@ -588,16 +602,16 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// it assumes you're updating a layer that is tracking all
/// damage.
/// </summary>
private void UpdateTargetLayer(SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp, object layerMapKey, FixedPoint2 threshold)
private void UpdateTargetLayer(Entity<SpriteComponent> spriteEnt, DamageVisualsComponent damageVisComp, object layerMapKey, FixedPoint2 threshold)
{
if (damageVisComp.Overlay && damageVisComp.DamageOverlayGroups != null)
{
if (!damageVisComp.DisabledLayers[layerMapKey])
{
var layerState = damageVisComp.LayerMapKeyStates[layerMapKey];
spriteComponent.LayerMapTryGet($"{layerMapKey}trackDamage", out var spriteLayer);
SpriteSystem.LayerMapTryGet(spriteEnt.AsNullable(), $"{layerMapKey}trackDamage", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(spriteEnt,
spriteLayer,
$"{layerState}",
threshold);
@@ -606,9 +620,9 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
else if (!damageVisComp.Overlay)
{
var layerState = damageVisComp.LayerMapKeyStates[layerMapKey];
spriteComponent.LayerMapTryGet(layerMapKey, out var spriteLayer);
SpriteSystem.LayerMapTryGet(spriteEnt.AsNullable(), $"{layerMapKey}", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(spriteEnt,
spriteLayer,
$"{layerState}",
threshold);
@@ -618,16 +632,20 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// <summary>
/// Updates a target layer by damage group.
/// </summary>
private void UpdateTargetLayer(SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp, object layerMapKey, string damageGroup, FixedPoint2 threshold)
private void UpdateTargetLayer(Entity<SpriteComponent, DamageVisualsComponent> entity, object layerMapKey, string damageGroup, FixedPoint2 threshold)
{
var spriteComponent = entity.Comp1;
var damageVisComp = entity.Comp2;
if (damageVisComp.Overlay && damageVisComp.DamageOverlayGroups != null)
{
if (damageVisComp.DamageOverlayGroups.ContainsKey(damageGroup) && !damageVisComp.DisabledLayers[layerMapKey])
{
var layerState = damageVisComp.LayerMapKeyStates[layerMapKey];
spriteComponent.LayerMapTryGet($"{layerMapKey}{damageGroup}", out var spriteLayer);
SpriteSystem.LayerMapTryGet((entity, spriteComponent), $"{layerMapKey}{damageGroup}", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(
(entity, spriteComponent),
spriteLayer,
$"{layerState}_{damageGroup}",
threshold);
@@ -636,9 +654,10 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
else if (!damageVisComp.Overlay)
{
var layerState = damageVisComp.LayerMapKeyStates[layerMapKey];
spriteComponent.LayerMapTryGet(layerMapKey, out var spriteLayer);
SpriteSystem.LayerMapTryGet((entity, spriteComponent), $"{layerMapKey}", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(
(entity, spriteComponent),
spriteLayer,
$"{layerState}_{damageGroup}",
threshold);
@@ -648,11 +667,11 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// <summary>
/// Updates an overlay that is tracking all damage.
/// </summary>
private void UpdateOverlay(SpriteComponent spriteComponent, FixedPoint2 threshold)
private void UpdateOverlay(Entity<SpriteComponent> spriteEnt, FixedPoint2 threshold)
{
spriteComponent.LayerMapTryGet($"DamageOverlay", out var spriteLayer);
SpriteSystem.LayerMapTryGet(spriteEnt.AsNullable(), $"DamageOverlay", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(spriteEnt,
spriteLayer,
$"DamageOverlay",
threshold);
@@ -661,15 +680,19 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// <summary>
/// Updates an overlay based on damage group.
/// </summary>
private void UpdateOverlay(SpriteComponent spriteComponent, DamageVisualsComponent damageVisComp, string damageGroup, FixedPoint2 threshold)
private void UpdateOverlay(Entity<SpriteComponent, DamageVisualsComponent> entity, string damageGroup, FixedPoint2 threshold)
{
var spriteComponent = entity.Comp1;
var damageVisComp = entity.Comp2;
if (damageVisComp.DamageOverlayGroups != null)
{
if (damageVisComp.DamageOverlayGroups.ContainsKey(damageGroup))
{
spriteComponent.LayerMapTryGet($"DamageOverlay{damageGroup}", out var spriteLayer);
SpriteSystem.LayerMapTryGet((entity, spriteComponent), $"DamageOverlay{damageGroup}", out var spriteLayer, false);
UpdateDamageLayerState(spriteComponent,
UpdateDamageLayerState(
(entity, spriteComponent),
spriteLayer,
$"DamageOverlay_{damageGroup}",
threshold);
@@ -683,19 +706,19 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
/// function calls it), and what threshold
/// was passed into it.
/// </summary>
private void UpdateDamageLayerState(SpriteComponent spriteComponent, int spriteLayer, string statePrefix, FixedPoint2 threshold)
private void UpdateDamageLayerState(Entity<SpriteComponent> spriteEnt, int spriteLayer, string statePrefix, FixedPoint2 threshold)
{
if (threshold == 0)
{
spriteComponent.LayerSetVisible(spriteLayer, false);
SpriteSystem.LayerSetVisible(spriteEnt.AsNullable(), spriteLayer, false);
}
else
{
if (!spriteComponent[spriteLayer].Visible)
if (!spriteEnt.Comp[spriteLayer].Visible)
{
spriteComponent.LayerSetVisible(spriteLayer, true);
SpriteSystem.LayerSetVisible(spriteEnt.AsNullable(), spriteLayer, true);
}
spriteComponent.LayerSetState(spriteLayer, $"{statePrefix}_{threshold}");
SpriteSystem.LayerSetRsiState(spriteEnt.AsNullable(), spriteLayer, $"{statePrefix}_{threshold}");
}
}
}

View File

@@ -21,34 +21,34 @@ public sealed class DamageStateVisualizerSystem : VisualizerSystem<DamageStateVi
}
// Brain no worky rn so this was just easier.
foreach (var key in new []{ DamageStateVisualLayers.Base, DamageStateVisualLayers.BaseUnshaded })
foreach (var key in new[] { DamageStateVisualLayers.Base, DamageStateVisualLayers.BaseUnshaded })
{
if (!sprite.LayerMapTryGet(key, out _)) continue;
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out _, false)) continue;
sprite.LayerSetVisible(key, false);
SpriteSystem.LayerSetVisible((uid, sprite), key, false);
}
foreach (var (key, state) in layers)
{
// Inheritance moment.
if (!sprite.LayerMapTryGet(key, out _)) continue;
if (!SpriteSystem.LayerMapTryGet((uid, sprite), key, out _, false)) continue;
sprite.LayerSetVisible(key, true);
sprite.LayerSetState(key, state);
SpriteSystem.LayerSetVisible((uid, sprite), key, true);
SpriteSystem.LayerSetRsiState((uid, sprite), key, state);
}
// So they don't draw over mobs anymore
if (data == MobState.Dead)
{
if (sprite.DrawDepth > (int) DrawDepth.DeadMobs)
if (sprite.DrawDepth > (int)DrawDepth.DeadMobs)
{
component.OriginalDrawDepth = sprite.DrawDepth;
sprite.DrawDepth = (int) DrawDepth.DeadMobs;
SpriteSystem.SetDrawDepth((uid, sprite), (int)DrawDepth.DeadMobs);
}
}
else if (component.OriginalDrawDepth != null)
{
sprite.DrawDepth = component.OriginalDrawDepth.Value;
SpriteSystem.SetDrawDepth((uid, sprite), component.OriginalDrawDepth.Value);
component.OriginalDrawDepth = null;
}
}

View File

@@ -9,7 +9,6 @@ public sealed class DeliveryVisualizerSystem : VisualizerSystem<DeliveryComponen
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private static readonly ProtoId<JobIconPrototype> UnknownIcon = "JobIconUnknown";
@@ -25,11 +24,11 @@ public sealed class DeliveryVisualizerSystem : VisualizerSystem<DeliveryComponen
if (!_prototype.TryIndex<JobIconPrototype>(job, out var icon))
{
args.Sprite.LayerSetTexture(DeliveryVisualLayers.JobStamp, _sprite.Frame0(_prototype.Index("JobIconUnknown")));
SpriteSystem.LayerSetTexture((uid, args.Sprite), DeliveryVisualLayers.JobStamp, SpriteSystem.Frame0(_prototype.Index("JobIconUnknown")));
return;
}
args.Sprite.LayerSetTexture(DeliveryVisualLayers.JobStamp, _sprite.Frame0(icon.Icon));
SpriteSystem.LayerSetTexture((uid, args.Sprite), DeliveryVisualLayers.JobStamp, SpriteSystem.Frame0(icon.Icon));
}
}
@@ -42,6 +41,8 @@ public enum DeliveryVisualLayers : byte
PriorityTape,
Breakage,
Trash,
Bomb,
BombPrimed,
}
public enum DeliverySpawnerVisualLayers : byte

View File

@@ -5,6 +5,8 @@ namespace Content.Client.Dice;
public sealed class DiceSystem : SharedDiceSystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
@@ -18,11 +20,11 @@ public sealed class DiceSystem : SharedDiceSystem
return;
// TODO maybe just move each die to its own RSI?
var state = sprite.LayerGetState(0).Name;
var state = _sprite.LayerGetRsiState((entity.Owner, sprite), 0).Name;
if (state == null)
return;
var prefix = state.Substring(0, state.IndexOf('_'));
sprite.LayerSetState(0, $"{prefix}_{entity.Comp.CurrentValue}");
_sprite.LayerSetRsiState((entity.Owner, sprite), 0, $"{prefix}_{entity.Comp.CurrentValue}");
}
}

View File

@@ -8,18 +8,19 @@ namespace Content.Client.DisplacementMap;
public sealed class DisplacementMapSystem : EntitySystem
{
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/// <summary>
/// Attempting to apply a displacement map to a specific layer of SpriteComponent
/// </summary>
/// <param name="data">Information package for applying the displacement map</param>
/// <param name="sprite">SpriteComponent</param>
/// <param name="sprite">Entity with SpriteComponent</param>
/// <param name="index">Index of the layer where the new map layer will be added</param>
/// <param name="key">Unique layer key, which will determine which layer to apply displacement map to</param>
/// <param name="displacementKey">The key of the new displacement map layer added by this function.</param>
/// <returns></returns>
public bool TryAddDisplacement(DisplacementData data,
SpriteComponent sprite,
Entity<SpriteComponent> sprite,
int index,
object key,
out string displacementKey)
@@ -30,10 +31,9 @@ public sealed class DisplacementMapSystem : EntitySystem
return false;
if (data.ShaderOverride != null)
sprite.LayerSetShader(index, data.ShaderOverride);
sprite.Comp.LayerSetShader(index, data.ShaderOverride);
if (sprite.LayerMapTryGet(displacementKey, out var oldIndex))
sprite.RemoveLayer(oldIndex);
_sprite.RemoveLayer(sprite.AsNullable(), displacementKey, false);
//allows you not to write it every time in the YML
foreach (var pair in data.SizeMaps)
@@ -55,7 +55,7 @@ public sealed class DisplacementMapSystem : EntitySystem
// 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);
var actualRSI = _sprite.LayerGetEffectiveRsi(sprite.AsNullable(), index);
if (actualRSI is not null)
{
if (actualRSI.Size.X != actualRSI.Size.Y)
@@ -72,9 +72,20 @@ public sealed class DisplacementMapSystem : EntitySystem
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
displacementLayer.CopyToShaderParameters!.LayerKey = key.ToString() ?? "this is impossible";
sprite.AddLayer(displacementLayer, index);
sprite.LayerMapSet(displacementKey, index);
_sprite.AddLayer(sprite.AsNullable(), displacementLayer, index);
_sprite.LayerMapSet(sprite.AsNullable(), displacementKey, index);
return true;
}
/// <inheritdoc cref="TryAddDisplacement"/>
[Obsolete("Use the Entity<SpriteComponent> overload")]
public bool TryAddDisplacement(DisplacementData data,
SpriteComponent sprite,
int index,
object key,
out string displacementKey)
{
return TryAddDisplacement(data, (sprite.Owner, sprite), index, key, out displacementKey);
}
}

View File

@@ -13,6 +13,7 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
[Dependency] private readonly AnimationPlayerSystem _animationSystem = default!;
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private const string AnimationKey = "disposal_unit_animation";
@@ -67,13 +68,13 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
if (!_appearanceSystem.TryGetData<DisposalUnitComponent.VisualState>(ent, DisposalUnitComponent.Visuals.VisualState, out var state, appearance))
return;
sprite.LayerSetVisible(DisposalUnitVisualLayers.Unanchored, state == DisposalUnitComponent.VisualState.UnAnchored);
sprite.LayerSetVisible(DisposalUnitVisualLayers.Base, state == DisposalUnitComponent.VisualState.Anchored);
sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayFlush, state == DisposalUnitComponent.VisualState.OverlayFlushing);
sprite.LayerSetVisible(DisposalUnitVisualLayers.BaseCharging, state == DisposalUnitComponent.VisualState.OverlayCharging);
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.Unanchored, state == DisposalUnitComponent.VisualState.UnAnchored);
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.Base, state == DisposalUnitComponent.VisualState.Anchored);
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.OverlayFlush, state == DisposalUnitComponent.VisualState.OverlayFlushing);
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.BaseCharging, state == DisposalUnitComponent.VisualState.OverlayCharging);
var chargingState = sprite.LayerMapTryGet(DisposalUnitVisualLayers.BaseCharging, out var chargingLayer)
? sprite.LayerGetState(chargingLayer)
var chargingState = _sprite.LayerMapTryGet((ent, sprite), DisposalUnitVisualLayers.BaseCharging, out var chargingLayer, false)
? _sprite.LayerGetRsiState((ent, sprite), chargingLayer)
: new RSI.StateId(DefaultChargeState);
// This is a transient state so not too worried about replaying in range.
@@ -81,8 +82,8 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
{
if (!_animationSystem.HasRunningAnimation(ent, AnimationKey))
{
var flushState = sprite.LayerMapTryGet(DisposalUnitVisualLayers.OverlayFlush, out var flushLayer)
? sprite.LayerGetState(flushLayer)
var flushState = _sprite.LayerMapTryGet((ent, sprite), DisposalUnitVisualLayers.OverlayFlush, out var flushLayer, false)
? _sprite.LayerGetRsiState((ent, sprite), flushLayer)
: new RSI.StateId(DefaultFlushState);
// Setup the flush animation to play
@@ -124,16 +125,16 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
if (!_appearanceSystem.TryGetData<DisposalUnitComponent.HandleState>(ent, DisposalUnitComponent.Visuals.Handle, out var handleState, appearance))
handleState = DisposalUnitComponent.HandleState.Normal;
sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayEngaged, handleState != DisposalUnitComponent.HandleState.Normal);
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.OverlayEngaged, handleState != DisposalUnitComponent.HandleState.Normal);
if (!_appearanceSystem.TryGetData<DisposalUnitComponent.LightStates>(ent, DisposalUnitComponent.Visuals.Light, out var lightState, appearance))
lightState = DisposalUnitComponent.LightStates.Off;
sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayCharging,
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.OverlayCharging,
(lightState & DisposalUnitComponent.LightStates.Charging) != 0);
sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayReady,
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.OverlayReady,
(lightState & DisposalUnitComponent.LightStates.Ready) != 0);
sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayFull,
_sprite.LayerSetVisible((ent, sprite), DisposalUnitVisualLayers.OverlayFull,
(lightState & DisposalUnitComponent.LightStates.Full) != 0);
}
}

View File

@@ -21,6 +21,7 @@ public sealed class DoAfterOverlay : Overlay
private readonly MetaDataSystem _meta;
private readonly ProgressColorSystem _progressColor;
private readonly SharedContainerSystem _container;
private readonly SpriteSystem _sprite;
private readonly Texture _barTexture;
private readonly ShaderInstance _unshadedShader;
@@ -45,6 +46,7 @@ public sealed class DoAfterOverlay : Overlay
_meta = _entManager.EntitySysManager.GetEntitySystem<MetaDataSystem>();
_container = _entManager.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
_progressColor = _entManager.System<ProgressColorSystem>();
_sprite = _entManager.System<SpriteSystem>();
var sprite = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
_barTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite);
@@ -118,7 +120,7 @@ public sealed class DoAfterOverlay : Overlay
// Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
// by the bar.
float yOffset = sprite.Bounds.Height / 2f + 0.05f;
var yOffset = _sprite.GetLocalBounds((uid, sprite)).Height / 2f + 0.05f;
// Position above the entity (we've already applied the matrix transform to the entity itself)
// Offset by the texture size for every do_after we have.
@@ -135,7 +137,7 @@ public sealed class DoAfterOverlay : Overlay
if (doAfter.CancelledTime != null)
{
var elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
elapsedRatio = (float)Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
color = GetProgressColor(0, flash ? alpha : 0);
@@ -143,7 +145,7 @@ public sealed class DoAfterOverlay : Overlay
else
{
var elapsed = time - doAfter.StartTime;
elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
elapsedRatio = (float)Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
color = GetProgressColor(elapsedRatio, alpha);
}

View File

@@ -10,6 +10,7 @@ namespace Content.Client.Doors;
public sealed class AirlockSystem : SharedAirlockSystem
{
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -21,7 +22,7 @@ public sealed class AirlockSystem : SharedAirlockSystem
private void OnComponentStartup(EntityUid uid, AirlockComponent comp, ComponentStartup args)
{
// Has to be on component startup because we don't know what order components initialize in and running this before DoorComponent inits _will_ crash.
if(!TryComp<DoorComponent>(uid, out var door))
if (!TryComp<DoorComponent>(uid, out var door))
return;
if (comp.OpenUnlitVisible) // Otherwise there are flashes of the fallback sprite between clicking on the door and the door closing animation starting.
@@ -31,17 +32,17 @@ public sealed class AirlockSystem : SharedAirlockSystem
}
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
{
LayerKey = DoorVisualLayers.BaseUnlit,
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningSpriteState, 0f) },
}
{
LayerKey = DoorVisualLayers.BaseUnlit,
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningSpriteState, 0f) },
}
);
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
{
LayerKey = DoorVisualLayers.BaseUnlit,
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingSpriteState, 0f) },
}
{
LayerKey = DoorVisualLayers.BaseUnlit,
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingSpriteState, 0f) },
}
);
door.DenyingAnimation = new Animation()
@@ -57,19 +58,19 @@ public sealed class AirlockSystem : SharedAirlockSystem
}
};
if(!comp.AnimatePanel)
if (!comp.AnimatePanel)
return;
((Animation)door.OpeningAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick()
{
LayerKey = WiresVisualLayers.MaintenancePanel,
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningPanelSpriteState, 0f)},
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningPanelSpriteState, 0f) },
});
((Animation)door.ClosingAnimation).AnimationTracks.Add(new AnimationTrackSpriteFlick
{
LayerKey = WiresVisualLayers.MaintenancePanel,
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingPanelSpriteState, 0f)},
KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingPanelSpriteState, 0f) },
});
}
@@ -101,11 +102,12 @@ public sealed class AirlockSystem : SharedAirlockSystem
&& !boltedVisible && !emergencyLightsVisible;
}
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible);
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseBolted, boltedVisible);
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseUnlit, unlitVisible);
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseBolted, boltedVisible);
if (comp.EmergencyAccessLayer)
{
args.Sprite.LayerSetVisible(
_sprite.LayerSetVisible(
(uid, args.Sprite),
DoorVisualLayers.BaseEmergencyAccess,
emergencyLightsVisible
&& state != DoorState.Open
@@ -118,12 +120,12 @@ public sealed class AirlockSystem : SharedAirlockSystem
switch (state)
{
case DoorState.Open:
args.Sprite.LayerSetState(DoorVisualLayers.BaseUnlit, comp.ClosingSpriteState);
args.Sprite.LayerSetAnimationTime(DoorVisualLayers.BaseUnlit, 0);
_sprite.LayerSetRsiState((uid, args.Sprite), DoorVisualLayers.BaseUnlit, comp.ClosingSpriteState);
_sprite.LayerSetAnimationTime((uid, args.Sprite), DoorVisualLayers.BaseUnlit, 0);
break;
case DoorState.Closed:
args.Sprite.LayerSetState(DoorVisualLayers.BaseUnlit, comp.OpeningSpriteState);
args.Sprite.LayerSetAnimationTime(DoorVisualLayers.BaseUnlit, 0);
_sprite.LayerSetRsiState((uid, args.Sprite), DoorVisualLayers.BaseUnlit, comp.OpeningSpriteState);
_sprite.LayerSetAnimationTime((uid, args.Sprite), DoorVisualLayers.BaseUnlit, 0);
break;
}
}

View File

@@ -11,6 +11,7 @@ public sealed class DoorSystem : SharedDoorSystem
{
[Dependency] private readonly AnimationPlayerSystem _animationSystem = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -85,7 +86,7 @@ public sealed class DoorSystem : SharedDoorSystem
state = DoorState.Closed;
if (AppearanceSystem.TryGetData<string>(entity, DoorVisuals.BaseRSI, out var baseRsi, args.Component))
UpdateSpriteLayers(args.Sprite, baseRsi);
UpdateSpriteLayers((entity.Owner, args.Sprite), baseRsi);
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey))
_animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey);
@@ -95,21 +96,21 @@ public sealed class DoorSystem : SharedDoorSystem
private void UpdateAppearanceForDoorState(Entity<DoorComponent> entity, SpriteComponent sprite, DoorState state)
{
sprite.DrawDepth = state is DoorState.Open ? entity.Comp.OpenDrawDepth : entity.Comp.ClosedDrawDepth;
_sprite.SetDrawDepth((entity.Owner, sprite), state is DoorState.Open ? entity.Comp.OpenDrawDepth : entity.Comp.ClosedDrawDepth);
switch (state)
{
case DoorState.Open:
foreach (var (layer, layerState) in entity.Comp.OpenSpriteStates)
{
sprite.LayerSetState(layer, layerState);
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
}
return;
case DoorState.Closed:
foreach (var (layer, layerState) in entity.Comp.ClosedSpriteStates)
{
sprite.LayerSetState(layer, layerState);
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
}
return;
@@ -138,7 +139,7 @@ public sealed class DoorSystem : SharedDoorSystem
}
}
private void UpdateSpriteLayers(SpriteComponent sprite, string baseRsi)
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string baseRsi)
{
if (!_resourceCache.TryGetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / baseRsi, out var res))
{
@@ -146,6 +147,6 @@ public sealed class DoorSystem : SharedDoorSystem
return;
}
sprite.BaseRSI = res.RSI;
_sprite.SetBaseRsi(sprite.AsNullable(), res.RSI);
}
}

View File

@@ -8,6 +8,7 @@ namespace Content.Client.Doors;
public sealed class FirelockSystem : SharedFirelockSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -18,7 +19,7 @@ public sealed class FirelockSystem : SharedFirelockSystem
protected override void OnComponentStartup(Entity<FirelockComponent> ent, ref ComponentStartup args)
{
base.OnComponentStartup(ent, ref args);
if(!TryComp<DoorComponent>(ent.Owner, out var door))
if (!TryComp<DoorComponent>(ent.Owner, out var door))
return;
door.ClosedSpriteStates.Add((DoorVisualLayers.BaseUnlit, ent.Comp.WarningLightSpriteState));
@@ -57,7 +58,7 @@ public sealed class FirelockSystem : SharedFirelockSystem
|| state == DoorState.Denying
|| (_appearanceSystem.TryGetData<bool>(uid, DoorVisuals.ClosedLights, out var closedLights, args.Component) && closedLights);
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible && !boltedVisible);
args.Sprite.LayerSetVisible(DoorVisualLayers.BaseBolted, boltedVisible);
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseUnlit, unlitVisible && !boltedVisible);
_sprite.LayerSetVisible((uid, args.Sprite), DoorVisualLayers.BaseBolted, boltedVisible);
}
}

View File

@@ -13,8 +13,9 @@ namespace Content.Client.Doors;
public sealed class TurnstileSystem : SharedTurnstileSystem
{
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private static EntProtoId _examineArrow = "TurnstileArrow";
private static readonly EntProtoId ExamineArrow = "TurnstileArrow";
private const string AnimationKey = "Turnstile";
@@ -33,12 +34,12 @@ public sealed class TurnstileSystem : SharedTurnstileSystem
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
sprite.LayerSetState(TurnstileVisualLayers.Base, new RSI.StateId(ent.Comp.DefaultState));
_sprite.LayerSetRsiState((ent.Owner, sprite), TurnstileVisualLayers.Base, new RSI.StateId(ent.Comp.DefaultState));
}
private void OnExamined(Entity<TurnstileComponent> ent, ref ExaminedEvent args)
{
Spawn(_examineArrow, new EntityCoordinates(ent, 0, 0));
Spawn(ExamineArrow, new EntityCoordinates(ent, 0, 0));
}
protected override void PlayAnimation(EntityUid uid, string stateId)

View File

@@ -7,6 +7,7 @@ namespace Content.Client.Dragon;
public sealed class DragonSystem : EntitySystem
{
[Dependency] private readonly SharedPointLightSystem _lights = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -31,7 +32,7 @@ public sealed class DragonSystem : EntitySystem
switch (state.State)
{
case DragonRiftState.Charging:
sprite?.LayerSetColor(0, Color.FromHex("#569fff"));
_sprite.LayerSetColor((uid, sprite), 0, Color.FromHex("#569fff"));
if (light != null)
{
@@ -39,7 +40,7 @@ public sealed class DragonSystem : EntitySystem
}
break;
case DragonRiftState.AlmostFinished:
sprite?.LayerSetColor(0, Color.FromHex("#cf4cff"));
_sprite.LayerSetColor((uid, sprite), 0, Color.FromHex("#cf4cff"));
if (light != null)
{
@@ -47,7 +48,7 @@ public sealed class DragonSystem : EntitySystem
}
break;
case DragonRiftState.Finished:
sprite?.LayerSetColor(0, Color.FromHex("#edbc36"));
_sprite.LayerSetColor((uid, sprite), 0, Color.FromHex("#edbc36"));
if (light != null)
{

View File

@@ -2,6 +2,7 @@ using Content.Shared.Drugs;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.Player;
using Robust.Shared.Random;
namespace Content.Client.Drugs;
@@ -12,6 +13,7 @@ public sealed class DrugOverlaySystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private RainbowOverlay _overlay = default!;
@@ -45,7 +47,10 @@ public sealed class DrugOverlaySystem : EntitySystem
private void OnInit(EntityUid uid, SeeingRainbowsComponent component, ComponentInit args)
{
if (_player.LocalEntity == uid)
{
_overlay.Phase = _random.NextFloat(MathF.Tau); // random starting phase for movement effect
_overlayMan.AddOverlay(_overlay);
}
}
private void OnShutdown(EntityUid uid, SeeingRainbowsComponent component, ComponentShutdown args)

View File

@@ -24,16 +24,27 @@ public sealed class RainbowOverlay : Overlay
public float Intoxication = 0.0f;
public float TimeTicker = 0.0f;
public float Phase = 0.0f;
private const float VisualThreshold = 10.0f;
private const float PowerDivisor = 250.0f;
private float _timeScale = 0.0f;
private float _warpScale = 0.0f;
private float EffectScale => Math.Clamp((Intoxication - VisualThreshold) / PowerDivisor, 0.0f, 1.0f);
public RainbowOverlay()
{
IoCManager.InjectDependencies(this);
_rainbowShader = _prototypeManager.Index<ShaderPrototype>("Rainbow").InstanceUnique();
_config.OnValueChanged(CCVars.ReducedMotion, OnReducedMotionChanged, invokeImmediately: true);
}
private void OnReducedMotionChanged(bool reducedMotion)
{
_timeScale = reducedMotion ? 0.0f : 1.0f;
_warpScale = reducedMotion ? 0.0f : 1.0f;
}
protected override void FrameUpdate(FrameEventArgs args)
@@ -51,7 +62,7 @@ public sealed class RainbowOverlay : Overlay
if (!statusSys.TryGetTime(playerEntity.Value, DrugOverlaySystem.RainbowKey, out var time, status))
return;
var timeLeft = (float) (time.Value.Item2 - time.Value.Item1).TotalSeconds;
var timeLeft = (float)(time.Value.Item2 - time.Value.Item1).TotalSeconds;
TimeTicker += args.DeltaSeconds;
@@ -61,7 +72,7 @@ public sealed class RainbowOverlay : Overlay
}
else
{
Intoxication -= Intoxication/(timeLeft - TimeTicker) * args.DeltaSeconds;
Intoxication -= Intoxication / (timeLeft - TimeTicker) * args.DeltaSeconds;
}
}
@@ -78,16 +89,15 @@ public sealed class RainbowOverlay : Overlay
protected override void Draw(in OverlayDrawArgs args)
{
// TODO disable only the motion part or ike's idea (single static frame of the overlay)
if (_config.GetCVar(CCVars.ReducedMotion))
return;
if (ScreenTexture == null)
return;
var handle = args.WorldHandle;
_rainbowShader.SetParameter("SCREEN_TEXTURE", ScreenTexture);
_rainbowShader.SetParameter("effectScale", EffectScale);
_rainbowShader.SetParameter("colorScale", EffectScale);
_rainbowShader.SetParameter("timeScale", _timeScale);
_rainbowShader.SetParameter("warpScale", _warpScale * EffectScale);
_rainbowShader.SetParameter("phase", Phase);
handle.UseShader(_rainbowShader);
handle.DrawRect(args.WorldBounds, Color.White);
handle.UseShader(null);

View File

@@ -13,6 +13,7 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/// <summary>
/// It's a little on the long side but given we use multiple colours denoting what happened it makes it easier to register.
@@ -44,7 +45,7 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
if (TryComp<SpriteComponent>(uid, out var sprite))
{
sprite.Color = component.Color;
_sprite.SetColor((uid, sprite), component.Color);
}
}

View File

@@ -53,15 +53,12 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
private void ShowHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
while (electrifiedQuery.MoveNext(out var uid, out _, out var appearanceComp, out var spriteComp))
{
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
continue;
if (electrified)
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
SpriteSystem.LayerSetVisible((uid, spriteComp), ElectrifiedLayers.HUD, electrified);
}
}
@@ -70,10 +67,9 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
private void RemoveHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
while (electrifiedQuery.MoveNext(out var uid, out _, out _, out var spriteComp))
{
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
SpriteSystem.LayerSetVisible((uid, spriteComp), ElectrifiedLayers.HUD, false);
}
}
@@ -87,9 +83,6 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
return;
var player = _playerMan.LocalEntity;
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
SpriteSystem.LayerSetVisible((uid, args.Sprite), ElectrifiedLayers.HUD, electrified && HasComp<ShowElectrocutionHUDComponent>(player));
}
}

View File

@@ -1,12 +1,14 @@
using Content.Shared.Ensnaring;
using Content.Shared.Ensnaring.Components;
using Robust.Client.GameObjects;
using Robust.Shared.Utility;
namespace Content.Client.Ensnaring;
public sealed class EnsnareableSystem : SharedEnsnareableSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -19,25 +21,25 @@ public sealed class EnsnareableSystem : SharedEnsnareableSystem
{
base.OnEnsnareInit(ent, ref args);
if(!TryComp<SpriteComponent>(ent.Owner, out var sprite))
if (!TryComp<SpriteComponent>(ent.Owner, out var sprite))
return;
// TODO remove this, this should just be in yaml.
sprite.LayerMapReserveBlank(EnsnaredVisualLayers.Ensnared);
_sprite.LayerMapReserve((ent.Owner, sprite), EnsnaredVisualLayers.Ensnared);
}
private void OnAppearanceChange(EntityUid uid, EnsnareableComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null || !args.Sprite.LayerMapTryGet(EnsnaredVisualLayers.Ensnared, out var layer))
if (args.Sprite == null || !_sprite.LayerMapTryGet((uid, args.Sprite), EnsnaredVisualLayers.Ensnared, out var layer, false))
return;
if (_appearance.TryGetData<bool>(uid, EnsnareableVisuals.IsEnsnared, out var isEnsnared, args.Component))
{
if (component.Sprite != null)
{
args.Sprite.LayerSetRSI(layer, component.Sprite);
args.Sprite.LayerSetState(layer, component.State);
args.Sprite.LayerSetVisible(layer, isEnsnared);
_sprite.LayerSetRsi((uid, args.Sprite), layer, new ResPath(component.Sprite));
_sprite.LayerSetRsiState((uid, args.Sprite), layer, component.State);
_sprite.LayerSetVisible((uid, args.Sprite), layer, isEnsnared);
}
}
}

View File

@@ -12,6 +12,6 @@ public sealed class ClusterGrenadeVisualizerSystem : VisualizerSystem<ClusterGre
return;
if (AppearanceSystem.TryGetData<int>(uid, ClusterGrenadeVisuals.GrenadesCounter, out var grenadesCounter, args.Component))
args.Sprite.LayerSetState(0, $"{comp.State}-{grenadesCounter}");
SpriteSystem.LayerSetRsiState((uid, args.Sprite), 0, $"{comp.State}-{grenadesCounter}");
}
}

View File

@@ -4,7 +4,6 @@ using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameStates;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.Client.Explosion;
@@ -19,7 +18,7 @@ public sealed class ExplosionOverlaySystem : EntitySystem
[Dependency] private readonly IResourceCache _resCache = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;
[Dependency] private readonly SharedPointLightSystem _lights = default!;
[Dependency] private readonly IMapManager _mapMan = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public override void Initialize()
@@ -69,7 +68,7 @@ public sealed class ExplosionOverlaySystem : EntitySystem
}
// Map may have been deleted.
if (_mapMan.MapExists(component.Epicenter.MapId))
if (_mapSystem.MapExists(component.Epicenter.MapId))
{
// spawn in a client-side light source at the epicenter
var lightEntity = Spawn("ExplosionLight", component.Epicenter);

View File

@@ -9,6 +9,7 @@ public sealed partial class TriggerSystem
{
[Dependency] private readonly AnimationPlayerSystem _player = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/*
* Currently all of the appearance stuff is hardcoded for portable flashers
@@ -79,7 +80,7 @@ public sealed partial class TriggerSystem
if (!_appearance.TryGetData<ProximityTriggerVisuals>(uid, ProximityTriggerVisualState.State, out var state, appearance))
return;
if (!spriteComponent.LayerMapTryGet(ProximityTriggerVisualLayers.Base, out var layer))
if (!_sprite.LayerMapTryGet((uid, spriteComponent), ProximityTriggerVisualLayers.Base, out var layer, false))
// Don't do anything if the sprite doesn't have the layer.
return;
@@ -89,7 +90,7 @@ public sealed partial class TriggerSystem
// Don't interrupt the flash animation
if (_player.HasRunningAnimation(uid, player, AnimKey)) return;
_player.Stop(uid, player, AnimKey);
spriteComponent.LayerSetState(layer, "on");
_sprite.LayerSetRsiState((uid, spriteComponent), layer, "on");
break;
case ProximityTriggerVisuals.Active:
if (_player.HasRunningAnimation(uid, player, AnimKey)) return;
@@ -98,7 +99,7 @@ public sealed partial class TriggerSystem
case ProximityTriggerVisuals.Off:
default:
_player.Stop(uid, player, AnimKey);
spriteComponent.LayerSetState(layer, "off");
_sprite.LayerSetRsiState((uid, spriteComponent), layer, "off");
break;
}
}

View File

@@ -1,43 +1,116 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'fax-machine-ui-window'}"
MinWidth="250">
<BoxContainer Orientation="Vertical" VerticalExpand="True">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Label Text="{Loc 'fax-machine-ui-paper'}" />
<Control MinWidth="4" />
<Label Name="PaperStatusLabel" />
</BoxContainer>
<Control HorizontalExpand="True" MinHeight="20" />
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Label Text="{Loc 'fax-machine-ui-from'}" />
<Control MinWidth="4" />
<Label Name="FromLabel" />
</BoxContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Label Text="{Loc 'fax-machine-ui-to'}" />
<Control MinWidth="4" />
<OptionButton Name="PeerSelector" HorizontalExpand="True" />
</BoxContainer>
<Control HorizontalExpand="True" MinHeight="20" />
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Button Name="FileButton"
Text="{Loc 'fax-machine-ui-file-button'}"
HorizontalExpand="False"/>
<Button Name="PaperButton"
Text="{Loc 'fax-machine-ui-paper-button-normal'}"
HorizontalExpand="False"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
<Button Name="CopyButton"
Text="{Loc 'fax-machine-ui-copy-button'}"
HorizontalExpand="False"
Disabled="True" />
<Button Name="SendButton"
Text="{Loc 'fax-machine-ui-send-button'}"
HorizontalExpand="True"
Disabled="True" />
<Button Name="RefreshButton"
Text="{Loc 'fax-machine-ui-refresh-button'}" />
</BoxContainer>
<DefaultWindow
xmlns="https://spacestation14.io"
Title="{Loc 'fax-machine-ui-window'}"
MinSize="380 220">
<BoxContainer Orientation="Vertical"
SeparationOverride="2"
VerticalExpand="True">
<PanelContainer StyleClasses="PanelBackgroundBaseDark" HorizontalExpand="True">
<BoxContainer Orientation="Vertical"
Margin="0 0 0 2">
<!-- From Line -->
<BoxContainer Orientation="Horizontal">
<!-- From Value Name -->
<Label Text="{Loc 'fax-machine-ui-from'}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"/>
<Control HorizontalExpand="True"
MinWidth="8"
HorizontalAlignment="Center"/>
<!-- From Value -->
<Label Name="FromLabel"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Align="Right"/>
</BoxContainer>
<!-- To Line -->
<BoxContainer
Orientation="Horizontal">
<!-- To Label -->
<Label Text="{Loc 'fax-machine-ui-to'}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"/>
<Control HorizontalExpand="True"
MinWidth="8"
HorizontalAlignment="Center"/>
<BoxContainer Orientation="Horizontal">
<!-- To Value -->
<OptionButton Name="PeerSelector"
StyleClasses="OpenRight" />
<!-- Refresh Fax Recipients -->
<Button StyleClasses="OpenLeft"
Name="RefreshButton"
ToolTip="{Loc 'fax-machine-ui-refresh-button'}">
<TextureButton
MouseFilter="Ignore"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Scale="0.9 0.9"
StyleClasses="Refresh" />
</Button>
</BoxContainer>
</BoxContainer>
<PanelContainer StyleClasses="LowDivider" Margin="0 4 0 4"/>
<!-- Send & Copy -->
<BoxContainer Orientation="Vertical">
<!-- Paper Status -->
<Label Name="PaperStatusLabel"
HorizontalAlignment="Center" />
<BoxContainer>
<Button Name="CopyButton"
Text="{Loc 'fax-machine-ui-copy-button'}"
StyleClasses="OpenRight"
HorizontalExpand="True"
Disabled="True" />
<Button Name="SendButton"
Text="{Loc 'fax-machine-ui-send-button'}"
StyleClasses="OpenLeft"
HorizontalExpand="True"
Disabled="True" />
</BoxContainer>
</BoxContainer>
</BoxContainer>
</PanelContainer>
<PanelContainer StyleClasses="PanelBackgroundBaseDark"
HorizontalExpand="True" Margin="0 10 0 0"
VerticalExpand="True" VerticalAlignment="Bottom">
<BoxContainer Orientation="Vertical"
VerticalExpand="True">
<!-- Other actions -->
<BoxContainer Margin="0 4 0 4">
<Button Name="PaperButton"
Text="{Loc 'fax-machine-ui-paper-button-normal'}"
StyleClasses="OpenRight"
HorizontalExpand="True"/>
<Button Name="FileButton"
Text="{Loc 'fax-machine-ui-file-button'}"
StyleClasses="OpenLeft"
HorizontalExpand="True"/>
</BoxContainer>
<!-- It would be cool to add a display of the inserted file here. -->
</BoxContainer>
</PanelContainer>
</BoxContainer>
</DefaultWindow>

View File

@@ -10,6 +10,7 @@ namespace Content.Client.Fluids;
public sealed class PuddleSystem : SharedPuddleSystem
{
[Dependency] private readonly IconSmoothSystem _smooth = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -27,7 +28,7 @@ public sealed class PuddleSystem : SharedPuddleSystem
if (args.AppearanceData.TryGetValue(PuddleVisuals.CurrentVolume, out var volumeObj))
{
volume = (float) volumeObj;
volume = (float)volumeObj;
}
// Update smoothing and sprite based on volume.
@@ -35,19 +36,19 @@ public sealed class PuddleSystem : SharedPuddleSystem
{
if (volume < LowThreshold)
{
args.Sprite.LayerSetState(0, $"{smooth.StateBase}a");
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}a");
_smooth.SetEnabled(uid, false, smooth);
}
else if (volume < MediumThreshold)
{
args.Sprite.LayerSetState(0, $"{smooth.StateBase}b");
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}b");
_smooth.SetEnabled(uid, false, smooth);
}
else
{
if (!smooth.Enabled)
{
args.Sprite.LayerSetState(0, $"{smooth.StateBase}0");
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}0");
_smooth.SetEnabled(uid, true, smooth);
_smooth.DirtyNeighbours(uid);
}
@@ -58,12 +59,12 @@ public sealed class PuddleSystem : SharedPuddleSystem
if (args.AppearanceData.TryGetValue(PuddleVisuals.SolutionColor, out var colorObj))
{
var color = (Color) colorObj;
args.Sprite.Color = color * baseColor;
var color = (Color)colorObj;
_sprite.SetColor((uid, args.Sprite), color * baseColor);
}
else
{
args.Sprite.Color *= baseColor;
_sprite.SetColor((uid, args.Sprite), args.Sprite.Color * baseColor);
}
}

View File

@@ -15,6 +15,7 @@ namespace Content.Client.Ghost
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly PointLightSystem _pointLightSystem = default!;
[Dependency] private readonly ContentEyeSystem _contentEye = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public int AvailableGhostRoleCount { get; private set; }
@@ -35,7 +36,7 @@ namespace Content.Client.Ghost
var query = AllEntityQuery<GhostComponent, SpriteComponent>();
while (query.MoveNext(out var uid, out _, out var sprite))
{
sprite.Visible = value || uid == _playerManager.LocalEntity;
_sprite.SetVisible((uid, sprite), value || uid == _playerManager.LocalEntity);
}
}
}
@@ -72,7 +73,7 @@ namespace Content.Client.Ghost
private void OnStartup(EntityUid uid, GhostComponent component, ComponentStartup args)
{
if (TryComp(uid, out SpriteComponent? sprite))
sprite.Visible = GhostVisibility || uid == _playerManager.LocalEntity;
_sprite.SetVisible((uid, sprite), GhostVisibility || uid == _playerManager.LocalEntity);
}
private void OnToggleLighting(EntityUid uid, EyeComponent component, ToggleLightingActionEvent args)
@@ -150,7 +151,7 @@ namespace Content.Client.Ghost
private void OnGhostState(EntityUid uid, GhostComponent component, ref AfterAutoHandleStateEvent args)
{
if (TryComp<SpriteComponent>(uid, out var sprite))
sprite.LayerSetColor(0, component.Color);
_sprite.LayerSetColor((uid, sprite), 0, component.Color);
if (uid != _playerManager.LocalEntity)
return;

View File

@@ -25,6 +25,7 @@ public sealed class GhostToggleSelfVisibility : IConsoleCommand
if (!entityManager.TryGetComponent(attachedEntity, out SpriteComponent? spriteComponent))
return;
spriteComponent.Visible = !spriteComponent.Visible;
var spriteSys = entityManager.System<SpriteSystem>();
spriteSys.SetVisible((attachedEntity.Value, spriteComponent), !spriteComponent.Visible);
}
}

View File

@@ -7,6 +7,8 @@ namespace Content.Client.Gravity;
public sealed partial class GravitySystem : SharedGravitySystem
{
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
@@ -26,34 +28,34 @@ public sealed partial class GravitySystem : SharedGravitySystem
{
if (comp.SpriteMap.TryGetValue(state, out var spriteState))
{
var layer = args.Sprite.LayerMapGet(GravityGeneratorVisualLayers.Base);
args.Sprite.LayerSetState(layer, spriteState);
var layer = _sprite.LayerMapGet((uid, args.Sprite), GravityGeneratorVisualLayers.Base);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, spriteState);
}
}
if (_appearanceSystem.TryGetData<float>(uid, PowerChargeVisuals.Charge, out var charge, args.Component))
{
var layer = args.Sprite.LayerMapGet(GravityGeneratorVisualLayers.Core);
var layer = _sprite.LayerMapGet((uid, args.Sprite), GravityGeneratorVisualLayers.Core);
switch (charge)
{
case < 0.2f:
args.Sprite.LayerSetVisible(layer, false);
_sprite.LayerSetVisible((uid, args.Sprite), layer, false);
break;
case >= 0.2f and < 0.4f:
args.Sprite.LayerSetVisible(layer, true);
args.Sprite.LayerSetState(layer, comp.CoreStartupState);
_sprite.LayerSetVisible((uid, args.Sprite), layer, true);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, comp.CoreStartupState);
break;
case >= 0.4f and < 0.6f:
args.Sprite.LayerSetVisible(layer, true);
args.Sprite.LayerSetState(layer, comp.CoreIdleState);
_sprite.LayerSetVisible((uid, args.Sprite), layer, true);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, comp.CoreIdleState);
break;
case >= 0.6f and < 0.8f:
args.Sprite.LayerSetVisible(layer, true);
args.Sprite.LayerSetState(layer, comp.CoreActivatingState);
_sprite.LayerSetVisible((uid, args.Sprite), layer, true);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, comp.CoreActivatingState);
break;
default:
args.Sprite.LayerSetVisible(layer, true);
args.Sprite.LayerSetState(layer, comp.CoreActivatedState);
_sprite.LayerSetVisible((uid, args.Sprite), layer, true);
_sprite.LayerSetRsiState((uid, args.Sprite), layer, comp.CoreActivatedState);
break;
}
}

View File

@@ -19,13 +19,15 @@ namespace Content.Client.Guidebook.Controls;
/// Control for embedding a microwave recipe into a guidebook.
/// </summary>
[UsedImplicitly, GenerateTypedNameReferences]
public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag, ISearchableControl
public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag, ISearchableControl, IPrototypeRepresentationControl
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private ISawmill _sawmill = default!;
public IPrototype? RepresentedPrototype { get; private set; }
public GuideMicrowaveEmbed()
{
RobustXamlLoader.Load(this);
@@ -80,6 +82,8 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
{
var entity = _prototype.Index<EntityPrototype>(recipe.Result);
RepresentedPrototype = entity;
IconContainer.AddChild(new GuideEntityEmbed(recipe.Result, false, false));
ResultName.SetMarkup(entity.Name);
ResultDescription.SetMarkup(entity.Description);
@@ -99,8 +103,9 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
solidNameMsg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-solid-name-display", ("ingredient", ingredient.Name)));
solidNameMsg.Pop();
var solidNameLabel = new RichTextLabel();
var solidNameLabel = new GuidebookRichPrototypeLink();
solidNameLabel.SetMessage(solidNameMsg);
solidNameLabel.LinkedPrototype = ingredient;
IngredientsGrid.AddChild(solidNameLabel);
@@ -129,9 +134,10 @@ public sealed partial class GuideMicrowaveEmbed : PanelContainer, IDocumentTag,
liquidColorMsg.AddMarkupOrThrow(Loc.GetString("guidebook-microwave-reagent-color-display", ("color", reagent.SubstanceColor)));
liquidColorMsg.Pop();
var liquidColorLabel = new RichTextLabel();
var liquidColorLabel = new GuidebookRichPrototypeLink();
liquidColorLabel.SetMessage(liquidColorMsg);
liquidColorLabel.HorizontalAlignment = Control.HAlignment.Center;
liquidColorLabel.LinkedPrototype = reagent;
IngredientsGrid.AddChild(liquidColorLabel);

View File

@@ -22,13 +22,15 @@ namespace Content.Client.Guidebook.Controls;
/// Control for embedding a reagent into a guidebook.
/// </summary>
[UsedImplicitly, GenerateTypedNameReferences]
public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISearchableControl
public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISearchableControl, IPrototypeRepresentationControl
{
[Dependency] private readonly IEntitySystemManager _systemManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
private readonly ChemistryGuideDataSystem _chemistryGuideData;
public IPrototype? RepresentedPrototype { get; private set; }
public GuideReagentEmbed()
{
RobustXamlLoader.Load(this);
@@ -80,6 +82,8 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
private void GenerateControl(ReagentPrototype reagent)
{
RepresentedPrototype = reagent;
NameBackground.PanelOverride = new StyleBoxFlat
{
BackgroundColor = reagent.SubstanceColor

View File

@@ -4,13 +4,11 @@
HorizontalExpand="True"
Margin="0 0 0 5">
<BoxContainer Orientation="Horizontal">
<BoxContainer Name="ReactantsContainer" Orientation="Vertical" HorizontalExpand="True"
<BoxContainer Orientation="Vertical" HorizontalExpand="True"
VerticalAlignment="Center">
<RichTextLabel Name="ReactantsLabel"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Access="Public"
Visible="False" />
<BoxContainer Name="ReactantsContainer" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
<!-- Reactants will be added as children here -->
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextureRect TexturePath="/Textures/Interface/Misc/beakerlarge.png"
@@ -23,11 +21,9 @@
Margin="2 0 0 0" />
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center">
<RichTextLabel Name="ProductsLabel"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Access="Public"
Visible="False" />
<BoxContainer Name="ProductsContainer" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
<!-- Products will be added as children here -->
</BoxContainer>
</BoxContainer>
</BoxContainer>
<PanelContainer StyleClasses="LowDivider" Margin="0 5 0 5" />

View File

@@ -34,16 +34,16 @@ public sealed partial class GuideReagentReaction : BoxContainer, ISearchableCont
public GuideReagentReaction(ReactionPrototype prototype, IPrototypeManager protoMan, IEntitySystemManager sysMan) : this(protoMan)
{
var reactantsLabel = ReactantsLabel;
SetReagents(prototype.Reactants, ref reactantsLabel, protoMan);
var productLabel = ProductsLabel;
Container container = ReactantsContainer;
SetReagents(prototype.Reactants, ref container, protoMan);
Container productContainer = ProductsContainer;
var products = new Dictionary<string, FixedPoint2>(prototype.Products);
foreach (var (reagent, reactantProto) in prototype.Reactants)
{
if (reactantProto.Catalyst)
products.Add(reagent, reactantProto.Amount);
}
SetReagents(products, ref productLabel, protoMan);
SetReagents(products, ref productContainer, protoMan, false);
var mixingCategories = new List<MixingCategoryPrototype>();
if (prototype.MixingCategories != null)
@@ -85,8 +85,8 @@ public sealed partial class GuideReagentReaction : BoxContainer, ISearchableCont
entContainer.AddChild(nameLabel);
ReactantsContainer.AddChild(entContainer);
var productLabel = ProductsLabel;
SetReagents(solution.Contents, ref productLabel, protoMan);
Container productContainer = ProductsContainer;
SetReagents(solution.Contents, ref productContainer, protoMan, false);
SetMixingCategory(categories, null, sysMan);
}
@@ -95,75 +95,80 @@ public sealed partial class GuideReagentReaction : BoxContainer, ISearchableCont
IPrototypeManager protoMan,
IEntitySystemManager sysMan) : this(protoMan)
{
ReactantsLabel.Visible = true;
ReactantsLabel.SetMarkup(Loc.GetString("guidebook-reagent-sources-gas-wrapper",
var label = new RichTextLabel();
label.SetMarkup(Loc.GetString("guidebook-reagent-sources-gas-wrapper",
("name", Loc.GetString(prototype.Name).ToLower())));
ReactantsContainer.Visible = true;
ReactantsContainer.AddChild(label);
if (prototype.Reagent != null)
{
var quantity = new Dictionary<string, FixedPoint2>
{
{ prototype.Reagent, FixedPoint2.New(0.21f) }
};
var productLabel = ProductsLabel;
SetReagents(quantity, ref productLabel, protoMan);
Container productContainer = ProductsContainer;
SetReagents(quantity, ref productContainer, protoMan, false);
}
SetMixingCategory(categories, null, sysMan);
}
private void SetReagents(List<ReagentQuantity> reagents, ref RichTextLabel label, IPrototypeManager protoMan)
private void SetReagents(List<ReagentQuantity> reagents, ref Container container, IPrototypeManager protoMan, bool addLinks = true)
{
var amounts = new Dictionary<string, FixedPoint2>();
foreach (var (reagent, quantity) in reagents)
{
amounts.Add(reagent.Prototype, quantity);
}
SetReagents(amounts, ref label, protoMan);
SetReagents(amounts, ref container, protoMan, addLinks);
}
private void SetReagents(
Dictionary<string, ReactantPrototype> reactants,
ref RichTextLabel label,
IPrototypeManager protoMan)
ref Container container,
IPrototypeManager protoMan,
bool addLinks = true)
{
var amounts = new Dictionary<string, FixedPoint2>();
foreach (var (reagent, reactantPrototype) in reactants)
{
amounts.Add(reagent, reactantPrototype.Amount);
}
SetReagents(amounts, ref label, protoMan);
SetReagents(amounts, ref container, protoMan, addLinks);
}
[PublicAPI]
private void SetReagents(
Dictionary<ProtoId<MixingCategoryPrototype>, ReactantPrototype> reactants,
ref RichTextLabel label,
IPrototypeManager protoMan)
ref Container container,
IPrototypeManager protoMan,
bool addLinks = true)
{
var amounts = new Dictionary<string, FixedPoint2>();
foreach (var (reagent, reactantPrototype) in reactants)
{
amounts.Add(reagent, reactantPrototype.Amount);
}
SetReagents(amounts, ref label, protoMan);
SetReagents(amounts, ref container, protoMan, addLinks);
}
private void SetReagents(Dictionary<string, FixedPoint2> reagents, ref RichTextLabel label, IPrototypeManager protoMan)
private void SetReagents(Dictionary<string, FixedPoint2> reagents, ref Container container, IPrototypeManager protoMan, bool addLinks = true)
{
var msg = new FormattedMessage();
var reagentCount = reagents.Count;
var i = 0;
foreach (var (product, amount) in reagents.OrderByDescending(p => p.Value))
{
var productProto = protoMan.Index<ReagentPrototype>(product);
var msg = new FormattedMessage();
msg.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-recipes-reagent-display",
("reagent", protoMan.Index<ReagentPrototype>(product).LocalizedName), ("ratio", amount)));
i++;
if (i < reagentCount)
msg.PushNewline();
("reagent", productProto.LocalizedName), ("ratio", amount)));
var label = new GuidebookRichPrototypeLink();
if (addLinks)
label.LinkedPrototype = productProto;
label.SetMessage(msg);
container.AddChild(label);
}
msg.Pop();
label.SetMessage(msg);
label.Visible = true;
container.Visible = true;
}
private void SetMixingCategory(IReadOnlyList<ProtoId<MixingCategoryPrototype>> mixingCategories, ReactionPrototype? prototype, IEntitySystemManager sysMan)

View File

@@ -0,0 +1,71 @@
using Content.Client.Guidebook.RichText;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using Content.Client.UserInterface.ControlExtensions;
namespace Content.Client.Guidebook.Controls;
/// <summary>
/// A RichTextLabel which is a link to a specified IPrototype.
/// The link is activated by the owner if the prototype is represented
/// somewhere in the same document.
/// </summary>
public sealed class GuidebookRichPrototypeLink : Control, IPrototypeLinkControl
{
private bool _linkActive = false;
private FormattedMessage? _message;
private readonly RichTextLabel _richTextLabel;
public void EnablePrototypeLink()
{
if (_message == null)
return;
_linkActive = true;
DefaultCursorShape = CursorShape.Hand;
_richTextLabel.SetMessage(_message, null, TextLinkTag.LinkColor);
}
public GuidebookRichPrototypeLink() : base()
{
MouseFilter = MouseFilterMode.Pass;
OnKeyBindDown += HandleClick;
_richTextLabel = new RichTextLabel();
AddChild(_richTextLabel);
}
public void SetMessage(FormattedMessage message)
{
_message = message;
_richTextLabel.SetMessage(_message);
}
public IPrototype? LinkedPrototype { get; set; }
private void HandleClick(GUIBoundKeyEventArgs args)
{
if (!_linkActive)
return;
if (args.Function != EngineKeyFunctions.UIClick)
return;
if (this.TryGetParentHandler<IAnchorClickHandler>(out var handler))
{
handler.HandleAnchor(this);
args.Handle();
}
else
Logger.Warning("Warning! No valid IAnchorClickHandler found.");
}
}
public interface IAnchorClickHandler
{
public void HandleAnchor(IPrototypeLinkControl prototypeLinkControl);
}

View File

@@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Linq;
using Content.Client.Guidebook.RichText;
using Content.Client.UserInterface.ControlExtensions;
@@ -6,6 +7,7 @@ using Content.Client.UserInterface.Controls.FancyTree;
using Content.Client.UserInterface.Systems.Info;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.ContentPack;
@@ -14,7 +16,7 @@ using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
[GenerateTypedNameReferences]
public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler, IAnchorClickHandler
{
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
[Dependency] private readonly IResourceManager _resourceManager = default!;
@@ -53,6 +55,38 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
ShowGuide(entry);
}
public void HandleAnchor(IPrototypeLinkControl prototypeLinkControl)
{
var prototype = prototypeLinkControl.LinkedPrototype;
if (prototype == null)
return;
var (linkableControls, _) = GetLinkableControlsAndLinks(EntryContainer);
foreach (var linkableControl in linkableControls)
{
if (linkableControl.RepresentedPrototype != prototype)
continue;
if (linkableControl is not Control control)
return;
// Check if the target item is currently filtered out
if (!control.Visible)
control.Visible = true;
UserInterfaceManager.DeferAction(() =>
{
if (control.GetControlScrollPosition() is not {} position)
return;
Scroll.HScrollTarget = position.X;
Scroll.VScrollTarget = position.Y;
});
break;
}
}
private void OnSelectionChanged(TreeItem? item)
{
if (item != null && item.Metadata is GuideEntry entry)
@@ -94,6 +128,23 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
LastEntry = entry.Id;
var (linkableControls, linkControls) = GetLinkableControlsAndLinks(EntryContainer);
HashSet<IPrototype> availablePrototypeLinks = new();
foreach (var linkableControl in linkableControls)
{
var prototype = linkableControl.RepresentedPrototype;
if (prototype != null)
availablePrototypeLinks.Add(prototype);
}
foreach (var linkControl in linkControls)
{
var prototype = linkControl.LinkedPrototype;
if (prototype != null && availablePrototypeLinks.Contains(prototype))
linkControl.EnablePrototypeLink();
}
}
public void UpdateGuides(
@@ -209,4 +260,30 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
}
}
private static (List<IPrototypeRepresentationControl>, List<IPrototypeLinkControl>) GetLinkableControlsAndLinks(Control parent)
{
List<IPrototypeRepresentationControl> linkableList = new();
List<IPrototypeLinkControl> linkList = new();
foreach (var child in parent.Children)
{
var hasChildren = child.ChildCount > 0;
if (child is IPrototypeLinkControl linkChild)
linkList.Add(linkChild);
else if (child is IPrototypeRepresentationControl linkableChild)
linkableList.Add(linkableChild);
if (!hasChildren)
continue;
var (childLinkableList, childLinkList) = GetLinkableControlsAndLinks(child);
linkableList.AddRange(childLinkableList);
linkList.AddRange(childLinkList);
}
return (linkableList, linkList);
}
}

View File

@@ -0,0 +1,28 @@
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
/// <summary>
/// Interface for controls which represent a Prototype
/// These can be linked to from a IPrototypeLinkControl
/// </summary>
public interface IPrototypeRepresentationControl
{
// The prototype that this control represents
public IPrototype? RepresentedPrototype { get; }
}
/// <summary>
/// Interface for controls which can be clicked to navigate
/// to a specified prototype representation on the same page.
/// </summary>
public interface IPrototypeLinkControl
{
// This control is a link to the specified prototype
public IPrototype? LinkedPrototype { get; }
// Initially the link will not be enabled,
// the owner can enable the link once there is a valid target
// for the Prototype link.
public void EnablePrototypeLink();
}

View File

@@ -5,12 +5,15 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.RichText;
using Robust.Shared.Input;
using Robust.Shared.Utility;
using Content.Client.UserInterface.ControlExtensions;
namespace Content.Client.Guidebook.RichText;
[UsedImplicitly]
public sealed class TextLinkTag : IMarkupTag
{
public static Color LinkColor => Color.CornflowerBlue;
public string Name => "textlink";
public Control? Control;
@@ -30,7 +33,7 @@ public sealed class TextLinkTag : IMarkupTag
label.Text = text;
label.MouseFilter = Control.MouseFilterMode.Stop;
label.FontColorOverride = Color.CornflowerBlue;
label.FontColorOverride = LinkColor;
label.DefaultCursorShape = Control.CursorShape.Hand;
label.OnMouseEntered += _ => label.FontColorOverride = Color.LightSkyBlue;
@@ -50,17 +53,10 @@ public sealed class TextLinkTag : IMarkupTag
if (Control == null)
return;
var current = Control;
while (current != null)
{
current = current.Parent;
if (current is not ILinkClickHandler handler)
continue;
if (Control.TryGetParentHandler<ILinkClickHandler>(out var handler))
handler.HandleClick(link);
return;
}
Logger.Warning($"Warning! No valid ILinkClickHandler found.");
else
Logger.Warning("Warning! No valid ILinkClickHandler found.");
}
}

View File

@@ -17,6 +17,7 @@ using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.Hands.Systems
{
@@ -28,6 +29,7 @@ namespace Content.Client.Hands.Systems
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly StrippableSystem _stripSys = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
@@ -297,7 +299,7 @@ namespace Content.Client.Hands.Systems
{
foreach (var key in revealedLayers)
{
sprite.RemoveLayer(key);
_sprite.RemoveLayer((uid, sprite), key);
}
revealedLayers.Clear();
@@ -333,7 +335,7 @@ namespace Content.Client.Hands.Systems
continue;
}
var index = sprite.LayerMapReserveBlank(key);
var index = _sprite.LayerMapReserve((uid, sprite), key);
// 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
@@ -341,12 +343,12 @@ namespace Content.Client.Hands.Systems
&& sprite[index].Rsi == null)
{
if (TryComp<ItemComponent>(held, out var itemComponent) && itemComponent.RsiPath != null)
sprite.LayerSetRSI(index, itemComponent.RsiPath);
_sprite.LayerSetRsi((uid, sprite), index, new ResPath(itemComponent.RsiPath));
else if (TryComp(held, out SpriteComponent? clothingSprite))
sprite.LayerSetRSI(index, clothingSprite.BaseRSI);
_sprite.LayerSetRsi((uid, sprite), index, clothingSprite.BaseRSI);
}
sprite.LayerSetData(index, layerData);
_sprite.LayerSetData((uid, sprite), index, layerData);
// Add displacement maps
var displacement = hand.Location switch
@@ -356,7 +358,7 @@ namespace Content.Client.Hands.Systems
_ => handComp.HandDisplacement
};
if (displacement is not null && _displacement.TryAddDisplacement(displacement, sprite, index, key, out var displacementKey))
if (displacement is not null && _displacement.TryAddDisplacement(displacement, (uid, sprite), index, key, out var displacementKey))
revealedLayers.Add(displacementKey);
}

View File

@@ -11,6 +11,7 @@ public sealed class HolidaySystem : EntitySystem
{
[Dependency] private readonly IResourceCache _rescache = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -29,6 +30,6 @@ public sealed class HolidaySystem : EntitySystem
var path = SpriteSpecifierSerializer.TextureRoot / rsistring;
if (_rescache.TryGetResource(path, out RSIResource? rsi))
args.Sprite.BaseRSI = rsi.RSI;
_sprite.SetBaseRsi((ent.Owner, args.Sprite), rsi.RSI);
}
}

View File

@@ -13,6 +13,7 @@ public sealed class HolopadSystem : SharedHolopadSystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -58,8 +59,8 @@ public sealed class HolopadSystem : SharedHolopadSystem
return;
// Remove all sprite layers
for (int i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
hologramSprite.RemoveLayer(i);
for (var i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
_sprite.RemoveLayer((hologram, hologramSprite), i);
if (TryComp<SpriteComponent>(target, out var targetSprite))
{
@@ -67,17 +68,16 @@ public sealed class HolopadSystem : SharedHolopadSystem
if (TryComp<HolographicAvatarComponent>(target, out var targetAvatar) &&
targetAvatar.LayerData != null)
{
for (int i = 0; i < targetAvatar.LayerData.Length; i++)
for (var i = 0; i < targetAvatar.LayerData.Length; i++)
{
var layer = targetAvatar.LayerData[i];
hologramSprite.AddLayer(targetAvatar.LayerData[i], i);
_sprite.AddLayer((hologram, hologramSprite), targetAvatar.LayerData[i], i);
}
}
// Otherwise copy the target's current physical appearance
else
{
hologramSprite.CopyFrom(targetSprite);
_sprite.CopySprite((target.Value, targetSprite), (hologram, hologramSprite));
}
}
@@ -87,25 +87,27 @@ public sealed class HolopadSystem : SharedHolopadSystem
if (string.IsNullOrEmpty(holopadhologram.RsiPath) || string.IsNullOrEmpty(holopadhologram.RsiState))
return;
var layer = new PrototypeLayerData();
layer.RsiPath = holopadhologram.RsiPath;
layer.State = holopadhologram.RsiState;
var layer = new PrototypeLayerData
{
RsiPath = holopadhologram.RsiPath,
State = holopadhologram.RsiState
};
hologramSprite.AddLayer(layer);
_sprite.AddLayer((hologram, hologramSprite), layer, null);
}
// Override specific values
hologramSprite.Color = Color.White;
hologramSprite.Offset = holopadhologram.Offset;
hologramSprite.DrawDepth = (int)DrawDepth.Mobs;
_sprite.SetColor((hologram, hologramSprite), Color.White);
_sprite.SetOffset((hologram, hologramSprite), holopadhologram.Offset);
_sprite.SetDrawDepth((hologram, hologramSprite), (int)DrawDepth.Mobs);
hologramSprite.NoRotation = true;
hologramSprite.DirectionOverride = Direction.South;
hologramSprite.EnableDirectionOverride = true;
// Remove shading from all layers (except displacement maps)
for (int i = 0; i < hologramSprite.AllLayers.Count(); i++)
for (var i = 0; i < hologramSprite.AllLayers.Count(); i++)
{
if (hologramSprite.TryGetLayer(i, out var layer) && layer.ShaderPrototype != "DisplacedStencilDraw")
if (_sprite.TryGetLayer((hologram, hologramSprite), i, out var layer, false) && layer.ShaderPrototype != "DisplacedStencilDraw")
hologramSprite.LayerSetShader(i, "unshaded");
}

View File

@@ -18,6 +18,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
[Dependency] private readonly MarkingManager _markingManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
public override void Initialize()
{
@@ -30,31 +31,37 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
private void OnHandleState(EntityUid uid, HumanoidAppearanceComponent component, ref AfterAutoHandleStateEvent args)
{
UpdateSprite(component, Comp<SpriteComponent>(uid));
UpdateSprite((uid, component, Comp<SpriteComponent>(uid)));
}
private void OnCvarChanged(bool value)
{
var humanoidQuery = EntityManager.AllEntityQueryEnumerator<HumanoidAppearanceComponent, SpriteComponent>();
while (humanoidQuery.MoveNext(out var _, out var humanoidComp, out var spriteComp))
while (humanoidQuery.MoveNext(out var uid, out var humanoidComp, out var spriteComp))
{
UpdateSprite(humanoidComp, spriteComp);
UpdateSprite((uid, humanoidComp, spriteComp));
}
}
private void UpdateSprite(HumanoidAppearanceComponent component, SpriteComponent sprite)
private void UpdateSprite(Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
{
UpdateLayers(component, sprite);
ApplyMarkingSet(component, sprite);
UpdateLayers(entity);
ApplyMarkingSet(entity);
sprite[sprite.LayerMapReserveBlank(HumanoidVisualLayers.Eyes)].Color = component.EyeColor;
var humanoidAppearance = entity.Comp1;
var sprite = entity.Comp2;
sprite[_sprite.LayerMapReserve((entity.Owner, sprite), HumanoidVisualLayers.Eyes)].Color = humanoidAppearance.EyeColor;
}
private static bool IsHidden(HumanoidAppearanceComponent humanoid, HumanoidVisualLayers layer)
=> humanoid.HiddenLayers.ContainsKey(layer) || humanoid.PermanentlyHidden.Contains(layer);
private void UpdateLayers(HumanoidAppearanceComponent component, SpriteComponent sprite)
private void UpdateLayers(Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
{
var component = entity.Comp1;
var sprite = entity.Comp2;
var oldLayers = new HashSet<HumanoidVisualLayers>(component.BaseLayers.Keys);
component.BaseLayers.Clear();
@@ -65,34 +72,36 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
{
oldLayers.Remove(key);
if (!component.CustomBaseLayers.ContainsKey(key))
SetLayerData(component, sprite, key, id, sexMorph: true);
SetLayerData(entity, key, id, sexMorph: true);
}
// add custom layers
foreach (var (key, info) in component.CustomBaseLayers)
{
oldLayers.Remove(key);
SetLayerData(component, sprite, key, info.Id, sexMorph: false, color: info.Color);
SetLayerData(entity, key, info.Id, sexMorph: false, color: info.Color);
}
// hide old layers
// TODO maybe just remove them altogether?
foreach (var key in oldLayers)
{
if (sprite.LayerMapTryGet(key, out var index))
if (_sprite.LayerMapTryGet((entity.Owner, sprite), key, out var index, false))
sprite[index].Visible = false;
}
}
private void SetLayerData(
HumanoidAppearanceComponent component,
SpriteComponent sprite,
Entity<HumanoidAppearanceComponent, SpriteComponent> entity,
HumanoidVisualLayers key,
string? protoId,
bool sexMorph = false,
Color? color = null)
{
var layerIndex = sprite.LayerMapReserveBlank(key);
var component = entity.Comp1;
var sprite = entity.Comp2;
var layerIndex = _sprite.LayerMapReserve((entity.Owner, sprite), key);
var layer = sprite[layerIndex];
layer.Visible = !IsHidden(component, key);
@@ -112,7 +121,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
layer.Color = component.SkinColor.WithAlpha(proto.LayerAlpha);
if (proto.BaseSprite != null)
sprite.LayerSetSprite(layerIndex, proto.BaseSprite);
_sprite.LayerSetSprite((entity.Owner, sprite), layerIndex, proto.BaseSprite);
}
/// <summary>
@@ -215,14 +224,17 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
humanoid.SkinColor = profile.Appearance.SkinColor;
humanoid.EyeColor = profile.Appearance.EyeColor;
UpdateSprite(humanoid, Comp<SpriteComponent>(uid));
UpdateSprite((uid, humanoid, Comp<SpriteComponent>(uid)));
}
private void ApplyMarkingSet(HumanoidAppearanceComponent humanoid, SpriteComponent sprite)
private void ApplyMarkingSet(Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
{
var humanoid = entity.Comp1;
var sprite = entity.Comp2;
// I am lazy and I CBF resolving the previous mess, so I'm just going to nuke the markings.
// Really, markings should probably be a separate component altogether.
ClearAllMarkings(humanoid, sprite);
ClearAllMarkings(entity);
var censorNudity = _configurationManager.GetCVar(CCVars.AccessibilityClientCensorNudity) ||
_configurationManager.GetCVar(CCVars.AccessibilityServerCensorNudity);
@@ -236,7 +248,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
{
if (_markingManager.TryGetMarking(marking, out var markingPrototype))
{
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, humanoid, sprite);
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, entity);
if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentTop)
applyUndergarmentTop = false;
else if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentBottom)
@@ -247,16 +259,19 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
humanoid.ClientOldMarkings = new MarkingSet(humanoid.MarkingSet);
AddUndergarments(humanoid, sprite, applyUndergarmentTop, applyUndergarmentBottom);
AddUndergarments(entity, applyUndergarmentTop, applyUndergarmentBottom);
}
private void ClearAllMarkings(HumanoidAppearanceComponent humanoid, SpriteComponent sprite)
private void ClearAllMarkings(Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
{
var humanoid = entity.Comp1;
var sprite = entity.Comp2;
foreach (var markingList in humanoid.ClientOldMarkings.Markings.Values)
{
foreach (var marking in markingList)
{
RemoveMarking(marking, sprite);
RemoveMarking(marking, (entity, sprite));
}
}
@@ -266,12 +281,12 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
{
foreach (var marking in markingList)
{
RemoveMarking(marking, sprite);
RemoveMarking(marking, (entity, sprite));
}
}
}
private void RemoveMarking(Marking marking, SpriteComponent spriteComp)
private void RemoveMarking(Marking marking, Entity<SpriteComponent> spriteEnt)
{
if (!_markingManager.TryGetMarking(marking, out var prototype))
{
@@ -286,26 +301,28 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
}
var layerId = $"{marking.MarkingId}-{rsi.RsiState}";
if (!spriteComp.LayerMapTryGet(layerId, out var index))
if (!_sprite.LayerMapTryGet(spriteEnt.AsNullable(), layerId, out var index, false))
{
continue;
}
spriteComp.LayerMapRemove(layerId);
spriteComp.RemoveLayer(index);
_sprite.LayerMapRemove(spriteEnt.AsNullable(), layerId);
_sprite.RemoveLayer(spriteEnt.AsNullable(), index);
}
}
private void AddUndergarments(HumanoidAppearanceComponent humanoid, SpriteComponent sprite, bool undergarmentTop, bool undergarmentBottom)
private void AddUndergarments(Entity<HumanoidAppearanceComponent, SpriteComponent> entity, bool undergarmentTop, bool undergarmentBottom)
{
var humanoid = entity.Comp1;
if (undergarmentTop && humanoid.UndergarmentTop != null)
{
var marking = new Marking(humanoid.UndergarmentTop, new List<Color> { new Color() });
if (_markingManager.TryGetMarking(marking, out var prototype))
{
// Markings are added to ClientOldMarkings because otherwise it causes issues when toggling the feature on/off.
humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentTop, new List<Marking>{ marking });
ApplyMarking(prototype, null, true, humanoid, sprite);
humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentTop, new List<Marking> { marking });
ApplyMarking(prototype, null, true, entity);
}
}
@@ -314,8 +331,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
var marking = new Marking(humanoid.UndergarmentBottom, new List<Color> { new Color() });
if (_markingManager.TryGetMarking(marking, out var prototype))
{
humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentBottom, new List<Marking>{ marking });
ApplyMarking(prototype, null, true, humanoid, sprite);
humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentBottom, new List<Marking> { marking });
ApplyMarking(prototype, null, true, entity);
}
}
}
@@ -323,10 +340,12 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
private void ApplyMarking(MarkingPrototype markingPrototype,
IReadOnlyList<Color>? colors,
bool visible,
HumanoidAppearanceComponent humanoid,
SpriteComponent sprite)
Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
{
if (!sprite.LayerMapTryGet(markingPrototype.BodyPart, out int targetLayer))
var humanoid = entity.Comp1;
var sprite = entity.Comp2;
if (!_sprite.LayerMapTryGet((entity.Owner, sprite), markingPrototype.BodyPart, out var targetLayer, false))
{
return;
}
@@ -346,14 +365,14 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
var layerId = $"{markingPrototype.ID}-{rsi.RsiState}";
if (!sprite.LayerMapTryGet(layerId, out _))
if (!_sprite.LayerMapTryGet((entity.Owner, sprite), layerId, out _, false))
{
var layer = sprite.AddLayer(markingSprite, targetLayer + j + 1);
sprite.LayerMapSet(layerId, layer);
sprite.LayerSetSprite(layerId, rsi);
var layer = _sprite.AddLayer((entity.Owner, sprite), markingSprite, targetLayer + j + 1);
_sprite.LayerMapSet((entity.Owner, sprite), layerId, layer);
_sprite.LayerSetSprite((entity.Owner, sprite), layerId, rsi);
}
sprite.LayerSetVisible(layerId, visible);
_sprite.LayerSetVisible((entity.Owner, sprite), layerId, visible);
if (!visible || setting == null) // this is kinda implied
{
@@ -365,16 +384,16 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
// So if that happens just default to white?
if (colors != null && j < colors.Count)
{
sprite.LayerSetColor(layerId, colors[j]);
_sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
}
else
{
sprite.LayerSetColor(layerId, Color.White);
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
}
if (humanoid.MarkingsDisplacement.TryGetValue(markingPrototype.BodyPart, out var displacementData) && markingPrototype.CanBeDisplaced)
{
_displacement.TryAddDisplacement(displacementData, sprite, targetLayer + j + 1, layerId, out _);
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _);
}
}
}
@@ -394,7 +413,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
if (!spriteInfo.MatchSkin)
continue;
var index = sprite.LayerMapReserveBlank(layer);
var index = _sprite.LayerMapReserve((uid, sprite), layer);
sprite[index].Color = skinColor.WithAlpha(spriteInfo.LayerAlpha);
}
}
@@ -409,11 +428,11 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
base.SetLayerVisibility(ent, layer, visible, slot, ref dirty);
var sprite = Comp<SpriteComponent>(ent);
if (!sprite.LayerMapTryGet(layer, out var index))
if (!_sprite.LayerMapTryGet((ent.Owner, sprite), layer, out var index, false))
{
if (!visible)
return;
index = sprite.LayerMapReserveBlank(layer);
index = _sprite.LayerMapReserve((ent.Owner, sprite), layer);
}
var spriteLayer = sprite[index];
@@ -430,7 +449,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
foreach (var marking in markingList)
{
if (_markingManager.TryGetMarking(marking, out var markingPrototype) && markingPrototype.BodyPart == layer)
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, ent, sprite);
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, (ent, ent.Comp, sprite));
}
}
}

View File

@@ -19,15 +19,15 @@ public sealed partial class IconSmoothSystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
sprite.LayerSetOffset(EdgeLayer.South, new Vector2(0, -1f));
sprite.LayerSetOffset(EdgeLayer.East, new Vector2(1f, 0f));
sprite.LayerSetOffset(EdgeLayer.North, new Vector2(0, 1f));
sprite.LayerSetOffset(EdgeLayer.West, new Vector2(-1f, 0f));
_sprite.LayerSetOffset((uid, sprite), EdgeLayer.South, new Vector2(0, -1f));
_sprite.LayerSetOffset((uid, sprite), EdgeLayer.East, new Vector2(1, 0f));
_sprite.LayerSetOffset((uid, sprite), EdgeLayer.North, new Vector2(0, 1f));
_sprite.LayerSetOffset((uid, sprite), EdgeLayer.West, new Vector2(-1, 0f));
sprite.LayerSetVisible(EdgeLayer.South, false);
sprite.LayerSetVisible(EdgeLayer.East, false);
sprite.LayerSetVisible(EdgeLayer.North, false);
sprite.LayerSetVisible(EdgeLayer.West, false);
_sprite.LayerSetVisible((uid, sprite), EdgeLayer.South, false);
_sprite.LayerSetVisible((uid, sprite), EdgeLayer.East, false);
_sprite.LayerSetVisible((uid, sprite), EdgeLayer.North, false);
_sprite.LayerSetVisible((uid, sprite), EdgeLayer.West, false);
}
private void OnEdgeShutdown(EntityUid uid, SmoothEdgeComponent component, ComponentShutdown args)
@@ -35,10 +35,10 @@ public sealed partial class IconSmoothSystem
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
sprite.LayerMapRemove(EdgeLayer.South);
sprite.LayerMapRemove(EdgeLayer.East);
sprite.LayerMapRemove(EdgeLayer.North);
sprite.LayerMapRemove(EdgeLayer.West);
_sprite.LayerMapRemove((uid, sprite), EdgeLayer.South);
_sprite.LayerMapRemove((uid, sprite), EdgeLayer.East);
_sprite.LayerMapRemove((uid, sprite), EdgeLayer.North);
_sprite.LayerMapRemove((uid, sprite), EdgeLayer.West);
}
private void CalculateEdge(EntityUid uid, DirectionFlag directions, SpriteComponent? sprite = null, SmoothEdgeComponent? component = null)
@@ -48,16 +48,16 @@ public sealed partial class IconSmoothSystem
for (var i = 0; i < 4; i++)
{
var dir = (DirectionFlag) Math.Pow(2, i);
var dir = (DirectionFlag)Math.Pow(2, i);
var edge = GetEdge(dir);
if ((dir & directions) != 0x0)
{
sprite.LayerSetVisible(edge, false);
_sprite.LayerSetVisible((uid, sprite), edge, false);
continue;
}
sprite.LayerSetVisible(edge, true);
_sprite.LayerSetVisible((uid, sprite), edge, true);
}
}

View File

@@ -17,6 +17,7 @@ namespace Content.Client.IconSmoothing
public sealed partial class IconSmoothSystem : EntitySystem
{
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
private readonly Queue<EntityUid> _dirtyEntities = new();
private readonly Queue<EntityUid> _anchorChangedEntities = new();
@@ -57,7 +58,7 @@ namespace Content.Client.IconSmoothing
if (component.Mode != IconSmoothingMode.Corners || !TryComp(uid, out SpriteComponent? sprite))
return;
SetCornerLayers(sprite, component);
SetCornerLayers((uid, sprite), component);
if (component.Shader != null)
{
@@ -74,25 +75,25 @@ namespace Content.Client.IconSmoothing
return;
component.StateBase = newState;
SetCornerLayers(sprite, component);
SetCornerLayers((uid, sprite), component);
}
private void SetCornerLayers(SpriteComponent sprite, IconSmoothComponent component)
private void SetCornerLayers(Entity<SpriteComponent?> sprite, IconSmoothComponent component)
{
sprite.LayerMapRemove(CornerLayers.SE);
sprite.LayerMapRemove(CornerLayers.NE);
sprite.LayerMapRemove(CornerLayers.NW);
sprite.LayerMapRemove(CornerLayers.SW);
_sprite.LayerMapRemove(sprite, CornerLayers.SE);
_sprite.LayerMapRemove(sprite, CornerLayers.NE);
_sprite.LayerMapRemove(sprite, CornerLayers.NW);
_sprite.LayerMapRemove(sprite, CornerLayers.SW);
var state0 = $"{component.StateBase}0";
sprite.LayerMapSet(CornerLayers.SE, sprite.AddLayerState(state0));
sprite.LayerSetDirOffset(CornerLayers.SE, DirectionOffset.None);
sprite.LayerMapSet(CornerLayers.NE, sprite.AddLayerState(state0));
sprite.LayerSetDirOffset(CornerLayers.NE, DirectionOffset.CounterClockwise);
sprite.LayerMapSet(CornerLayers.NW, sprite.AddLayerState(state0));
sprite.LayerSetDirOffset(CornerLayers.NW, DirectionOffset.Flip);
sprite.LayerMapSet(CornerLayers.SW, sprite.AddLayerState(state0));
sprite.LayerSetDirOffset(CornerLayers.SW, DirectionOffset.Clockwise);
_sprite.LayerMapSet(sprite, CornerLayers.SE, _sprite.AddRsiLayer(sprite, state0));
_sprite.LayerSetDirOffset(sprite, CornerLayers.SE, DirectionOffset.None);
_sprite.LayerMapSet(sprite, CornerLayers.NE, _sprite.AddRsiLayer(sprite, state0));
_sprite.LayerSetDirOffset(sprite, CornerLayers.NE, DirectionOffset.CounterClockwise);
_sprite.LayerMapSet(sprite, CornerLayers.NW, _sprite.AddRsiLayer(sprite, state0));
_sprite.LayerSetDirOffset(sprite, CornerLayers.NW, DirectionOffset.Flip);
_sprite.LayerMapSet(sprite, CornerLayers.SW, _sprite.AddRsiLayer(sprite, state0));
_sprite.LayerSetDirOffset(sprite, CornerLayers.SW, DirectionOffset.Clockwise);
}
private void OnShutdown(EntityUid uid, IconSmoothComponent component, ComponentShutdown args)
@@ -298,7 +299,7 @@ namespace Content.Client.IconSmoothing
{
if (gridEntity == null)
{
sprite.Comp.LayerSetState(0, $"{smooth.StateBase}0");
_sprite.LayerSetRsiState(sprite.AsNullable(), 0, $"{smooth.StateBase}0");
return;
}
@@ -324,11 +325,11 @@ namespace Content.Client.IconSmoothing
if (matching)
{
sprite.Comp.LayerSetState(0, $"{smooth.StateBase}1");
_sprite.LayerSetRsiState(sprite.AsNullable(), 0, $"{smooth.StateBase}1");
}
else
{
sprite.Comp.LayerSetState(0, $"{smooth.StateBase}0");
_sprite.LayerSetRsiState(sprite.AsNullable(), 0, $"{smooth.StateBase}0");
}
}
@@ -338,7 +339,7 @@ namespace Content.Client.IconSmoothing
if (gridEntity == null)
{
sprite.Comp.LayerSetState(0, $"{smooth.StateBase}{(int)dirs}");
_sprite.LayerSetRsiState(sprite.AsNullable(), 0, $"{smooth.StateBase}{(int)dirs}");
return;
}
@@ -355,7 +356,7 @@ namespace Content.Client.IconSmoothing
if (MatchingEntity(smooth, _mapSystem.GetAnchoredEntitiesEnumerator(gridUid, grid, pos.Offset(Direction.West)), smoothQuery))
dirs |= CardinalConnectDirs.West;
sprite.Comp.LayerSetState(0, $"{smooth.StateBase}{(int)dirs}");
_sprite.LayerSetRsiState(sprite.AsNullable(), 0, $"{smooth.StateBase}{(int)dirs}");
var directions = DirectionFlag.None;
@@ -399,10 +400,10 @@ namespace Content.Client.IconSmoothing
// At the very least each event currently only queues a sprite for updating.
// Oh god sprite component is a mess.
var sprite = spriteEnt.Comp;
sprite.LayerSetState(CornerLayers.NE, $"{smooth.StateBase}{(int)cornerNE}");
sprite.LayerSetState(CornerLayers.SE, $"{smooth.StateBase}{(int)cornerSE}");
sprite.LayerSetState(CornerLayers.SW, $"{smooth.StateBase}{(int)cornerSW}");
sprite.LayerSetState(CornerLayers.NW, $"{smooth.StateBase}{(int)cornerNW}");
_sprite.LayerSetRsiState(spriteEnt.AsNullable(), CornerLayers.NE, $"{smooth.StateBase}{(int)cornerNE}");
_sprite.LayerSetRsiState(spriteEnt.AsNullable(), CornerLayers.SE, $"{smooth.StateBase}{(int)cornerSE}");
_sprite.LayerSetRsiState(spriteEnt.AsNullable(), CornerLayers.SW, $"{smooth.StateBase}{(int)cornerSW}");
_sprite.LayerSetRsiState(spriteEnt.AsNullable(), CornerLayers.NW, $"{smooth.StateBase}{(int)cornerNW}");
var directions = DirectionFlag.None;

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