diff --git a/src/main/java/org/saturnclient/common/provider/SaturnProvider.java b/src/main/java/org/saturnclient/common/provider/SaturnProvider.java index 4d63eec..998f539 100644 --- a/src/main/java/org/saturnclient/common/provider/SaturnProvider.java +++ b/src/main/java/org/saturnclient/common/provider/SaturnProvider.java @@ -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); } diff --git a/src/main/java/org/saturnclient/ui/PanelScreen.java b/src/main/java/org/saturnclient/ui/PanelScreen.java index 2bf84a2..e8c8380 100644 --- a/src/main/java/org/saturnclient/ui/PanelScreen.java +++ b/src/main/java/org/saturnclient/ui/PanelScreen.java @@ -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); diff --git a/src/main/java/org/saturnclient/ui/RenderScope.java b/src/main/java/org/saturnclient/ui/RenderScope.java index 0bbc677..808da81 100644 --- a/src/main/java/org/saturnclient/ui/RenderScope.java +++ b/src/main/java/org/saturnclient/ui/RenderScope.java @@ -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( "%s", 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); diff --git a/src/main/java/org/saturnclient/ui/SaturnScreen.java b/src/main/java/org/saturnclient/ui/SaturnScreen.java index 14e6b46..a730b3d 100644 --- a/src/main/java/org/saturnclient/ui/SaturnScreen.java +++ b/src/main/java/org/saturnclient/ui/SaturnScreen.java @@ -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. diff --git a/src/main/java/org/saturnclient/ui/elements/Panel.java b/src/main/java/org/saturnclient/ui/elements/Panel.java index 2b3369e..5392842 100644 --- a/src/main/java/org/saturnclient/ui/elements/Panel.java +++ b/src/main/java/org/saturnclient/ui/elements/Panel.java @@ -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()); }