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
{
public class SingularityOverlay : Overlay
{
[Dependency] private readonly IEntityManager _entityManager = default ! ;
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
2021-11-02 01:11:58 +00:00
[Dependency] private readonly IEyeManager _eyeManager = 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-11-02 01:11:58 +00:00
var viewportWB = _eyeManager . GetWorldViewport ( ) ;
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-03-09 04:33:41 -06:00
foreach ( SingularityShaderInstance instance in _singularities . Values )
{
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-06-24 04:48:11 +02:00
var singuloEntity = distortion . Owner ;
2021-05-28 10:44:13 +01:00
if ( ! _singularities . Keys . Contains ( singuloEntity . Uid ) & & SinguloQualifies ( singuloEntity , currentEyeLoc ) )
2021-03-09 04:33:41 -06:00
{
2021-06-24 04:48:11 +02:00
_singularities . Add ( singuloEntity . Uid , new SingularityShaderInstance ( singuloEntity . Transform . 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 ;
foreach ( var activeSinguloUid in activeShaderIds ) //Remove all singulos that are added and no longer qualify
2021-03-09 04:33:41 -06:00
{
2021-06-24 04:48:11 +02:00
if ( _entityManager . TryGetEntity ( activeSinguloUid , out var singuloEntity ) )
2021-03-09 04:33:41 -06:00
{
2021-05-28 10:44:13 +01:00
if ( ! SinguloQualifies ( singuloEntity , currentEyeLoc ) )
2021-03-09 04:33:41 -06:00
{
_singularities . Remove ( activeSinguloUid ) ;
}
else
{
2021-06-24 04:48:11 +02:00
if ( ! singuloEntity . TryGetComponent < SingularityDistortionComponent > ( out var distortion ) )
2021-03-09 04:33:41 -06:00
{
_singularities . Remove ( activeSinguloUid ) ;
}
else
{
var shaderInstance = _singularities [ activeSinguloUid ] ;
shaderInstance . CurrentMapCoords = singuloEntity . Transform . 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
{
_singularities . Remove ( activeSinguloUid ) ;
}
}
}
2021-05-28 10:44:13 +01:00
private bool SinguloQualifies ( IEntity singuloEntity , MapCoordinates currentEyeLoc )
2021-03-09 04:33:41 -06:00
{
2021-06-24 04:48:11 +02:00
return singuloEntity . Transform . MapID = = currentEyeLoc . MapId & & singuloEntity . Transform . Coordinates . InRange ( _entityManager , EntityCoordinates . FromMap ( _entityManager , singuloEntity . Transform . 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
}
}
}
}