Parallax refactors (#7654)
This commit is contained in:
@@ -1,72 +1,95 @@
|
||||
using System;
|
||||
using Content.Client.Parallax.Managers;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Parallax
|
||||
namespace Content.Client.Parallax;
|
||||
|
||||
public sealed class ParallaxOverlay : Overlay
|
||||
{
|
||||
public sealed class ParallaxOverlay : Overlay
|
||||
[Dependency] private readonly IParallaxManager _parallaxManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowWorld;
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public ParallaxOverlay()
|
||||
{
|
||||
[Dependency] private readonly IParallaxManager _parallaxManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||
}
|
||||
|
||||
private const float Slowness = 0.5f;
|
||||
|
||||
private Texture? _parallaxTexture;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowWorld;
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public ParallaxOverlay()
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (args.Viewport.Eye == null)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_parallaxManager.ParallaxTexture == null)
|
||||
if (!_configurationManager.GetCVar(CCVars.ParallaxEnabled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var screenHandle = args.WorldHandle;
|
||||
screenHandle.UseShader(_shader);
|
||||
|
||||
foreach (var layer in _parallaxManager.ParallaxLayers)
|
||||
{
|
||||
var tex = layer.Texture;
|
||||
|
||||
// Size of the texture in world units.
|
||||
var size = (tex.Size / (float) EyeManager.PixelsPerMeter) * layer.Config.Scale;
|
||||
|
||||
// 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.
|
||||
var home = layer.Config.WorldHomePosition + _parallaxManager.ParallaxAnchor;
|
||||
|
||||
// Origin - start with the parallax shift itself.
|
||||
var originBL = (args.Viewport.Eye.Position.Position - home) * layer.Config.Slowness;
|
||||
|
||||
// Place at the home.
|
||||
originBL += home;
|
||||
|
||||
// Adjust.
|
||||
originBL += layer.Config.WorldAdjustPosition;
|
||||
|
||||
// Centre the image.
|
||||
originBL -= size / 2;
|
||||
|
||||
if (layer.Config.Tiled)
|
||||
{
|
||||
_parallaxManager.OnTextureLoaded += texture => _parallaxTexture = texture;
|
||||
// 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)
|
||||
{
|
||||
for (var y = flooredBL.Y; y < args.WorldAABB.Top; y += size.Y)
|
||||
{
|
||||
screenHandle.DrawTextureRect(tex, Box2.FromDimensions((x, y), size));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_parallaxTexture = _parallaxManager.ParallaxTexture;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (_parallaxTexture == null || args.Viewport.Eye == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var screenHandle = args.WorldHandle;
|
||||
screenHandle.UseShader(_shader);
|
||||
|
||||
var (sizeX, sizeY) = _parallaxTexture.Size / (float) EyeManager.PixelsPerMeter;
|
||||
var (posX, posY) = args.Viewport.Eye.Position;
|
||||
var o = new Vector2(posX * Slowness, posY * Slowness);
|
||||
|
||||
// Remove offset so we can floor.
|
||||
var (l, b) = args.WorldAABB.BottomLeft - o;
|
||||
|
||||
// Floor to background size.
|
||||
l = sizeX * MathF.Floor(l / sizeX);
|
||||
b = sizeY * MathF.Floor(b / sizeY);
|
||||
|
||||
// Re-offset.
|
||||
l += o.X;
|
||||
b += o.Y;
|
||||
|
||||
for (var x = l; x < args.WorldAABB.Right; x += sizeX)
|
||||
{
|
||||
for (var y = b; y < args.WorldAABB.Top; y += sizeY)
|
||||
{
|
||||
screenHandle.DrawTexture(_parallaxTexture, (x, y));
|
||||
}
|
||||
screenHandle.DrawTextureRect(tex, Box2.FromDimensions(originBL, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user