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
5 changed files with 65 additions and 9 deletions
Showing only changes of commit 4d9c629eaf - Show all commits
@@ -28,6 +28,12 @@ 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);
}
@@ -1,5 +1,6 @@
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;
@@ -38,6 +39,9 @@ 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);
@@ -34,6 +34,14 @@ public interface RenderScope {
if (color == 0)
return;
drawTexture(getRoundedRectangle(width, height, radius), x, y, 0, 0, width, height, color);
}
/**
* The white rounded rectangle that {@link #drawRoundedRectangle} tints, as a
* cached texture.
*/
default IdentifierRef getRoundedRectangle(int width, int height, int radius) {
radius = Math.min(radius, width / 2);
radius = Math.min(radius, height / 2);
@@ -42,7 +50,24 @@ public interface RenderScope {
width, height,
radius, radius);
drawSvgShape(rect, "rounded_" + width + "_" + height + "_" + radius, x, y, width, height, color);
return getSvgShape(rect, "rounded_" + width + "_" + height + "_" + radius, width, height);
}
/**
* 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.
*/
default void drawGlass(int x, int y, int width, int height, int radius) {
drawGlass(getRoundedRectangle(width, height, radius), x, y, width, height);
}
/**
* Draws the blurred game behind the screen where {@code mask}, stretched
* over the area, is opaque.
*/
default void drawGlass(IdentifierRef mask, int x, int y, int width, int height) {
}
/**
@@ -89,15 +114,22 @@ public interface RenderScope {
* {@code color}.
*/
private void drawSvgShape(String shape, String cacheKey, int x, int y, int width, int height, int color) {
drawTexture(getSvgShape(shape, cacheKey, width, height), x, y, 0, 0, width, height, color);
}
/**
* {@code shape} (SVG elements in a {@code width} x {@code height} canvas,
* drawn in white) rendered to a cached texture.
*/
private IdentifierRef getSvgShape(String shape, String cacheKey, int width, int height) {
String svg = String.format(
"<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>%s</svg>",
width, height, shape);
InputStream svgStream = new ByteArrayInputStream(svg.getBytes(StandardCharsets.UTF_8));
drawTexture(SvgTexture.getSvg(svgStream,
IdentifierRef.ofSaturn("textures/gui/tmp_rect/" + cacheKey),
width * 4, height * 4), x, y, 0, 0, width, height, color);
return SvgTexture.getSvg(svgStream, IdentifierRef.ofSaturn("textures/gui/tmp_rect/" + cacheKey),
width * 4, height * 4);
}
void drawBorder(int x, int y, int width, int height, int color);
@@ -46,11 +46,11 @@ public abstract class SaturnScreen {
}
/**
* How much to blur the game behind this screen right now: the client's
* setting, faded in over the screen's first moments.
* 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.
*/
public int getBackgroundBlur() {
if (!blurBackground || start == null) {
public int getBlurRadius() {
if (start == null) {
return 0;
}
@@ -58,6 +58,14 @@ 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.
@@ -6,7 +6,8 @@ import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
/**
* The translucent, outlined surface that screens lay their content on.
* The translucent, outlined surface that screens lay their content on,
* frosted over the game where glass is supported.
*/
public class Panel extends Element {
@@ -16,6 +17,11 @@ 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,
Theme.getPanelBg(), Theme.getBorder());
}