2021-03-09 04:33:41 -06:00
#nullable enable
using Robust.Shared.IoC ;
using Robust.Shared.Maths ;
using Robust.Shared.Prototypes ;
using System.Collections.Generic ;
using Robust.Client.Graphics ;
using System.Linq ;
using Robust.Shared.Enums ;
using Robust.Shared.GameObjects ;
using Content.Client.GameObjects.Components.Singularity ;
using Robust.Shared.Map ;
namespace Content.Client.Graphics.Overlays
{
public class SingularityOverlay : Overlay
{
[Dependency] private readonly IComponentManager _componentManager = default ! ;
[Dependency] private readonly IEntityManager _entityManager = default ! ;
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
[Dependency] private readonly IEyeManager _eyeManager = default ! ;
[Dependency] private readonly IClyde _displayManager = default ! ;
public override OverlaySpace Space = > OverlaySpace . WorldSpace ;
public override bool RequestScreenTexture = > true ;
private readonly ShaderInstance _shader ;
Dictionary < EntityUid , SingularityShaderInstance > _singularities = new Dictionary < EntityUid , SingularityShaderInstance > ( ) ;
public SingularityOverlay ( )
{
IoCManager . InjectDependencies ( this ) ;
_shader = _prototypeManager . Index < ShaderPrototype > ( "Singularity" ) . Instance ( ) . Duplicate ( ) ;
}
public override bool OverwriteTargetFrameBuffer ( )
{
return _singularities . Count ( ) > 0 ;
}
2021-04-19 09:52:40 +02:00
protected override void Draw ( in OverlayDrawArgs args )
2021-03-09 04:33:41 -06:00
{
SingularityQuery ( ) ;
foreach ( SingularityShaderInstance instance in _singularities . Values )
{
var tempCoords = _eyeManager . WorldToScreen ( instance . CurrentMapCoords ) ;
tempCoords . Y = _displayManager . ScreenSize . Y - tempCoords . Y ;
_shader ? . SetParameter ( "positionInput" , tempCoords ) ;
if ( ScreenTexture ! = null )
_shader ? . SetParameter ( "SCREEN_TEXTURE" , ScreenTexture ) ;
_shader ? . SetParameter ( "intensity" , LevelToIntensity ( instance . Level ) ) ;
_shader ? . SetParameter ( "falloff" , LevelToFalloff ( instance . Level ) ) ;
2021-04-19 09:52:40 +02:00
var worldHandle = args . WorldHandle ;
worldHandle . UseShader ( _shader ) ;
2021-03-09 04:33:41 -06:00
var viewport = _eyeManager . GetWorldViewport ( ) ;
worldHandle . DrawRect ( viewport , Color . White ) ;
}
}
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-03-09 04:33:41 -06:00
private float _maxDist = 15.0f ;
private void SingularityQuery ( )
{
var currentEyeLoc = _eyeManager . CurrentEye . Position ;
2021-03-14 22:19:14 -05:00
var currentMap = _eyeManager . CurrentMap ; //TODO: support multiple viewports once it is added
2021-03-09 04:33:41 -06:00
var singuloComponents = _componentManager . EntityQuery < IClientSingularityInstance > ( ) ;
2021-03-14 22:19:14 -05:00
foreach ( var singuloInterface in singuloComponents ) //Add all singulos that are not added yet but qualify
2021-03-09 04:33:41 -06:00
{
var singuloComponent = ( Component ) singuloInterface ;
var singuloEntity = singuloComponent . Owner ;
2021-03-14 22:19:14 -05:00
if ( ! _singularities . Keys . Contains ( singuloEntity . Uid ) & & singuloEntity . Transform . MapID = = currentMap & & singuloEntity . Transform . Coordinates . InRange ( _entityManager , EntityCoordinates . FromMap ( _entityManager , singuloEntity . Transform . ParentUid , currentEyeLoc ) , _maxDist ) )
2021-03-09 04:33:41 -06:00
{
_singularities . Add ( singuloEntity . Uid , new SingularityShaderInstance ( singuloEntity . Transform . MapPosition . Position , singuloInterface . Level ) ) ;
}
}
var activeShaderUids = _singularities . Keys ;
2021-03-14 22:19:14 -05:00
foreach ( var activeSinguloUid in activeShaderUids ) //Remove all singulos that are added and no longer qualify
2021-03-09 04:33:41 -06:00
{
if ( _entityManager . TryGetEntity ( activeSinguloUid , out IEntity ? singuloEntity ) )
{
2021-03-14 22:19:14 -05:00
if ( singuloEntity . Transform . MapID ! = currentMap | | ! singuloEntity . Transform . Coordinates . InRange ( _entityManager , EntityCoordinates . FromMap ( _entityManager , singuloEntity . Transform . ParentUid , currentEyeLoc ) , _maxDist ) )
2021-03-09 04:33:41 -06:00
{
_singularities . Remove ( activeSinguloUid ) ;
}
else
{
if ( ! singuloEntity . TryGetComponent < IClientSingularityInstance > ( out var singuloInterface ) )
{
_singularities . Remove ( activeSinguloUid ) ;
}
else
{
var shaderInstance = _singularities [ activeSinguloUid ] ;
shaderInstance . CurrentMapCoords = singuloEntity . Transform . MapPosition . Position ;
shaderInstance . Level = singuloInterface . Level ;
}
}
}
else
{
_singularities . Remove ( activeSinguloUid ) ;
}
}
}
//I am lazy
private float LevelToIntensity ( int level )
{
switch ( level )
{
case 0 :
return 0.0f ;
case 1 :
return 2.7f ;
case 2 :
return 14.4f ;
case 3 :
return 47.2f ;
case 4 :
return 180.0f ;
case 5 :
return 600.0f ;
case 6 :
return 800.0f ;
}
return - 1.0f ;
}
private float LevelToFalloff ( int level )
{
switch ( level )
{
case 0 :
return 9999f ;
case 1 :
return 6.4f ;
case 2 :
return 7.0f ;
case 3 :
return 8.0f ;
case 4 :
return 10.0f ;
case 5 :
return 12.0f ;
case 6 :
return 12.0f ;
}
return - 1.0f ;
}
private sealed class SingularityShaderInstance
{
public Vector2 CurrentMapCoords ;
public int Level ;
public SingularityShaderInstance ( Vector2 mapCoords , int level )
{
CurrentMapCoords = mapCoords ;
Level = level ;
}
}
}
}