Skip to content

Commit f721758

Browse files
committed
Initial implementation
1 parent 6b7a109 commit f721758

1 file changed

Lines changed: 103 additions & 34 deletions

File tree

  • src/main/java/meteordevelopment/meteorclient/systems/hud/elements

src/main/java/meteordevelopment/meteorclient/systems/hud/elements/ArmorHud.java

Lines changed: 103 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
package meteordevelopment.meteorclient.systems.hud.elements;
77

8-
import meteordevelopment.meteorclient.renderer.text.TextRenderer;
98
import meteordevelopment.meteorclient.settings.*;
109
import meteordevelopment.meteorclient.systems.hud.Hud;
1110
import meteordevelopment.meteorclient.systems.hud.HudElement;
@@ -33,7 +32,7 @@ public class ArmorHud extends HudElement {
3332
.name("orientation")
3433
.description("How to display armor.")
3534
.defaultValue(Orientation.Horizontal)
36-
.onChanged(_ -> calculateSize())
35+
.onChanged(_ -> calculateSize(HudRenderer.INSTANCE))
3736
.build()
3837
);
3938

@@ -57,7 +56,7 @@ public class ArmorHud extends HudElement {
5756
.name("durability")
5857
.description("How to display armor durability.")
5958
.defaultValue(Durability.Bar)
60-
.onChanged(_ -> calculateSize())
59+
.onChanged(_ -> calculateSize(HudRenderer.INSTANCE))
6160
.build()
6261
);
6362

@@ -83,7 +82,7 @@ public class ArmorHud extends HudElement {
8382
.name("custom-scale")
8483
.description("Applies a custom scale to this hud element.")
8584
.defaultValue(false)
86-
.onChanged(_ -> calculateSize())
85+
.onChanged(_ -> calculateSize(HudRenderer.INSTANCE))
8786
.build()
8887
);
8988

