2023-07-08 14:08:32 +10:00
using System.Numerics ;
2021-06-09 22:19:39 +02:00
using Content.Client.Parallax.Managers ;
2022-05-04 17:55:21 +01:00
using Content.Shared.CCVar ;
2023-02-12 13:15:09 +11:00
using Content.Shared.Parallax.Biomes ;
2019-04-15 21:11:38 -06:00
using Robust.Client.Graphics ;
2022-05-04 17:55:21 +01:00
using Robust.Shared.Configuration ;
2021-03-09 04:33:41 -06:00
using Robust.Shared.Enums ;
2022-07-25 15:10:23 +10:00
using Robust.Shared.Map ;
2019-04-15 21:11:38 -06:00
using Robust.Shared.Prototypes ;
2022-07-25 15:10:23 +10:00
using Robust.Shared.Timing ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
namespace Content.Client.Parallax ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
public sealed class ParallaxOverlay : Overlay
{
2023-02-12 13:15:09 +11:00
[Dependency] private readonly IEntityManager _entManager = default ! ;
2022-07-25 15:10:23 +10:00
[Dependency] private readonly IGameTiming _timing = default ! ;
2022-05-04 17:55:21 +01:00
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
[Dependency] private readonly IConfigurationManager _configurationManager = default ! ;
2023-02-12 13:15:09 +11:00
[Dependency] private readonly IMapManager _mapManager = default ! ;
2022-07-25 15:10:23 +10:00
[Dependency] private readonly IParallaxManager _manager = default ! ;
private readonly ParallaxSystem _parallax ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
public override OverlaySpace Space = > OverlaySpace . WorldSpaceBelowWorld ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
public ParallaxOverlay ( )
{
2023-01-17 20:26:52 +11:00
ZIndex = ParallaxSystem . ParallaxZIndex ;
2022-05-04 17:55:21 +01:00
IoCManager . InjectDependencies ( this ) ;
2023-02-12 13:15:09 +11:00
_parallax = _entManager . System < ParallaxSystem > ( ) ;
}
protected override bool BeforeDraw ( in OverlayDrawArgs args )
{
2023-03-31 21:50:11 -05:00
if ( args . MapId = = MapId . Nullspace | | _entManager . HasComponent < BiomeComponent > ( _mapManager . GetMapEntityId ( args . MapId ) ) )
2023-02-12 13:15:09 +11:00
return false ;
2022-07-25 15:10:23 +10:00
2023-02-12 13:15:09 +11:00
return true ;
2022-05-04 17:55:21 +01:00
}
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
protected override void Draw ( in OverlayDrawArgs args )
{
2022-07-25 15:10:23 +10:00
if ( args . MapId = = MapId . Nullspace )
2022-05-04 17:55:21 +01:00
return ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
if ( ! _configurationManager . GetCVar ( CCVars . ParallaxEnabled ) )
return ;
2018-11-30 21:54:30 +01:00
2022-07-25 15:10:23 +10:00
var position = args . Viewport . Eye ? . Position . Position ? ? Vector2 . Zero ;
2023-06-28 21:22:03 +10:00
var worldHandle = args . WorldHandle ;
2022-05-04 17:55:21 +01:00
2022-07-25 15:10:23 +10:00
var layers = _parallax . GetParallaxLayers ( args . MapId ) ;
var realTime = ( float ) _timing . RealTime . TotalSeconds ;
foreach ( var layer in layers )
2018-11-30 21:54:30 +01:00
{
2022-07-25 15:10:23 +10:00
ShaderInstance ? shader ;
if ( ! string . IsNullOrEmpty ( layer . Config . Shader ) )
shader = _prototypeManager . Index < ShaderPrototype > ( layer . Config . Shader ) . Instance ( ) ;
else
shader = null ;
2023-06-28 21:22:03 +10:00
worldHandle . UseShader ( shader ) ;
2022-05-04 17:55:21 +01:00
var tex = layer . Texture ;
// Size of the texture in world units.
var size = ( tex . Size / ( float ) EyeManager . PixelsPerMeter ) * layer . Config . Scale ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
// The "home" position is the effective origin of this layer.
// Parallax shifting is relative to the home, and shifts away from the home and towards the Eye centre.
// The effects of this are such that a slowness of 1 anchors the layer to the centre of the screen, while a slowness of 0 anchors the layer to the world.
// (For values 0.0 to 1.0 this is in effect a lerp, but it's deliberately unclamped.)
// The ParallaxAnchor adapts the parallax for station positioning and possibly map-specific tweaks.
2022-07-25 15:10:23 +10:00
var home = layer . Config . WorldHomePosition + _manager . ParallaxAnchor ;
var scrolled = layer . Config . Scrolling * realTime ;
2019-07-06 19:20:20 +02:00
2022-05-04 17:55:21 +01:00
// Origin - start with the parallax shift itself.
2022-07-25 15:10:23 +10:00
var originBL = ( position - home ) * layer . Config . Slowness + scrolled ;
2018-11-30 21:54:30 +01:00
2022-05-04 17:55:21 +01:00
// Place at the home.
originBL + = home ;
2021-04-19 09:52:40 +02:00
2022-05-04 17:55:21 +01:00
// Adjust.
originBL + = layer . Config . WorldAdjustPosition ;
2021-04-19 09:52:40 +02:00
2022-05-04 17:55:21 +01:00
// Centre the image.
originBL - = size / 2 ;
2021-04-19 09:52:40 +02:00
2022-05-04 17:55:21 +01:00
if ( layer . Config . Tiled )
2021-04-19 09:52:40 +02:00
{
2022-05-04 17:55:21 +01:00
// Remove offset so we can floor.
var flooredBL = args . WorldAABB . BottomLeft - originBL ;
// Floor to background size.
flooredBL = ( flooredBL / size ) . Floored ( ) * size ;
// Re-offset.
flooredBL + = originBL ;
for ( var x = flooredBL . X ; x < args . WorldAABB . Right ; x + = size . X )
2021-04-19 09:52:40 +02:00
{
2022-05-04 17:55:21 +01:00
for ( var y = flooredBL . Y ; y < args . WorldAABB . Top ; y + = size . Y )
{
2023-07-08 14:08:32 +10:00
worldHandle . DrawTextureRect ( tex , Box2 . FromDimensions ( new Vector2 ( x , y ) , size ) ) ;
2022-05-04 17:55:21 +01:00
}
2020-01-26 05:02:12 -08:00
}
}
2022-05-04 17:55:21 +01:00
else
{
2023-06-28 21:22:03 +10:00
worldHandle . DrawTextureRect ( tex , Box2 . FromDimensions ( originBL , size ) ) ;
2022-05-04 17:55:21 +01:00
}
2018-11-30 21:54:30 +01:00
}
2022-07-25 15:10:23 +10:00
2023-06-28 21:22:03 +10:00
worldHandle . UseShader ( null ) ;
2018-11-30 21:54:30 +01:00
}
}
2022-05-04 17:55:21 +01:00