Redesign cosmetics

CosmeticsMenu replaces the cloak and hat menus and stores: the player on
the left, turned by dragging, and on the right Cloaks and Hats tabs over a
grid of every cosmetic. Clicking an owned one equips it, and clicking one
not owned yet claims it, which is free. The equipped one is outlined and
badged, and the grid asks to connect when there's no Saturn session.

SkinPreview is now a drag-to-rotate player view, and its EntityDrawer draws
the player filling a box at a given yaw, returning false when there's no
player. CosmeticPreview and TabMenu go with the old screens.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-09-27 17:33:25 +02:00
co-authored by claude
parent a413648be9
commit 7264c7b38b
12 changed files with 412 additions and 568 deletions
@@ -1,63 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.Utils;
public class TabMenu extends Element {
public static class TabMenuComponent {
Runnable onClick;
IdentifierRef sprite;
public TabMenuComponent(IdentifierRef sprite, Runnable onClick) {
this.onClick = onClick;
this.sprite = sprite;
}
}
TabMenuComponent[] components;
public int selectedScreen = 0;
public TabMenu(int active, TabMenuComponent... components) {
this.components = components;
width = 25 * components.length + 6;
height = 30;
this.selectedScreen = active;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Theme.PRIMARY.value);
int col = 0;
for (TabMenuComponent component : components) {
int x = 25 * col + 5;
boolean hovering = ctx.isHovering(x, 5, 20, 20) || selectedScreen == col;
if (hovering) {
renderScope.drawRoundedRectangle(x, 5, 20, 20, Theme.WIDGET_RADIUS.value, Theme.ACCENT.value);
}
renderScope.drawTexture(component.sprite, x + 5, 10, 0, 0, 10, 10,
hovering ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
col++;
}
}
@Override
public void click(int mouseX, int mouseY) {
int col = 0;
for (TabMenuComponent component : components) {
int x = 25 * col + 5;
if (Utils.isHovering(mouseX - x, mouseY - 5, 20, 20, 1.0f)) {
component.onClick.run();
}
col++;
}
}
}