Files
common/src/main/java/org/saturnclient/ui/SaturnScreen.java
T
selimaj-devandclaude a7e3e537b1 Add GUI scale sliders for Saturn's screens
The title screen, the menus and the HUD menus (emote wheel, shift menu)
each get a scale slider, relative to Minecraft's GUI scale. The HUD
editor stays in GUI pixels.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 18:59:47 +02:00

190 lines
5.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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() {
}
}