@@ -92,7 +91,7 @@ public class ArmorHud extends HudElement {
9291
.description("Custom scale.")
9392
.visible(customScale::get)
9493
.defaultValue(2)
95-
.onChanged(_ -> calculateSize())
94+
.onChanged(_ -> calculateSize(HudRenderer.INSTANCE))
9695
.min(0.5)
9796
.sliderRange(0.5, 3)
9897
.build()
@@ -118,26 +117,94 @@ public class ArmorHud extends HudElement {
118117
public ArmorHud() {
119118
super(INFO);
120119

121-
calculateSize();
120+
calculateSize(HudRenderer.INSTANCE);
122121
}
123122

124-
private void calculateSize() {
125-
switch (orientation.get()) {
126-
// Four item stacks plus
127-
case Horizontal -> setSize((16 * 4 + 2 * 4) * getScale(), 16 * getScale());
128-
case Vertical -> setSize(16 * getScale(), (16 * 4 + 2 * 4) * getScale());
129-
}
123+
@Override
124+
public void tick(HudRenderer renderer) {
125+
calculateSize(renderer);
130126
}
131127

132-
@Override
133-
public void render(HudRenderer renderer) {
134-
int emptySlots = 0;
128+
private boolean showsDurabilityText() {
129+
return durability.get() == Durability.Total || durability.get() == Durability.Percentage;
130+
}
131+
132+
private double getIconSize() {
133+
return 16 * getScale();
134+
}
135135

136+
private double getPadding() {
137+
return 2 * getScale();
138+
}
139+
140+
// Durability text scale relative to the icon scale: 1x (normal HUD text scale) at the default
141+
// icon scale, growing/shrinking as the icon's custom scale changes. Uses a square root so the
142+
// text doesn't grow as aggressively as the icon does at the higher end of the scale slider.
143+
private double getTextScale() {
144+
return Math.sqrt(getScale() / scale.getDefaultValue().floatValue()) * Hud.get().getTextScale();
145+
}
146+
147+
// Spacing between items along the main layout axis: columns in Horizontal, rows in Vertical.
148+
// The durability text doesn't affect this since it's drawn on the cross axis (below in Horizontal,
149+
// to the right in Vertical), not between items.
150+
private double getItemStride() {
151+
return getIconSize() + getPadding();
152+
}
153+
154+
private ItemStack[] getArmorItems() {
136155
// default order is from boots to helmet
137-
ItemStack[] armor = flipOrder.get() ?
156+
return flipOrder.get() ?
138157
new ItemStack[]{getItem(EquipmentSlot.HEAD), getItem(EquipmentSlot.CHEST), getItem(EquipmentSlot.LEGS), getItem(EquipmentSlot.FEET)} :
139158
new ItemStack[]{getItem(EquipmentSlot.FEET), getItem(EquipmentSlot.LEGS), getItem(EquipmentSlot.CHEST), getItem(EquipmentSlot.HEAD)};
159+
}
160+
161+
private String getDurabilityText(ItemStack itemStack) {
162+
return switch (durability.get()) {
163+
case Total -> Integer.toString(itemStack.getMaxDamage() - itemStack.getDamageValue());
164+
case Percentage ->
165+
Integer.toString(Math.round(((itemStack.getMaxDamage() - itemStack.getDamageValue()) * 100f) / (float) itemStack.getMaxDamage()));
166+
default -> "";
167+
};
168+
}
140169

170+
// Widest durability text among the currently displayed items, used to size the Vertical orientation's width.
171+
private double getMaxDurabilityTextWidth(HudRenderer renderer) {
172+
double maxWidth = 0;
173+
174+
for (ItemStack stack : getArmorItems()) {
175+
if (!stack.isDamageableItem()) continue;
176+
maxWidth = Math.max(maxWidth, renderer.textWidth(getDurabilityText(stack), durabilityShadow.get(), getTextScale()));
177+
}
178+
179+
return maxWidth;
180+
}
181+
182+
private void calculateSize(HudRenderer renderer) {
183+
double iconSize = getIconSize();
184+
double stride = getItemStride();
185+
boolean showsText = showsDurabilityText();
186+
187+
switch (orientation.get()) {
188+
case Horizontal -> {
189+
// Text sits below each icon, so it grows the box's height.
190+
double height = iconSize;
191+
if (showsText) height += getPadding() + renderer.textHeight(durabilityShadow.get(), getTextScale());
192+
setSize(stride * 4, height);
193+
}
194+
case Vertical -> {
195+
// Text sits to the right of each icon, so it grows the box's width instead of its height.
196+
double width = iconSize;
197+
if (showsText) width += getPadding() + getMaxDurabilityTextWidth(renderer);
198+
setSize(width, stride * 4);
199+
}
200+
}
201+
}
202+
203+
@Override
204+
public void render(HudRenderer renderer) {
205+
ItemStack[] armor = getArmorItems();
206+
207+
int emptySlots = 0;
141208
for (ItemStack stack : armor) {
142209
if (stack.isEmpty()) emptySlots++;
143210
}
@@ -150,40 +217,42 @@ public void render(HudRenderer renderer) {
150217
double x = this.x;
151218
double y = this.y;
152219

220+
double iconSize = getIconSize();
221+
double padding = getPadding();
222+
double stride = getItemStride();
223+
boolean showsText = showsDurabilityText();
224+
boolean vertical = orientation.get() == Orientation.Vertical;
225+
153226
double armorX, armorY;
154227

155228
for (int position = 0; position < 4; position++) {
156229
ItemStack itemStack = armor[position];
157230

158-
if (orientation.get() == Orientation.Vertical) {
231+
if (vertical) {
159232
armorX = x;
160-
armorY = y + position * 18 * getScale();
233+
armorY = y + position * stride;
161234
} else {
162-
armorX = x + position * 18 * getScale();
235+
armorX = x + position * stride;
163236
armorY = y;
164237
}
165238

166239
renderer.item(itemStack, (int) armorX, (int) armorY, getScale(), (itemStack.isDamageableItem() && durability.get() == Durability.Bar));
167240

168-
if (itemStack.isDamageableItem() && durability.get() != Durability.Bar && durability.get() != Durability.None) {
169-
String message = switch (durability.get()) {
170-
case Total -> Integer.toString(itemStack.getMaxDamage() - itemStack.getDamageValue());
171-
case Percentage ->
172-
Integer.toString(Math.round(((itemStack.getMaxDamage() - itemStack.getDamageValue()) * 100f) / (float) itemStack.getMaxDamage()));
173-
default -> "err";
174-
};
175-
176-
double messageWidth = renderer.textWidth(message);
241+
if (itemStack.isDamageableItem() && showsText && durability.get() != Durability.Bar) {
242+
String message = getDurabilityText(itemStack);
243+
double messageWidth = renderer.textWidth(message, durabilityShadow.get(), getTextScale());
244+
double textHeight = renderer.textHeight(durabilityShadow.get(), getTextScale());
177245

178-
if (orientation.get() == Orientation.Vertical) {
179-
armorX = x + 8 * getScale() - messageWidth / 2.0;
180-
armorY = y + (18 * position * getScale()) + (18 * getScale() - renderer.textHeight());
246+
double textX, textY;
247+
if (vertical) {
248+
textX = armorX + iconSize + padding;
249+
textY = armorY + iconSize / 2.0 - textHeight / 2.0;
181250
} else {
182-
armorX = x + 18 * position * getScale() + 8 * getScale() - messageWidth / 2.0;
183-
armorY = y + (getHeight() - renderer.textHeight());
251+
textX = armorX + iconSize / 2.0 - messageWidth / 2.0;
252+
textY = armorY + iconSize + padding;
184253
}
185254

186-
TextRenderer.get().render(message, armorX, armorY, durabilityColor.get(), durabilityShadow.get());
255+
renderer.text(message, textX, textY, durabilityColor.get(), durabilityShadow.get(), getTextScale());
187256
}
188257
}
189258
});

0 commit comments

Comments
 (0)