| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- using System.Numerics;
- using Content.Client.Resources;
- using Robust.Client.Graphics;
- using Robust.Client.ResourceManagement;
- using Robust.Client.UserInterface;
- namespace Content.Client.Weapons.Ranged.ItemStatus;
- public abstract class BaseBulletRenderer : Control
- {
- private int _capacity;
- private LayoutParameters _params;
- public int Rows { get; set; } = 2;
- public int Count { get; set; }
- public int Capacity
- {
- get => _capacity;
- set
- {
- if (_capacity == value)
- return;
- _capacity = value;
- InvalidateMeasure();
- }
- }
- protected LayoutParameters Parameters
- {
- get => _params;
- set
- {
- _params = value;
- InvalidateMeasure();
- }
- }
- protected override Vector2 MeasureOverride(Vector2 availableSize)
- {
- var countPerRow = Math.Min(Capacity, CountPerRow(availableSize.X));
- var rows = Math.Min((int) MathF.Ceiling(Capacity / (float) countPerRow), Rows);
- var height = _params.ItemHeight * rows + (_params.VerticalSeparation * rows - 1);
- var width = RowWidth(countPerRow);
- return new Vector2(width, height);
- }
- protected override void Draw(DrawingHandleScreen handle)
- {
- // Scale rendering in this control by UIScale.
- var currentTransform = handle.GetTransform();
- handle.SetTransform(Matrix3Helpers.CreateScale(new Vector2(UIScale)) * currentTransform);
- var countPerRow = CountPerRow(Size.X);
- var pos = new Vector2();
- var spent = Capacity - Count;
- var bulletsDone = 0;
- // Draw by rows, bottom to top.
- for (var row = 0; row < Rows; row++)
- {
- var altColor = false;
- var thisRowCount = Math.Min(countPerRow, Capacity - bulletsDone);
- if (thisRowCount <= 0)
- break;
- // Handle MinCountPerRow
- // We only do this if:
- // 1. The next row would have less than MinCountPerRow bullets.
- // 2. The next row is actually visible (we aren't the last row).
- // 3. MinCountPerRow is actually smaller than the count per row (avoid degenerate cases).
- // 4. There's enough bullets that at least one will end up on the next row.
- var nextRowCount = Capacity - bulletsDone - thisRowCount;
- if (nextRowCount < _params.MinCountPerRow && row != Rows - 1 && _params.MinCountPerRow < countPerRow && nextRowCount > 0)
- thisRowCount -= _params.MinCountPerRow - nextRowCount;
- // Account for row width to right-align.
- var rowWidth = RowWidth(thisRowCount);
- pos.X += Size.X - rowWidth;
- // Draw row left to right (so overlapping works)
- for (var bullet = 0; bullet < thisRowCount; bullet++)
- {
- var absIdx = Capacity - bulletsDone - thisRowCount + bullet;
- var renderPos = pos;
- renderPos.Y = Size.Y - renderPos.Y - _params.ItemHeight;
- DrawItem(handle, renderPos, absIdx < spent, altColor);
- pos.X += _params.ItemSeparation;
- altColor ^= true;
- }
- bulletsDone += thisRowCount;
- pos.X = 0;
- pos.Y += _params.ItemHeight + _params.VerticalSeparation;
- }
- }
- protected abstract void DrawItem(DrawingHandleScreen handle, Vector2 renderPos, bool spent, bool altColor);
- private int CountPerRow(float width)
- {
- return (int) ((width - _params.ItemWidth + _params.ItemSeparation) / _params.ItemSeparation);
- }
- private int RowWidth(int count)
- {
- return (count - 1) * _params.ItemSeparation + _params.ItemWidth;
- }
- protected struct LayoutParameters
- {
- public int ItemHeight;
- public int ItemSeparation;
- public int ItemWidth;
- public int VerticalSeparation;
- /// <summary>
- /// Try to ensure there's at least this many bullets on one row.
- /// </summary>
- /// <remarks>
- /// For example, if there are two rows and the second row has only two bullets,
- /// we "steal" some bullets from the row below it to make it look nicer.
- /// </remarks>
- public int MinCountPerRow;
- }
- }
- /// <summary>
- /// Renders one or more rows of bullets for item status.
- /// </summary>
- /// <remarks>
- /// This is a custom control to allow complex responsive layout logic.
- /// </remarks>
- public sealed class BulletRender : BaseBulletRenderer
- {
- public const int MinCountPerRow = 7;
- public const int BulletHeight = 12;
- public const int VerticalSeparation = 2;
- private static readonly LayoutParameters LayoutNormal = new LayoutParameters
- {
- ItemHeight = BulletHeight,
- ItemSeparation = 3,
- ItemWidth = 5,
- VerticalSeparation = VerticalSeparation,
- MinCountPerRow = MinCountPerRow
- };
- private static readonly LayoutParameters LayoutTiny = new LayoutParameters
- {
- ItemHeight = BulletHeight,
- ItemSeparation = 2,
- ItemWidth = 2,
- VerticalSeparation = VerticalSeparation,
- MinCountPerRow = MinCountPerRow
- };
- private static readonly Color ColorA = Color.FromHex("#b68f0e");
- private static readonly Color ColorB = Color.FromHex("#d7df60");
- private static readonly Color ColorGoneA = Color.FromHex("#000000");
- private static readonly Color ColorGoneB = Color.FromHex("#222222");
- private readonly Texture _bulletTiny;
- private readonly Texture _bulletNormal;
- private BulletType _type = BulletType.Normal;
- public BulletType Type
- {
- get => _type;
- set
- {
- if (_type == value)
- return;
- Parameters = _type switch
- {
- BulletType.Normal => LayoutNormal,
- BulletType.Tiny => LayoutTiny,
- _ => throw new ArgumentOutOfRangeException()
- };
- _type = value;
- }
- }
- public BulletRender()
- {
- var resC = IoCManager.Resolve<IResourceCache>();
- _bulletTiny = resC.GetTexture("/Textures/Interface/ItemStatus/Bullets/tiny.png");
- _bulletNormal = resC.GetTexture("/Textures/Interface/ItemStatus/Bullets/normal.png");
- Parameters = LayoutNormal;
- }
- protected override void DrawItem(DrawingHandleScreen handle, Vector2 renderPos, bool spent, bool altColor)
- {
- Color color;
- if (spent)
- color = altColor ? ColorGoneA : ColorGoneB;
- else
- color = altColor ? ColorA : ColorB;
- var texture = _type == BulletType.Tiny ? _bulletTiny : _bulletNormal;
- handle.DrawTexture(texture, renderPos, color);
- }
- public enum BulletType
- {
- Normal,
- Tiny
- }
- }
- public sealed class BatteryBulletRenderer : BaseBulletRenderer
- {
- private static readonly Color ItemColor = Color.FromHex("#E00000");
- private static readonly Color ItemColorGone = Color.Black;
- private const int SizeH = 10;
- private const int SizeV = 10;
- private const int Separation = 4;
- public BatteryBulletRenderer()
- {
- Parameters = new LayoutParameters
- {
- ItemWidth = SizeH,
- ItemHeight = SizeV,
- ItemSeparation = SizeH + Separation,
- MinCountPerRow = 3,
- VerticalSeparation = Separation
- };
- }
- protected override void DrawItem(DrawingHandleScreen handle, Vector2 renderPos, bool spent, bool altColor)
- {
- var color = spent ? ItemColorGone : ItemColor;
- handle.DrawRect(UIBox2.FromDimensions(renderPos, new Vector2(SizeH, SizeV)), color);
- }
- }
|