mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Update postshaders for multi-shader support (#44735)
This commit is contained in:
parent
066a4f9b58
commit
b822e090ef
10 changed files with 256 additions and 99 deletions
25
Content.Client/Graphics/ContentPostShaderIds.cs
Normal file
25
Content.Client/Graphics/ContentPostShaderIds.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
namespace Content.Client.Graphics;
|
||||
|
||||
public static class ContentPostShaderIds
|
||||
{
|
||||
public const string Stealth = "stealth";
|
||||
public const string FloorOcclusion = "floor-occlusion";
|
||||
public const string Holopad = "holopad";
|
||||
public const string InteractionOutline = "interaction-outline";
|
||||
public const string TargetOutline = "target-outline";
|
||||
public const string DragDropOutline = "drag-drop-outline";
|
||||
|
||||
public static readonly string[] BeforeOutlines =
|
||||
{
|
||||
InteractionOutline,
|
||||
TargetOutline,
|
||||
DragDropOutline,
|
||||
};
|
||||
|
||||
public static readonly string[] AfterBaseEffects =
|
||||
{
|
||||
Stealth,
|
||||
FloorOcclusion,
|
||||
Holopad,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client.Graphics;
|
||||
using Content.Shared.Chat.TypingIndicator;
|
||||
using Content.Shared.Holopad;
|
||||
using Robust.Client.GameObjects;
|
||||
|
|
@ -30,10 +31,10 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
|
|||
|
||||
private void OnShaderRender(Entity<HolopadHologramComponent> entity, ref BeforePostShaderRenderEvent ev)
|
||||
{
|
||||
if (ev.Sprite.PostShader == null)
|
||||
if (ev.Id != ContentPostShaderIds.Holopad)
|
||||
return;
|
||||
|
||||
UpdateHologramSprite(entity, entity.Comp.LinkedEntity);
|
||||
UpdateHologramSprite(entity, entity.Comp.LinkedEntity, ev.Shader);
|
||||
}
|
||||
|
||||
private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args)
|
||||
|
|
@ -50,7 +51,7 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
|
|||
RaiseNetworkEvent(netEv);
|
||||
}
|
||||
|
||||
private void UpdateHologramSprite(EntityUid hologram, EntityUid? target)
|
||||
private void UpdateHologramSprite(EntityUid hologram, EntityUid? target, ShaderInstance? shader = null)
|
||||
{
|
||||
// Get required components
|
||||
if (!TryComp<SpriteComponent>(hologram, out var hologramSprite) ||
|
||||
|
|
@ -110,15 +111,19 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
|
|||
hologramSprite.LayerSetShader(i, "unshaded");
|
||||
}
|
||||
|
||||
UpdateHologramShader(hologram, hologramSprite, holopadhologram);
|
||||
UpdateHologramShader(hologram, hologramSprite, holopadhologram, shader);
|
||||
}
|
||||
|
||||
private void UpdateHologramShader(EntityUid uid, SpriteComponent sprite, HolopadHologramComponent holopadHologram)
|
||||
private void UpdateHologramShader(
|
||||
EntityUid uid,
|
||||
SpriteComponent sprite,
|
||||
HolopadHologramComponent holopadHologram,
|
||||
ShaderInstance? shader = null)
|
||||
{
|
||||
// Find the texture height of the largest layer
|
||||
float texHeight = sprite.AllLayers.Max(x => x.PixelSize.Y);
|
||||
|
||||
var instance = ProtoMan.Index<ShaderPrototype>(holopadHologram.ShaderName).InstanceUnique();
|
||||
var instance = shader ?? ProtoMan.Index<ShaderPrototype>(holopadHologram.ShaderName).InstanceUnique();
|
||||
instance.SetParameter("color1", new Vector3(holopadHologram.Color1.R, holopadHologram.Color1.G, holopadHologram.Color1.B));
|
||||
instance.SetParameter("color2", new Vector3(holopadHologram.Color2.R, holopadHologram.Color2.G, holopadHologram.Color2.B));
|
||||
instance.SetParameter("alpha", holopadHologram.Alpha);
|
||||
|
|
@ -126,7 +131,10 @@ public sealed partial class HolopadSystem : SharedHolopadSystem
|
|||
instance.SetParameter("texHeight", texHeight);
|
||||
instance.SetParameter("t", (float)_timing.CurTime.TotalSeconds * holopadHologram.ScrollRate);
|
||||
|
||||
sprite.PostShader = instance;
|
||||
sprite.RaiseShaderEvent = true;
|
||||
_sprite.SetPostShader((uid, sprite), new SpriteComponent.PostShaderArgs(ContentPostShaderIds.Holopad, instance)
|
||||
{
|
||||
RaiseShaderEvent = true,
|
||||
Before = ContentPostShaderIds.BeforeOutlines,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
namespace Content.Client.Interactable.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class InteractionOutlineComponent : Component;
|
||||
public sealed partial class InteractionOutlineComponent : Component
|
||||
{
|
||||
public bool InRange;
|
||||
public int LastRenderScale;
|
||||
public bool Active;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.CombatMode;
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Client.Outline;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.CCVar;
|
||||
|
|
@ -101,7 +102,8 @@ public sealed partial class DragDropSystem : SharedDragDropSystem
|
|||
private ShaderInstance? _dropTargetInRangeShader;
|
||||
private ShaderInstance? _dropTargetOutOfRangeShader;
|
||||
|
||||
private readonly List<SpriteComponent> _highlightedSprites = new();
|
||||
private readonly HashSet<SpriteComponent> _highlightedSprites = new();
|
||||
private readonly HashSet<SpriteComponent> _nextHighlightedSprites = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
@ -422,8 +424,7 @@ public sealed partial class DragDropSystem : SharedDragDropSystem
|
|||
// highlights the possible targets which are visible
|
||||
// and able to be dropped on by the current dragged entity
|
||||
|
||||
// remove current highlights
|
||||
RemoveHighlights();
|
||||
_nextHighlightedSprites.Clear();
|
||||
|
||||
// find possible targets on screen even if not reachable
|
||||
// TODO: Duplicated in SpriteSystem and TargetOutlineSystem. Should probably be cached somewhere for a frame?
|
||||
|
|
@ -455,32 +456,52 @@ public sealed partial class DragDropSystem : SharedDragDropSystem
|
|||
&& _interactionSystem.InRangeUnobstructed(user.Value, entity);
|
||||
}
|
||||
|
||||
if (inRangeSprite.PostShader != null &&
|
||||
inRangeSprite.PostShader != _dropTargetInRangeShader &&
|
||||
inRangeSprite.PostShader != _dropTargetOutOfRangeShader)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// highlight depending on whether its in or out of range
|
||||
inRangeSprite.PostShader = valid.Value ? _dropTargetInRangeShader : _dropTargetOutOfRangeShader;
|
||||
SetDragDropPostShader((entity, inRangeSprite), valid.Value ? _dropTargetInRangeShader! : _dropTargetOutOfRangeShader!);
|
||||
inRangeSprite.RenderOrder = EntityManager.CurrentTick.Value;
|
||||
_highlightedSprites.Add(inRangeSprite);
|
||||
_nextHighlightedSprites.Add(inRangeSprite);
|
||||
}
|
||||
|
||||
foreach (var highlightedSprite in _highlightedSprites)
|
||||
{
|
||||
if (_nextHighlightedSprites.Contains(highlightedSprite))
|
||||
continue;
|
||||
|
||||
_sprite.RemovePostShader(highlightedSprite, ContentPostShaderIds.DragDropOutline);
|
||||
highlightedSprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
_highlightedSprites.Clear();
|
||||
foreach (var highlightedSprite in _nextHighlightedSprites)
|
||||
{
|
||||
_highlightedSprites.Add(highlightedSprite);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDragDropPostShader(Entity<SpriteComponent?> sprite, ShaderInstance shader)
|
||||
{
|
||||
if (_sprite.TryGetPostShader(sprite, ContentPostShaderIds.DragDropOutline, out var entry) &&
|
||||
entry.Shader == shader)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_sprite.SetPostShader(sprite, new SpriteComponent.PostShaderArgs(ContentPostShaderIds.DragDropOutline, shader)
|
||||
{
|
||||
After = ContentPostShaderIds.AfterBaseEffects,
|
||||
});
|
||||
}
|
||||
|
||||
private void RemoveHighlights()
|
||||
{
|
||||
foreach (var highlightedSprite in _highlightedSprites)
|
||||
{
|
||||
if (highlightedSprite.PostShader != _dropTargetInRangeShader && highlightedSprite.PostShader != _dropTargetOutOfRangeShader)
|
||||
continue;
|
||||
|
||||
highlightedSprite.PostShader = null;
|
||||
_sprite.RemovePostShader(highlightedSprite, ContentPostShaderIds.DragDropOutline);
|
||||
highlightedSprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
_highlightedSprites.Clear();
|
||||
_nextHighlightedSprites.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client.Graphics;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Robust.Client.GameObjects;
|
||||
|
|
@ -11,6 +12,7 @@ public sealed partial class FloorOcclusionSystem : SharedFloorOcclusionSystem
|
|||
private static readonly ProtoId<ShaderPrototype> HorizontalCut = "HorizontalCut";
|
||||
|
||||
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
@ -48,16 +50,16 @@ public sealed partial class FloorOcclusionSystem : SharedFloorOcclusionSystem
|
|||
|
||||
var shader = ProtoMan.Index(HorizontalCut).Instance();
|
||||
|
||||
if (sprite.Comp.PostShader is not null && sprite.Comp.PostShader != shader)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
sprite.Comp.PostShader = shader;
|
||||
_sprite.SetPostShader(sprite, new SpriteComponent.PostShaderArgs(ContentPostShaderIds.FloorOcclusion, shader)
|
||||
{
|
||||
Before = ContentPostShaderIds.BeforeOutlines,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.Comp.PostShader = null;
|
||||
_sprite.RemovePostShader(sprite, ContentPostShaderIds.FloorOcclusion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using Content.Client.ContextMenu.UI;
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Client.Interactable.Components;
|
||||
using Content.Client.Viewport;
|
||||
using Content.Shared.CCVar;
|
||||
|
|
@ -18,6 +20,11 @@ namespace Content.Client.Outline;
|
|||
|
||||
public sealed partial class InteractionOutlineSystem : EntitySystem
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> ShaderInRange = "SelectionOutlineInrange";
|
||||
private static readonly ProtoId<ShaderPrototype> ShaderOutOfRange = "SelectionOutline";
|
||||
private const float DefaultWidth = 1;
|
||||
private readonly Dictionary<(bool InRange, int RenderScale), ShaderInstance> _shaderCache = new();
|
||||
|
||||
[Dependency] private IConfigurationManager _configManager = default!;
|
||||
[Dependency] private IEyeManager _eyeManager = default!;
|
||||
[Dependency] private IInputManager _inputManager = default!;
|
||||
|
|
@ -25,9 +32,8 @@ public sealed partial class InteractionOutlineSystem : EntitySystem
|
|||
[Dependency] private IStateManager _stateManager = default!;
|
||||
[Dependency] private IUserInterfaceManager _uiManager = default!;
|
||||
[Dependency] private SharedInteractionSystem _interactionSystem = default!;
|
||||
|
||||
[Dependency] private EntityQuery<InteractionOutlineComponent> _outlineQuery = default!;
|
||||
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
|
||||
[Dependency] private IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to currently draw the outline. The outline may be temporarily disabled by other systems
|
||||
|
|
@ -39,42 +45,34 @@ public sealed partial class InteractionOutlineSystem : EntitySystem
|
|||
/// </summary>
|
||||
private bool _cvarEnabled = true;
|
||||
|
||||
private const float OutlineWidth = 1;
|
||||
|
||||
private static readonly ProtoId<ShaderPrototype> ShaderInRange = "SelectionOutlineInrange";
|
||||
private static readonly ProtoId<ShaderPrototype> ShaderOutOfRange = "SelectionOutline";
|
||||
|
||||
private ShaderInstance? _shaderInRange;
|
||||
private ShaderInstance? _shaderOutOfRange;
|
||||
|
||||
private EntityUid? _lastHoveredEntity;
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
foreach (var shader in _shaderCache.Values)
|
||||
{
|
||||
shader.Dispose();
|
||||
}
|
||||
|
||||
_shaderCache.Clear();
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_shaderInRange = ProtoMan.Index(ShaderInRange).InstanceUnique();
|
||||
_shaderOutOfRange = ProtoMan.Index(ShaderOutOfRange).InstanceUnique();
|
||||
|
||||
Subs.CVar(_configManager, CCVars.OutlineEnabled, SetCvarEnabled);
|
||||
SubscribeLocalEvent<InteractionOutlineComponent, ComponentShutdown>(OnShutdown);
|
||||
UpdatesAfter.Add(typeof(SharedEyeSystem));
|
||||
}
|
||||
|
||||
private void CleanupLastHoveredShader()
|
||||
private void OnShutdown(Entity<InteractionOutlineComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
var uid = _lastHoveredEntity;
|
||||
_lastHoveredEntity = null;
|
||||
RemoveOutline(ent);
|
||||
|
||||
if (!_outlineQuery.HasComp(uid))
|
||||
return;
|
||||
|
||||
if (!_spriteQuery.TryComp(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (sprite.PostShader != _shaderInRange && sprite.PostShader != _shaderOutOfRange)
|
||||
return;
|
||||
|
||||
sprite.PostShader = null;
|
||||
if (_lastHoveredEntity == ent.Owner)
|
||||
_lastHoveredEntity = null;
|
||||
}
|
||||
|
||||
public void SetCvarEnabled(bool cvarEnabled)
|
||||
|
|
@ -86,7 +84,11 @@ public sealed partial class InteractionOutlineSystem : EntitySystem
|
|||
if (_cvarEnabled)
|
||||
return;
|
||||
|
||||
CleanupLastHoveredShader();
|
||||
if (_lastHoveredEntity == null || Deleted(_lastHoveredEntity))
|
||||
return;
|
||||
|
||||
if (TryComp(_lastHoveredEntity, out InteractionOutlineComponent? outline))
|
||||
RemoveOutline((_lastHoveredEntity.Value, outline));
|
||||
}
|
||||
|
||||
public void SetEnabled(bool enabled)
|
||||
|
|
@ -101,7 +103,11 @@ public sealed partial class InteractionOutlineSystem : EntitySystem
|
|||
if (enabled)
|
||||
return;
|
||||
|
||||
CleanupLastHoveredShader();
|
||||
if (_lastHoveredEntity == null || Deleted(_lastHoveredEntity))
|
||||
return;
|
||||
|
||||
if (TryComp(_lastHoveredEntity, out InteractionOutlineComponent? outline))
|
||||
RemoveOutline((_lastHoveredEntity.Value, outline));
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
|
|
@ -156,24 +162,106 @@ public sealed partial class InteractionOutlineSystem : EntitySystem
|
|||
renderScale = _eyeManager.MainViewport.GetRenderScale();
|
||||
}
|
||||
|
||||
if (_lastHoveredEntity != entityToClick)
|
||||
{
|
||||
CleanupLastHoveredShader();
|
||||
|
||||
_lastHoveredEntity = entityToClick;
|
||||
}
|
||||
|
||||
if (!_outlineQuery.HasComp(entityToClick))
|
||||
return;
|
||||
|
||||
if (!_spriteQuery.TryComp(entityToClick, out var sprite))
|
||||
return;
|
||||
|
||||
var inRange = false;
|
||||
if (localSession.AttachedEntity != null)
|
||||
if (localSession.AttachedEntity != null && !Deleted(entityToClick))
|
||||
inRange = _interactionSystem.InRangeUnobstructed(localSession.AttachedEntity.Value, entityToClick.Value);
|
||||
|
||||
var shader = sprite.PostShader = inRange ? _shaderInRange : _shaderOutOfRange;
|
||||
shader?.SetParameter("outline_width", OutlineWidth * renderScale);
|
||||
InteractionOutlineComponent? outline;
|
||||
|
||||
if (entityToClick == _lastHoveredEntity)
|
||||
{
|
||||
if (entityToClick != null && TryComp(entityToClick, out outline))
|
||||
{
|
||||
UpdateOutline((entityToClick.Value, outline), inRange, renderScale);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_lastHoveredEntity != null && !Deleted(_lastHoveredEntity) &&
|
||||
TryComp(_lastHoveredEntity, out outline))
|
||||
{
|
||||
RemoveOutline((_lastHoveredEntity.Value, outline));
|
||||
}
|
||||
|
||||
_lastHoveredEntity = entityToClick;
|
||||
|
||||
if (_lastHoveredEntity != null && TryComp(_lastHoveredEntity, out outline))
|
||||
{
|
||||
AddOutline((_lastHoveredEntity.Value, outline), inRange, renderScale);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddOutline(Entity<InteractionOutlineComponent> ent, bool inInteractionRange, int renderScale)
|
||||
{
|
||||
ent.Comp.LastRenderScale = renderScale;
|
||||
ent.Comp.InRange = inInteractionRange;
|
||||
ent.Comp.Active = true;
|
||||
|
||||
if (!TryComp(ent.Owner, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
SetOutlinePostShader((ent.Owner, sprite), inInteractionRange, renderScale);
|
||||
}
|
||||
|
||||
private void RemoveOutline(Entity<InteractionOutlineComponent> ent)
|
||||
{
|
||||
if (TryComp(ent.Owner, out SpriteComponent? sprite))
|
||||
{
|
||||
_sprite.RemovePostShader((ent.Owner, sprite), ContentPostShaderIds.InteractionOutline);
|
||||
sprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
ent.Comp.Active = false;
|
||||
}
|
||||
|
||||
private void UpdateOutline(Entity<InteractionOutlineComponent> ent, bool inInteractionRange, int renderScale)
|
||||
{
|
||||
if (!TryComp(ent.Owner, out SpriteComponent? sprite)
|
||||
|| !_sprite.HasPostShader((ent.Owner, sprite), ContentPostShaderIds.InteractionOutline)
|
||||
|| inInteractionRange == ent.Comp.InRange && ent.Comp.LastRenderScale == renderScale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.InRange = inInteractionRange;
|
||||
ent.Comp.LastRenderScale = renderScale;
|
||||
|
||||
SetOutlinePostShader((ent.Owner, sprite), ent.Comp.InRange, ent.Comp.LastRenderScale);
|
||||
}
|
||||
|
||||
private void SetOutlinePostShader(Entity<SpriteComponent?> sprite, bool inRange, int renderScale)
|
||||
{
|
||||
var shader = GetShader(inRange, renderScale);
|
||||
if (_sprite.TryGetPostShader(sprite, ContentPostShaderIds.InteractionOutline, out var entry) &&
|
||||
entry.Shader == shader)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_sprite.SetPostShader(sprite, new SpriteComponent.PostShaderArgs(ContentPostShaderIds.InteractionOutline, shader)
|
||||
{
|
||||
After = ContentPostShaderIds.AfterBaseEffects,
|
||||
});
|
||||
}
|
||||
|
||||
private ShaderInstance GetShader(bool inRange, int renderScale)
|
||||
{
|
||||
var key = (inRange, renderScale);
|
||||
if (_shaderCache.TryGetValue(key, out var shader))
|
||||
return shader;
|
||||
|
||||
shader = MakeNewShader(inRange, renderScale);
|
||||
_shaderCache.Add(key, shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
private ShaderInstance MakeNewShader(bool inRange, int renderScale)
|
||||
{
|
||||
var shaderName = inRange ? ShaderInRange : ShaderOutOfRange;
|
||||
|
||||
var instance = _prototypeManager.Index(shaderName).InstanceUnique();
|
||||
instance.SetParameter("outline_width", DefaultWidth * renderScale);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Client.GameObjects;
|
||||
|
|
@ -27,6 +28,7 @@ public sealed partial class TargetOutlineSystem : EntitySystem
|
|||
[Dependency] private EntityWhitelistSystem _whitelistSystem = default!;
|
||||
[Dependency] private SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
private bool _enabled = false;
|
||||
|
||||
|
|
@ -154,9 +156,9 @@ public sealed partial class TargetOutlineSystem : EntitySystem
|
|||
if (!valid)
|
||||
{
|
||||
// was this previously valid?
|
||||
if (_highlightedSprites.Remove(sprite) && (sprite.PostShader == _shaderTargetValid || sprite.PostShader == _shaderTargetInvalid))
|
||||
if (_highlightedSprites.Remove(sprite))
|
||||
{
|
||||
sprite.PostShader = null;
|
||||
_sprite.RemovePostShader(sprite, ContentPostShaderIds.TargetOutline);
|
||||
sprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
|
|
@ -173,13 +175,11 @@ public sealed partial class TargetOutlineSystem : EntitySystem
|
|||
valid = (origin - target).LengthSquared() <= Range;
|
||||
}
|
||||
|
||||
if (sprite.PostShader != null &&
|
||||
sprite.PostShader != _shaderTargetValid &&
|
||||
sprite.PostShader != _shaderTargetInvalid)
|
||||
return;
|
||||
|
||||
// highlight depending on whether its in or out of range
|
||||
sprite.PostShader = valid ? _shaderTargetValid : _shaderTargetInvalid;
|
||||
_sprite.SetPostShader(sprite, new SpriteComponent.PostShaderArgs(ContentPostShaderIds.TargetOutline, valid ? _shaderTargetValid! : _shaderTargetInvalid!)
|
||||
{
|
||||
After = ContentPostShaderIds.AfterBaseEffects,
|
||||
});
|
||||
sprite.RenderOrder = EntityManager.CurrentTick.Value;
|
||||
_highlightedSprites.Add(sprite);
|
||||
}
|
||||
|
|
@ -189,10 +189,7 @@ public sealed partial class TargetOutlineSystem : EntitySystem
|
|||
{
|
||||
foreach (var sprite in _highlightedSprites)
|
||||
{
|
||||
if (sprite.PostShader != _shaderTargetValid && sprite.PostShader != _shaderTargetInvalid)
|
||||
continue;
|
||||
|
||||
sprite.PostShader = null;
|
||||
_sprite.RemovePostShader(sprite, ContentPostShaderIds.TargetOutline);
|
||||
sprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Client.Interactable.Components;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Shared.Stealth;
|
||||
using Content.Shared.Stealth.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
|
@ -42,9 +43,19 @@ public sealed partial class StealthSystem : SharedStealthSystem
|
|||
return;
|
||||
|
||||
_sprite.SetColor((uid, sprite), Color.White);
|
||||
sprite.PostShader = enabled ? _shader : null;
|
||||
sprite.GetScreenTexture = enabled;
|
||||
sprite.RaiseShaderEvent = enabled;
|
||||
if (enabled)
|
||||
{
|
||||
_sprite.SetPostShader((uid, sprite), new SpriteComponent.PostShaderArgs(ContentPostShaderIds.Stealth, _shader)
|
||||
{
|
||||
GetScreenTexture = true,
|
||||
RaiseShaderEvent = true,
|
||||
Before = ContentPostShaderIds.BeforeOutlines,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.RemovePostShader((uid, sprite), ContentPostShaderIds.Stealth);
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
|
|
@ -53,11 +64,8 @@ public sealed partial class StealthSystem : SharedStealthSystem
|
|||
return;
|
||||
}
|
||||
|
||||
if (TryComp(uid, out InteractionOutlineComponent? outline))
|
||||
{
|
||||
RemCompDeferred(uid, outline);
|
||||
if (HasComp<InteractionOutlineComponent>(uid))
|
||||
component.HadOutline = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, StealthComponent component, ComponentStartup args)
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ void fragment()
|
|||
highp vec4 tex = zTexture(UV);
|
||||
highp float modifier = (UV.y > c ^^ !below) ? 1.0 : alphaModifier;
|
||||
|
||||
COLOR = vec4(tex.x, tex.y, tex.z, tex.w * modifier);
|
||||
COLOR = vec4(tex.rgb * modifier, tex.a * modifier);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,11 +70,14 @@ void fragment() {
|
|||
maxa = max(a, maxa);
|
||||
mina = min(a, mina);
|
||||
|
||||
a = texture2D(TEXTURE, UV + vec2(outline_width, outline_width)*ps).a;
|
||||
maxa = max(a, maxa);
|
||||
mina = min(a, mina);
|
||||
a = texture2D(TEXTURE, UV + vec2(outline_width, outline_width)*ps).a;
|
||||
maxa = max(a, maxa);
|
||||
mina = min(a, mina);
|
||||
|
||||
lowp float sampledLight = outline_fullbright ? 1.0 : clamp( (pow( zGrayscale_BT601(lightSample.rgb) * light_whitepoint, light_gamma) / light_whitepoint ) * light_boost, 0.0, 1.0);
|
||||
COLOR = mix(col, outline_color * vec4(vec3(1.0), sampledLight), maxa - col.a);
|
||||
highp float outlineAmount = max(maxa - col.a, 0.0);
|
||||
highp float outlineAlpha = outline_color.a * sampledLight * outlineAmount;
|
||||
highp vec4 outline = vec4(outline_color.rgb * outlineAlpha, outlineAlpha);
|
||||
COLOR = mix(outline, col, step(0.01, col.a));
|
||||
lightSample = vec3(1.0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue