2024-08-17 23:59:11 +03:00
using Robust.Client.Graphics ;
using Robust.Shared.Enums ;
using Robust.Shared.Prototypes ;
using System.Numerics ;
using Content.Shared._White.Explosion ;
namespace Content.Client._White.Explosion ;
public sealed class ExplosionShockWaveOverlay : Overlay , IEntityEventSubscriber
{
[Dependency] private readonly IEntityManager _entMan = default ! ;
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
private SharedTransformSystem ? _xformSystem ;
public override OverlaySpace Space = > OverlaySpace . WorldSpace ;
public override bool RequestScreenTexture = > true ;
private readonly ShaderInstance _shader ;
/// <summary>
/// Maximum number of distortions that can be shown on screen at a time.
/// </summary>
2024-08-23 11:38:46 +03:00
public const int MaxCount = 15 ;
2024-08-17 23:59:11 +03:00
public ExplosionShockWaveOverlay ( )
{
IoCManager . InjectDependencies ( this ) ;
_shader = _prototypeManager . Index < ShaderPrototype > ( "ShockWave" ) . Instance ( ) . Duplicate ( ) ;
}
private readonly Vector2 [ ] _positions = new Vector2 [ MaxCount ] ;
private readonly float [ ] _falloffPower = new float [ MaxCount ] ;
private readonly float [ ] _sharpness = new float [ MaxCount ] ;
private readonly float [ ] _width = new float [ MaxCount ] ;
private int _count ;
protected override bool BeforeDraw ( in OverlayDrawArgs args )
{
if ( args . Viewport . Eye = = null | | _xformSystem is null & & ! _entMan . TrySystem ( out _xformSystem ) )
return false ;
var query = _entMan . EntityQueryEnumerator < ExplosionShockWaveComponent , TransformComponent > ( ) ;
_count = 0 ;
while ( query . MoveNext ( out var uid , out var distortion , out var xform ) )
{
if ( xform . MapID ! = args . MapId )
continue ;
var mapPos = _xformSystem . GetWorldPosition ( uid ) ;
var tempCoords = args . Viewport . WorldToLocal ( mapPos ) ;
// normalized coords, 0 - 1 plane. This is pure hell, we subtract 1 because fragment calculates from the bottom and local goes from the top of the viewport
tempCoords . Y = 1 - ( tempCoords . Y / args . Viewport . Size . Y ) ;
tempCoords . X / = args . Viewport . Size . X ;
_positions [ _count ] = tempCoords ;
_falloffPower [ _count ] = distortion . FalloffPower ;
_sharpness [ _count ] = distortion . Sharpness ;
_width [ _count ] = distortion . Width ;
_count + + ;
if ( _count = = MaxCount )
break ;
}
return _count > 0 ;
}
protected override void Draw ( in OverlayDrawArgs args )
{
if ( ScreenTexture = = null | | args . Viewport . Eye = = null )
return ;
_shader ? . SetParameter ( "renderScale" , args . Viewport . RenderScale * args . Viewport . Eye . Scale ) ;
_shader ? . SetParameter ( "count" , _count ) ;
_shader ? . SetParameter ( "position" , _positions ) ;
_shader ? . SetParameter ( "falloffPower" , _falloffPower ) ;
_shader ? . SetParameter ( "sharpness" , _sharpness ) ;
_shader ? . SetParameter ( "width" , _width ) ;
_shader ? . SetParameter ( "SCREEN_TEXTURE" , ScreenTexture ) ;
var worldHandle = args . WorldHandle ;
worldHandle . UseShader ( _shader ) ;
worldHandle . DrawRect ( args . WorldAABB , Color . White ) ;
worldHandle . UseShader ( null ) ;
}
}