2021-03-09 04:33:41 -06:00
using System.Collections.Generic ;
using System.Linq ;
2021-06-24 04:48:11 +02:00
using Content.Shared.Singularity.Components ;
2021-06-09 22:19:39 +02:00
using Robust.Client.Graphics ;
2021-03-09 04:33:41 -06:00
using Robust.Shared.Enums ;
using Robust.Shared.GameObjects ;
2021-06-09 22:19:39 +02:00
using Robust.Shared.IoC ;
2021-03-09 04:33:41 -06:00
using Robust.Shared.Map ;
2021-06-09 22:19:39 +02:00
using Robust.Shared.Maths ;
using Robust.Shared.Prototypes ;
2021-03-09 04:33:41 -06:00
2021-06-09 22:19:39 +02:00
namespace Content.Client.Singularity
2021-03-09 04:33:41 -06:00
{
2022-02-16 00:23:23 -07:00
public sealed class SingularityOverlay : Overlay
2021-03-09 04:33:41 -06:00
{
[Dependency] private readonly IEntityManager _entityManager = default ! ;
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
2021-06-24 04:48:11 +02:00
private const float MaxDist = 15.0f ;
2021-03-09 04:33:41 -06:00
public override OverlaySpace Space = > OverlaySpace . WorldSpace ;
public override bool RequestScreenTexture = > true ;
private readonly ShaderInstance _shader ;
2021-06-24 04:48:11 +02:00
private readonly Dictionary < EntityUid , SingularityShaderInstance > _singularities = new ( ) ;
2021-03-09 04:33:41 -06:00
public SingularityOverlay ( )
{
IoCManager . InjectDependencies ( this ) ;
_shader = _prototypeManager . Index < ShaderPrototype > ( "Singularity" ) . Instance ( ) . Duplicate ( ) ;
}
public override bool OverwriteTargetFrameBuffer ( )
{
2021-06-24 04:48:11 +02:00
return _singularities . Count > 0 ;
2021-03-09 04:33:41 -06:00
}
2021-04-19 09:52:40 +02:00
protected override void Draw ( in OverlayDrawArgs args )
2021-03-09 04:33:41 -06:00
{
2021-05-28 10:44:13 +01:00
SingularityQuery ( args . Viewport . Eye ) ;
2021-03-09 04:33:41 -06:00
2021-12-10 05:47:21 +00:00
var viewportWB = args . WorldAABB ;
2021-06-03 08:55:50 +01:00
// Has to be correctly handled because of the way intensity/falloff transform works so just do it.
_shader ? . SetParameter ( "renderScale" , args . Viewport . RenderScale ) ;
2021-12-05 18:09:01 +01:00
foreach ( var instance in _singularities . Values )
2021-03-09 04:33:41 -06:00
{
2021-05-28 10:44:13 +01:00
// To be clear, this needs to use "inside-viewport" pixels.
// In other words, specifically NOT IViewportControl.WorldToScreen (which uses outer coordinates).
var tempCoords = args . Viewport . WorldToLocal ( instance . CurrentMapCoords ) ;
tempCoords . Y = args . Viewport . Size . Y - tempCoords . Y ;
2021-03-09 04:33:41 -06:00
_shader ? . SetParameter ( "positionInput" , tempCoords ) ;
if ( ScreenTexture ! = null )
_shader ? . SetParameter ( "SCREEN_TEXTURE" , ScreenTexture ) ;
2021-06-03 08:55:50 +01:00
_shader ? . SetParameter ( "intensity" , instance . Intensity ) ;
_shader ? . SetParameter ( "falloff" , instance . Falloff ) ;
2021-03-09 04:33:41 -06:00
2021-04-19 09:52:40 +02:00
var worldHandle = args . WorldHandle ;
worldHandle . UseShader ( _shader ) ;
2021-05-28 10:44:13 +01:00
worldHandle . DrawRect ( viewportWB , Color . White ) ;
2021-03-09 04:33:41 -06:00
}
}
2021-03-14 22:19:14 -05:00
//Queries all singulos on the map and either adds or removes them from the list of rendered singulos based on whether they should be drawn (in range? on the same z-level/map? singulo entity still exists?)
2021-05-28 10:44:13 +01:00
private void SingularityQuery ( IEye ? currentEye )
2021-03-09 04:33:41 -06:00
{
2021-05-28 10:44:13 +01:00
if ( currentEye = = null )
{
_singularities . Clear ( ) ;
return ;
}
2021-06-24 04:48:11 +02:00
2021-05-28 10:44:13 +01:00
var currentEyeLoc = currentEye . Position ;
2021-03-09 04:33:41 -06:00
2021-09-28 13:35:29 +02:00
var distortions = _entityManager . EntityQuery < SingularityDistortionComponent > ( ) ;
2021-06-24 04:48:11 +02:00
foreach ( var distortion in distortions ) //Add all singulos that are not added yet but qualify
2021-03-09 04:33:41 -06:00
{
2021-12-06 00:52:58 +01:00
var singuloEntity = distortion . Owner ;
2021-06-24 04:48:11 +02:00
2021-12-03 15:53:09 +01:00
if ( ! _singularities . Keys . Contains ( singuloEntity ) & & SinguloQualifies ( singuloEntity , currentEyeLoc ) )
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
_singularities . Add ( singuloEntity , new SingularityShaderInstance ( _entityManager . GetComponent < TransformComponent > ( singuloEntity ) . MapPosition . Position , distortion . Intensity , distortion . Falloff ) ) ;
2021-03-09 04:33:41 -06:00
}
}
2021-06-24 04:48:11 +02:00
var activeShaderIds = _singularities . Keys ;
2021-12-05 18:09:01 +01:00
foreach ( var activeSingulo in activeShaderIds ) //Remove all singulos that are added and no longer qualify
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
if ( _entityManager . EntityExists ( activeSingulo ) )
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
if ( ! SinguloQualifies ( activeSingulo , currentEyeLoc ) )
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
_singularities . Remove ( activeSingulo ) ;
2021-03-09 04:33:41 -06:00
}
else
{
2021-12-05 18:09:01 +01:00
if ( ! _entityManager . TryGetComponent < SingularityDistortionComponent ? > ( activeSingulo , out var distortion ) )
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
_singularities . Remove ( activeSingulo ) ;
2021-03-09 04:33:41 -06:00
}
else
{
2021-12-05 18:09:01 +01:00
var shaderInstance = _singularities [ activeSingulo ] ;
shaderInstance . CurrentMapCoords = _entityManager . GetComponent < TransformComponent > ( activeSingulo ) . MapPosition . Position ;
2021-06-24 04:48:11 +02:00
shaderInstance . Intensity = distortion . Intensity ;
shaderInstance . Falloff = distortion . Falloff ;
2021-03-09 04:33:41 -06:00
}
}
}
else
{
2021-12-05 18:09:01 +01:00
_singularities . Remove ( activeSingulo ) ;
2021-03-09 04:33:41 -06:00
}
}
}
2021-12-05 18:09:01 +01:00
private bool SinguloQualifies ( EntityUid singuloEntity , MapCoordinates currentEyeLoc )
2021-03-09 04:33:41 -06:00
{
2021-12-05 18:09:01 +01:00
return _entityManager . GetComponent < TransformComponent > ( singuloEntity ) . MapID = = currentEyeLoc . MapId & & _entityManager . GetComponent < TransformComponent > ( singuloEntity ) . Coordinates . InRange ( _entityManager , EntityCoordinates . FromMap ( _entityManager , _entityManager . GetComponent < TransformComponent > ( singuloEntity ) . ParentUid , currentEyeLoc ) , MaxDist ) ;
2021-03-09 04:33:41 -06:00
}
private sealed class SingularityShaderInstance
{
public Vector2 CurrentMapCoords ;
2021-05-28 10:44:13 +01:00
public float Intensity ;
public float Falloff ;
2021-06-24 04:48:11 +02:00
2021-05-28 10:44:13 +01:00
public SingularityShaderInstance ( Vector2 mapCoords , float intensity , float falloff )
2021-03-09 04:33:41 -06:00
{
CurrentMapCoords = mapCoords ;
2021-05-28 10:44:13 +01:00
Intensity = intensity ;
Falloff = falloff ;
2021-03-09 04:33:41 -06:00
}
}
}
}