Adding more implementations

This commit is contained in:
2026-03-06 10:59:07 +01:00
parent 0084457008
commit fc87506965
21 changed files with 77 additions and 543 deletions
@@ -0,0 +1,12 @@
package org.saturnclient.common.minecraft;
import java.io.File;
import java.io.InputStream;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
public interface IMinecraftClient {
public File getRunDirectory();
public InputStream getResource(SaturnIdentifier identifier);
}
@@ -6,4 +6,13 @@ public class MinecraftBinding {
public MinecraftBinding(Object binding) { public MinecraftBinding(Object binding) {
this.inner = binding; this.inner = binding;
} }
@SuppressWarnings("unchecked")
public <T> T get() {
try {
return (T) inner;
} catch (ClassCastException e) {
return null;
}
}
} }
@@ -1,19 +1,17 @@
package org.saturnclient.common.minecraft; package org.saturnclient.common.minecraft;
import java.io.File;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
public abstract class MinecraftProvider { public abstract class MinecraftProvider {
public static MinecraftProvider PROVIDER; public static MinecraftProvider PROVIDER;
public abstract IMinecraftClient getClient();
public abstract Object createIdentifier(String namespace, String path); public abstract Object createIdentifier(String namespace, String path);
public abstract boolean isKeyPressed(int key); public abstract boolean isKeyPressed(int key);
public abstract File getRunDirectory();
public abstract int getWidth(String text, int font); public abstract int getWidth(String text, int font);
public abstract void registerBufferedImageTexture(SaturnIdentifier i, BufferedImage bi); public abstract void registerBufferedImageTexture(SaturnIdentifier i, BufferedImage bi);
@@ -23,7 +23,7 @@ public class Config {
} }
public static void init() { public static void init() {
File configFile = new File(MinecraftProvider.PROVIDER.getRunDirectory(), "saturn.json"); File configFile = new File(MinecraftProvider.PROVIDER.getClient().getRunDirectory(), "saturn.json");
config = new ConfigManager(configFile, "Saturn Client"); config = new ConfigManager(configFile, "Saturn Client");
config.property("Realistic logo", realisticLogo); config.property("Realistic logo", realisticLogo);
@@ -52,8 +52,6 @@ public interface RenderScope {
public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y, int seed); public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y, int seed);
public void drawItem(SaturnItemStack entity, SaturnItemStack stack, int x, int y, int seed);
public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height); public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height);
public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height, int color); public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height, int color);
@@ -1,5 +1,7 @@
package org.saturnclient.ui.elements; package org.saturnclient.ui.elements;
import org.saturnclient.common.minecraft.IMinecraftClient;
import org.saturnclient.common.minecraft.MinecraftProvider;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import org.saturnclient.ui.Element; import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.ElementContext;
@@ -15,11 +17,12 @@ public class ImageTexture extends Element {
@Override @Override
public void render(RenderScope renderScope, ElementContext ctx) { public void render(RenderScope renderScope, ElementContext ctx) {
if (sprite.toString().endsWith(".svg")) { if (sprite.toString().endsWith(".svg")) {
MinecraftClient client = MinecraftClient.getInstance(); IMinecraftClient client = MinecraftProvider.PROVIDER.getClient();
// Get the actual window pixel dimensions for the image // Get the actual window pixel dimensions for the image
int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth()); int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth());
int renderHeight = (int) (height * client.getWindow().getFramebufferHeight() / client.getWindow().getHeight()); int renderHeight = (int) (height * client.getWindow().getFramebufferHeight()
/ client.getWindow().getHeight());
sprite = SvgTexture.getSvg(client, sprite, renderWidth * 2, renderHeight * 2); sprite = SvgTexture.getSvg(client, sprite, renderWidth * 2, renderHeight * 2);
} }
@@ -8,7 +8,6 @@ import org.saturnclient.config.manager.Property;
import org.saturnclient.ui.Element; import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.ElementRenderer;
public class Scroll extends Element { public class Scroll extends Element {
private static Property<Integer> scrollBarRadius = Property.integer(10); private static Property<Integer> scrollBarRadius = Property.integer(10);
@@ -6,16 +6,13 @@ import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class TextureButton extends Element { public class TextureButton extends Element {
Identifier sprite; SaturnIdentifier sprite;
private Runnable onClick; private Runnable onClick;
static int padding = 14; static int padding = 14;
public TextureButton(SaturnIdentifier sprite, Runnable onClick) { public TextureButton(SaturnIdentifier sprite, Runnable onClick) {
this.sprite = (Identifier) sprite.inner; this.sprite = sprite;
this.onClick = onClick; this.onClick = onClick;
} }
@@ -24,8 +21,6 @@ public class TextureButton extends Element {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value); ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
int texWidth = width - padding; int texWidth = width - padding;
int texHeight = height - padding; int texHeight = height - padding;
@@ -9,6 +9,8 @@ import java.util.List;
import com.kitfox.svg.SVGDiagram; import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGUniverse; import com.kitfox.svg.SVGUniverse;
import org.saturnclient.common.minecraft.IMinecraftClient;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
public class SvgTexture { public class SvgTexture {
@@ -47,7 +49,7 @@ public class SvgTexture {
return image; return image;
} }
public static SaturnIdentifier getSvg(MinecraftClient client, SaturnIdentifier svgImage, int width, int height) { public static SaturnIdentifier getSvg(IMinecraftClient client, SaturnIdentifier svgImage, int width, int height) {
SaturnIdentifier id = SaturnIdentifier SaturnIdentifier id = SaturnIdentifier
.of(svgImage.toString().replaceAll("\\.svg$", (width + "_" + height).toString() + ".png")); .of(svgImage.toString().replaceAll("\\.svg$", (width + "_" + height).toString() + ".png"));
@@ -55,10 +57,7 @@ public class SvgTexture {
return id; return id;
} }
try (InputStream svgStream = client try (InputStream svgStream = client.getResource(svgImage)) {
.getResourceManager()
.getResource(svgImage).get()
.getInputStream()) {
BufferedImage image = renderSvg(svgStream, width, height); BufferedImage image = renderSvg(svgStream, width, height);
@@ -4,7 +4,6 @@ import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@@ -12,12 +11,12 @@ import org.joml.Matrix4f;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import org.saturnclient.common.minecraft.bindings.SaturnItemStack;
import org.saturnclient.common.minecraft.bindings.SaturnSprite;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor; import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.font.TextRenderer.TextLayerType; import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
@@ -41,29 +40,30 @@ import net.minecraft.util.crash.CrashReportSection;
import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World; import net.minecraft.world.World;
public class RenderScope { public class RenderScopeImpl implements RenderScope {
public MatrixStack matrices; public MatrixStack matrices;
public VertexConsumerProvider.Immediate vertexConsumers; public VertexConsumerProvider.Immediate vertexConsumers;
// private Function<Identifier, RenderLayer> renderLayers;
private ScissorStack scissorStack = new ScissorStack(); private ScissorStack scissorStack = new ScissorStack();
private int opacity = 255 << 24; private int opacity = 255 << 24;
private final ItemRenderState itemRenderState; private final ItemRenderState itemRenderState;
public RenderScope(DrawContext context) { public RenderScopeImpl(DrawContext context) {
this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers()); this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers());
} }
public RenderScope(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers) { public RenderScopeImpl(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers) {
this.matrices = matrices; this.matrices = matrices;
this.vertexConsumers = vertexConsumers; this.vertexConsumers = vertexConsumers;
this.scissorStack = new ScissorStack(); this.scissorStack = new ScissorStack();
this.itemRenderState = new ItemRenderState(); this.itemRenderState = new ItemRenderState();
} }
@Override
public void setOpacity(float alpha) { public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24; this.opacity = (int) (alpha * 255) << 24;
} }
@Override
public int getColor(int color) { public int getColor(int color) {
int originalAlpha = (color >>> 24) & 0xFF; int originalAlpha = (color >>> 24) & 0xFF;
int newAlpha = (opacity >>> 24) & 0xFF; int newAlpha = (opacity >>> 24) & 0xFF;
@@ -71,10 +71,7 @@ public class RenderScope {
return (mixedAlpha << 24) | (color & 0x00FFFFFF); return (mixedAlpha << 24) | (color & 0x00FFFFFF);
} }
public void setRenderLayer(Function<Identifier, RenderLayer> renderLayers) { @Override
// this.renderLayers = renderLayers;
}
public void drawRect(int x, int y, int width, int height, int color) { public void drawRect(int x, int y, int width, int height, int color) {
if (color == 0) if (color == 0)
return; return;
@@ -106,10 +103,12 @@ public class RenderScope {
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0).color(color); vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0).color(color);
} }
@Override
public void drawText(String text, int x, int y, int font, int color) { public void drawText(String text, int x, int y, int font, int color) {
drawText(1.0f, text, x, y, font, color); drawText(1.0f, text, x, y, font, color);
} }
@Override
public void drawText(float scale, String text, int x, int y, int font, int color) { public void drawText(float scale, String text, int x, int y, int font, int color) {
if (color == 0) if (color == 0)
return; return;
@@ -175,6 +174,7 @@ public class RenderScope {
this.matrices.pop(); this.matrices.pop();
} }
@Override
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) { public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
if (color == 0) if (color == 0)
return; return;
@@ -199,29 +199,34 @@ public class RenderScope {
this.matrices.pop(); this.matrices.pop();
} }
@Override
public int getScaledWindowWidth() { public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getScaledWidth(); return SaturnClient.client.getWindow().getScaledWidth();
} }
@Override
public int getScaledWindowHeight() { public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getScaledHeight();
} }
/* Saturn common sprites */ @Override
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height, int color) { public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height, int color) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color); this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
} }
@Override
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height) { public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height); this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height);
} }
@Override
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height, public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height,
int regionWith, int regionWith,
int regionHeight, int textureWidth, int textureHeight) { int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1); this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
} }
@Override
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height, public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionWidth,
int regionHeight, int textureWidth, int textureHeight, int color) { int regionHeight, int textureWidth, int textureHeight, int color) {
@@ -256,7 +261,8 @@ public class RenderScope {
float v2, int color) { float v2, int color) {
if (sprite.toString().endsWith(".svg")) { if (sprite.toString().endsWith(".svg")) {
sprite = SvgTexture.getSvg(MinecraftClient.getInstance(), sprite, (x2 - x1) * 2, (y2 - y1) * 2); // sprite = SvgTexture.getSvg(MinecraftClient.getInstance(), sprite, (x2 - x1) *
// 2, (y2 - y1) * 2);
} }
if (color == 0) if (color == 0)
@@ -280,16 +286,19 @@ public class RenderScope {
matrices.pop(); matrices.pop();
} }
@Override
public void enableScissor(int x1, int y1, int x2, int y2) { public void enableScissor(int x1, int y1, int x2, int y2) {
ScreenRect screenRect = (new ScreenRect(x1, y1, x2 - x1, y2 - y1)) ScreenRect screenRect = (new ScreenRect(x1, y1, x2 - x1, y2 - y1))
.transform(this.matrices.peek().getPositionMatrix()); .transform(this.matrices.peek().getPositionMatrix());
this.setScissor(this.scissorStack.push(screenRect)); this.setScissor(this.scissorStack.push(screenRect));
} }
@Override
public void disableScissor() { public void disableScissor() {
this.setScissor(this.scissorStack.pop()); this.setScissor(this.scissorStack.pop());
} }
@Override
public boolean scissorContains(int x, int y) { public boolean scissorContains(int x, int y) {
return this.scissorStack.containsPoint(x, y); return this.scissorStack.containsPoint(x, y);
} }
@@ -311,6 +320,7 @@ public class RenderScope {
} }
@Override
public void draw() { public void draw() {
this.vertexConsumers.draw(); this.vertexConsumers.draw();
} }
@@ -351,33 +361,34 @@ public class RenderScope {
} }
} }
public void drawItem(ItemStack item, int x, int y) { @Override
public void drawItem(SaturnItemStack item, int x, int y) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0); this.drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0);
} }
public void drawItem(ItemStack stack, int x, int y, int seed) { @Override
public void drawItem(SaturnItemStack stack, int x, int y, int seed) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed); this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed);
} }
public void drawItem(ItemStack stack, int x, int y, int seed, int z) { @Override
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed, z); public void drawItem(SaturnItemStack stack, int x, int y, int seed, int z) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, (ItemStack) stack.inner, x, y, seed, z);
} }
public void drawItemWithoutEntity(ItemStack stack, int x, int y) { @Override
public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y) {
this.drawItemWithoutEntity(stack, x, y, 0); this.drawItemWithoutEntity(stack, x, y, 0);
} }
public void drawItemWithoutEntity(ItemStack stack, int x, int y, int seed) { @Override
public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y, int seed) {
this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed); this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed);
} }
public void drawItem(LivingEntity entity, ItemStack stack, int x, int y, int seed) { private void drawItem(@Nullable LivingEntity entity, @Nullable World world, SaturnItemStack stack, int x, int y,
this.drawItem(entity, entity.getWorld(), stack, x, y, seed);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y,
int seed) { int seed) {
this.drawItem(entity, world, stack, x, y, seed, 0); this.drawItem(entity, world, (ItemStack) stack.inner, x, y, seed, 0);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed, private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed,
@@ -421,11 +432,14 @@ public class RenderScope {
} }
} }
public void drawSpriteStretched(Sprite sprite, int x, int y, int width, int height) { @Override
public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height) {
this.drawSpriteStretched(sprite, x, y, width, height, -1); this.drawSpriteStretched(sprite, x, y, width, height, -1);
} }
public void drawSpriteStretched(Sprite sprite, int x, int y, int width, int height, int color) { @Override
public void drawSpriteStretched(SaturnSprite saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite.inner;
if (color == 0) if (color == 0)
return; return;
if (width != 0 && height != 0) { if (width != 0 && height != 0) {
@@ -94,7 +94,7 @@ public abstract class SaturnScreen extends Screen {
// We are using a Abstracted RenderScope because older minecraft versions don't // We are using a Abstracted RenderScope because older minecraft versions don't
// use DrawContext // use DrawContext
RenderScope renderScope = new RenderScope(context.getMatrices(), RenderScope renderScope = new RenderScopeImpl(context.getMatrices(),
((DrawContextAccessor) context).getVertexConsumers()); ((DrawContextAccessor) context).getVertexConsumers());
renderScope.matrices.push(); renderScope.matrices.push();
@@ -8,8 +8,6 @@ import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.Utils; import org.saturnclient.ui.Utils;
import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Fonts;
import net.minecraft.client.render.RenderLayer;
public class Select extends Element { public class Select extends Element {
private Property<Integer> prop; private Property<Integer> prop;
@@ -21,8 +19,6 @@ public class Select extends Element {
@Override @Override
public void render(RenderScope renderScope, ElementContext ctx) { public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
renderScope.drawText(0.8f, "<", 0, 0, Theme.FONT.value, Theme.FOREGROUND.value); renderScope.drawText(0.8f, "<", 0, 0, Theme.FONT.value, Theme.FOREGROUND.value);
String text = prop.getSelection(); String text = prop.getSelection();
@@ -1,66 +0,0 @@
package org.saturnclient.ui.elements;
import java.util.ArrayList;
import java.util.List;
import org.saturnclient.config.AnimationConfig;
import org.saturnclient.config.Config;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.ElementRenderer;
public class AnimationStagger extends Element {
protected List<Element> children = new ArrayList<>();
public int delay;
public AnimationStagger(int delay) {
this.delay = delay;
}
public AnimationStagger(AnimationConfig config) {
this.delay = config.stagger.value;
}
public void draw(Element element) {
if (!Config.stagger.value) {
element.animation = null;
}
if (element.animation != null) {
element.animation.delay = delay * children.size();
}
ElementRenderer.draw(children, element);
this.height = Math.max(this.height, element.y + element.height);
this.width = Math.max(this.width, element.x + element.width);
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
ElementRenderer.render(children, ctx.elapsed, renderScope,
ctx.mouseX,
ctx.mouseY);
}
@Override
public void mouseClicked(double mouseX, double mouseY, int button) {
ElementRenderer.mouseClicked(children, mouseX, mouseY, button);
}
@Override
public void keyPressed(int keyCode, int scanCode, int modifiers) {
ElementRenderer.keyPressed(children, keyCode, scanCode, modifiers);
}
@Override
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
ElementRenderer.mouseDragged(children, mouseX, mouseY, button, deltaX, deltaY);
}
@Override
public void mouseReleased(double mouseX, double mouseY, int button) {
ElementRenderer.mouseReleased(children, mouseX, mouseY, button);
}
}
@@ -1,35 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts;
public class Button extends Element {
private String text;
private Runnable onClick;
public Button(String text, Runnable onClick) {
this.text = text;
this.onClick = onClick;
this.dimensions(Fonts.getWidth(text, Theme.FONT.value) + 50, 38);
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
renderScope.drawText(text, Fonts.centerX(width, text, Theme.FONT.value), Fonts.centerY(height),
Theme.FONT.value,
ctx.isHovering() ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}
@@ -1,33 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class ClickableTexture extends Element {
Identifier sprite;
private Runnable onClick;
public ClickableTexture(Identifier sprite, Runnable onClick) {
this.sprite = sprite;
this.onClick = onClick;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height,
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}
@@ -1,37 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
public class ImageTexture extends Element {
Identifier sprite;
public ImageTexture(Identifier sprite) {
this.sprite = sprite;
}
public ImageTexture(SaturnIdentifier sprite) {
this.sprite = (Identifier) sprite.inner;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
if (sprite.toString().endsWith(".svg")) {
MinecraftClient client = MinecraftClient.getInstance();
// Get the actual window pixel dimensions for the image
int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth());
int renderHeight = (int) (height * client.getWindow().getFramebufferHeight() / client.getWindow().getHeight());
sprite = SvgTexture.getSvg(client, sprite, renderWidth * 2, renderHeight * 2);
}
renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height);
}
}
@@ -1,58 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Theme;
import org.saturnclient.config.manager.Property;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.anim.SlideX;
import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.Textures;
public class Notification extends Element {
private static Property<Integer> error = Property.color(0xFFbf212f);
private static Property<Integer> info = Property.color(0xFF264b96);
private static Property<Integer> success = Property.color(0xFF27b376);
public static enum NotificationKind {
Error,
Info,
Success,
}
NotificationKind kind;
String text;
String title;
public Notification(int width, int height, NotificationKind kind, String title, String text) {
this.kind = kind;
this.text = text;
this.title = title;
this.width = (int) Math.max(Fonts.getWidth(text, 1) * 0.6f, Fonts.getWidth(title, 1)) + 20;
this.height = 50;
this.x = width - this.width - 15;
this.y = height - this.height - 15;
this.animation = new SlideX(700, -width);
this.duration = 3000;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, 10, Theme.PRIMARY.value);
switch (kind) {
case Error:
renderScope.drawTexture(Textures.CIRCLE_X, 9, 9, 0, 0, 15, 15, error.value);
break;
case Info:
renderScope.drawTexture(Textures.INFO, 9, 9, 0, 0, 15, 15, info.value);
break;
case Success:
renderScope.drawTexture(Textures.CHECK, 9, 9, 0, 0, 15, 15, success.value);
break;
}
renderScope.drawText(0.7f, title, 32, 10, 1, -1);
renderScope.drawText(0.5f, text, 32, 28, 1, -1);
}
}
@@ -1,131 +0,0 @@
package org.saturnclient.ui.elements;
import java.util.ArrayList;
import java.util.List;
import org.saturnclient.config.Theme;
import org.saturnclient.config.manager.Property;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.ElementRenderer;
public class Scroll extends Element {
private static Property<Integer> scrollBarRadius = Property.integer(10);
private static Property<Integer> scrollBarWidth = Property.integer(5);
private static Property<Integer> scrollBarPadding = Property.integer(5);
int padding = 0;
protected List<Element> children = new ArrayList<>();
int scroll = 0;
int maxScroll = 0;
public Scroll(int padding) {
this.padding = padding;
}
public void draw(Element element) {
ElementRenderer.draw(children, element);
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
calculateMaxScroll();
renderScope.drawRoundedRectangle(0, 0, width, height,
Theme.BG_RADIUS.value, Theme.BACKGROUND.value);
renderScope.enableScissor(padding, padding, width - padding, height - padding);
renderScope.matrices.push();
renderScope.matrices.translate(padding, -scroll + padding, 0);
ElementRenderer.render(children, ctx.elapsed, renderScope,
ctx.mouseX - padding,
ctx.mouseY - padding + scroll);
renderScope.matrices.pop();
renderScope.disableScissor();
if (maxScroll > 0) {
renderScope.drawRoundedRectangle(
width - scrollBarWidth.value - scrollBarPadding.value,
calculateScrollBarY(),
scrollBarWidth.value,
calculateScrollBarHeight(),
scrollBarRadius.value,
Theme.SCROLL.value);
}
}
@Override
public void scroll(int mouseX, int mouseY, double horizontalAmount, double verticalAmount) {
scroll -= verticalAmount;
if (scroll < 0) {
scroll = 0;
} else if (scroll > maxScroll) {
scroll = maxScroll;
}
}
@Override
public Element dimensions(int width, int height) {
super.dimensions(width, height);
maxScroll = 0;
for (Element element : children) {
maxScroll = Math.max(maxScroll, (element.y + element.height + padding) - (height - padding * 2));
}
return this;
}
int calculateScrollBarHeight() {
if (maxScroll <= 0)
return height - (scrollBarPadding.value * 2);
return Math.max(20, (height * height) / (height + maxScroll + 10)) - (scrollBarPadding.value * 2);
}
int calculateScrollBarY() {
int scrollBarHeight = calculateScrollBarHeight();
if (maxScroll <= 0)
return scrollBarPadding.value;
int y = (scroll * (height - scrollBarHeight - scrollBarPadding.value * 2)) / maxScroll + scrollBarPadding.value;
return Math.min(y, height - scrollBarHeight - scrollBarPadding.value);
}
private void calculateMaxScroll() {
maxScroll = 0;
for (Element element : children) {
int bottom = element.y + element.height;
maxScroll = Math.max(maxScroll, bottom - height + padding);
}
if (maxScroll > 0) {
maxScroll = maxScroll + 10;
} else {
maxScroll = 0;
}
}
@Override
public void keyPressed(int keyCode, int scanCode, int modifiers) {
ElementRenderer.keyPressed(children, keyCode, scanCode, modifiers);
}
@Override
public void mouseClicked(double mouseX, double mouseY, int button) {
ElementRenderer.mouseClicked(children, mouseX - padding, mouseY - padding + scroll, button);
}
@Override
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
ElementRenderer.mouseDragged(children, mouseX - padding, mouseY - padding + scroll, button, deltaX, deltaY);
}
@Override
public void mouseReleased(double mouseX, double mouseY, int button) {
ElementRenderer.mouseReleased(children, mouseX - padding, mouseY - padding + scroll, button);
}
}
@@ -1,65 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.Utils;
import net.minecraft.util.Identifier;
public class TabMenu extends Element {
public static class TabMenuComponent {
Runnable onClick;
Identifier sprite;
public TabMenuComponent(SaturnIdentifier sprite, Runnable onClick) {
this.onClick = onClick;
this.sprite = (Identifier) sprite.inner;
}
}
TabMenuComponent[] components;
public int selectedScreen = 0;
public TabMenu(int active, TabMenuComponent... components) {
this.components = components;
width = 25 * components.length + 6;
height = 30;
this.selectedScreen = active;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Theme.PRIMARY.value);
int col = 0;
for (TabMenuComponent component : components) {
int x = 25 * col + 5;
boolean hovering = ctx.isHovering(x, 5, 20, 20) || selectedScreen == col;
if (hovering) {
renderScope.drawRoundedRectangle(x, 5, 20, 20, Theme.WIDGET_RADIUS.value, Theme.ACCENT.value);
}
renderScope.drawTexture(component.sprite, x + 5, 10, 0, 0, 10, 10,
hovering ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
col++;
}
}
@Override
public void click(int mouseX, int mouseY) {
int col = 0;
for (TabMenuComponent component : components) {
int x = 25 * col + 5;
if (Utils.isHovering(mouseX - x, mouseY - 5, 20, 20, 1.0f)) {
component.onClick.run();
}
col++;
}
}
}
@@ -1,22 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts;
public class Text extends Element {
private String text;
public Text(String text) {
this.text = text;
width = Fonts.getWidth(text, Theme.FONT.value);
height = Fonts.getHeight();
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawText(this.text, 0, 0, Theme.FONT.value, Theme.FOREGROUND.value);
}
}
@@ -1,42 +0,0 @@
package org.saturnclient.ui.elements;
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
import org.saturnclient.config.Theme;
import org.saturnclient.ui.Element;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class TextureButton extends Element {
Identifier sprite;
private Runnable onClick;
static int padding = 14;
public TextureButton(SaturnIdentifier sprite, Runnable onClick) {
this.sprite = (Identifier) sprite.inner;
this.onClick = onClick;
}
@Override
public void render(RenderScope renderScope, ElementContext ctx) {
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
int texWidth = width - padding;
int texHeight = height - padding;
renderScope.drawTexture(sprite, padding / 2, padding / 2, 0, 0, texWidth, texHeight,
ctx.isHovering() ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}