199 lines
7.4 KiB
Java
199 lines
7.4 KiB
Java
package org.saturnclient.ui;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.InputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Locale;
|
|
|
|
import org.saturnclient.common.ref.asset.IdentifierRef;
|
|
import org.saturnclient.common.ref.asset.SpriteRef;
|
|
import org.saturnclient.common.ref.game.ItemStackRef;
|
|
import org.saturnclient.common.ref.render.MatrixStackRef;
|
|
import org.saturnclient.ui.resources.SvgTexture;
|
|
|
|
public interface RenderScope {
|
|
|
|
// ----------------------------
|
|
// Matrix & Transform
|
|
// ----------------------------
|
|
MatrixStackRef getMatrixStack();
|
|
|
|
// ----------------------------
|
|
// Color & Opacity
|
|
// ----------------------------
|
|
void setOpacity(float alpha);
|
|
|
|
int getColor(int color);
|
|
|
|
// ----------------------------
|
|
// Shapes
|
|
// ----------------------------
|
|
void drawRectangle(int x, int y, int width, int height, int color);
|
|
|
|
default void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
|
|
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);
|
|
|
|
String rect = String.format(
|
|
"<rect width='%d' height='%d' rx='%d' ry='%d' fill='white'/>",
|
|
width, height,
|
|
radius, radius);
|
|
|
|
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 by {@code blur}, cut to exactly the
|
|
* shape {@link #drawRoundedRectangle} draws. Render scopes without glass
|
|
* draw nothing.
|
|
*/
|
|
default void drawGlass(int x, int y, int width, int height, int radius, int blur) {
|
|
drawGlass(getRoundedRectangle(width, height, radius), x, y, width, height, blur);
|
|
}
|
|
|
|
/**
|
|
* Draws the game behind the screen, blurred by {@code blur}, where
|
|
* {@code mask}, stretched over the area, is opaque.
|
|
*/
|
|
default void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
|
|
}
|
|
|
|
/**
|
|
* A {@link #drawRoundedRectangle} with a border, frosted with glass blurred
|
|
* by {@code blur} when the background isn't solid. A blur of 0 leaves it
|
|
* plain, showing the screen's own background blur.
|
|
*/
|
|
default void drawGlassRectangle(int x, int y, int width, int height, int radius, int blur, int thickness,
|
|
int background, int border) {
|
|
if (blur > 0 && background >>> 24 < 0xFF) {
|
|
drawGlass(x, y, width, height, radius, blur);
|
|
}
|
|
|
|
drawRoundedRectangle(x, y, width, height, radius, thickness, background, border);
|
|
}
|
|
|
|
/**
|
|
* Draws a rounded outline that stays inside the given bounds, so it lines up
|
|
* with a {@link #drawRoundedRectangle} of the same size and radius.
|
|
*/
|
|
default void drawRoundedBorder(int x, int y, int width, int height, int radius, int thickness, int color) {
|
|
if (color == 0 || thickness <= 0)
|
|
return;
|
|
|
|
radius = Math.min(radius, width / 2);
|
|
radius = Math.min(radius, height / 2);
|
|
thickness = Math.min(thickness, Math.min(width, height) / 2);
|
|
|
|
// The stroke is centered on the path, so inset it by half its width.
|
|
float inset = thickness / 2f;
|
|
float innerRadius = Math.max(0, radius - inset);
|
|
|
|
String rect = String.format(Locale.ROOT,
|
|
"<rect x='%.1f' y='%.1f' width='%.1f' height='%.1f' rx='%.1f' ry='%.1f' " +
|
|
"fill='none' stroke='white' stroke-width='%d'/>",
|
|
inset, inset,
|
|
width - (float) thickness, height - (float) thickness,
|
|
innerRadius, innerRadius,
|
|
thickness);
|
|
|
|
drawSvgShape(rect, "rounded_border_" + width + "_" + height + "_" + radius + "_" + thickness,
|
|
x, y, width, height, color);
|
|
}
|
|
|
|
/**
|
|
* Draws a rounded rectangle filled with {@code background} and outlined with
|
|
* {@code border}. Either color can be 0 to skip that part.
|
|
*/
|
|
default void drawRoundedRectangle(int x, int y, int width, int height, int radius, int thickness,
|
|
int background, int border) {
|
|
drawRoundedRectangle(x, y, width, height, radius, background);
|
|
drawRoundedBorder(x, y, width, height, radius, thickness, border);
|
|
}
|
|
|
|
/**
|
|
* Renders {@code shape} (SVG elements in a {@code width} x {@code height}
|
|
* canvas, drawn in white) to a cached texture and draws it tinted with
|
|
* {@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));
|
|
|
|
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);
|
|
|
|
void fill(int x1, int y1, int x2, int y2, int color);
|
|
|
|
// ----------------------------
|
|
// Text
|
|
// ----------------------------
|
|
void drawText(String text, int x, int y, int font, int color);
|
|
|
|
void drawText(float scale, String text, int x, int y, int font, int color);
|
|
|
|
// ----------------------------
|
|
// Textures & Sprites
|
|
// ----------------------------
|
|
void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height);
|
|
|
|
void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color);
|
|
|
|
void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
|
|
int regionWidth, int regionHeight, int textureWidth, int textureHeight);
|
|
|
|
void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
|
|
int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color);
|
|
|
|
void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height);
|
|
|
|
void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height, int color);
|
|
|
|
// ----------------------------
|
|
// Items
|
|
// ----------------------------
|
|
void drawItem(ItemStackRef item, int x, int y);
|
|
|
|
// ----------------------------
|
|
// Scissor / Clipping
|
|
// ----------------------------
|
|
void enableScissor(int x1, int y1, int x2, int y2);
|
|
|
|
void disableScissor();
|
|
|
|
boolean scissorContains(int x, int y);
|
|
|
|
// ----------------------------
|
|
// Window Info / Draw
|
|
// ----------------------------
|
|
int getScaledWindowWidth();
|
|
|
|
int getScaledWindowHeight();
|
|
|
|
void draw();
|
|
} |