Merge pull request #60 from saturnclientmc/refactor-renderscope

Refactor RenderScope and improved support with 1.21.6
This commit is contained in:
2026-03-26 02:28:33 +01:00
committed by GitHub
18 changed files with 787 additions and 1209 deletions
+1 -1
Submodule common updated: 6873f76c43...53dfa37b64
@@ -65,8 +65,8 @@ public class RenderMixin {
ModLayout dim = hud.getDimensions(); ModLayout dim = hud.getDimensions();
scope.getMatrixStack().push(); scope.getMatrixStack().push();
scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value, 0f); scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value);
scope.getMatrixStack().scale(dim.scale.value, dim.scale.value, 1.0f); scope.getMatrixStack().scale(dim.scale.value, dim.scale.value);
if (dim.renderBackground) { if (dim.renderBackground) {
scope.drawRoundedRectangle(0, 0, dim.width, dim.height, scope.drawRoundedRectangle(0, 0, dim.width, dim.height,
@@ -2,18 +2,19 @@ package org.saturnclient.impl.mixins;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.saturnclient.common.ref.render.MatrixStackRef; import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.RotationAxis;
@Mixin(MatrixStack.class) @Mixin(MatrixStack.class)
public abstract class MatrixStackMixin implements MatrixStackRef { public abstract class MatrixStackMixin implements MatrixStackRef {
@Shadow
public abstract void push();
@Shadow @Shadow
public abstract void translate(double x, double y, double z); public abstract void pop();
@Shadow @Shadow
public abstract void translate(float x, float y, float z); public abstract void translate(float x, float y, float z);
@@ -27,33 +28,23 @@ public abstract class MatrixStackMixin implements MatrixStackRef {
@Shadow @Shadow
public abstract void multiply(Quaternionf quaternion, float originX, float originY, float originZ); public abstract void multiply(Quaternionf quaternion, float originX, float originY, float originZ);
@Shadow
public abstract void push();
@Shadow
public abstract void pop();
@Invoker("peek")
public abstract MatrixStack.Entry peekM();
@Shadow
public abstract boolean isEmpty();
@Shadow
public abstract void loadIdentity();
@Override @Override
public void multiply(QuaternionfRef quaternion) { public void translate(float x, float y) {
this.multiply((Quaternionf) quaternion); translate(x, y, 0);
} }
@Override @Override
public void multiply(QuaternionfRef quaternion, float originX, float originY, float originZ) { public void scale(float x, float y) {
this.multiply((Quaternionf) quaternion, originX, originY, originZ); scale(x, y, 1.0f);
} }
@Override @Override
public Object peek() { public void rotate(float angle, float originX, float originY, float originZ) {
return this.peekM(); multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle), originX, originY, originZ);
} }
}
@Override
public void rotate(float angle) {
multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle));
}
}
@@ -3,7 +3,6 @@ package org.saturnclient.impl.ui;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
@@ -51,27 +50,28 @@ public class EntityDrawerImpl implements EntityDrawer {
public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f, public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f,
Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) { Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) {
renderScope.getMatrixStack().push(); if (renderScope instanceof RenderScopeImpl scopeImpl) {
renderScope.getMatrixStack().translate((double) x, (double) y, 50.0); scopeImpl.matrices.push();
renderScope.getMatrixStack().scale(size, size, -size); scopeImpl.matrices.translate((double) x, (double) y, 0);
renderScope.getMatrixStack().translate(vector3f.x, vector3f.y, vector3f.z); scopeImpl.matrices.scale(size, size, -size);
renderScope.getMatrixStack().multiply((QuaternionfRef) quaternionf); scopeImpl.matrices.translate(vector3f.x, vector3f.y, vector3f.z);
renderScope.draw(); scopeImpl.matrices.multiply(quaternionf);
DiffuseLighting.method_34742(); scopeImpl.draw();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher(); DiffuseLighting.method_34742();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false); entityRenderDispatcher.setRenderShadows(false);
if (renderScope instanceof RenderScopeImpl r) { scopeImpl.draw((vertexConsumers) -> {
r.draw((vertexConsumers) -> {
entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F, entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F,
r.matrices, vertexConsumers, scopeImpl.matrices, vertexConsumers, 15728880);
15728880);
}); });
scopeImpl.draw();
entityRenderDispatcher.setRenderShadows(true);
scopeImpl.getMatrixStack().pop();
DiffuseLighting.enableGuiDepthLighting();
} }
renderScope.draw();
entityRenderDispatcher.setRenderShadows(true);
renderScope.getMatrixStack().pop();
DiffuseLighting.enableGuiDepthLighting();
} }
@Override @Override
@@ -10,7 +10,6 @@ import org.joml.Matrix4f;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.common.provider.Providers;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.asset.SpriteRef; import org.saturnclient.common.ref.asset.SpriteRef;
import org.saturnclient.common.ref.game.ItemStackRef; import org.saturnclient.common.ref.game.ItemStackRef;
@@ -42,16 +41,21 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.crash.CrashException; import net.minecraft.util.crash.CrashException;
import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection; import net.minecraft.util.crash.CrashReportSection;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World; import net.minecraft.world.World;
public class RenderScopeImpl implements RenderScope { public class RenderScopeImpl implements RenderScope {
// ----------------------------
// Fields
// ----------------------------
public MatrixStack matrices; public MatrixStack matrices;
public VertexConsumerProvider.Immediate vertexConsumers; public VertexConsumerProvider.Immediate vertexConsumers;
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;
// ----------------------------
// Constructors
// ----------------------------
public RenderScopeImpl(DrawContext context) { public RenderScopeImpl(DrawContext context) {
this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers()); this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers());
} }
@@ -63,11 +67,17 @@ public class RenderScopeImpl implements RenderScope {
this.itemRenderState = new ItemRenderState(); this.itemRenderState = new ItemRenderState();
} }
// ----------------------------
// Matrix & Transform
// ----------------------------
@Override @Override
public MatrixStackRef getMatrixStack() { public MatrixStackRef getMatrixStack() {
return (MatrixStackRef) matrices; return (MatrixStackRef) matrices;
} }
// ----------------------------
// Color & Opacity
// ----------------------------
@Override @Override
public void setOpacity(float alpha) { public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24; this.opacity = (int) (alpha * 255) << 24;
@@ -81,132 +91,12 @@ public class RenderScopeImpl implements RenderScope {
return (mixedAlpha << 24) | (color & 0x00FFFFFF); return (mixedAlpha << 24) | (color & 0x00FFFFFF);
} }
// ----------------------------
// Draw / Window Info
// ----------------------------
@Override @Override
public void drawRect(int x, int y, int width, int height, int color) { public void draw() {
if (color == 0) this.vertexConsumers.draw();
return;
color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
int i;
if (x1 < x2) {
i = x1;
x1 = x2;
x2 = i;
}
if (y1 < y2) {
i = y1;
y1 = y2;
y2 = i;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui());
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 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) {
drawText(1.0f, text, x, y, font, color);
}
@Override
public void drawText(float scale, String text, int x, int y, int font, int color) {
if (color == 0)
return;
if (font == 0) {
scale *= 2;
}
int i = 0;
for (String line : text.split("\n")) {
color = getColor(color);
matrices.push();
matrices.translate(x, y + (i * Fonts.getHeight()), 0);
matrices.scale(scale, scale, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer;
textRenderer.draw((Text) Fonts.setFont(line, font), 0,
font == 0 ? 1 : 7, color, false,
this.matrices.peek().getPositionMatrix(),
this.vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
matrices.pop();
i++;
}
}
private void drawRoundedCorner(int width, int height, int radius, int color) {
int w = width * 20;
int h = height * 20;
for (int y = 0; y < h; y++) {
int startX = 0;
if (y < radius) {
double dy = radius - y - 0.5;
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
startX = radius - (int) dx;
}
this.drawRect(startX, y, w - startX, 1, color);
}
}
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
// Top
this.matrices.push();
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerWidth, cornerHeight, radius * 10, color);
this.matrices.pop();
// Bottom
this.matrices.push();
this.matrices.translate(cornerWidth, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(90));
this.matrices.translate(0, -cornerWidth, 0);
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerHeight, cornerWidth, radius * 10, color);
this.matrices.pop();
}
@Override
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
if (color == 0)
return;
radius = Math.min(radius, Math.min(width, height));
int cornerWidth = width / 2;
int cornerHeight = height / 2;
this.matrices.push();
this.matrices.translate(x, y, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.translate(cornerWidth * 2, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(180));
this.matrices.translate(0, 0, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.pop();
} }
@Override @Override
@@ -219,66 +109,167 @@ public class RenderScopeImpl implements RenderScope {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getScaledHeight();
} }
public void draw(Consumer<VertexConsumerProvider> drawer) {
drawer.accept(this.vertexConsumers);
this.vertexConsumers.draw();
}
// ----------------------------
// Shapes
// ----------------------------
@Override @Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) { public void drawRectangle(int x, int y, int width, int height, int color) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef 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);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWith,
int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public 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) {
this.drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0.0F) / (float) textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color);
}
/* Minecraft sprites */
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith,
int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth,
int regionHeight, int textureWidth, int textureHeight, int color) {
this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float) textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color);
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1,
float v2, int color) {
if (sprite.toString().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg(Providers.saturn.getClient(),
(IdentifierRef) (Object) sprite,
(x2 - x1) * 2, (y2 - y1) * 2);
}
if (color == 0) if (color == 0)
return; return;
color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui());
vertexConsumer.vertex(matrix4f, x1, y1, 0).color(color);
vertexConsumer.vertex(matrix4f, x1, y2, 0).color(color);
vertexConsumer.vertex(matrix4f, x2, y2, 0).color(color);
vertexConsumer.vertex(matrix4f, x2, y1, 0).color(color);
}
@Override
public void fill(int x1, int y1, int x2, int y2, int color) {
fill(x1, y1, x2, y2, 0, color);
}
public void fill(int x1, int y1, int x2, int y2, int z, int color) {
fill(RenderLayer.getGui(), x1, y1, x2, y2, z, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int color) {
fill(layer, x1, y1, x2, y2, 0, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.vertex(matrix4f, x1, y1, z).color(color);
vertexConsumer.vertex(matrix4f, x1, y2, z).color(color);
vertexConsumer.vertex(matrix4f, x2, y2, z).color(color);
vertexConsumer.vertex(matrix4f, x2, y1, z).color(color);
}
@Override
public void drawBorder(int x, int y, int width, int height, int color) {
fill(x, y, x + width, y + 1, color);
fill(x, y + height - 1, x + width, y + height, color);
fill(x, y + 1, x + 1, y + height - 1, color);
fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
// ----------------------------
// Text
// ----------------------------
@Override
public void drawText(String text, int x, int y, int font, int 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) {
if (color == 0)
return;
if (font == 0)
scale *= 2;
int i = 0;
for (String line : text.split("\n")) {
color = getColor(color);
matrices.push();
matrices.translate(x, y + i * Fonts.getHeight(), 0);
matrices.scale(scale, scale, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer;
textRenderer.draw((Text) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false,
matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
matrices.pop();
i++;
}
}
// ----------------------------
// Textures & Sprites
// ----------------------------
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight) {
drawTexture(sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public 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) {
drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0.0f) / textureWidth, (u + regionWidth) / textureWidth,
(v + 0.0f) / textureHeight, (v + regionHeight) / textureHeight, color);
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite;
if (color == 0)
return;
if (width != 0 && height != 0) {
drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height,
sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV(), color);
}
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2,
float u1, float u2, float v1, float v2, int color) {
if (sprite.toString().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg((IdentifierRef) (Object) sprite, (x2 - x1) * 2,
(y2 - y1) * 2);
}
if (color == 0)
return;
x1 *= 4; x1 *= 4;
x2 *= 4; x2 *= 4;
y1 *= 4; y1 *= 4;
@@ -288,58 +279,99 @@ public class RenderScopeImpl implements RenderScope {
matrices.push(); matrices.push();
matrices.scale(0.25f, 0.25f, 1.0f); matrices.scale(0.25f, 0.25f, 1.0f);
RenderSystem.setShaderTexture(0, sprite); RenderSystem.setShaderTexture(0, sprite);
RenderLayer renderLayer = (RenderLayer) RenderLayer.getGuiTextured(sprite); RenderLayer renderLayer = RenderLayer.getGuiTextured(sprite);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); Matrix4f matrix4f = matrices.peek().getPositionMatrix();
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(renderLayer); VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0.0F).texture(u1, v1).color(color); vertexConsumer.vertex(matrix4f, x1, y1, 0).texture(u1, v1).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0.0F).texture(u1, v2).color(color); vertexConsumer.vertex(matrix4f, x1, y2, 0).texture(u1, v2).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 0.0F).texture(u2, v2).color(color); vertexConsumer.vertex(matrix4f, x2, y2, 0).texture(u2, v2).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0.0F).texture(u2, v1).color(color); vertexConsumer.vertex(matrix4f, x2, y1, 0).texture(u2, v1).color(color);
matrices.pop(); matrices.pop();
} }
// ----------------------------
// Items
// ----------------------------
@Override
public void drawItem(ItemStackRef item, int x, int y) {
drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y,
int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed,
int z) {
if (stack.isEmpty())
return;
SaturnClient.client.getItemModelManager().update(itemRenderState, stack, ModelTransformationMode.GUI,
false, world, entity, seed);
matrices.push();
matrices.translate(x + 8, y + 8, 150 + (itemRenderState.hasDepth() ? z : 0));
try {
matrices.scale(16.0f, -16.0f, 16.0f);
boolean disableLighting = !itemRenderState.isSideLit();
if (disableLighting) {
draw();
DiffuseLighting.disableGuiDepthLighting();
}
itemRenderState.render(matrices, vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
draw();
if (disableLighting)
DiffuseLighting.enableGuiDepthLighting();
} catch (Throwable e) {
CrashReport crashReport = CrashReport.create(e, "Rendering item");
CrashReportSection section = crashReport.addElement("Item being rendered");
section.add("Item Type", () -> String.valueOf(stack.getItem()));
section.add("Item Components", () -> String.valueOf(stack.getComponents()));
section.add("Item Foil", () -> String.valueOf(stack.hasGlint()));
throw new CrashException(crashReport);
}
matrices.pop();
}
// ----------------------------
// Scissor / Clipping
// ----------------------------
@Override @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(matrices.peek().getPositionMatrix());
this.setScissor(this.scissorStack.push(screenRect)); setScissor(scissorStack.push(screenRect));
} }
@Override @Override
public void disableScissor() { public void disableScissor() {
this.setScissor(this.scissorStack.pop()); setScissor(scissorStack.pop());
} }
@Override @Override
public boolean scissorContains(int x, int y) { public boolean scissorContains(int x, int y) {
return this.scissorStack.containsPoint(x, y); return scissorStack.containsPoint(x, y);
} }
private void setScissor(@Nullable ScreenRect rect) { private void setScissor(@Nullable ScreenRect rect) {
this.draw(); draw();
if (rect != null) { if (rect != null) {
Window window = SaturnClient.client.getWindow(); Window window = SaturnClient.client.getWindow();
int i = window.getFramebufferHeight(); int framebufferHeight = window.getFramebufferHeight();
double d = window.getScaleFactor(); double scaleFactor = window.getScaleFactor();
double e = (double) rect.getLeft() * d; RenderSystem.enableScissor(
double f = (double) i - (double) rect.getBottom() * d; (int) (rect.getLeft() * scaleFactor),
double g = (double) rect.width() * d; (int) (framebufferHeight - rect.getBottom() * scaleFactor),
double h = (double) rect.height() * d; Math.max(0, (int) (rect.width() * scaleFactor)),
RenderSystem.enableScissor((int) e, (int) f, Math.max(0, (int) g), Math.max(0, (int) h)); Math.max(0, (int) (rect.height() * scaleFactor)));
} else { } else {
RenderSystem.disableScissor(); RenderSystem.disableScissor();
} }
}
@Override
public void draw() {
this.vertexConsumers.draw();
}
public void draw(Consumer<VertexConsumerProvider> drawer) {
drawer.accept(this.vertexConsumers);
this.vertexConsumers.draw();
} }
static class ScissorStack { static class ScissorStack {
@@ -372,132 +404,4 @@ public class RenderScopeImpl implements RenderScope {
return this.stack.isEmpty() ? true : this.stack.peek().contains(p_329411_, p_333404_); return this.stack.isEmpty() ? true : this.stack.peek().contains(p_329411_, p_333404_);
} }
} }
@Override
public void drawItem(ItemStackRef item, int x, int y) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed, int z) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, (ItemStack) (Object) stack, x, y, seed, z);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y) {
this.drawItemWithoutEntity(stack, x, y, 0);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y, int seed) {
this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y,
int seed) {
this.drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed,
int z) {
if (!stack.isEmpty()) {
SaturnClient.client.getItemModelManager().update(this.itemRenderState, stack, ModelTransformationMode.GUI,
false, world, entity, seed);
this.matrices.push();
this.matrices.translate((float) (x + 8), (float) (y + 8),
(float) (150 + (this.itemRenderState.hasDepth() ? z : 0)));
try {
this.matrices.scale(16.0F, -16.0F, 16.0F);
boolean bl = !this.itemRenderState.isSideLit();
if (bl) {
this.draw();
DiffuseLighting.disableGuiDepthLighting();
}
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
this.draw();
if (bl) {
DiffuseLighting.enableGuiDepthLighting();
}
} catch (Throwable var11) {
CrashReport crashReport = CrashReport.create(var11, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered");
crashReportSection.add("Item Type", () -> {
return String.valueOf(stack.getItem());
});
crashReportSection.add("Item Components", () -> {
return String.valueOf(stack.getComponents());
});
crashReportSection.add("Item Foil", () -> {
return String.valueOf(stack.hasGlint());
});
throw new CrashException(crashReport);
}
this.matrices.pop();
}
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
this.drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite;
if (color == 0)
return;
if (width != 0 && height != 0) {
this.drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, sprite.getMinU(), sprite.getMaxU(),
sprite.getMinV(), sprite.getMaxV(), color);
}
}
public void fill(int x1, int y1, int x2, int y2, int color) {
this.fill(x1, y1, x2, y2, 0, color);
}
public void fill(int x1, int y1, int x2, int y2, int z, int color) {
this.fill(RenderLayer.getGui(), x1, y1, x2, y2, z, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int color) {
this.fill(layer, x1, y1, x2, y2, 0, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int i;
if (x1 < x2) {
i = x1;
x1 = x2;
x2 = i;
}
if (y1 < y2) {
i = y1;
y1 = y2;
y2 = i;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, (float) z).color(color);
}
public void drawBorder(int x, int y, int width, int height, int color) {
this.fill(x, y, x + width, y + 1, color);
this.fill(x, y + height - 1, x + width, y + height, color);
this.fill(x, y + 1, x + 1, y + height - 1, color);
this.fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
} }
@@ -65,8 +65,8 @@ public class RenderMixin {
ModLayout dim = hud.getDimensions(); ModLayout dim = hud.getDimensions();
scope.getMatrixStack().push(); scope.getMatrixStack().push();
scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value, 0f); scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value);
scope.getMatrixStack().scale(dim.scale.value, dim.scale.value, 1.0f); scope.getMatrixStack().scale(dim.scale.value, dim.scale.value);
if (dim.renderBackground) { if (dim.renderBackground) {
scope.drawRoundedRectangle(0, 0, dim.width, dim.height, scope.drawRoundedRectangle(0, 0, dim.width, dim.height,
@@ -1,45 +1,49 @@
package org.saturnclient.impl.mixins; package org.saturnclient.impl.mixins;
import org.joml.Quaternionfc; import org.joml.Quaternionfc;
import org.saturnclient.common.ref.render.MatrixStackRef; import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.RotationAxis;
@Mixin(MatrixStack.class) @Mixin(MatrixStack.class)
public abstract class MatrixStackMixin implements MatrixStackRef { public abstract class MatrixStackMixin implements MatrixStackRef {
@Shadow
public abstract void translate(double x, double y, double z);
@Shadow
public abstract void translate(float x, float y, float z);
@Shadow
public abstract void scale(float x, float y, float z);
@Shadow
public abstract void multiply(Quaternionfc quaternion);
@Shadow
public abstract void multiply(Quaternionfc quaternion, float originX, float originY, float originZ);
@Shadow @Shadow
public abstract void push(); public abstract void push();
@Shadow @Shadow
public abstract void pop(); public abstract void pop();
@Invoker("peek")
public abstract MatrixStack.Entry peekM();
@Shadow @Shadow
public abstract boolean isEmpty(); public abstract void translate(float x, float y, float z);
@Shadow @Shadow
public abstract void loadIdentity(); public abstract void scale(float x, float y, float z);
@Shadow
public abstract void multiply(Quaternionfc quaternion);
@Shadow
public abstract void multiply(Quaternionfc quaternion, float originX, float originY, float originZ);
@Override @Override
public void multiply(QuaternionfRef quaternion) { public void translate(float x, float y) {
this.multiply((Quaternionfc) quaternion); translate(x, y, 0);
} }
@Override @Override
public void multiply(QuaternionfRef quaternion, float originX, float originY, float originZ) { public void scale(float x, float y) {
this.multiply((Quaternionfc) quaternion, originX, originY, originZ); scale(x, y, 1.0f);
} }
@Override @Override
public Object peek() { public void rotate(float angle, float originX, float originY, float originZ) {
return this.peekM(); multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle), originX, originY, originZ);
}
@Override
public void rotate(float angle) {
multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle));
} }
} }
@@ -3,7 +3,6 @@ package org.saturnclient.impl.ui;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.ui.ElementContext; import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
@@ -51,27 +50,28 @@ public class EntityDrawerImpl implements EntityDrawer {
public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f, public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f,
Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) { Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) {
renderScope.getMatrixStack().push(); if (renderScope instanceof RenderScopeImpl scopeImpl) {
renderScope.getMatrixStack().translate((double) x, (double) y, 50.0); scopeImpl.matrices.push();
renderScope.getMatrixStack().scale(size, size, -size); scopeImpl.matrices.translate((double) x, (double) y, 0);
renderScope.getMatrixStack().translate(vector3f.x, vector3f.y, vector3f.z); scopeImpl.matrices.scale(size, size, -size);
renderScope.getMatrixStack().multiply((QuaternionfRef) quaternionf); scopeImpl.matrices.translate(vector3f.x, vector3f.y, vector3f.z);
renderScope.draw(); scopeImpl.matrices.multiply(quaternionf);
DiffuseLighting.disableGuiDepthLighting(); scopeImpl.draw();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher(); DiffuseLighting.disableGuiDepthLighting();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false); entityRenderDispatcher.setRenderShadows(false);
if (renderScope instanceof RenderScopeImpl r) { scopeImpl.draw((vertexConsumers) -> {
r.draw((vertexConsumers) -> {
entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F, entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F,
r.matrices, vertexConsumers, scopeImpl.matrices, vertexConsumers, 15728880);
15728880);
}); });
scopeImpl.draw();
entityRenderDispatcher.setRenderShadows(true);
scopeImpl.getMatrixStack().pop();
DiffuseLighting.enableGuiDepthLighting();
} }
renderScope.draw();
entityRenderDispatcher.setRenderShadows(true);
renderScope.getMatrixStack().pop();
DiffuseLighting.enableGuiDepthLighting();
} }
@Override @Override
@@ -10,7 +10,6 @@ import org.joml.Matrix4f;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.common.provider.Providers;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.asset.SpriteRef; import org.saturnclient.common.ref.asset.SpriteRef;
import org.saturnclient.common.ref.game.ItemStackRef; import org.saturnclient.common.ref.game.ItemStackRef;
@@ -35,23 +34,29 @@ import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.Window; import net.minecraft.client.util.Window;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemDisplayContext; import net.minecraft.item.ItemDisplayContext;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.crash.CrashException; import net.minecraft.util.crash.CrashException;
import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashReportSection; import net.minecraft.util.crash.CrashReportSection;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World; import net.minecraft.world.World;
public class RenderScopeImpl implements RenderScope { public class RenderScopeImpl implements RenderScope {
// ----------------------------
// Fields
// ----------------------------
public MatrixStack matrices; public MatrixStack matrices;
public VertexConsumerProvider.Immediate vertexConsumers; public VertexConsumerProvider.Immediate vertexConsumers;
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;
// ----------------------------
// Constructors
// ----------------------------
public RenderScopeImpl(DrawContext context) { public RenderScopeImpl(DrawContext context) {
this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers()); this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers());
} }
@@ -63,11 +68,17 @@ public class RenderScopeImpl implements RenderScope {
this.itemRenderState = new ItemRenderState(); this.itemRenderState = new ItemRenderState();
} }
// ----------------------------
// Matrix & Transform
// ----------------------------
@Override @Override
public MatrixStackRef getMatrixStack() { public MatrixStackRef getMatrixStack() {
return (MatrixStackRef) matrices; return (MatrixStackRef) matrices;
} }
// ----------------------------
// Color & Opacity
// ----------------------------
@Override @Override
public void setOpacity(float alpha) { public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24; this.opacity = (int) (alpha * 255) << 24;
@@ -81,132 +92,12 @@ public class RenderScopeImpl implements RenderScope {
return (mixedAlpha << 24) | (color & 0x00FFFFFF); return (mixedAlpha << 24) | (color & 0x00FFFFFF);
} }
// ----------------------------
// Draw / Window Info
// ----------------------------
@Override @Override
public void drawRect(int x, int y, int width, int height, int color) { public void draw() {
if (color == 0) this.vertexConsumers.draw();
return;
color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
int i;
if (x1 < x2) {
i = x1;
x1 = x2;
x2 = i;
}
if (y1 < y2) {
i = y1;
y1 = y2;
y2 = i;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui());
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 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) {
drawText(1.0f, text, x, y, font, color);
}
@Override
public void drawText(float scale, String text, int x, int y, int font, int color) {
if (color == 0)
return;
if (font == 0) {
scale *= 2;
}
int i = 0;
for (String line : text.split("\n")) {
color = getColor(color);
matrices.push();
matrices.translate(x, y + (i * Fonts.getHeight()), 0);
matrices.scale(scale, scale, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer;
textRenderer.draw((Text) Fonts.setFont(line, font), 0,
font == 0 ? 1 : 7, color, false,
this.matrices.peek().getPositionMatrix(),
this.vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
matrices.pop();
i++;
}
}
private void drawRoundedCorner(int width, int height, int radius, int color) {
int w = width * 20;
int h = height * 20;
for (int y = 0; y < h; y++) {
int startX = 0;
if (y < radius) {
double dy = radius - y - 0.5;
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
startX = radius - (int) dx;
}
this.drawRect(startX, y, w - startX, 1, color);
}
}
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
// Top
this.matrices.push();
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerWidth, cornerHeight, radius * 10, color);
this.matrices.pop();
// Bottom
this.matrices.push();
this.matrices.translate(cornerWidth, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(90));
this.matrices.translate(0, -cornerWidth, 0);
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerHeight, cornerWidth, radius * 10, color);
this.matrices.pop();
}
@Override
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
if (color == 0)
return;
radius = Math.min(radius, Math.min(width, height));
int cornerWidth = width / 2;
int cornerHeight = height / 2;
this.matrices.push();
this.matrices.translate(x, y, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.translate(cornerWidth * 2, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(180));
this.matrices.translate(0, 0, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.pop();
} }
@Override @Override
@@ -219,66 +110,167 @@ public class RenderScopeImpl implements RenderScope {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getScaledHeight();
} }
public void draw(Consumer<VertexConsumerProvider> drawer) {
drawer.accept(this.vertexConsumers);
this.vertexConsumers.draw();
}
// ----------------------------
// Shapes
// ----------------------------
@Override @Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) { public void drawRectangle(int x, int y, int width, int height, int color) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef 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);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWith,
int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public 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) {
this.drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0.0F) / (float) textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color);
}
/* Minecraft sprites */
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith,
int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth,
int regionHeight, int textureWidth, int textureHeight, int color) {
this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float) textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color);
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1,
float v2, int color) {
if (sprite.toString().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg(Providers.saturn.getClient(),
(IdentifierRef) (Object) sprite,
(x2 - x1) * 2, (y2 - y1) * 2);
}
if (color == 0) if (color == 0)
return; return;
color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui());
vertexConsumer.vertex(matrix4f, x1, y1, 0).color(color);
vertexConsumer.vertex(matrix4f, x1, y2, 0).color(color);
vertexConsumer.vertex(matrix4f, x2, y2, 0).color(color);
vertexConsumer.vertex(matrix4f, x2, y1, 0).color(color);
}
@Override
public void fill(int x1, int y1, int x2, int y2, int color) {
fill(x1, y1, x2, y2, 0, color);
}
public void fill(int x1, int y1, int x2, int y2, int z, int color) {
fill(RenderLayer.getGui(), x1, y1, x2, y2, z, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int color) {
fill(layer, x1, y1, x2, y2, 0, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.vertex(matrix4f, x1, y1, z).color(color);
vertexConsumer.vertex(matrix4f, x1, y2, z).color(color);
vertexConsumer.vertex(matrix4f, x2, y2, z).color(color);
vertexConsumer.vertex(matrix4f, x2, y1, z).color(color);
}
@Override
public void drawBorder(int x, int y, int width, int height, int color) {
fill(x, y, x + width, y + 1, color);
fill(x, y + height - 1, x + width, y + height, color);
fill(x, y + 1, x + 1, y + height - 1, color);
fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
// ----------------------------
// Text
// ----------------------------
@Override
public void drawText(String text, int x, int y, int font, int 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) {
if (color == 0)
return;
if (font == 0)
scale *= 2;
int i = 0;
for (String line : text.split("\n")) {
color = getColor(color);
matrices.push();
matrices.translate(x, y + i * Fonts.getHeight(), 0);
matrices.scale(scale, scale, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer;
textRenderer.draw((Text) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false,
matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
matrices.pop();
i++;
}
}
// ----------------------------
// Textures & Sprites
// ----------------------------
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight) {
drawTexture(sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public 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) {
drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0.0f) / textureWidth, (u + regionWidth) / textureWidth,
(v + 0.0f) / textureHeight, (v + regionHeight) / textureHeight, color);
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite;
if (color == 0)
return;
if (width != 0 && height != 0) {
drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height,
sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV(), color);
}
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2,
float u1, float u2, float v1, float v2, int color) {
if (sprite.toString().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg((IdentifierRef) (Object) sprite, (x2 - x1) * 2,
(y2 - y1) * 2);
}
if (color == 0)
return;
x1 *= 4; x1 *= 4;
x2 *= 4; x2 *= 4;
y1 *= 4; y1 *= 4;
@@ -287,58 +279,104 @@ public class RenderScopeImpl implements RenderScope {
matrices.push(); matrices.push();
matrices.scale(0.25f, 0.25f, 1.0f); matrices.scale(0.25f, 0.25f, 1.0f);
RenderLayer renderLayer = (RenderLayer) RenderLayer.getGuiTextured(sprite); RenderLayer renderLayer = RenderLayer.getGuiTextured(sprite);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); Matrix4f matrix4f = matrices.peek().getPositionMatrix();
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(renderLayer); VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0.0F).texture(u1, v1).color(color); vertexConsumer.vertex(matrix4f, x1, y1, 0).texture(u1, v1).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0.0F).texture(u1, v2).color(color); vertexConsumer.vertex(matrix4f, x1, y2, 0).texture(u1, v2).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 0.0F).texture(u2, v2).color(color); vertexConsumer.vertex(matrix4f, x2, y2, 0).texture(u2, v2).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0.0F).texture(u2, v1).color(color); vertexConsumer.vertex(matrix4f, x2, y1, 0).texture(u2, v1).color(color);
matrices.pop(); matrices.pop();
} }
// ----------------------------
// Items
// ----------------------------
@Override
public void drawItem(ItemStackRef item, int x, int y) {
drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y,
int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed,
int z) {
if (stack.isEmpty())
return;
SaturnClient.client.getItemModelManager().update(itemRenderState, stack, ItemDisplayContext.GUI, world, entity,
seed);
if (!stack.isEmpty()) {
SaturnClient.client.getItemModelManager().clearAndUpdate(this.itemRenderState, stack,
ItemDisplayContext.GUI, world,
entity, seed);
this.matrices.push();
this.matrices.translate((float) (x + 8), (float) (y + 8), (float) (150 + z));
try {
this.matrices.scale(16.0F, -16.0F, 16.0F);
boolean bl = !this.itemRenderState.isSideLit();
if (bl) {
this.draw();
DiffuseLighting.disableGuiDepthLighting();
}
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
this.draw();
if (bl) {
DiffuseLighting.enableGuiDepthLighting();
}
} catch (Throwable throwable) {
CrashReport crashReport = CrashReport.create(throwable, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered");
crashReportSection.add("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.add("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.add("Item Foil", () -> String.valueOf(stack.hasGlint()));
throw new CrashException(crashReport);
}
this.matrices.pop();
}
}
// ----------------------------
// Scissor / Clipping
// ----------------------------
@Override @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(matrices.peek().getPositionMatrix());
this.setScissor(this.scissorStack.push(screenRect)); setScissor(scissorStack.push(screenRect));
} }
@Override @Override
public void disableScissor() { public void disableScissor() {
this.setScissor(this.scissorStack.pop()); setScissor(scissorStack.pop());
} }
@Override @Override
public boolean scissorContains(int x, int y) { public boolean scissorContains(int x, int y) {
return this.scissorStack.containsPoint(x, y); return scissorStack.containsPoint(x, y);
} }
private void setScissor(@Nullable ScreenRect rect) { private void setScissor(@Nullable ScreenRect rect) {
this.draw(); draw();
if (rect != null) { if (rect != null) {
Window window = SaturnClient.client.getWindow(); Window window = SaturnClient.client.getWindow();
int i = window.getFramebufferHeight(); int framebufferHeight = window.getFramebufferHeight();
double d = window.getScaleFactor(); double scaleFactor = window.getScaleFactor();
double e = (double) rect.getLeft() * d; RenderSystem.enableScissor(
double f = (double) i - (double) rect.getBottom() * d; (int) (rect.getLeft() * scaleFactor),
double g = (double) rect.width() * d; (int) (framebufferHeight - rect.getBottom() * scaleFactor),
double h = (double) rect.height() * d; Math.max(0, (int) (rect.width() * scaleFactor)),
RenderSystem.enableScissor((int) e, (int) f, Math.max(0, (int) g), Math.max(0, (int) h)); Math.max(0, (int) (rect.height() * scaleFactor)));
} else { } else {
RenderSystem.disableScissor(); RenderSystem.disableScissor();
} }
}
@Override
public void draw() {
this.vertexConsumers.draw();
}
public void draw(Consumer<VertexConsumerProvider> drawer) {
drawer.accept(this.vertexConsumers);
this.vertexConsumers.draw();
} }
static class ScissorStack { static class ScissorStack {
@@ -371,131 +409,4 @@ public class RenderScopeImpl implements RenderScope {
return this.stack.isEmpty() ? true : this.stack.peek().contains(p_329411_, p_333404_); return this.stack.isEmpty() ? true : this.stack.peek().contains(p_329411_, p_333404_);
} }
} }
@Override
public void drawItem(ItemStackRef item, int x, int y) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed, int z) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, (ItemStack) (Object) stack, x, y, seed, z);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y) {
this.drawItemWithoutEntity(stack, x, y, 0);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y, int seed) {
this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y,
int seed) {
this.drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed,
int z) {
if (!stack.isEmpty()) {
SaturnClient.client.getItemModelManager().update(this.itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
this.matrices.push();
this.matrices.translate((float) (x + 8), (float) (y + 8),
(float) (150 + z)); //always has depth
try {
this.matrices.scale(16.0F, -16.0F, 16.0F);
boolean bl = !this.itemRenderState.isSideLit();
if (bl) {
this.draw();
DiffuseLighting.disableGuiDepthLighting();
}
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV);
this.draw();
if (bl) {
DiffuseLighting.enableGuiDepthLighting();
}
} catch (Throwable var11) {
CrashReport crashReport = CrashReport.create(var11, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered");
crashReportSection.add("Item Type", () -> {
return String.valueOf(stack.getItem());
});
crashReportSection.add("Item Components", () -> {
return String.valueOf(stack.getComponents());
});
crashReportSection.add("Item Foil", () -> {
return String.valueOf(stack.hasGlint());
});
throw new CrashException(crashReport);
}
this.matrices.pop();
}
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
this.drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite;
if (color == 0)
return;
if (width != 0 && height != 0) {
this.drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, sprite.getMinU(), sprite.getMaxU(),
sprite.getMinV(), sprite.getMaxV(), color);
}
}
public void fill(int x1, int y1, int x2, int y2, int color) {
this.fill(x1, y1, x2, y2, 0, color);
}
public void fill(int x1, int y1, int x2, int y2, int z, int color) {
this.fill(RenderLayer.getGui(), x1, y1, x2, y2, z, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int color) {
this.fill(layer, x1, y1, x2, y2, 0, color);
}
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int i;
if (x1 < x2) {
i = x1;
x1 = x2;
x2 = i;
}
if (y1 < y2) {
i = y1;
y1 = y2;
y2 = i;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, (float) z).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, (float) z).color(color);
}
public void drawBorder(int x, int y, int width, int height, int color) {
this.fill(x, y, x + width, y + 1, color);
this.fill(x, y + height - 1, x + width, y + height, color);
this.fill(x, y + 1, x + 1, y + height - 1, color);
this.fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
} }
@@ -62,8 +62,8 @@ public class RenderMixin {
ModLayout dim = hud.getDimensions(); ModLayout dim = hud.getDimensions();
scope.getMatrixStack().push(); scope.getMatrixStack().push();
scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value, 0f); scope.getMatrixStack().translate(dim.x.value, (float) dim.y.value);
scope.getMatrixStack().scale(dim.scale.value, dim.scale.value, 1.0f); scope.getMatrixStack().scale(dim.scale.value, dim.scale.value);
if (dim.renderBackground) { if (dim.renderBackground) {
scope.drawRoundedRectangle(0, 0, dim.width, dim.height, scope.drawRoundedRectangle(0, 0, dim.width, dim.height,
@@ -1,45 +0,0 @@
package org.saturnclient.impl.mixins;
import org.joml.Quaternionfc;
import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.client.util.math.MatrixStack;
@Mixin(MatrixStack.class)
public abstract class MatrixStackMixin implements MatrixStackRef {
@Shadow
public abstract void translate(double x, double y, double z);
@Shadow
public abstract void translate(float x, float y, float z);
@Shadow
public abstract void scale(float x, float y, float z);
@Shadow
public abstract void multiply(Quaternionfc quaternion);
@Shadow
public abstract void multiply(Quaternionfc quaternion, float originX, float originY, float originZ);
@Shadow
public abstract void push();
@Shadow
public abstract void pop();
@Invoker("peek")
public abstract MatrixStack.Entry peekM();
@Shadow
public abstract boolean isEmpty();
@Shadow
public abstract void loadIdentity();
@Override
public void multiply(QuaternionfRef quaternion) {
this.multiply((Quaternionfc) quaternion);
}
@Override
public void multiply(QuaternionfRef quaternion, float originX, float originY, float originZ) {
this.multiply((Quaternionfc) quaternion, originX, originY, originZ);
}
@Override
public Object peek() {
return this.peekM();
}
}
@@ -9,9 +9,6 @@ import org.saturnclient.common.ref.game.MinecraftClientRef;
import org.saturnclient.impl.cosmetics.utils.IdentifierUtils; import org.saturnclient.impl.cosmetics.utils.IdentifierUtils;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.util.Identifier;
public class SaturnProviderImpl implements SaturnProvider { public class SaturnProviderImpl implements SaturnProvider {
@Override @Override
public MinecraftClientRef getClient() { public MinecraftClientRef getClient() {
@@ -1,94 +1,44 @@
package org.saturnclient.impl.ref; package org.saturnclient.impl.ref;
import java.util.ArrayDeque;
import java.util.Deque;
import org.joml.Matrix3x2fStack; import org.joml.Matrix3x2fStack;
import org.saturnclient.common.ref.render.MatrixStackRef; import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.common.ref.render.QuaternionfRef;
public class Matrix3x2fStackRef implements MatrixStackRef { public class Matrix3x2fStackRef implements MatrixStackRef {
public final Matrix3x2fStack stack; public final Matrix3x2fStack stack;
// Our custom stack stores the reverse transforms
private final Deque<Transform> customStack = new ArrayDeque<>();
public Matrix3x2fStackRef(Matrix3x2fStack stack) { public Matrix3x2fStackRef(Matrix3x2fStack stack) {
this.stack = stack; this.stack = stack;
} }
@Override @Override
public void push() { public void push() {
// Push a new empty Transform stack.pushMatrix();
customStack.push(new Transform());
} }
@Override @Override
public void pop() { public void pop() {
if (customStack.isEmpty()) stack.popMatrix();
return;
// Apply inverse transforms in reverse order
Transform t = customStack.pop();
if (t.scaleX != 1 || t.scaleY != 1)
stack.scale(1f / t.scaleX, 1f / t.scaleY);
stack.translate(-t.translateX, -t.translateY);
// rotation inversion can be added here if needed
} }
@Override @Override
public void scale(float x, float y, float z) { public void scale(float x, float y) {
stack.scale(x, y); stack.scale(x, y);
if (!customStack.isEmpty()) {
Transform t = customStack.peek();
t.scaleX *= x;
t.scaleY *= y;
}
} }
@Override @Override
public void translate(float x, float y, float z) { public void translate(float x, float y) {
stack.translate(x, y); stack.translate(x, y);
if (!customStack.isEmpty()) {
Transform t = customStack.peek();
t.translateX += x;
t.translateY += y;
}
} }
@Override @Override
public void translate(double x, double y, double z) { public void rotate(float angle) {
translate((float) x, (float) y, (float) z); stack.rotate((float) Math.toRadians(angle));
} }
@Override @Override
public void multiply(QuaternionfRef quaternion) { public void rotate(float angle, float originX, float originY, float originZ) {
// Not implemented yet translate(originX, originY);
} rotate(angle);
translate(-originX, -originY);
@Override
public void multiply(QuaternionfRef quaternion, float originX, float originY, float originZ) {
// Not implemented yet
}
@Override
public void loadIdentity() {
customStack.clear();
}
@Override
public Object peek() {
return null;
}
@Override
public boolean isEmpty() {
return customStack.isEmpty();
}
private static class Transform {
float scaleX = 1f, scaleY = 1f;
float translateX = 0f, translateY = 0f;
// rotation can be added if needed
} }
} }
@@ -3,83 +3,68 @@ package org.saturnclient.impl.ui;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.saturnclient.common.ref.render.QuaternionfRef;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
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.SkinPreview.EntityDrawer; import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
public class EntityDrawerImpl implements EntityDrawer { public class EntityDrawerImpl implements EntityDrawer {
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float f,
float mouseX,
float mouseY, LivingEntity entity, float angle, boolean negativeAngle) {
float g = (float) (x1 + x2) / 2.0F;
float h = (float) (y1 + y2) / 2.0F;
renderScope.enableScissor(0, 6, x2, y2);
float i = (float) Math.atan((double) ((g - mouseX) / 40.0F));
float j = (float) Math.atan((double) ((h - mouseY) / 40.0F));
Quaternionf quaternionf = (new Quaternionf()).rotateZ(3.1415927F);
float k = entity.bodyYaw;
float l = entity.getYaw();
float m = entity.getPitch();
float n = entity.lastHeadYaw;
float o = entity.headYaw;
entity.setYaw(angle);
entity.bodyYaw = angle;
entity.setPitch(-(j * 20.0F));
entity.headYaw = negativeAngle ? (i * 40.0F) + 180f : -(i * 40.0F);
entity.lastHeadYaw = entity.getHeadYaw();
entity.setCustomNameVisible(false);
float p = entity.getScale();
Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + f * p, 0.0F);
float q = (float) size / p;
drawEntity(renderScope, g, h, q, vector3f, quaternionf, null, entity);
entity.setCustomNameVisible(true);
entity.bodyYaw = k;
entity.setYaw(l);
entity.setPitch(m);
entity.lastHeadYaw = n;
entity.headYaw = o;
renderScope.disableScissor();
}
public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f,
Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) {
renderScope.getMatrixStack().push();
renderScope.getMatrixStack().translate((double) x, (double) y, 50.0);
renderScope.getMatrixStack().scale(size, size, -size);
renderScope.getMatrixStack().translate(vector3f.x, vector3f.y, vector3f.z);
renderScope.getMatrixStack().multiply((QuaternionfRef) quaternionf);
renderScope.draw();
// DiffuseLighting.disableGuiDepthLighting();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false);
if (renderScope instanceof RenderScopeImpl r) {
// r.draw((vertexConsumers) -> {
// entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F,
// r.matrices, vertexConsumers,
// 15728880);
// });
}
renderScope.draw();
entityRenderDispatcher.setRenderShadows(true);
renderScope.getMatrixStack().pop();
// DiffuseLighting.enableGuiDepthLighting();
}
@Override @Override
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) { public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) {
LivingEntity entity = SaturnClient.client.player; LivingEntity entity = SaturnClient.client.player;
if (entity != null) { if (entity != null) {
drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale, entity, angle, drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale,
negativeAngle); SaturnClient.client.player);
} }
} }
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float scale,
float mouseX, float mouseY, LivingEntity entity) {
float f = (float) (x1 + x2) / 2.0F;
float g = (float) (y1 + y2) / 2.0F;
renderScope.enableScissor(x1, y1, x2, y2);
float h = (float) Math.atan((double) ((f - mouseX) / 40.0F));
float i = (float) Math.atan((double) ((g - mouseY) / 40.0F));
Quaternionf quaternionf = (new Quaternionf()).rotateZ((float) Math.PI);
Quaternionf quaternionf2 = (new Quaternionf()).rotateX(i * 20.0F * ((float) Math.PI / 180F));
quaternionf.mul(quaternionf2);
float j = entity.bodyYaw;
float k = entity.getYaw();
float l = entity.getPitch();
float m = entity.lastHeadYaw;
float n = entity.headYaw;
entity.bodyYaw = 180.0F + h * 20.0F;
entity.setYaw(180.0F + h * 40.0F);
entity.setPitch(-i * 20.0F);
entity.headYaw = entity.getYaw();
entity.lastHeadYaw = entity.getYaw();
float o = entity.getScale();
Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + scale * o, 0.0F);
float p = (float) size / o;
drawEntity(renderScope, x1, y1, x2, y2, p, vector3f, quaternionf, quaternionf2, entity);
entity.bodyYaw = j;
entity.setYaw(k);
entity.setPitch(l);
entity.lastHeadYaw = m;
entity.headYaw = n;
renderScope.disableScissor();
}
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, float scale,
Vector3f translation, Quaternionf rotation, @Nullable Quaternionf overrideCameraAngle,
LivingEntity entity) {
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
EntityRenderer<? super LivingEntity, ?> entityRenderer = entityRenderDispatcher.getRenderer(entity);
EntityRenderState entityRenderState = entityRenderer.getAndUpdateRenderState(entity, 1.0F);
entityRenderState.hitbox = null;
if (renderScope instanceof RenderScopeImpl i)
i.addEntity(entityRenderState, scale, translation, rotation, overrideCameraAngle, x1, y1, x2, y2);
}
} }
@@ -3,18 +3,15 @@ package org.saturnclient.impl.ui;
import java.util.ArrayDeque; 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 org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3x2f; import org.joml.Matrix3x2f;
import org.joml.Matrix3x2fStack; import org.joml.Matrix3x2fStack;
import org.joml.Matrix4f; import org.joml.Quaternionf;
import org.joml.Vector3f;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTextureView; import com.mojang.blaze3d.textures.GpuTextureView;
import org.saturnclient.common.provider.Providers;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.asset.SpriteRef; import org.saturnclient.common.ref.asset.SpriteRef;
import org.saturnclient.common.ref.game.ItemStackRef; import org.saturnclient.common.ref.game.ItemStackRef;
@@ -34,13 +31,14 @@ import net.minecraft.client.gui.render.state.GuiRenderState;
import net.minecraft.client.gui.render.state.ItemGuiElementRenderState; import net.minecraft.client.gui.render.state.ItemGuiElementRenderState;
import net.minecraft.client.gui.render.state.TextGuiElementRenderState; import net.minecraft.client.gui.render.state.TextGuiElementRenderState;
import net.minecraft.client.gui.render.state.TexturedQuadGuiElementRenderState; import net.minecraft.client.gui.render.state.TexturedQuadGuiElementRenderState;
import net.minecraft.client.gui.render.state.special.EntityGuiElementRenderState;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.item.ItemRenderState; import net.minecraft.client.render.item.ItemRenderState;
import net.minecraft.client.texture.GuiAtlasManager;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.TextureSetup; import net.minecraft.client.texture.TextureSetup;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemDisplayContext; import net.minecraft.item.ItemDisplayContext;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.crash.CrashException; import net.minecraft.util.crash.CrashException;
@@ -49,24 +47,21 @@ import net.minecraft.util.crash.CrashReportSection;
import net.minecraft.world.World; import net.minecraft.world.World;
public class RenderScopeImpl implements RenderScope { public class RenderScopeImpl implements RenderScope {
private final Matrix3x2fStackRef matrices;
private final GuiAtlasManager guiAtlasManager; public final Matrix3x2fStackRef matrices;
public final GuiRenderState state; public final GuiRenderState state;
private ScissorStack scissorStack; private ScissorStack scissorStack;
private int opacity = 255 << 24; private int opacity = 0xFF << 24;
private final ItemRenderState itemRenderState;
public RenderScopeImpl(DrawContext context) { public RenderScopeImpl(DrawContext context) {
this(context.getMatrices(), ((DrawContextAccessor) (Object) context).getState()); this(context.getMatrices(), ((DrawContextAccessor) (Object) context).getState());
} }
public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) { public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) {
this.state = state;
this.matrices = new Matrix3x2fStackRef(matrices); this.matrices = new Matrix3x2fStackRef(matrices);
this.guiAtlasManager = SaturnClient.client.getGuiAtlasManager(); this.state = state;
this.scissorStack = new ScissorStack(); this.scissorStack = new ScissorStack();
this.itemRenderState = new ItemRenderState();
} }
@Override @Override
@@ -76,7 +71,7 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public void setOpacity(float alpha) { public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24; this.opacity = ((int) (alpha * 255)) << 24;
} }
@Override @Override
@@ -90,38 +85,34 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public void fill(int x1, int y1, int x2, int y2, int color) { public void fill(int x1, int y1, int x2, int y2, int color) {
this.state.addSimpleElement( this.state.addSimpleElement(
new ColoredQuadGuiElementRenderState(RenderPipelines.GUI, TextureSetup.empty(), new ColoredQuadGuiElementRenderState(
RenderPipelines.GUI,
TextureSetup.empty(),
new Matrix3x2f(this.matrices.stack), new Matrix3x2f(this.matrices.stack),
x1, y1, x2, x1, y1, x2, y2, color, color,
y2, color, color, this.scissorStack.peekLast())); this.scissorStack.peekLast()));
} }
@Override @Override
public void fill(int x1, int y1, int x2, int y2, int z, int color) { public void drawRectangle(int x, int y, int width, int height, int color) {
this.fill(x1, y1, x2, y2, color);
}
@Override
public void drawRect(int x, int y, int width, int height, int color) {
if (color == 0) if (color == 0)
return; return;
color = getColor(color); color = getColor(color);
int x1 = x; int x1 = x;
int x2 = x + width; int x2 = x + width;
int y1 = y; int y1 = y;
int y2 = y + height; int y2 = y + height;
int i; if (x2 < x1) {
if (x1 < x2) { int tmp = x1;
i = x1;
x1 = x2; x1 = x2;
x2 = i; x2 = tmp;
} }
if (y2 < y1) {
if (y1 < y2) { int tmp = y1;
i = y1;
y1 = y2; y1 = y2;
y2 = i; y2 = tmp;
} }
this.fill(x1, y1, x2, y2, color); this.fill(x1, y1, x2, y2, color);
@@ -136,91 +127,31 @@ public class RenderScopeImpl implements RenderScope {
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;
if (font == 0) { if (font == 0)
scale *= 2; scale *= 2;
}
int i = 0; int lineIndex = 0;
for (String line : text.split("\n")) { for (String line : text.split("\n")) {
color = getColor(color); int finalColor = getColor(color);
this.state.addText(new TextGuiElementRenderState(SaturnClient.client.textRenderer,
((Text) Fonts.setFont(line, font)).asOrderedText(), new Matrix3x2f(this.matrices.stack), x, y,
color, 0, false, this.scissorStack.peekLast()));
matrices.push(); matrices.push();
matrices.translate(x, y + (i * Fonts.getHeight()), 0); matrices.translate(x, y + (lineIndex * Fonts.getHeight()));
matrices.scale(scale, scale, 0); matrices.scale(scale, scale);
i++;
this.state.addText(
new TextGuiElementRenderState(
SaturnClient.client.textRenderer,
((Text) Fonts.setFont(line, font)).asOrderedText(),
new Matrix3x2f(this.matrices.stack),
0, font == 0 ? 1 : 8,
finalColor, 0, false, this.scissorStack.peekLast()));
matrices.pop();
lineIndex++;
} }
} }
private void drawRoundedCorner(int width, int height, int radius, int color) {
int w = width * 20;
int h = height * 20;
for (int y = 0; y < h; y++) {
int startX = 0;
if (y < radius) {
double dy = radius - y - 0.5;
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
startX = radius - (int) dx;
}
this.drawRect(startX, y, w - startX, 1, color);
}
}
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
// Top
this.matrices.push();
this.matrices.scale(0.05f, 0.05f, 0);
this.drawRoundedCorner(cornerWidth, cornerHeight, radius * 10, color);
this.matrices.pop();
// Bottom
this.matrices.push();
this.matrices.translate(cornerWidth, cornerHeight * 2, 0);
this.matrices.stack.rotate((float) Math.toRadians(90));
this.matrices.translate(0, -cornerWidth, 0);
this.matrices.scale(0.05f, 0.05f, 0);
this.drawRoundedCorner(cornerHeight, cornerWidth, radius * 10, color);
this.matrices.pop();
}
@Override
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
if (color == 0)
return;
radius = Math.min(radius, Math.min(width, height));
int cornerWidth = width / 2;
int cornerHeight = height / 2;
this.matrices.push();
this.matrices.translate(x, y, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.translate(cornerWidth * 2, cornerHeight * 2, 0);
this.matrices.stack.rotate((float) Math.toRadians(90));
this.matrices.translate(0, 0, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.pop();
}
@Override @Override
public int getScaledWindowWidth() { public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getScaledWidth(); return SaturnClient.client.getWindow().getScaledWidth();
@@ -231,211 +162,184 @@ public class RenderScopeImpl implements RenderScope {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getScaledHeight();
} }
@Override // Texture rendering
public void drawTexture(IdentifierRef 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);
}
@Override @Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height) { public void drawTexture(IdentifierRef 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); drawTexture(sprite, x, y, u, v, width, height, -1);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
} }
@Override @Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWith, int regionWidth, int regionHeight, int textureWidth, int textureHeight) {
int regionHeight, int textureWidth, int textureHeight) { drawTexture(sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, -1);
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
} }
@Override @Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, public void drawTexture(IdentifierRef 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) { drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
this.drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height, (u + 0f) / textureWidth,
(u + 0.0F) / (float) textureWidth, (u + regionWidth) / textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight, (v + 0f) / textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color); (v + regionHeight) / textureHeight,
color);
} }
/* Minecraft sprites */ private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2,
float u1, float u2, float v1, float v2, int color) {
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier 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);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith,
int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth,
int regionHeight, int textureWidth, int textureHeight, int color) {
this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float) textureWidth,
(u + (float) regionWidth) / (float) textureWidth, (v + 0.0F) / (float) textureHeight,
(v + (float) regionHeight) / (float) textureHeight, color);
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1,
float v2, int color) {
GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager().getTexture(sprite).getGlTextureView();
if (color == 0) if (color == 0)
return; return;
x1 *= 4;
x2 *= 4;
y1 *= 4;
y2 *= 4;
color = getColor(color); color = getColor(color);
if (sprite.toString().endsWith(".svg")) { if (sprite.getPath().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg(Providers.saturn.getClient(), sprite = (Identifier) (Object) SvgTexture.getSvg(
(IdentifierRef) (Object) sprite, (IdentifierRef) (Object) sprite,
(x2 - x1) * 2, (y2 - y1) * 2); (x2 - x1) * 2, (y2 - y1) * 2);
} }
this.state.addSimpleElement(new TexturedQuadGuiElementRenderState(RenderPipelines.GUI, GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager()
TextureSetup.withoutGlTexture(gpuTextureView), new Matrix3x2f(this.matrices.stack), x1, y1, x2, y2, u1, u2, .getTexture(sprite).getGlTextureView();
v1, v2,
color, this.scissorStack.peekLast())); this.state.addSimpleElement(new TexturedQuadGuiElementRenderState(
RenderPipelines.GUI_TEXTURED,
TextureSetup.withoutGlTexture(gpuTextureView),
new Matrix3x2f(this.matrices.stack),
x1, y1, x2, y2, u1, u2, v1, v2, color,
this.scissorStack.peekLast()));
} }
// Scissor management
@Override @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)).transform(this.matrices.stack); ScreenRect rect = new ScreenRect(x1, y1, x2 - x1, y2 - y1).transform(this.matrices.stack);
this.scissorStack.push(screenRect); scissorStack.push(rect);
} }
@Override @Override
public void disableScissor() { public void disableScissor() {
this.scissorStack.pop(); scissorStack.pop();
} }
@Override @Override
public boolean scissorContains(int x, int y) { public boolean scissorContains(int x, int y) {
return this.scissorStack.contains(x, y); return scissorStack.contains(x, y);
} }
public static class ScissorStack { public static class ScissorStack {
private final Deque<ScreenRect> stack = new ArrayDeque(); private final Deque<ScreenRect> stack = new ArrayDeque<>();
ScissorStack() {
}
public ScreenRect push(ScreenRect rect) { public ScreenRect push(ScreenRect rect) {
ScreenRect screenRect = (ScreenRect) this.stack.peekLast(); ScreenRect last = stack.peekLast();
if (screenRect != null) { if (last != null) {
ScreenRect screenRect2 = (ScreenRect) Objects.requireNonNullElse(rect.intersection(screenRect), ScreenRect intersection = Objects.requireNonNullElse(rect.intersection(last), ScreenRect.empty());
ScreenRect.empty()); stack.addLast(intersection);
this.stack.addLast(screenRect2); return intersection;
return screenRect2;
} else { } else {
this.stack.addLast(rect); stack.addLast(rect);
return rect; return rect;
} }
} }
@Nullable @Nullable
public ScreenRect pop() { public ScreenRect pop() {
if (this.stack.isEmpty()) { if (stack.isEmpty())
throw new IllegalStateException("Scissor stack underflow"); throw new IllegalStateException("Scissor stack underflow");
} else { stack.removeLast();
this.stack.removeLast(); return stack.peekLast();
return (ScreenRect) this.stack.peekLast();
}
} }
@Nullable @Nullable
public ScreenRect peekLast() { public ScreenRect peekLast() {
return (ScreenRect) this.stack.peekLast(); return stack.peekLast();
} }
public boolean contains(int x, int y) { public boolean contains(int x, int y) {
return this.stack.isEmpty() ? true : ((ScreenRect) this.stack.peek()).contains(x, y); return stack.isEmpty() || stack.peekLast().contains(x, y);
} }
} }
// Item rendering
@Override @Override
public void drawItem(ItemStackRef item, int x, int y) { public void drawItem(ItemStackRef stack, int x, int y) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0); drawItem(null, SaturnClient.client.world, stack, x, y, 0);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, stack, x, y, seed);
}
@Override
public void drawItem(ItemStackRef stack, int x, int y, int seed, int z) {
this.drawItem(SaturnClient.client.player, SaturnClient.client.world, (ItemStack) (Object) stack, x, y, seed, z);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y) {
this.drawItemWithoutEntity(stack, x, y, 0);
}
@Override
public void drawItemWithoutEntity(ItemStackRef stack, int x, int y, int seed) {
this.drawItem((LivingEntity) null, SaturnClient.client.world, stack, x, y, seed);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y, private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y,
int seed) { int seed) {
this.drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0); drawItem(entity, world, (ItemStack) (Object) stack, 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,
int z) { int z) {
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
ItemRenderState itemRenderState = new ItemRenderState(); ItemRenderState state = new ItemRenderState();
SaturnClient.client.getItemModelManager().clearAndUpdate(itemRenderState, stack, ItemDisplayContext.GUI, SaturnClient.client.getItemModelManager().clearAndUpdate(state, stack, ItemDisplayContext.GUI, world,
world,
entity, seed); entity, seed);
try { try {
this.state.addItem(new ItemGuiElementRenderState(stack.getItem().getName().toString(), this.state.addItem(new ItemGuiElementRenderState(stack.getItem().getName().toString(),
new Matrix3x2f(this.matrices.stack), itemRenderState, x, y, this.scissorStack.peekLast())); new Matrix3x2f(this.matrices.stack), state, x, y, scissorStack.peekLast()));
} catch (Throwable throwable) { } catch (Throwable t) {
CrashReport crashReport = CrashReport.create(throwable, "Rendering item"); CrashReport report = CrashReport.create(t, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered"); CrashReportSection section = report.addElement("Item being rendered");
crashReportSection.add("Item Type", () -> String.valueOf(stack.getItem())); section.add("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.add("Item Components", () -> String.valueOf(stack.getComponents())); section.add("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.add("Item Foil", () -> String.valueOf(stack.hasGlint())); section.add("Item Foil", () -> String.valueOf(stack.hasGlint()));
throw new CrashException(crashReport); throw new CrashException(report);
} }
} }
} }
@Override
public void draw() {
}
@Override @Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) { public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
this.drawSpriteStretched(sprite, x, y, width, height, -1); drawSpriteStretched(sprite, x, y, width, height, -1);
} }
@Override @Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) { public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite; Sprite mcSprite = (Sprite) sprite;
if (color == 0) if (color == 0 || width == 0 || height == 0)
return; return;
if (width != 0 && height != 0) {
this.drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, sprite.getMinU(), sprite.getMaxU(), drawTexturedQuad(mcSprite.getAtlasId(), x, x + width, y, y + height,
sprite.getMinV(), sprite.getMaxV(), color); mcSprite.getMinU(), mcSprite.getMaxU(), mcSprite.getMinV(), mcSprite.getMaxV(), color);
} }
@Override
public void draw() {
// No-op for now
} }
public void drawBorder(int x, int y, int width, int height, int color) { public void drawBorder(int x, int y, int width, int height, int color) {
this.fill(x, y, x + width, y + 1, color); fill(x, y, x + width, y + 1, color);
this.fill(x, y + height - 1, x + width, y + height, color); fill(x, y + height - 1, x + width, y + height, color);
this.fill(x, y + 1, x + 1, y + height - 1, color); fill(x, y + 1, x + 1, y + height - 1, color);
this.fill(x + width - 1, y + 1, x + width, y + height - 1, color); fill(x + width - 1, y + 1, x + width, y + height - 1, color);
} }
}
public void addEntity(EntityRenderState entityState, float scale, Vector3f translation, Quaternionf rotation,
@Nullable Quaternionf overrideCameraAngle, int x1, int y1, int x2, int y2) {
Matrix3x2f mat = this.matrices.stack;
float offsetX = mat.m20;
float offsetY = mat.m21;
float scaleX = mat.m00; // current matrix X scale
float scaleY = mat.m11; // current matrix Y scale
int adjustedX1 = (int) (x1 * scaleX + offsetX);
int adjustedY1 = (int) (y1 * scaleY + offsetY);
int adjustedX2 = (int) (x2 * scaleX + offsetX);
int adjustedY2 = (int) (y2 * scaleY + offsetY);
float adjustedScale = scale * scaleX; // apply matrix scale to entity scale too
this.state.addSpecialElement(new EntityGuiElementRenderState(entityState, translation, rotation,
overrideCameraAngle, adjustedX1, adjustedY1, adjustedX2, adjustedY2, adjustedScale,
this.scissorStack.peekLast()));
}
}
@@ -3,21 +3,17 @@ package org.saturnclient.impl.ui;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.SaturnScreen; import org.saturnclient.ui.SaturnScreen;
import org.saturnclient.ui.SaturnScreen.ScreenProvider; import org.saturnclient.ui.SaturnScreen.ScreenProvider;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.PostEffectProcessor;
import net.minecraft.client.gui.CubeMapRenderer; import net.minecraft.client.gui.CubeMapRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.RotatingCubeMapRenderer; import net.minecraft.client.gui.RotatingCubeMapRenderer;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.DefaultFramebufferSet;
import net.minecraft.client.texture.ResourceTexture; import net.minecraft.client.texture.ResourceTexture;
import net.minecraft.client.texture.TextureManager; import net.minecraft.client.texture.TextureManager;
import net.minecraft.client.util.Pool;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -32,7 +28,6 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
ROTATING_PANORAMA_RENDERER = new RotatingCubeMapRenderer(PANORAMA_RENDERER); ROTATING_PANORAMA_RENDERER = new RotatingCubeMapRenderer(PANORAMA_RENDERER);
} }
private final Pool pool = new Pool(3);
public final SaturnScreen screen; public final SaturnScreen screen;
public static void preload(MinecraftClient client) { public static void preload(MinecraftClient client) {
@@ -56,7 +51,6 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
screen.init(); screen.init();
} }
@SuppressWarnings("deprecation")
@Override @Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) { public void render(DrawContext context, int mouseX, int mouseY, float delta) {
if (screen.start == null) { if (screen.start == null) {
@@ -67,24 +61,9 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
mouseX *= 2; mouseX *= 2;
mouseY *= 2; mouseY *= 2;
// if (client.world == null && client.getCurrentServerEntry() == null) { if (client.world == null && client.getCurrentServerEntry() == null) {
// ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, // ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, true);
// screen.backgroundOpacity, delta); }
// }
// PostEffectProcessor postEffectProcessor =
// this.client.getShaderLoader().loadPostEffect(
// Identifier.ofVanilla("blur"),
// DefaultFramebufferSet.MAIN_ONLY);
// if (postEffectProcessor != null) {
// float radius = screen.backgroundBlur * Math.min((float) elapsed / 700, 1.0f);
// postEffectProcessor.render(
// this.client.getFramebuffer(),
// this.pool,
// pass -> pass.setUniform("Radius", radius)
// );
// }
RenderScope renderScope = new RenderScopeImpl(context); RenderScope renderScope = new RenderScopeImpl(context);
@@ -7,7 +7,6 @@ import net.minecraft.client.util.InputUtil;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.client.ServiceClient;
import org.saturnclient.common.provider.Providers; import org.saturnclient.common.provider.Providers;
import org.saturnclient.ui.screens.EmoteWheel; import org.saturnclient.ui.screens.EmoteWheel;
import org.saturnclient.ui.screens.ShiftMenu; import org.saturnclient.ui.screens.ShiftMenu;
@@ -6,7 +6,6 @@
"client": [ "client": [
"IdentifierMixin", "IdentifierMixin",
"ItemStackMixin", "ItemStackMixin",
"MatrixStackMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"QuaternionfMixin", "QuaternionfMixin",
"WindowMixin", "WindowMixin",