ParallaxControl.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using System.Numerics;
  2. using Content.Client.Parallax.Managers;
  3. using Robust.Client.Graphics;
  4. using Robust.Client.UserInterface;
  5. using Robust.Shared.Random;
  6. using Robust.Shared.Timing;
  7. using Robust.Shared.ViewVariables;
  8. namespace Content.Client.Parallax;
  9. /// <summary>
  10. /// Renders the parallax background as a UI control.
  11. /// </summary>
  12. public sealed class ParallaxControl : Control
  13. {
  14. [Dependency] private readonly IGameTiming _timing = default!;
  15. [Dependency] private readonly IParallaxManager _parallaxManager = default!;
  16. [Dependency] private readonly IRobustRandom _random = default!;
  17. [ViewVariables(VVAccess.ReadWrite)] public Vector2 Offset { get; set; }
  18. public ParallaxControl()
  19. {
  20. IoCManager.InjectDependencies(this);
  21. Offset = new Vector2(_random.Next(0, 1000), _random.Next(0, 1000));
  22. RectClipContent = true;
  23. _parallaxManager.LoadParallaxByName("FastSpace");
  24. }
  25. protected override void Draw(DrawingHandleScreen handle)
  26. {
  27. foreach (var layer in _parallaxManager.GetParallaxLayers("FastSpace"))
  28. {
  29. var tex = layer.Texture;
  30. var texSize = (tex.Size.X * (int) Size.X, tex.Size.Y * (int) Size.X) * layer.Config.Scale.Floored() / 1920;
  31. var ourSize = PixelSize;
  32. var currentTime = (float) _timing.RealTime.TotalSeconds;
  33. var offset = Offset + new Vector2(currentTime * 100f, currentTime * 0f);
  34. if (layer.Config.Tiled)
  35. {
  36. // Multiply offset by slowness to match normal parallax
  37. var scaledOffset = (offset * layer.Config.Slowness).Floored();
  38. // Then modulo the scaled offset by the size to prevent drawing a bunch of offscreen tiles for really small images.
  39. scaledOffset.X %= texSize.X;
  40. scaledOffset.Y %= texSize.Y;
  41. // Note: scaledOffset must never be below 0 or there will be visual issues.
  42. // It could be allowed to be >= texSize on a given axis but that would be wasteful.
  43. for (var x = -scaledOffset.X; x < ourSize.X; x += texSize.X)
  44. {
  45. for (var y = -scaledOffset.Y; y < ourSize.Y; y += texSize.Y)
  46. {
  47. handle.DrawTextureRect(tex, UIBox2.FromDimensions(new Vector2(x, y), texSize));
  48. }
  49. }
  50. }
  51. else
  52. {
  53. var origin = ((ourSize - texSize) / 2) + layer.Config.ControlHomePosition;
  54. handle.DrawTextureRect(tex, UIBox2.FromDimensions(origin, texSize));
  55. }
  56. }
  57. }
  58. }