THE RETURN OF ITEM STATUS (#22986)
* THE RETURN OF ITEM STATUS Item status is now inline with the hands again. You can now see item status for both hands at once. If you have more than 2 hands, the last active hand of that side is displayed in the respective item status. The item status for the active hand is also highlighted. Item status has been given a new look so it looks unique and matches every UI theme. * Shrink item status to 125px This is going to require fixing the existing controls. Do that later. * New bullet item status rendering sex * Make gun item status look just a little bit nicer. Avoid only one or two bullets ending up on a single row of an item status. * Delete Eris theme files * More improvements Fixed the fact that left/right were flipped around when assigning status panel locations. Involved renaming all the UI textures. Redid how content margins are set from the theme. Less complex and cleaner now. Made the item name always left-aligned, just looks better since other UI elements don't adapt anyways. * Compact down item status text Now it fits 3 lines of text on one line. Yay. This is achieved by compacting RichTextLabels by reducing their line height and giving them a negative bottom margin. * Add item status sprites for Ashen theme. * Add status control to show beaker/bucket/jug solution/transfer volumes Also PollingItemStatusControl I'll be using that more. * Fix welder item status, clean up welder code The item status control implementation was ancient and bad. That's why it was buggy. Removed all the complex dated networking stuff for welders, we just sync the solution contents now anyways so none of that is needed anymore. This moves a buncha stuff to shared and just removes code. Cleanup. The code was doing some really dumb stuff. * Spray bottles show contents in item status. * cowtools * Fix plasmafire and clockwork themes. Actual git gaslighting wtf. --------- Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
ee4ef4b96a
commit
58f025ba80
178
Content.Client/Weapons/Ranged/ItemStatus/BulletRender.cs
Normal file
178
Content.Client/Weapons/Ranged/ItemStatus/BulletRender.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
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;
|
||||
|
||||
/// <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 : Control
|
||||
{
|
||||
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");
|
||||
|
||||
/// <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 const int MinCountPerRow = 7;
|
||||
|
||||
public const int BulletHeight = 12;
|
||||
public const int BulletSeparationNormal = 3;
|
||||
public const int BulletSeparationTiny = 2;
|
||||
public const int BulletWidthNormal = 5;
|
||||
public const int BulletWidthTiny = 2;
|
||||
public const int VerticalSeparation = 2;
|
||||
|
||||
private readonly Texture _bulletTiny;
|
||||
private readonly Texture _bulletNormal;
|
||||
|
||||
private int _capacity;
|
||||
private BulletType _type = BulletType.Normal;
|
||||
|
||||
public int Rows { get; set; } = 2;
|
||||
public int Count { get; set; }
|
||||
|
||||
public int Capacity
|
||||
{
|
||||
get => _capacity;
|
||||
set
|
||||
{
|
||||
_capacity = value;
|
||||
InvalidateMeasure();
|
||||
}
|
||||
}
|
||||
|
||||
public BulletType Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
_type = value;
|
||||
InvalidateMeasure();
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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 = BulletHeight * rows + (BulletSeparationNormal * 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(Matrix3.CreateScale(new Vector2(UIScale)) * currentTransform);
|
||||
|
||||
var countPerRow = CountPerRow(Size.X);
|
||||
|
||||
var (separation, _) = BulletParams();
|
||||
var texture = Type == BulletType.Normal ? _bulletNormal : _bulletTiny;
|
||||
|
||||
var pos = new Vector2();
|
||||
|
||||
var altColor = false;
|
||||
|
||||
var spent = Capacity - Count;
|
||||
|
||||
var bulletsDone = 0;
|
||||
|
||||
// Draw by rows, bottom to top.
|
||||
for (var row = 0; row < Rows; row++)
|
||||
{
|
||||
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).
|
||||
var nextRowCount = Capacity - bulletsDone - thisRowCount;
|
||||
if (nextRowCount < MinCountPerRow && row != Rows - 1 && MinCountPerRow < countPerRow)
|
||||
thisRowCount -= 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;
|
||||
Color color;
|
||||
if (absIdx >= spent)
|
||||
color = altColor ? ColorA : ColorB;
|
||||
else
|
||||
color = altColor ? ColorGoneA : ColorGoneB;
|
||||
|
||||
var renderPos = pos;
|
||||
renderPos.Y = Size.Y - renderPos.Y - BulletHeight;
|
||||
handle.DrawTexture(texture, renderPos, color);
|
||||
pos.X += separation;
|
||||
altColor ^= true;
|
||||
}
|
||||
|
||||
bulletsDone += thisRowCount;
|
||||
pos.X = 0;
|
||||
pos.Y += BulletHeight + VerticalSeparation;
|
||||
}
|
||||
}
|
||||
|
||||
private int CountPerRow(float width)
|
||||
{
|
||||
var (separation, bulletWidth) = BulletParams();
|
||||
return (int) ((width - bulletWidth + separation) / separation);
|
||||
}
|
||||
|
||||
private (int separation, int width) BulletParams()
|
||||
{
|
||||
return Type switch
|
||||
{
|
||||
BulletType.Normal => (BulletSeparationNormal, BulletWidthNormal),
|
||||
BulletType.Tiny => (BulletSeparationTiny, BulletWidthTiny),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private int RowWidth(int count)
|
||||
{
|
||||
var (separation, bulletWidth) = BulletParams();
|
||||
|
||||
return (count - 1) * separation + bulletWidth;
|
||||
}
|
||||
|
||||
public enum BulletType
|
||||
{
|
||||
Normal,
|
||||
Tiny
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,11 @@ using Content.Client.Items;
|
||||
using Content.Client.Resources;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.Weapons.Ranged.Components;
|
||||
using Content.Client.Weapons.Ranged.ItemStatus;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Graphics;
|
||||
|
||||
namespace Content.Client.Weapons.Ranged.Systems;
|
||||
|
||||
@@ -91,116 +91,26 @@ public sealed partial class GunSystem
|
||||
|
||||
private sealed class DefaultStatusControl : Control
|
||||
{
|
||||
private readonly BoxContainer _bulletsListTop;
|
||||
private readonly BoxContainer _bulletsListBottom;
|
||||
private readonly BulletRender _bulletRender;
|
||||
|
||||
public DefaultStatusControl()
|
||||
{
|
||||
MinHeight = 15;
|
||||
HorizontalExpand = true;
|
||||
VerticalAlignment = Control.VAlignment.Center;
|
||||
AddChild(new BoxContainer
|
||||
VerticalAlignment = VAlignment.Center;
|
||||
AddChild(_bulletRender = new BulletRender
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||
HorizontalExpand = true,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
SeparationOverride = 0,
|
||||
Children =
|
||||
{
|
||||
(_bulletsListTop = new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
SeparationOverride = 0
|
||||
}),
|
||||
new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
HorizontalExpand = true,
|
||||
Children =
|
||||
{
|
||||
new Control
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
Children =
|
||||
{
|
||||
(_bulletsListBottom = new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
SeparationOverride = 0
|
||||
}),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalAlignment = HAlignment.Right,
|
||||
VerticalAlignment = VAlignment.Bottom
|
||||
});
|
||||
}
|
||||
|
||||
public void Update(int count, int capacity)
|
||||
{
|
||||
_bulletsListTop.RemoveAllChildren();
|
||||
_bulletsListBottom.RemoveAllChildren();
|
||||
_bulletRender.Count = count;
|
||||
_bulletRender.Capacity = capacity;
|
||||
|
||||
string texturePath;
|
||||
if (capacity <= 20)
|
||||
{
|
||||
texturePath = "/Textures/Interface/ItemStatus/Bullets/normal.png";
|
||||
}
|
||||
else if (capacity <= 30)
|
||||
{
|
||||
texturePath = "/Textures/Interface/ItemStatus/Bullets/small.png";
|
||||
}
|
||||
else
|
||||
{
|
||||
texturePath = "/Textures/Interface/ItemStatus/Bullets/tiny.png";
|
||||
}
|
||||
|
||||
var texture = StaticIoC.ResC.GetTexture(texturePath);
|
||||
|
||||
const int tinyMaxRow = 60;
|
||||
|
||||
if (capacity > tinyMaxRow)
|
||||
{
|
||||
FillBulletRow(_bulletsListBottom, Math.Min(tinyMaxRow, count), tinyMaxRow, texture);
|
||||
FillBulletRow(_bulletsListTop, Math.Max(0, count - tinyMaxRow), capacity - tinyMaxRow, texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
FillBulletRow(_bulletsListBottom, count, capacity, texture);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillBulletRow(Control container, int count, int capacity, Texture texture)
|
||||
{
|
||||
var colorA = Color.FromHex("#b68f0e");
|
||||
var colorB = Color.FromHex("#d7df60");
|
||||
var colorGoneA = Color.FromHex("#000000");
|
||||
var colorGoneB = Color.FromHex("#222222");
|
||||
|
||||
var altColor = false;
|
||||
|
||||
for (var i = count; i < capacity; i++)
|
||||
{
|
||||
container.AddChild(new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
ModulateSelfOverride = altColor ? colorGoneA : colorGoneB
|
||||
});
|
||||
|
||||
altColor ^= true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
container.AddChild(new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
ModulateSelfOverride = altColor ? colorA : colorB
|
||||
});
|
||||
|
||||
altColor ^= true;
|
||||
}
|
||||
_bulletRender.Type = capacity > 50 ? BulletRender.BulletType.Tiny : BulletRender.BulletType.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +201,7 @@ public sealed partial class GunSystem
|
||||
|
||||
private sealed class ChamberMagazineStatusControl : Control
|
||||
{
|
||||
private readonly BoxContainer _bulletsList;
|
||||
private readonly BulletRender _bulletRender;
|
||||
private readonly TextureRect _chamberedBullet;
|
||||
private readonly Label _noMagazineLabel;
|
||||
private readonly Label _ammoCount;
|
||||
@@ -308,23 +218,16 @@ public sealed partial class GunSystem
|
||||
HorizontalExpand = true,
|
||||
Children =
|
||||
{
|
||||
(_chamberedBullet = new TextureRect
|
||||
{
|
||||
Texture = StaticIoC.ResC.GetTexture("/Textures/Interface/ItemStatus/Bullets/chambered_rotated.png"),
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
HorizontalAlignment = HAlignment.Right,
|
||||
}),
|
||||
new Control() { MinSize = new Vector2(5,0) },
|
||||
new Control
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
Margin = new Thickness(0, 0, 5, 0),
|
||||
Children =
|
||||
{
|
||||
(_bulletsList = new BoxContainer
|
||||
(_bulletRender = new BulletRender
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
SeparationOverride = 0
|
||||
HorizontalAlignment = HAlignment.Right,
|
||||
VerticalAlignment = VAlignment.Bottom
|
||||
}),
|
||||
(_noMagazineLabel = new Label
|
||||
{
|
||||
@@ -333,12 +236,25 @@ public sealed partial class GunSystem
|
||||
})
|
||||
}
|
||||
},
|
||||
new Control() { MinSize = new Vector2(5,0) },
|
||||
(_ammoCount = new Label
|
||||
new BoxContainer
|
||||
{
|
||||
StyleClasses = {StyleNano.StyleClassItemStatus},
|
||||
HorizontalAlignment = HAlignment.Right,
|
||||
}),
|
||||
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||
VerticalAlignment = VAlignment.Bottom,
|
||||
Margin = new Thickness(0, 0, 0, 2),
|
||||
Children =
|
||||
{
|
||||
(_ammoCount = new Label
|
||||
{
|
||||
StyleClasses = {StyleNano.StyleClassItemStatus},
|
||||
HorizontalAlignment = HAlignment.Right,
|
||||
}),
|
||||
(_chamberedBullet = new TextureRect
|
||||
{
|
||||
Texture = StaticIoC.ResC.GetTexture("/Textures/Interface/ItemStatus/Bullets/chambered.png"),
|
||||
HorizontalAlignment = HAlignment.Left,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -348,61 +264,24 @@ public sealed partial class GunSystem
|
||||
_chamberedBullet.ModulateSelfOverride =
|
||||
chambered ? Color.FromHex("#d7df60") : Color.Black;
|
||||
|
||||
_bulletsList.RemoveAllChildren();
|
||||
|
||||
if (!magazine)
|
||||
{
|
||||
_bulletRender.Visible = false;
|
||||
_noMagazineLabel.Visible = true;
|
||||
_ammoCount.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_bulletRender.Visible = true;
|
||||
_noMagazineLabel.Visible = false;
|
||||
_ammoCount.Visible = true;
|
||||
|
||||
var texturePath = "/Textures/Interface/ItemStatus/Bullets/normal.png";
|
||||
var texture = StaticIoC.ResC.GetTexture(texturePath);
|
||||
_bulletRender.Count = count;
|
||||
_bulletRender.Capacity = capacity;
|
||||
|
||||
_bulletRender.Type = capacity > 50 ? BulletRender.BulletType.Tiny : BulletRender.BulletType.Normal;
|
||||
|
||||
_ammoCount.Text = $"x{count:00}";
|
||||
capacity = Math.Min(capacity, 20);
|
||||
FillBulletRow(_bulletsList, count, capacity, texture);
|
||||
}
|
||||
|
||||
private static void FillBulletRow(Control container, int count, int capacity, Texture texture)
|
||||
{
|
||||
var colorA = Color.FromHex("#b68f0e");
|
||||
var colorB = Color.FromHex("#d7df60");
|
||||
var colorGoneA = Color.FromHex("#000000");
|
||||
var colorGoneB = Color.FromHex("#222222");
|
||||
|
||||
var altColor = false;
|
||||
|
||||
// Draw the empty ones
|
||||
for (var i = count; i < capacity; i++)
|
||||
{
|
||||
container.AddChild(new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
ModulateSelfOverride = altColor ? colorGoneA : colorGoneB,
|
||||
Stretch = TextureRect.StretchMode.KeepCentered
|
||||
});
|
||||
|
||||
altColor ^= true;
|
||||
}
|
||||
|
||||
// Draw the full ones, but limit the count to the capacity
|
||||
count = Math.Min(count, capacity);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
container.AddChild(new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
ModulateSelfOverride = altColor ? colorA : colorB,
|
||||
Stretch = TextureRect.StretchMode.KeepCentered
|
||||
});
|
||||
|
||||
altColor ^= true;
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayAlarmAnimation(Animation animation)
|
||||
|
||||
Reference in New Issue
Block a user