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 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() { } }