From 2f4ea77e6f29d1feb2a33560cee21cdca92ae938 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 27 Sep 2026 19:01:42 +0200 Subject: [PATCH] Restyle buttons, the Shift menu and the title screen Button is now primary (accent fill) or secondary (a translucent outlined surface), and IconButton is a square secondary button with a Lucide icon, replacing the PNG TextureButtons. Neither is scaled with Element.scale any more, which multiplied click positions instead of dividing them. The Shift menu is the HUD editor, the mod menu (its button was labelled "Settings") and cosmetics. The title screen centers the logo over a compact stack of the game's menus, with the player, a dock of Saturn's screens and the version along the bottom. The player chip shows the player's face from their skin and whether they're connected to Saturn. Co-Authored-By: Claude Opus 5.5 --- .../common/provider/SaturnProvider.java | 6 + .../ui/components/AccountChip.java | 54 ++++++++ .../org/saturnclient/ui/components/Dock.java | 85 +++++++++++++ .../org/saturnclient/ui/elements/Button.java | 46 +++++-- .../saturnclient/ui/elements/IconButton.java | 40 ++++++ .../saturnclient/ui/screens/ShiftMenu.java | 46 ++++--- .../saturnclient/ui/screens/TitleMenu.java | 119 ++++++++++++------ 7 files changed, 323 insertions(+), 73 deletions(-) create mode 100644 src/main/java/org/saturnclient/ui/components/AccountChip.java create mode 100644 src/main/java/org/saturnclient/ui/components/Dock.java create mode 100644 src/main/java/org/saturnclient/ui/elements/IconButton.java diff --git a/src/main/java/org/saturnclient/common/provider/SaturnProvider.java b/src/main/java/org/saturnclient/common/provider/SaturnProvider.java index 5efbf2e..4d63eec 100644 --- a/src/main/java/org/saturnclient/common/provider/SaturnProvider.java +++ b/src/main/java/org/saturnclient/common/provider/SaturnProvider.java @@ -22,6 +22,12 @@ public interface SaturnProvider { /** The Saturn Client mod version, e.g. {@code 0.1.0-beta3+1.21.11}. */ public String getModVersion(); + /** + * The signed-in player's 64x64 skin texture, or the default skin until + * theirs has loaded. + */ + public IdentifierRef getPlayerSkin(); + /** Shows a warning toast. Safe to call from any thread. */ public void showWarning(String title, String message); } diff --git a/src/main/java/org/saturnclient/ui/components/AccountChip.java b/src/main/java/org/saturnclient/ui/components/AccountChip.java new file mode 100644 index 0000000..554f9c6 --- /dev/null +++ b/src/main/java/org/saturnclient/ui/components/AccountChip.java @@ -0,0 +1,54 @@ +package org.saturnclient.ui.components; + +import org.saturnclient.client.ServiceClient; +import org.saturnclient.common.provider.Providers; +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.elements.Field; +import org.saturnclient.ui.resources.Fonts; + +/** + * The signed-in player: their skin's face, their name, and a dot that's green + * while connected to Saturn. + */ +public class AccountChip extends Element { + public static final int HEIGHT = 40; + + private static final int HEAD = 28; + private static final int PADDING = 6; + private static final int DOT = 7; + private static final float NAME_SCALE = 0.7f; + private static final int CONNECTED = 0xFF7FD1A8; + + private final String name; + + public AccountChip() { + String username = Providers.saturn.getClient().getUsername(); + this.name = username != null ? username : "Player"; + this.height = HEIGHT; + this.width = PADDING + HEAD + 10 + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + 10 + DOT + 12; + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1, Theme.getPanelBg(), + Theme.getBorder()); + + // The face, then the hat layer over it, from the 64x64 skin + IdentifierRef skin = Providers.saturn.getPlayerSkin(); + int headY = (height - HEAD) / 2; + renderScope.drawTexture(skin, PADDING, headY, 8, 8, HEAD, HEAD, 8, 8, 64, 64); + renderScope.drawTexture(skin, PADDING, headY, 40, 8, HEAD, HEAD, 8, 8, 64, 64); + + int nameX = PADDING + HEAD + 10; + renderScope.drawText(NAME_SCALE, name, nameX, Field.textY(height, NAME_SCALE), Theme.FONT.value, + Theme.FOREGROUND.value); + + int dotX = nameX + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + 10; + renderScope.drawRoundedRectangle(dotX, (height - DOT) / 2, DOT, DOT, DOT / 2, + ServiceClient.isConnected() ? CONNECTED : Theme.withAlpha(0.3f, Theme.FOREGROUND.value)); + } +} diff --git a/src/main/java/org/saturnclient/ui/components/Dock.java b/src/main/java/org/saturnclient/ui/components/Dock.java new file mode 100644 index 0000000..7f6d881 --- /dev/null +++ b/src/main/java/org/saturnclient/ui/components/Dock.java @@ -0,0 +1,85 @@ +package org.saturnclient.ui.components; + +import java.util.List; + +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.elements.Field; +import org.saturnclient.ui.resources.Fonts; + +/** + * A glass bar of buttons, each an icon with its label. + */ +public class Dock extends Element { + public record Item(IdentifierRef icon, String label, Runnable onClick) { + } + + public static final int HEIGHT = 52; + + private static final int PADDING = 6; + private static final int ITEM_HEIGHT = HEIGHT - PADDING * 2; + private static final int ITEM_PADDING = 14; + private static final int ICON = 17; + private static final int ICON_GAP = 8; + private static final int GAP = 4; + private static final float TEXT_SCALE = 0.7f; + + private final List items; + + public Dock(List items) { + this.items = items; + this.height = HEIGHT; + this.width = getItemX(items.size()) - GAP + PADDING; + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value + 4, 1, Theme.getPanelBg(), + Theme.withAlpha(0.1f, Theme.FOREGROUND.value)); + + for (int i = 0; i < items.size(); i++) { + Item item = items.get(i); + int x = getItemX(i); + int itemWidth = getItemWidth(item); + boolean hovered = ctx.isHovering(x, PADDING, itemWidth, ITEM_HEIGHT); + + if (hovered) { + renderScope.drawRoundedRectangle(x, PADDING, itemWidth, ITEM_HEIGHT, Theme.WIDGET_RADIUS.value, + Theme.withAlpha(0.08f, Theme.FOREGROUND.value)); + } + + int color = hovered ? Theme.ACCENT.value : Theme.PRIMARY_FG.value; + renderScope.drawTexture(item.icon(), x + ITEM_PADDING, PADDING + (ITEM_HEIGHT - ICON) / 2, 0, 0, ICON, + ICON, color); + renderScope.drawText(TEXT_SCALE, item.label(), x + ITEM_PADDING + ICON + ICON_GAP, + PADDING + Field.textY(ITEM_HEIGHT, TEXT_SCALE), Theme.FONT.value, + hovered ? Theme.FOREGROUND.value : Theme.PRIMARY_FG.value); + } + } + + @Override + public void click(int mouseX, int mouseY) { + for (int i = 0; i < items.size(); i++) { + int x = getItemX(i); + if (mouseX >= x && mouseX <= x + getItemWidth(items.get(i))) { + items.get(i).onClick().run(); + return; + } + } + } + + private int getItemX(int index) { + int x = PADDING; + for (int i = 0; i < index; i++) { + x += getItemWidth(items.get(i)) + GAP; + } + return x; + } + + private static int getItemWidth(Item item) { + return ITEM_PADDING * 2 + ICON + ICON_GAP + (int) (Fonts.getWidth(item.label(), Theme.FONT.value) * TEXT_SCALE); + } +} diff --git a/src/main/java/org/saturnclient/ui/elements/Button.java b/src/main/java/org/saturnclient/ui/elements/Button.java index 3c0d5ed..714514e 100644 --- a/src/main/java/org/saturnclient/ui/elements/Button.java +++ b/src/main/java/org/saturnclient/ui/elements/Button.java @@ -6,24 +6,52 @@ import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.resources.Fonts; +/** + * A text button: primary (filled with the accent color) for the main action, + * or secondary (a translucent, outlined surface) for the rest. + */ public class Button extends Element { - private String text; - private Runnable onClick; + public static final int HEIGHT = 40; - public Button(String text, Runnable onClick) { + private static final float TEXT_SCALE = 0.72f; + + private final String text; + private final boolean primary; + private final Runnable onClick; + + public Button(String text, boolean primary, Runnable onClick) { this.text = text; + this.primary = primary; this.onClick = onClick; - this.dimensions(Fonts.getWidth(text, Theme.FONT.value) + 50, 38); + this.width = (int) (Fonts.getWidth(text, Theme.FONT.value) * TEXT_SCALE) + 48; + this.height = HEIGHT; } @Override public void render(RenderScope renderScope, ElementContext ctx) { - renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, - ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value); + boolean hovered = ctx.isHovering(); + drawSurface(renderScope, width, height, primary, hovered); - renderScope.drawText(text, Fonts.centerX(width, text, Theme.FONT.value), Fonts.centerY(height), - Theme.FONT.value, - ctx.isHovering() ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value); + int textX = (width - (int) (Fonts.getWidth(text, Theme.FONT.value) * TEXT_SCALE)) / 2; + renderScope.drawText(TEXT_SCALE, text, textX, Field.textY(height, TEXT_SCALE), Theme.FONT.value, + primary ? Theme.ACCENT_FG.value : hovered ? Theme.FOREGROUND.value : Theme.PRIMARY_FG.value); + } + + /** + * The button's surface, shared with {@link IconButton}. + */ + static void drawSurface(RenderScope renderScope, int width, int height, boolean primary, boolean hovered) { + if (primary) { + // Lighten the accent on hover by laying white over it + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Theme.ACCENT.value); + if (hovered) { + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 0x26FFFFFF); + } + } else { + renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1, + hovered ? Theme.withAlpha(0.9f, Theme.PRIMARY.value) : Theme.getPanelBg(), + Theme.withAlpha(hovered ? 0.25f : 0.1f, Theme.FOREGROUND.value)); + } } @Override diff --git a/src/main/java/org/saturnclient/ui/elements/IconButton.java b/src/main/java/org/saturnclient/ui/elements/IconButton.java new file mode 100644 index 0000000..764d297 --- /dev/null +++ b/src/main/java/org/saturnclient/ui/elements/IconButton.java @@ -0,0 +1,40 @@ +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; + +/** + * A square secondary {@link Button} showing an icon, which turns the accent + * color on hover. + */ +public class IconButton extends Element { + private static final float ICON_RATIO = 0.48f; + + private final IdentifierRef icon; + private final Runnable onClick; + + public IconButton(IdentifierRef icon, Runnable onClick) { + this.icon = icon; + this.onClick = onClick; + this.width = Button.HEIGHT; + this.height = Button.HEIGHT; + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + boolean hovered = ctx.isHovering(); + Button.drawSurface(renderScope, width, height, false, hovered); + + int size = (int) (Math.min(width, height) * ICON_RATIO); + renderScope.drawTexture(icon, (width - size) / 2, (height - size) / 2, 0, 0, size, size, + hovered ? Theme.ACCENT.value : Theme.PRIMARY_FG.value); + } + + @Override + public void click(int mouseX, int mouseY) { + onClick.run(); + } +} diff --git a/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java b/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java index 2915e68..6b1770b 100644 --- a/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java +++ b/src/main/java/org/saturnclient/ui/screens/ShiftMenu.java @@ -8,18 +8,24 @@ import org.saturnclient.ui.anim.Fade; import org.saturnclient.ui.anim.SlideY; import org.saturnclient.ui.elements.AnimationStagger; import org.saturnclient.ui.elements.Button; +import org.saturnclient.ui.elements.IconButton; import org.saturnclient.ui.elements.ImageTexture; -import org.saturnclient.ui.elements.TextureButton; import org.saturnclient.ui.resources.Textures; +/** + * The in-game quick menu: the logo over the HUD editor, mod menu and + * cosmetics. + */ public class ShiftMenu extends SaturnScreen { + private static final int MODS_WIDTH = 120; + private static final int GAP = 6; + public ShiftMenu() { super("Shift Menu"); } @Override public void ui() { - // Logo animations (unchanged) draw(new ImageTexture(Textures.LOGO_TEXT) .dimensions(98, 10) .center(width, height, 0, -36) @@ -30,32 +36,24 @@ public class ShiftMenu extends SaturnScreen { .center(width, height, 0, -80) .animation(new SlideY(AnimationConfig.logo, -20))); - // Spacing and sizes - int btnWidth = 120; - int btnHeight = 40; - int spacing = 4; - - // Create stagger - AnimationStagger stagger = new AnimationStagger(AnimationConfig.shiftMenu.stagger.value); + int x = 0; - stagger.draw(new TextureButton(Textures.HUD_ICON, () -> { - Providers.saturn.getClient().setScreen(new HudEditor()); - }).dimensions(btnHeight, btnHeight).position(0, 0) - .animation(new Fade(AnimationConfig.shiftMenu))); + stagger.draw(new IconButton(Textures.ICON_HUD_EDITOR, + () -> Providers.saturn.getClient().setScreen(new HudEditor())) + .position(x, 0).animation(new Fade(AnimationConfig.shiftMenu))); + x += Button.HEIGHT + GAP; - stagger.draw(new Button("Settings", () -> { - Providers.saturn.getClient().setScreen(new ModMenu()); - }).dimensions(btnWidth, btnHeight).position(btnHeight + spacing, 0) - .animation(new Fade(AnimationConfig.shiftMenu))); + stagger.draw(new Button("Mods", true, () -> Providers.saturn.getClient().setScreen(new ModMenu())) + .dimensions(MODS_WIDTH, Button.HEIGHT) + .position(x, 0).animation(new Fade(AnimationConfig.shiftMenu))); + x += MODS_WIDTH + GAP; - stagger.draw(new TextureButton(Textures.COSMETICS, () -> { - Providers.saturn.getClient().setScreen(new CosmeticsMenu()); - }).dimensions(btnHeight, btnHeight).position(btnWidth + btnHeight + (spacing * 2), 0) - .animation(new Fade(AnimationConfig.shiftMenu))); + stagger.draw(new IconButton(Textures.ICON_COSMETICS, + () -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())) + .position(x, 0).animation(new Fade(AnimationConfig.shiftMenu))); + x += Button.HEIGHT; - // Draw the stagger at the absolute center of the screen - draw(stagger.dimensions(btnWidth + (btnHeight * 2) + (spacing * 2), btnHeight).center(width, height, 0, - 0)); + draw(stagger.position((width - x) / 2, (height - Button.HEIGHT) / 2)); } } diff --git a/src/main/java/org/saturnclient/ui/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui/screens/TitleMenu.java index d134334..781a007 100644 --- a/src/main/java/org/saturnclient/ui/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui/screens/TitleMenu.java @@ -1,21 +1,40 @@ package org.saturnclient.ui.screens; +import java.util.List; + import org.saturnclient.common.provider.Providers; import org.saturnclient.common.ref.game.MinecraftClientRef.MinecraftScreen; import org.saturnclient.config.AnimationConfig; import org.saturnclient.config.Config; +import org.saturnclient.config.Theme; +import org.saturnclient.ui.Element; import org.saturnclient.ui.SaturnScreen; import org.saturnclient.ui.anim.Fade; import org.saturnclient.ui.anim.SlideFade; import org.saturnclient.ui.anim.SlideY; +import org.saturnclient.ui.components.AccountChip; +import org.saturnclient.ui.components.Dock; import org.saturnclient.ui.elements.AnimationStagger; import org.saturnclient.ui.elements.Button; import org.saturnclient.ui.elements.ImageTexture; -import org.saturnclient.ui.elements.TextureButton; +import org.saturnclient.ui.elements.Label; import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Textures; +/** + * Saturn's title screen: the logo over the game's menus in the middle, and + * along the bottom the player, a dock of Saturn's screens and the version. + */ public class TitleMenu extends SaturnScreen { + private static final int LOGO = 88; + private static final int WORDMARK_WIDTH = 200; + private static final int WORDMARK_HEIGHT = 20; + private static final int COLUMN_WIDTH = 280; + private static final int BUTTON_HEIGHT = 36; + private static final int GAP = 8; + private static final int EDGE = 28; + private static final float VERSION_SCALE = 0.62f; + public TitleMenu() { super("Title Menu"); } @@ -24,53 +43,73 @@ public class TitleMenu extends SaturnScreen { public void ui() { blurBackground = false; - draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).center(width, height, 0, -40) - .animation(new Fade(AnimationConfig.logo.duration.value))); - draw(new ImageTexture(Config.getLogo()).dimensions(98, 98).center(width, height, 0, -84) + // Logo and menus, centered together a little above the middle + int menusHeight = BUTTON_HEIGHT * 3 + GAP * 2; + int blockHeight = LOGO + 16 + WORDMARK_HEIGHT + 36 + menusHeight; + int top = (height - blockHeight) / 2 - 20; + + draw(new ImageTexture(Config.getLogo()) + .dimensions(LOGO, LOGO) + .position((width - LOGO) / 2, top) .animation(new SlideY(AnimationConfig.logo, -20))); + draw(new ImageTexture(Textures.LOGO_TEXT_BIG) + .dimensions(WORDMARK_WIDTH, WORDMARK_HEIGHT) + .position((width - WORDMARK_WIDTH) / 2, top + LOGO + 16) + .animation(new Fade(AnimationConfig.logo.duration.value))); - AnimationStagger mainButtonStagger = new AnimationStagger(AnimationConfig.mainMenu); + int rowHeight = BUTTON_HEIGHT + GAP; + int halfWidth = (COLUMN_WIDTH - GAP) / 2; + AnimationStagger menus = new AnimationStagger(AnimationConfig.mainMenu); - mainButtonStagger.draw(new Button("SINGLEPLAYER", () -> { - Providers.saturn.getClient().setScreen(MinecraftScreen.SelectWorld); - }).scale(0.69f).dimensions(420, 52).position(0, 0) - .animation(new SlideFade(AnimationConfig.mainMenu, -10))); + addMenuButton(menus, new Button("Singleplayer", true, + () -> Providers.saturn.getClient().setScreen(MinecraftScreen.SelectWorld)) + .dimensions(COLUMN_WIDTH, BUTTON_HEIGHT).position(0, 0)); + addMenuButton(menus, new Button("Multiplayer", false, + () -> Providers.saturn.getClient().setScreen(MinecraftScreen.Multiplayer)) + .dimensions(COLUMN_WIDTH, BUTTON_HEIGHT).position(0, rowHeight)); + addMenuButton(menus, new Button("Options", false, + () -> Providers.saturn.getClient().setScreen(MinecraftScreen.Options)) + .dimensions(halfWidth, BUTTON_HEIGHT).position(0, rowHeight * 2)); + addMenuButton(menus, new Button("Quit", false, + () -> Providers.saturn.getClient().scheduleStop()) + .dimensions(halfWidth, BUTTON_HEIGHT).position(COLUMN_WIDTH - halfWidth, rowHeight * 2)); - mainButtonStagger.draw(new Button("MULTIPLAYER", () -> { - Providers.saturn.getClient().setScreen(MinecraftScreen.Multiplayer); - }).scale(0.69f).dimensions(420, 52).position(0, 40) - .animation(new SlideFade(AnimationConfig.mainMenu, -10))); + draw(menus.position((width - COLUMN_WIDTH) / 2, top + LOGO + 16 + WORDMARK_HEIGHT + 36)); - mainButtonStagger.draw(new Button("OPTIONS", () -> { - Providers.saturn.getClient().setScreen(MinecraftScreen.Options); - }).scale(0.69f).dimensions(206, 52).position(0, 80) - .animation(new SlideFade(AnimationConfig.mainMenu, -10))); + // Along the bottom: the player, Saturn's screens, the version + draw(new AccountChip() + .position(EDGE, height - EDGE - AccountChip.HEIGHT) + .animation(new Fade(AnimationConfig.mainMenu))); - mainButtonStagger.draw(new Button("QUIT", () -> { - Providers.saturn.getClient().scheduleStop(); - }).scale(0.69f).dimensions(206, 52).position(146, 80) - .animation(new SlideFade(AnimationConfig.mainMenu, -10))); + Dock dock = new Dock(List.of( + new Dock.Item(Textures.ICON_MODS, "Mods", + () -> Providers.saturn.getClient().setScreen(new ModMenu())), + new Dock.Item(Textures.ICON_COSMETICS, "Cosmetics", + () -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())), + new Dock.Item(Textures.ICON_HUD_EDITOR, "HUD editor", + () -> Providers.saturn.getClient().setScreen(new HudEditor())))); + draw(dock.position((width - dock.width) / 2, height - EDGE - Dock.HEIGHT) + .animation(new SlideFade(AnimationConfig.mainMenu, 12))); - draw(mainButtonStagger.dimensions(289, 143).center(width, height, 0, 50)); + String version = getVersionText(); + int versionWidth = (int) (Fonts.getWidth(version, Theme.getBodyFont()) * VERSION_SCALE); + int versionHeight = (int) (Fonts.getHeight() * VERSION_SCALE); + draw(new Label(() -> version, VERSION_SCALE, Theme::getBodyFont, Theme::getMutedFg) + .position(width - EDGE - versionWidth, height - EDGE - (AccountChip.HEIGHT + versionHeight) / 2) + .animation(new Fade(AnimationConfig.mainMenu))); + } - int s = Fonts.getHeight() + 20; + /** + * "Saturn Client 0.1.0 · Minecraft 1.21.11", from the mod version + * "0.1.0+1.21.11". + */ + private static String getVersionText() { + String[] version = Providers.saturn.getModVersion().split("\\+", 2); + String text = "Saturn Client " + version[0]; + return version.length > 1 ? text + " · Minecraft " + version[1] : text; + } - AnimationStagger saturnStagger = new AnimationStagger(AnimationConfig.mainMenu.stagger.value); - - saturnStagger.draw(new TextureButton(Textures.HUD_ICON, () -> { - Providers.saturn.getClient().setScreen(new HudEditor()); - }).dimensions(s, s).position(0, 0).animation(new SlideFade(AnimationConfig.mainMenu, s + 8))); - - saturnStagger.draw(new TextureButton(Textures.SETTINGS, () -> { - Providers.saturn.getClient().setScreen(new ModMenu()); - }).dimensions(s, s).position(s + 2, 0) - .animation(new SlideFade(AnimationConfig.mainMenu, s + 8))); - - saturnStagger.draw(new TextureButton(Textures.CLOAK, () -> { - Providers.saturn.getClient().setScreen(new CosmeticsMenu()); - }).dimensions(s, s).position((s + 2) * 2, 0) - .animation(new SlideFade(AnimationConfig.mainMenu, s + 8))); - - draw(saturnStagger.dimensions(((s + 2) * 2) + s, s).centerHorizontal(width, height, 0, 8)); + private static void addMenuButton(AnimationStagger stagger, Element button) { + stagger.draw(button.animation(new SlideFade(AnimationConfig.mainMenu, -10))); } }