Files
common/src/main/java/org/saturnclient/ui/screens/TitleMenu.java
T
selimaj-devandclaude c973e053aa Open Saturn's settings from the title dock and put Saturn first
The Saturn logo in the title screen's dock now opens Saturn's settings instead of the shift menu,
and it comes first: Saturn, mods, cosmetics, then Minecraft's options last. The shift menu is still
on its key in game.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:34:24 +02:00

154 lines
6.9 KiB
Java

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.property.FloatProperty;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.SaturnScreen;
import org.saturnclient.ui.anim.Animation;
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.IconButton;
import org.saturnclient.ui.elements.ImageTexture;
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, the
* player and a quit button in the top corners, and along the bottom a dock
* (Saturn's settings, its mods and cosmetics, then Minecraft's options) and the version.
*/
public class TitleMenu extends SaturnScreen {
// The logo and wordmark as the shift menu has them: the wordmark over the logo's foot
private static final int LOGO = 98;
private static final int WORDMARK_WIDTH = 98;
private static final int WORDMARK_HEIGHT = 10;
private static final int WORDMARK_Y = 88;
/** From the logo's foot to the menus, close so they read as one block */
private static final int MENUS_GAP = 14;
private static final int COLUMN_WIDTH = 280;
private static final int BUTTON_HEIGHT = 36;
private static final int GAP = 8;
/** Space around the account chip, quit button, dock and version, from the screen's edges */
private static final int EDGE = 14;
/** The top corners sit a little tighter */
private static final int TOP_EDGE = 10;
/** As tall as the account chip beside it */
private static final int QUIT_SIZE = AccountChip.HEIGHT;
// The intro comes in in reading order, left to right and top to bottom, one step apart
private static final int STEP_ACCOUNT = 0;
private static final int STEP_QUIT = 1;
private static final int STEP_LOGO = 2;
private static final int STEP_MENUS = 3;
/** After the two menus */
private static final int STEP_VERSION = 5;
private static final int STEP_DOCK = 6;
private static final float VERSION_SCALE = 0.5f;
private static final float VERSION_ALPHA = 0.6f;
public TitleMenu() {
super("Title Menu");
}
@Override
protected FloatProperty getScaleSetting() {
return Config.titleScale;
}
@Override
public void ui() {
blurBackground = false;
// Logo and menus, centered together a little above the middle
int menusHeight = BUTTON_HEIGHT * 2 + GAP;
int blockHeight = LOGO + MENUS_GAP + menusHeight;
int top = (height - blockHeight) / 2 - 20;
draw(new ImageTexture(Config.getLogo())
.dimensions(LOGO, LOGO)
.position((width - LOGO) / 2, top)
.animation(step(new SlideY(AnimationConfig.logo, -20), STEP_LOGO)));
draw(new ImageTexture(Textures.LOGO_TEXT)
.dimensions(WORDMARK_WIDTH, WORDMARK_HEIGHT)
.position((width - WORDMARK_WIDTH) / 2, top + WORDMARK_Y)
.animation(step(new Fade(AnimationConfig.logo.duration.value), STEP_LOGO)));
AnimationStagger menus = new AnimationStagger(AnimationConfig.mainMenu)
.after(stepDelay(STEP_MENUS));
addMenuButton(menus, new Button("Singleplayer",
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.SelectWorld))
.dimensions(COLUMN_WIDTH, BUTTON_HEIGHT).position(0, 0));
addMenuButton(menus, new Button("Multiplayer",
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.Multiplayer))
.dimensions(COLUMN_WIDTH, BUTTON_HEIGHT).position(0, BUTTON_HEIGHT + GAP));
draw(menus.position((width - COLUMN_WIDTH) / 2, top + LOGO + MENUS_GAP));
// Top corners: the player, and quitting the game
draw(new AccountChip()
.position(TOP_EDGE, TOP_EDGE)
.animation(step(new SlideFade(AnimationConfig.mainMenu, 8), STEP_ACCOUNT)));
draw(new IconButton(Textures.ICON_CLOSE, () -> Providers.saturn.getClient().scheduleStop())
.dimensions(QUIT_SIZE, QUIT_SIZE)
.position(width - TOP_EDGE - QUIT_SIZE, TOP_EDGE)
.animation(step(new SlideFade(AnimationConfig.mainMenu, 8), STEP_QUIT)));
// Along the bottom: the dock, Saturn first (its settings) and Minecraft's options last, and the version
Dock dock = new Dock(List.of(
new Dock.Item(Textures.LOGO, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
new Dock.Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
new Dock.Item(Textures.ICON_COSMETICS,
() -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())),
new Dock.Item(Textures.ICON_SETTINGS,
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.Options))));
draw(dock.position((width - dock.width) / 2, height - EDGE - Dock.HEIGHT)
.animation(step(new SlideFade(AnimationConfig.mainMenu, -12), STEP_DOCK)));
String version = getVersionText();
int versionHeight = (int) (Fonts.getHeight() * VERSION_SCALE);
draw(new Label(() -> version, VERSION_SCALE, Theme::getBodyFont,
() -> Theme.withAlpha(VERSION_ALPHA, Theme.getMutedFg()))
.position(EDGE, height - EDGE - versionHeight)
.animation(step(new Fade(AnimationConfig.mainMenu), STEP_VERSION)));
}
/**
* When the intro's {@code step} starts, in ms: the Main Menu stagger apart,
* or all at once when staggering is off.
*/
private static int stepDelay(int step) {
return Config.stagger.value ? step * AnimationConfig.mainMenu.stagger.value : 0;
}
private static Animation step(Animation animation, int step) {
animation.delay = stepDelay(step);
return animation;
}
/**
* "Saturn 0.1.0 · 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 " + version[0];
return version.length > 1 ? text + " · " + version[1] : text;
}
private static void addMenuButton(AnimationStagger stagger, Element button) {
stagger.draw(button.animation(new SlideFade(AnimationConfig.mainMenu, -10)));
}
}