Add GUI scale and glass, and rework the title screen #8

Merged
selimaj-dev merged 10 commits from glass-blur into master 2026-09-28 20:01:19 +00:00
2 changed files with 45 additions and 27 deletions
Showing only changes of commit adedd688a7 - Show all commits
@@ -15,12 +15,13 @@ import org.saturnclient.ui.resources.Fonts;
* while connected to Saturn. * while connected to Saturn.
*/ */
public class AccountChip extends Element { public class AccountChip extends Element {
public static final int HEIGHT = 40; public static final int HEIGHT = 32;
private static final int HEAD = 28; private static final int HEAD = 18;
private static final int PADDING = 6; private static final int PADDING = 7;
private static final int DOT = 7; private static final int GAP = 8;
private static final float NAME_SCALE = 0.7f; private static final int DOT = 6;
private static final float NAME_SCALE = 0.55f;
private static final int CONNECTED = 0xFF7FD1A8; private static final int CONNECTED = 0xFF7FD1A8;
private final String name; private final String name;
@@ -29,7 +30,8 @@ public class AccountChip extends Element {
String username = Providers.saturn.getClient().getUsername(); String username = Providers.saturn.getClient().getUsername();
this.name = username != null ? username : "Player"; this.name = username != null ? username : "Player";
this.height = HEIGHT; this.height = HEIGHT;
this.width = PADDING + HEAD + 10 + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + 10 + DOT + 12; this.width = PADDING + HEAD + GAP + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + GAP + DOT
+ GAP + 2;
} }
@Override @Override
@@ -43,11 +45,11 @@ public class AccountChip extends Element {
renderScope.drawTexture(skin, PADDING, headY, 8, 8, HEAD, HEAD, 8, 8, 64, 64); 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); renderScope.drawTexture(skin, PADDING, headY, 40, 8, HEAD, HEAD, 8, 8, 64, 64);
int nameX = PADDING + HEAD + 10; int nameX = PADDING + HEAD + GAP;
renderScope.drawText(NAME_SCALE, name, nameX, Field.textY(height, NAME_SCALE), Theme.FONT.value, renderScope.drawText(NAME_SCALE, name, nameX, Field.textY(height, NAME_SCALE), Theme.FONT.value,
Theme.FOREGROUND.value); Theme.FOREGROUND.value);
int dotX = nameX + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + 10; int dotX = nameX + (int) (Fonts.getWidth(name, Theme.FONT.value) * NAME_SCALE) + GAP;
renderScope.drawRoundedRectangle(dotX, (height - DOT) / 2, DOT, DOT, DOT / 2, renderScope.drawRoundedRectangle(dotX, (height - DOT) / 2, DOT, DOT, DOT / 2,
ServiceClient.isConnected() ? CONNECTED : Theme.withAlpha(0.3f, Theme.FOREGROUND.value)); ServiceClient.isConnected() ? CONNECTED : Theme.withAlpha(0.3f, Theme.FOREGROUND.value));
} }
@@ -27,7 +27,7 @@ import org.saturnclient.ui.resources.Textures;
/** /**
* Saturn's title screen: the logo over the game's menus in the middle, the * 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 of * player and a quit button in the top corners, and along the bottom a dock of
* Saturn's screens and Minecraft's options, and the version. * Saturn's screens, the shift menu and Minecraft's options, and the version.
*/ */
public class TitleMenu extends SaturnScreen { public class TitleMenu extends SaturnScreen {
// The logo and wordmark as the shift menu has them: the wordmark over the logo's foot // The logo and wordmark as the shift menu has them: the wordmark over the logo's foot
@@ -42,12 +42,19 @@ public class TitleMenu extends SaturnScreen {
private static final int GAP = 8; private static final int GAP = 8;
/** Space around the account chip, quit button, dock and version, from the screen's edges */ /** Space around the account chip, quit button, dock and version, from the screen's edges */
private static final int EDGE = 14; private static final int EDGE = 14;
private static final int QUIT_SIZE = 32; /** 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, in ms: the logo, then the menus, then what's around the edges // The intro comes in in reading order, left to right and top to bottom, one step apart
private static final int MENUS_DELAY = 250; private static final int STEP_ACCOUNT = 0;
private static final int EDGES_DELAY = 450; private static final int STEP_QUIT = 1;
private static final int EDGES_STAGGER = 60; 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_SCALE = 0.5f;
private static final float VERSION_ALPHA = 0.6f; private static final float VERSION_ALPHA = 0.6f;
@@ -72,13 +79,14 @@ public class TitleMenu extends SaturnScreen {
draw(new ImageTexture(Config.getLogo()) draw(new ImageTexture(Config.getLogo())
.dimensions(LOGO, LOGO) .dimensions(LOGO, LOGO)
.position((width - LOGO) / 2, top) .position((width - LOGO) / 2, top)
.animation(new SlideY(AnimationConfig.logo, -20))); .animation(step(new SlideY(AnimationConfig.logo, -20), STEP_LOGO)));
draw(new ImageTexture(Textures.LOGO_TEXT) draw(new ImageTexture(Textures.LOGO_TEXT)
.dimensions(WORDMARK_WIDTH, WORDMARK_HEIGHT) .dimensions(WORDMARK_WIDTH, WORDMARK_HEIGHT)
.position((width - WORDMARK_WIDTH) / 2, top + WORDMARK_Y) .position((width - WORDMARK_WIDTH) / 2, top + WORDMARK_Y)
.animation(new Fade(AnimationConfig.logo.duration.value))); .animation(step(new Fade(AnimationConfig.logo.duration.value), STEP_LOGO)));
AnimationStagger menus = new AnimationStagger(AnimationConfig.mainMenu).after(MENUS_DELAY); AnimationStagger menus = new AnimationStagger(AnimationConfig.mainMenu)
.after(stepDelay(STEP_MENUS));
addMenuButton(menus, new Button("Singleplayer", addMenuButton(menus, new Button("Singleplayer",
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.SelectWorld)) () -> Providers.saturn.getClient().setScreen(MinecraftScreen.SelectWorld))
@@ -91,34 +99,42 @@ public class TitleMenu extends SaturnScreen {
// Top corners: the player, and quitting the game // Top corners: the player, and quitting the game
draw(new AccountChip() draw(new AccountChip()
.position(EDGE, EDGE) .position(TOP_EDGE, TOP_EDGE)
.animation(delayed(new SlideFade(AnimationConfig.mainMenu, 8), EDGES_DELAY))); .animation(step(new SlideFade(AnimationConfig.mainMenu, 8), STEP_ACCOUNT)));
draw(new IconButton(Textures.ICON_CLOSE, () -> Providers.saturn.getClient().scheduleStop()) draw(new IconButton(Textures.ICON_CLOSE, () -> Providers.saturn.getClient().scheduleStop())
.dimensions(QUIT_SIZE, QUIT_SIZE) .dimensions(QUIT_SIZE, QUIT_SIZE)
.position(width - EDGE - QUIT_SIZE, EDGE + (AccountChip.HEIGHT - QUIT_SIZE) / 2) .position(width - TOP_EDGE - QUIT_SIZE, TOP_EDGE)
.animation(delayed(new SlideFade(AnimationConfig.mainMenu, 8), EDGES_DELAY))); .animation(step(new SlideFade(AnimationConfig.mainMenu, 8), STEP_QUIT)));
// Along the bottom: the dock of Saturn's screens and Minecraft's options, and the version // Along the bottom: the dock of Saturn's screens, the shift menu and Minecraft's options, and the version
Dock dock = new Dock(List.of( Dock dock = new Dock(List.of(
new Dock.Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())), new Dock.Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
new Dock.Item(Textures.ICON_COSMETICS, new Dock.Item(Textures.ICON_COSMETICS,
() -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())), () -> Providers.saturn.getClient().setScreen(new CosmeticsMenu())),
new Dock.Item(Textures.LOGO, () -> Providers.saturn.getClient().setScreen(new ClientSettings())), new Dock.Item(Textures.LOGO, () -> Providers.saturn.getClient().setScreen(new ShiftMenu())),
new Dock.Item(Textures.ICON_SETTINGS, new Dock.Item(Textures.ICON_SETTINGS,
() -> Providers.saturn.getClient().setScreen(MinecraftScreen.Options)))); () -> Providers.saturn.getClient().setScreen(MinecraftScreen.Options))));
draw(dock.position((width - dock.width) / 2, height - EDGE - Dock.HEIGHT) draw(dock.position((width - dock.width) / 2, height - EDGE - Dock.HEIGHT)
.animation(delayed(new SlideFade(AnimationConfig.mainMenu, -12), EDGES_DELAY + EDGES_STAGGER))); .animation(step(new SlideFade(AnimationConfig.mainMenu, -12), STEP_DOCK)));
String version = getVersionText(); String version = getVersionText();
int versionHeight = (int) (Fonts.getHeight() * VERSION_SCALE); int versionHeight = (int) (Fonts.getHeight() * VERSION_SCALE);
draw(new Label(() -> version, VERSION_SCALE, Theme::getBodyFont, draw(new Label(() -> version, VERSION_SCALE, Theme::getBodyFont,
() -> Theme.withAlpha(VERSION_ALPHA, Theme.getMutedFg())) () -> Theme.withAlpha(VERSION_ALPHA, Theme.getMutedFg()))
.position(EDGE, height - EDGE - versionHeight) .position(EDGE, height - EDGE - versionHeight)
.animation(delayed(new Fade(AnimationConfig.mainMenu), EDGES_DELAY + EDGES_STAGGER * 2))); .animation(step(new Fade(AnimationConfig.mainMenu), STEP_VERSION)));
} }
private static Animation delayed(Animation animation, int delay) { /**
animation.delay = delay; * 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; return animation;
} }