AtmosPipeAppearanceSystem.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using Content.Client.SubFloor;
  2. using Content.Shared.Atmos;
  3. using Content.Shared.Atmos.Components;
  4. using Content.Shared.Atmos.Piping;
  5. using JetBrains.Annotations;
  6. using Robust.Client.GameObjects;
  7. namespace Content.Client.Atmos.EntitySystems;
  8. [UsedImplicitly]
  9. public sealed class AtmosPipeAppearanceSystem : EntitySystem
  10. {
  11. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<PipeAppearanceComponent, ComponentInit>(OnInit);
  16. SubscribeLocalEvent<PipeAppearanceComponent, AppearanceChangeEvent>(OnAppearanceChanged, after: [typeof(SubFloorHideSystem)]);
  17. }
  18. private void OnInit(EntityUid uid, PipeAppearanceComponent component, ComponentInit args)
  19. {
  20. if (!TryComp(uid, out SpriteComponent? sprite))
  21. return;
  22. foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
  23. {
  24. sprite.LayerMapReserveBlank(layerKey);
  25. var layer = sprite.LayerMapGet(layerKey);
  26. sprite.LayerSetRSI(layer, component.Sprite.RsiPath);
  27. sprite.LayerSetState(layer, component.Sprite.RsiState);
  28. sprite.LayerSetDirOffset(layer, ToOffset(layerKey));
  29. }
  30. }
  31. private void HideAllPipeConnection(SpriteComponent sprite)
  32. {
  33. foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
  34. {
  35. if (!sprite.LayerMapTryGet(layerKey, out var key))
  36. continue;
  37. var layer = sprite[key];
  38. layer.Visible = false;
  39. }
  40. }
  41. private void OnAppearanceChanged(EntityUid uid, PipeAppearanceComponent component, ref AppearanceChangeEvent args)
  42. {
  43. if (args.Sprite == null)
  44. return;
  45. if (!args.Sprite.Visible)
  46. {
  47. // This entity is probably below a floor and is not even visible to the user -> don't bother updating sprite data.
  48. // Note that if the subfloor visuals change, then another AppearanceChangeEvent will get triggered.
  49. return;
  50. }
  51. if (!_appearance.TryGetData<PipeDirection>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
  52. {
  53. HideAllPipeConnection(args.Sprite);
  54. return;
  55. }
  56. if (!_appearance.TryGetData<Color>(uid, PipeColorVisuals.Color, out var color, args.Component))
  57. color = Color.White;
  58. // transform connected directions to local-coordinates
  59. var connectedDirections = worldConnectedDirections.RotatePipeDirection(-Transform(uid).LocalRotation);
  60. foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
  61. {
  62. if (!args.Sprite.LayerMapTryGet(layerKey, out var key))
  63. continue;
  64. var layer = args.Sprite[key];
  65. var dir = (PipeDirection) layerKey;
  66. var visible = connectedDirections.HasDirection(dir);
  67. layer.Visible &= visible;
  68. if (!visible)
  69. continue;
  70. layer.Color = color;
  71. }
  72. }
  73. private SpriteComponent.DirectionOffset ToOffset(PipeConnectionLayer layer)
  74. {
  75. return layer switch
  76. {
  77. PipeConnectionLayer.NorthConnection => SpriteComponent.DirectionOffset.Flip,
  78. PipeConnectionLayer.EastConnection => SpriteComponent.DirectionOffset.CounterClockwise,
  79. PipeConnectionLayer.WestConnection => SpriteComponent.DirectionOffset.Clockwise,
  80. _ => SpriteComponent.DirectionOffset.None,
  81. };
  82. }
  83. private enum PipeConnectionLayer : byte
  84. {
  85. NorthConnection = PipeDirection.North,
  86. SouthConnection = PipeDirection.South,
  87. EastConnection = PipeDirection.East,
  88. WestConnection = PipeDirection.West,
  89. }
  90. }