The world or panorama keeps its animated background blur, while glass behind menus and behind widgets (buttons, the dock, the account chip) each get a fixed blur of their own. Glass is left out when its blur is 0. Co-Authored-By: Claude Opus 5.5 <[email protected]>
190 lines
5.5 KiB
Java
190 lines
5.5 KiB
Java
package org.saturnclient.ui;
|
||
|
||
import java.time.Duration;
|
||
import java.time.Instant;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
import org.saturnclient.config.Config;
|
||
import org.saturnclient.config.property.FloatProperty;
|
||
|
||
public abstract class SaturnScreen {
|
||
/** How long the background blur takes to fade in, in ms */
|
||
private static final int BLUR_FADE_IN = 700;
|
||
|
||
public static interface ScreenProvider {
|
||
public void close();
|
||
|
||
/** The screen's width in GUI pixels */
|
||
public int getWidth();
|
||
|
||
/** The screen's height in GUI pixels */
|
||
public int getHeight();
|
||
}
|
||
|
||
// General
|
||
public int width;
|
||
public int height;
|
||
public String title;
|
||
/** GUI pixels per Saturn unit, from {@link #getScale()} when the screen was built */
|
||
public float scale = 0.5f;
|
||
/** Whether a mouse button is held, so the screen isn't rebuilt under a drag */
|
||
private boolean mouseDown = false;
|
||
|
||
// Saturn Screen
|
||
public List<Element> elements = new ArrayList<>();
|
||
public float backgroundOpacity = 1.0f;
|
||
public Instant start = null;
|
||
/** Whether the game behind this screen is blurred, by the client's background blur setting */
|
||
public boolean blurBackground = true;
|
||
|
||
// Provider
|
||
public ScreenProvider provider;
|
||
|
||
public SaturnScreen(String title) {
|
||
this.title = title;
|
||
}
|
||
|
||
/**
|
||
* 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 getBackgroundBlur() {
|
||
if (!blurBackground || start == null) {
|
||
return 0;
|
||
}
|
||
|
||
long elapsed = Duration.between(start, Instant.now()).toMillis();
|
||
return Math.round(Config.backgroundBlur.value * Math.min(elapsed / (float) BLUR_FADE_IN, 1f));
|
||
}
|
||
|
||
/**
|
||
* The GUI scale setting this screen follows; the menu scale unless the
|
||
* screen is another kind.
|
||
*/
|
||
protected FloatProperty getScaleSetting() {
|
||
return Config.menuScale;
|
||
}
|
||
|
||
/**
|
||
* GUI pixels per Saturn unit. At 1× a Saturn unit is half a GUI pixel.
|
||
* Enlarging stops where the screen would be smaller than 320x240 GUI
|
||
* pixels, the least Minecraft's own GUI scale leaves.
|
||
*/
|
||
public float getScale() {
|
||
float fit = Math.min(provider.getWidth() / 320f, provider.getHeight() / 240f);
|
||
return 0.5f * Math.min(getScaleSetting().value, Math.max(1f, fit));
|
||
}
|
||
|
||
/**
|
||
* Rebuilds the screen if its scale setting changed, once no drag is going
|
||
* on (the slider being dragged would be replaced).
|
||
*/
|
||
public void updateScale() {
|
||
if (!mouseDown && getScale() != scale) {
|
||
init();
|
||
}
|
||
}
|
||
|
||
public void init() {
|
||
elements.clear();
|
||
scale = getScale();
|
||
width = (int) (provider.getWidth() / scale);
|
||
height = (int) (provider.getHeight() / scale);
|
||
Popup.reset(width, height);
|
||
ui(); // abstraction to render the saturn ui and also render extra stuff here
|
||
}
|
||
|
||
public abstract void ui();
|
||
|
||
public void draw(Element element) {
|
||
ElementRenderer.draw(elements, element);
|
||
}
|
||
|
||
// --------------
|
||
// Rendering
|
||
// --------------
|
||
|
||
public void render(RenderScope renderScope, int mouseX, int mouseY, float delta, long elapsed) {
|
||
renderScope.getMatrixStack().push();
|
||
|
||
renderScope.getMatrixStack().scale(scale, scale);
|
||
|
||
ElementRenderer.render(new ArrayList<>(elements), elapsed, renderScope, mouseX, mouseY);
|
||
Popup.render(renderScope, elapsed, mouseX, mouseY);
|
||
|
||
renderScope.getMatrixStack().pop();
|
||
}
|
||
|
||
// --------------
|
||
// Events
|
||
// --------------
|
||
|
||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||
mouseDown = true;
|
||
mouseX /= scale;
|
||
mouseY /= scale;
|
||
|
||
if (!Popup.mouseClicked(mouseX, mouseY, button)) {
|
||
ElementRenderer.mouseClicked(elements, mouseX, mouseY, button);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||
mouseX /= scale;
|
||
mouseY /= scale;
|
||
|
||
if (!Popup.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) {
|
||
ElementRenderer.mouseDragged(elements, mouseX, mouseY, button, deltaX, deltaY);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||
mouseDown = false;
|
||
mouseX /= scale;
|
||
mouseY /= scale;
|
||
|
||
// Everything hears the release, so no element is left thinking it's being dragged.
|
||
Popup.mouseReleased(mouseX, mouseY, button);
|
||
ElementRenderer.mouseReleased(elements, mouseX, mouseY, button);
|
||
|
||
return false;
|
||
}
|
||
|
||
public boolean mouseScrolled(
|
||
double mouseX,
|
||
double mouseY,
|
||
double horizontalAmount,
|
||
double verticalAmount) {
|
||
mouseX /= scale;
|
||
mouseY /= scale;
|
||
|
||
if (!Popup.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount)) {
|
||
ElementRenderer.mouseScrolled(elements, mouseX, mouseY, horizontalAmount, verticalAmount);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public void resize(int width, int height) {
|
||
init();
|
||
}
|
||
|
||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||
ElementRenderer.keyPressed(elements, keyCode, scanCode, modifiers);
|
||
|
||
return false;
|
||
}
|
||
|
||
public boolean shouldPause() {
|
||
return true;
|
||
}
|
||
|
||
public void onClose() {
|
||
}
|
||
}
|