diff --git a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs index 127988c7e3..7f477619a4 100644 --- a/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Client/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using Content.Client.Atmos.Overlays; using Content.Shared.Atmos; using Content.Shared.Atmos.EntitySystems; @@ -9,9 +5,7 @@ using JetBrains.Annotations; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; using Robust.Client.Utility; -using Robust.Shared.IoC; using Robust.Shared.Map; -using Robust.Shared.Maths; using Robust.Shared.Utility; namespace Content.Client.Atmos.EntitySystems @@ -41,6 +35,8 @@ namespace Content.Client.Atmos.EntitySystems private readonly Dictionary> _tileData = new(); + public const int GasOverlayZIndex = 1; + public override void Initialize() { base.Initialize(); @@ -86,8 +82,8 @@ namespace Content.Client.Atmos.EntitySystems } var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay()) - overlayManager.AddOverlay(new GasTileOverlay()); + overlayManager.AddOverlay(new GasTileOverlay()); + overlayManager.AddOverlay(new FireTileOverlay()); } private void HandleGasOverlayMessage(GasOverlayMessage message) @@ -124,8 +120,8 @@ namespace Content.Client.Atmos.EntitySystems base.Shutdown(); _mapManager.OnGridRemoved -= OnGridRemoved; var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay()) - overlayManager.RemoveOverlay(); + overlayManager.RemoveOverlay(); + overlayManager.RemoveOverlay(); } private void OnGridRemoved(MapId mapId, GridId gridId) @@ -155,6 +151,20 @@ namespace Content.Client.Atmos.EntitySystems return new GasOverlayEnumerator(overlays, this); } + public FireOverlayEnumerator GetFireOverlays(GridId gridIndex, Vector2i indices) + { + if (!_tileData.TryGetValue(gridIndex, out var chunks)) + return default; + + var chunkIndex = GetGasChunkIndices(indices); + if (!chunks.TryGetValue(chunkIndex, out var chunk)) + return default; + + var overlays = chunk.GetData(indices); + + return new FireOverlayEnumerator(overlays, this); + } + public override void FrameUpdate(float frameTime) { base.FrameUpdate(frameTime); @@ -184,11 +194,10 @@ namespace Content.Client.Atmos.EntitySystems } } - public struct GasOverlayEnumerator : IDisposable + public struct GasOverlayEnumerator { private readonly GasTileOverlaySystem _system; private readonly GasData[]? _data; - private byte _fireState; // TODO: Take Fire Temperature into account, when we code fire color private readonly int _length; // We cache the length so we can avoid a pointer dereference, for speed. Brrr. @@ -198,7 +207,6 @@ namespace Content.Client.Atmos.EntitySystems { // Gas can't be null, as the caller to this constructor already ensured it wasn't. _data = data.Gas; - _fireState = data.FireState; _system = system; @@ -217,6 +225,25 @@ namespace Content.Client.Atmos.EntitySystems return true; } + overlay = default; + return false; + } + } + + public struct FireOverlayEnumerator + { + private readonly GasTileOverlaySystem _system; + private byte _fireState; + // TODO: Take Fire Temperature into account, when we code fire color + + public FireOverlayEnumerator(in GasOverlayData data, GasTileOverlaySystem system) + { + _fireState = data.FireState; + _system = system; + } + public bool MoveNext(out (Texture Texture, Color Color) overlay) + { + if (_fireState != 0) { var state = _fireState - 1; @@ -232,10 +259,6 @@ namespace Content.Client.Atmos.EntitySystems overlay = default; return false; } - - public void Dispose() - { - } } } } diff --git a/Content.Client/Atmos/Overlays/FireTileOverlay.cs b/Content.Client/Atmos/Overlays/FireTileOverlay.cs new file mode 100644 index 0000000000..d22d617430 --- /dev/null +++ b/Content.Client/Atmos/Overlays/FireTileOverlay.cs @@ -0,0 +1,57 @@ +using Content.Client.Atmos.EntitySystems; +using Robust.Client.Graphics; +using Robust.Shared.Enums; +using Robust.Shared.Prototypes; +using Robust.Shared.Map; + +namespace Content.Client.Atmos.Overlays +{ + public sealed class FireTileOverlay : Overlay + { + private readonly GasTileOverlaySystem _gasTileOverlaySystem; + + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; + private readonly ShaderInstance _shader; + + public FireTileOverlay() + { + IoCManager.InjectDependencies(this); + + _gasTileOverlaySystem = EntitySystem.Get(); + _shader = _prototypeManager.Index("unshaded").Instance().Duplicate(); + ZIndex = GasTileOverlaySystem.GasOverlayZIndex + 1; + } + + protected override void Draw(in OverlayDrawArgs args) + { + var drawHandle = args.WorldHandle; + + var mapId = args.Viewport.Eye!.Position.MapId; + var worldBounds = args.WorldBounds; + + drawHandle.UseShader(_shader); + + foreach (var mapGrid in _mapManager.FindGridsIntersecting(mapId, worldBounds)) + { + if (!_gasTileOverlaySystem.HasData(mapGrid.Index)) + continue; + + drawHandle.SetTransform(mapGrid.WorldMatrix); + + foreach (var tile in mapGrid.GetTilesIntersecting(worldBounds)) + { + var enumerator = _gasTileOverlaySystem.GetFireOverlays(mapGrid.Index, tile.GridIndices); + while (enumerator.MoveNext(out var tuple)) + { + drawHandle.DrawTexture(tuple.Texture, new Vector2(tile.X, tile.Y), tuple.Color); + } + } + } + + drawHandle.SetTransform(Matrix3.Identity); + } + } +} diff --git a/Content.Client/Atmos/Overlays/GasTileOverlay.cs b/Content.Client/Atmos/Overlays/GasTileOverlay.cs index 3cfddcd114..4db9a341f7 100644 --- a/Content.Client/Atmos/Overlays/GasTileOverlay.cs +++ b/Content.Client/Atmos/Overlays/GasTileOverlay.cs @@ -8,7 +8,7 @@ using Robust.Shared.Maths; namespace Content.Client.Atmos.Overlays { - public class GasTileOverlay : Overlay + public sealed class GasTileOverlay : Overlay { private readonly GasTileOverlaySystem _gasTileOverlaySystem; @@ -21,6 +21,7 @@ namespace Content.Client.Atmos.Overlays IoCManager.InjectDependencies(this); _gasTileOverlaySystem = EntitySystem.Get(); + ZIndex = GasTileOverlaySystem.GasOverlayZIndex; } protected override void Draw(in OverlayDrawArgs args) @@ -46,8 +47,6 @@ namespace Content.Client.Atmos.Overlays } } } - - drawHandle.SetTransform(Matrix3.Identity); } } } diff --git a/Content.Client/Atmos/Visualizers/FireVisualizer.cs b/Content.Client/Atmos/Visualizers/FireVisualizer.cs index bac26efaa7..504543201f 100644 --- a/Content.Client/Atmos/Visualizers/FireVisualizer.cs +++ b/Content.Client/Atmos/Visualizers/FireVisualizer.cs @@ -30,6 +30,7 @@ namespace Content.Client.Atmos.Visualizers sprite.LayerMapReserveBlank(FireVisualLayers.Fire); sprite.LayerSetVisible(FireVisualLayers.Fire, false); + sprite.LayerSetShader(FireVisualLayers.Fire, "unshaded"); } public override void OnChangeData(AppearanceComponent component)