Armor HUD: vertical or horizontal layout

Adds an Alignment setting (default Vertical, so existing config is
unchanged). Vertical stacks each piece in a column (icon + percent
side by side); Horizontal lays pieces across, icon on top with the
percent centered underneath. Element bounds track the flow so drag,
snap and hover use the right footprint in both orientations.
This commit is contained in:
froslanz
2026-10-24 14:17:46 -04:00
parent a5622036f0
commit 53630c5ea3
@@ -19,6 +19,7 @@ public class ArmorHudModule extends HudModule {
private static final int CRITICAL = 0xFF5555;
public final Setting<Boolean> icons = bool("Icons", true);
public final Setting<Align> alignment = mode("Alignment", Align.VERTICAL);
public ArmorHudModule() {
super("Armor", "Display armor durability", 70, 40);
@@ -32,15 +33,17 @@ public class ArmorHudModule extends HudModule {
float x = getX();
float y = getY();
boolean showIcons = icons.getValue();
int rowHeight = showIcons ? 16 : FrosFont.lineHeight();
boolean horizontal = alignment.getValue() == Align.HORIZONTAL;
int slotSize = showIcons ? 16 : FrosFont.lineHeight();
int gap = showIcons ? 3 : 6;
int rows = 0;
int textWidth = 0;
int cross = 0;
int flow = 0;
for (EquipmentSlot slot : SLOTS) {
ItemStack stack = mc.player.getItemBySlot(slot);
if (stack.isEmpty()) continue;
float rowY = y + rows * rowHeight;
float ratio = durability(stack);
String percent = ratio < 0f ? "\u2014" : Math.round(ratio * 100) + "%";
int color = ratio < 0f ? -1
@@ -48,26 +51,61 @@ public class ArmorHudModule extends HudModule {
: ratio >= 0.3f ? WORN
: CRITICAL;
// origin of this slot along the flow (down or across) and cross axis
int slotX = (int) (horizontal ? x + flow : x);
int slotY = (int) (horizontal ? y : y + flow);
int textX;
int textY;
int size;
if (showIcons) {
e.getContext().renderItem(stack, (int) x, (int) rowY);
textX = (int) x + 19;
textY = (int) (rowY + 8 - FrosFont.visualCenter());
e.getContext().renderItem(stack, slotX, slotY);
if (horizontal) {
// icon on top, percent centered underneath it
textX = (int) (slotX + (slotSize - FrosFont.width(percent)) / 2f);
textY = (int) (slotY + slotSize + 1 - FrosFont.visualCenter());
size = Math.max(slotSize, FrosFont.width(percent));
} else {
textX = slotX + slotSize + 3;
textY = (int) (slotY + 8 - FrosFont.visualCenter());
size = textX - slotX + FrosFont.width(percent);
}
} else {
Component name = stack.getHoverName();
FrosFont.draw(e.getContext(), name, (int) x, (int) rowY, -1);
textX = (int) (x + FrosFont.width(name) + 4);
textY = (int) rowY;
FrosFont.draw(e.getContext(), name, slotX, slotY, -1);
int nameWidth = FrosFont.width(name);
if (horizontal) {
// name on top, percent centered underneath it
textX = (int) (slotX + (nameWidth - FrosFont.width(percent)) / 2f);
textY = slotY + FrosFont.lineHeight();
size = nameWidth;
} else {
textX = slotX + nameWidth + 4;
textY = slotY;
size = textX - slotX + FrosFont.width(percent);
}
}
FrosFont.draw(e.getContext(), percent, textX, textY, color);
textWidth = Math.max(textWidth, textX - (int) x + FrosFont.width(percent));
if (horizontal) {
flow += size + gap;
cross = Math.max(cross, slotSize + FrosFont.lineHeight());
} else {
flow += slotSize;
cross = Math.max(cross, size);
}
rows++;
}
if (rows > 0) {
setWidth(textWidth);
setHeight(rows * rowHeight);
if (horizontal) {
setWidth(Math.max(0, flow - gap));
setHeight(cross);
} else {
setWidth(cross);
setHeight(flow);
}
}
}
@@ -77,4 +115,9 @@ public class ArmorHudModule extends HudModule {
if (max <= 0) return -1f;
return (max - stack.getDamageValue()) / (float) max;
}
public enum Align {
VERTICAL,
HORIZONTAL
}
}