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
10 changed files with 45 additions and 43 deletions
Showing only changes of commit 7bc308155e - Show all commits
@@ -28,12 +28,6 @@ public interface SaturnProvider {
*/
public IdentifierRef getPlayerSkin();
/**
* Whether this version draws glass (the blurred game behind translucent
* panels), so screens needn't blur the whole background.
*/
public boolean supportsGlass();
/** Shows a warning toast. Safe to call from any thread. */
public void showWarning(String title, String message);
}
@@ -19,7 +19,11 @@ public class Config {
public static BoolProperty saturnTitleScreen = Property.bool(true);
public static BoolProperty cloakPhysics = Property.bool(true);
public static BoolProperty stagger = Property.bool(true);
/** The world or panorama behind Saturn's screens, faded in as they open */
public static IntProperty backgroundBlur = Property.integer(5).range(0, 10);
/** Glass behind translucent menus (panels), and widgets (buttons, the dock) */
public static IntProperty menuBlur = Property.integer(8).range(0, 20);
public static IntProperty widgetBlur = Property.integer(6).range(0, 20);
// How big Saturn's screens are, relative to Minecraft's GUI scale
public static FloatProperty titleScale = guiScale();
public static FloatProperty menuScale = guiScale();
@@ -43,7 +47,9 @@ public class Config {
config.property("Open Emote Wheel", openEmoteWheel, "The key that opens the emote wheel");
config.property("Cloak Physics", cloakPhysics, "Let cloaks swing as you move");
config.property("Stagger Animations", stagger, "Animate list items one after another");
config.property("Background blur", backgroundBlur, "How much the game behind Saturn's screens is blurred");
config.property("World blur", backgroundBlur, "How much the world or panorama behind Saturn's screens is blurred");
config.property("Menu blur", menuBlur, "How much the game is blurred through translucent menus");
config.property("Widget blur", widgetBlur, "How much the game is blurred through translucent buttons and the dock");
config.property("Title screen scale", titleScale, "How big the title screen is, relative to Minecraft's GUI scale");
config.property("Menu scale", menuScale, "How big the mods, settings and cosmetics menus are, relative to Minecraft's GUI scale");
config.property("HUD menu scale", hudMenuScale, "How big the emote wheel and shift menu are, relative to Minecraft's GUI scale");
@@ -1,6 +1,5 @@
package org.saturnclient.ui;
import org.saturnclient.common.provider.Providers;
import org.saturnclient.ui.components.Sidebar;
import org.saturnclient.ui.elements.ImageTexture;
import org.saturnclient.ui.elements.Panel;
@@ -39,9 +38,6 @@ public abstract class PanelScreen extends SaturnScreen {
@Override
public final void ui() {
// The panels are frosted themselves, so the rest of the game stays clear.
blurBackground = !Providers.saturn.supportsGlass();
panelWidth = Math.min(MAX_WIDTH, width - MARGIN * 2 - Sidebar.WIDTH - GAP);
panelHeight = Math.min(MAX_HEIGHT, height - MARGIN * 2);
@@ -55,19 +55,33 @@ public interface RenderScope {
/**
* Frosts a rounded rectangle for a translucent background to be drawn over:
* the game behind the screen, blurred, cut to exactly the shape
* {@link #drawRoundedRectangle} draws. Draws nothing on versions without
* glass.
* the game behind the screen, blurred by {@code blur}, cut to exactly the
* shape {@link #drawRoundedRectangle} draws. Draws nothing on versions
* without glass.
*/
default void drawGlass(int x, int y, int width, int height, int radius) {
drawGlass(getRoundedRectangle(width, height, radius), x, y, width, height);
default void drawGlass(int x, int y, int width, int height, int radius, int blur) {
drawGlass(getRoundedRectangle(width, height, radius), x, y, width, height, blur);
}
/**
* Draws the blurred game behind the screen where {@code mask}, stretched
* over the area, is opaque.
* Draws the game behind the screen, blurred by {@code blur}, where
* {@code mask}, stretched over the area, is opaque.
*/
default void drawGlass(IdentifierRef mask, int x, int y, int width, int height) {
default void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
}
/**
* A {@link #drawRoundedRectangle} with a border, frosted with glass blurred
* by {@code blur} when the background isn't solid. A blur of 0 leaves it
* plain, showing the screen's own background blur.
*/
default void drawGlassRectangle(int x, int y, int width, int height, int radius, int blur, int thickness,
int background, int border) {
if (blur > 0 && background >>> 24 < 0xFF) {
drawGlass(x, y, width, height, radius, blur);
}
drawRoundedRectangle(x, y, width, height, radius, thickness, background, border);
}
/**
@@ -46,11 +46,11 @@ public abstract class SaturnScreen {
}
/**
* How much to blur the game behind this screen and its glass right now: the
* client's setting, faded in over the screen's first moments.
* How much to blur the game behind this screen right now: the client's
* setting, faded in over the screen's first moments.
*/
public int getBlurRadius() {
if (start == null) {
public int getBackgroundBlur() {
if (!blurBackground || start == null) {
return 0;
}
@@ -58,14 +58,6 @@ public abstract class SaturnScreen {
return Math.round(Config.backgroundBlur.value * Math.min(elapsed / (float) BLUR_FADE_IN, 1f));
}
/**
* How much to blur the whole game behind this screen right now, or 0 when it
* isn't.
*/
public int getBackgroundBlur() {
return blurBackground ? getBlurRadius() : 0;
}
/**
* The GUI scale setting this screen follows; the menu scale unless the
* screen is another kind.
@@ -3,6 +3,7 @@ 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.Config;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
@@ -36,8 +37,8 @@ public class AccountChip extends Element {
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1, Theme.getPanelBg(),
Theme.getBorder());
renderScope.drawGlassRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Config.widgetBlur.value, 1,
Theme.getPanelBg(), Theme.getBorder());
// The face, then the hat layer over it, from the 64x64 skin
IdentifierRef skin = Providers.saturn.getPlayerSkin();
@@ -3,6 +3,7 @@ package org.saturnclient.ui.components;
import java.util.List;
import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.config.Config;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
@@ -32,7 +33,8 @@ public class Dock extends Element {
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value + 4, 1, Theme.getPanelBg(),
renderScope.drawGlassRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value + 4, Config.widgetBlur.value, 1,
Theme.getPanelBg(),
Theme.withAlpha(0.1f, Theme.FOREGROUND.value));
for (int i = 0; i < items.size(); i++) {
@@ -1,5 +1,6 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Config;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
@@ -38,7 +39,7 @@ public class Button extends Element {
* The button's surface, shared with {@link IconButton}.
*/
static void drawSurface(RenderScope renderScope, int width, int height, boolean hovered) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1,
renderScope.drawGlassRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Config.widgetBlur.value, 1,
hovered ? Theme.PRIMARY.value : Theme.getPanelBg(),
Theme.withAlpha(hovered ? 0.25f : 0.1f, Theme.FOREGROUND.value));
}
@@ -1,5 +1,6 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Config;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
@@ -17,12 +18,7 @@ public class Panel extends Element {
}
public static void drawBackground(RenderScope renderScope, int width, int height) {
// Frosted behind a background that isn't solid
if (Theme.getPanelBg() >>> 24 < 0xFF) {
renderScope.drawGlass(0, 0, width, height, Theme.BG_RADIUS.value);
}
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.BG_RADIUS.value, 1,
renderScope.drawGlassRectangle(0, 0, width, height, Theme.BG_RADIUS.value, Config.menuBlur.value, 1,
Theme.getPanelBg(), Theme.getBorder());
}
}
@@ -131,8 +131,8 @@ public class EmoteWheel extends SaturnScreen {
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1,
Theme.getPanelBg(), Theme.getBorder());
renderScope.drawGlassRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Config.widgetBlur.value,
1, Theme.getPanelBg(), Theme.getBorder());
float titleScale = 0.54f;
drawCentered(renderScope, "EMOTES", titleScale, pages > 1 ? 24 : (height - 10) / 2, Theme.getMutedFg());