Adds 26.1 as a Stonecutter version (step 3 of #39). Its jar also loads on the 26.1.1 and 26.1.2 hotfixes. Most of 26.1's changes are renames: the GUI's render methods became extract methods and GuiGraphics became GuiGraphicsExtractor, which Stonecutter replacements cover along with the moved render state package and GuiRenderState's add methods. The rest are version comments: - The menu panorama is drawn by GuiRenderer from vanilla's cube map; the new GuiRendererMixin swaps in Saturn's while a Saturn screen is open (empty on older versions). - The camera works out the FOV and aligns with its entity in alignWithEntity, so the zoom and freelook hooks move to CameraMixin. - Gamma and the menu blur are read while extracting render state. - The glass blur's post chain takes a Projection and its buffer. - The dragon's alpha render type is gone; capes use entityCutout. - Fabric API renamed KeyBindingHelper to KeyMappingHelper. The docs describe the 26.x build and Java 25. Co-Authored-By: Claude Opus 5.5 <[email protected]>
843 lines
31 KiB
Java
843 lines
31 KiB
Java
package org.saturnclient.impl.ui;
|
|
|
|
// 1.21.6 rewrote GUI rendering: render states and a 2D matrix stack (Matrix3x2fStack) instead of
|
|
// drawing into vertex consumers with a MatrixStack. This file has one implementation for each side.
|
|
//? if >=1.21.6 {
|
|
import java.util.ArrayDeque;
|
|
import java.util.Deque;
|
|
import java.util.HashSet;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.joml.Matrix3x2f;
|
|
import org.joml.Matrix3x2fStack;
|
|
import org.joml.Quaternionf;
|
|
import org.joml.Vector3f;
|
|
|
|
import com.mojang.blaze3d.textures.GpuTextureView;
|
|
|
|
import org.saturnclient.common.ref.asset.IdentifierRef;
|
|
import org.saturnclient.common.ref.asset.SpriteRef;
|
|
import org.saturnclient.common.ref.game.ItemStackRef;
|
|
import org.saturnclient.common.ref.render.MatrixStackRef;
|
|
import org.saturnclient.impl.ref.Matrix3x2fStackRef;
|
|
import org.saturnclient.saturnclient.SaturnClient;
|
|
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
|
import org.saturnclient.ui.RenderScope;
|
|
import org.saturnclient.ui.resources.Fonts;
|
|
import org.saturnclient.ui.resources.SvgTexture;
|
|
|
|
import net.minecraft.client.renderer.RenderPipelines;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
|
import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiTextRenderState;
|
|
import net.minecraft.client.gui.render.state.BlitRenderState;
|
|
import net.minecraft.client.gui.render.state.pip.GuiEntityRenderState;
|
|
import net.minecraft.client.renderer.entity.state.EntityRenderState;
|
|
//? if >=1.21.7 {
|
|
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
|
|
//?} else
|
|
//import net.minecraft.client.renderer.item.ItemStackRenderState;
|
|
import net.minecraft.client.renderer.texture.AbstractTexture;
|
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
|
import net.minecraft.client.gui.render.TextureSetup;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.item.ItemDisplayContext;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.world.level.Level;
|
|
|
|
public class RenderScopeImpl implements RenderScope {
|
|
|
|
public final Matrix3x2fStackRef matrices;
|
|
public final GuiRenderState state;
|
|
|
|
private ScissorStack scissorStack;
|
|
private int opacity = 0xFF << 24;
|
|
// The glass blurs made for this scope's frame
|
|
private final Set<Integer> capturedBlurs = new HashSet<>();
|
|
|
|
public RenderScopeImpl(GuiGraphics context) {
|
|
this(context.pose(), ((DrawContextAccessor) (Object) context).getState());
|
|
}
|
|
|
|
public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) {
|
|
this.matrices = new Matrix3x2fStackRef(matrices);
|
|
this.state = state;
|
|
this.scissorStack = new ScissorStack();
|
|
}
|
|
|
|
@Override
|
|
public MatrixStackRef getMatrixStack() {
|
|
return matrices;
|
|
}
|
|
|
|
@Override
|
|
public void setOpacity(float alpha) {
|
|
this.opacity = ((int) (alpha * 255)) << 24;
|
|
}
|
|
|
|
@Override
|
|
public int getColor(int color) {
|
|
int originalAlpha = (color >>> 24) & 0xFF;
|
|
int newAlpha = (opacity >>> 24) & 0xFF;
|
|
int mixedAlpha = (originalAlpha * newAlpha) / 255;
|
|
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
|
|
}
|
|
|
|
@Override
|
|
public void fill(int x1, int y1, int x2, int y2, int color) {
|
|
this.state.submitGuiElement(
|
|
new ColoredRectangleRenderState(
|
|
RenderPipelines.GUI,
|
|
TextureSetup.noTexture(),
|
|
new Matrix3x2f(this.matrices.stack),
|
|
x1, y1, x2, y2, color, color,
|
|
this.scissorStack.peekLast()));
|
|
}
|
|
|
|
@Override
|
|
public void drawRectangle(int x, int y, int width, int height, int color) {
|
|
if (color == 0)
|
|
return;
|
|
color = getColor(color);
|
|
|
|
int x1 = x;
|
|
int x2 = x + width;
|
|
int y1 = y;
|
|
int y2 = y + height;
|
|
|
|
if (x2 < x1) {
|
|
int tmp = x1;
|
|
x1 = x2;
|
|
x2 = tmp;
|
|
}
|
|
if (y2 < y1) {
|
|
int tmp = y1;
|
|
y1 = y2;
|
|
y2 = tmp;
|
|
}
|
|
|
|
this.fill(x1, y1, x2, y2, 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 lineIndex = 0;
|
|
for (String line : text.split("\n")) {
|
|
int finalColor = getColor(color);
|
|
|
|
matrices.push();
|
|
matrices.translate(x, y + (lineIndex * Fonts.getHeight()));
|
|
matrices.scale(scale, scale);
|
|
|
|
this.state.submitText(
|
|
new GuiTextRenderState(
|
|
SaturnClient.client.font,
|
|
((Component) Fonts.setFont(line, font)).getVisualOrderText(),
|
|
new Matrix3x2f(this.matrices.stack),
|
|
0, font == 0 ? 1 : 8,
|
|
//? if >=1.21.11 {
|
|
finalColor, 0, false, false, this.scissorStack.peekLast()));
|
|
//?} else
|
|
//finalColor, 0, false, this.scissorStack.peekLast()));
|
|
|
|
matrices.pop();
|
|
|
|
lineIndex++;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getScaledWindowWidth() {
|
|
return SaturnClient.client.getWindow().getGuiScaledWidth();
|
|
}
|
|
|
|
@Override
|
|
public int getScaledWindowHeight() {
|
|
return SaturnClient.client.getWindow().getGuiScaledHeight();
|
|
}
|
|
|
|
// Texture rendering
|
|
@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, -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
|
|
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 + 0f) / textureWidth,
|
|
(u + regionWidth) / textureWidth,
|
|
(v + 0f) / textureHeight,
|
|
(v + regionHeight) / 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 (color == 0)
|
|
return;
|
|
color = getColor(color);
|
|
|
|
if (sprite.getPath().endsWith(".svg")) {
|
|
sprite = (Identifier) (Object) SvgTexture.getSvg(
|
|
(IdentifierRef) (Object) sprite,
|
|
(x2 - x1) * 2, (y2 - y1) * 2);
|
|
}
|
|
|
|
GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager()
|
|
.getTexture(sprite).getTextureView();
|
|
|
|
//? if >=1.21.11
|
|
AbstractTexture abstractTexture = SaturnClient.client.getTextureManager().getTexture(sprite);
|
|
|
|
this.state.submitGuiElement(new BlitRenderState(
|
|
RenderPipelines.GUI_TEXTURED,
|
|
//? if >=1.21.11 {
|
|
TextureSetup.singleTexture(gpuTextureView, abstractTexture.getSampler()),
|
|
//?} else
|
|
//TextureSetup.singleTexture(gpuTextureView),
|
|
new Matrix3x2f(this.matrices.stack),
|
|
x1, y1, x2, y2, u1, u2, v1, v2, color,
|
|
this.scissorStack.peekLast()));
|
|
}
|
|
|
|
@Override
|
|
public void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
|
|
int color = getColor(0xFFFFFFFF);
|
|
if (mask == null || color >>> 24 == 0)
|
|
return;
|
|
|
|
if (capturedBlurs.add(blur)) {
|
|
GlassRenderer.captureBackdrop(blur);
|
|
}
|
|
|
|
AbstractTexture maskTexture = SaturnClient.client.getTextureManager().getTexture((Identifier) (Object) mask);
|
|
this.state.submitGuiElement(new BlitRenderState(
|
|
GlassRenderer.PIPELINE,
|
|
GlassRenderer.textures(maskTexture, blur),
|
|
new Matrix3x2f(this.matrices.stack),
|
|
x, y, x + width, y + height, 0, 1, 0, 1, color,
|
|
this.scissorStack.peekLast()));
|
|
}
|
|
|
|
// Scissor management
|
|
@Override
|
|
public void enableScissor(int x1, int y1, int x2, int y2) {
|
|
ScreenRectangle rect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1).transformAxisAligned(this.matrices.stack);
|
|
scissorStack.push(rect);
|
|
}
|
|
|
|
@Override
|
|
public void disableScissor() {
|
|
scissorStack.pop();
|
|
}
|
|
|
|
@Override
|
|
public boolean scissorContains(int x, int y) {
|
|
return scissorStack.contains(x, y);
|
|
}
|
|
|
|
public static class ScissorStack {
|
|
private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
|
|
|
|
public ScreenRectangle push(ScreenRectangle rect) {
|
|
ScreenRectangle last = stack.peekLast();
|
|
if (last != null) {
|
|
ScreenRectangle intersection = Objects.requireNonNullElse(rect.intersection(last), ScreenRectangle.empty());
|
|
stack.addLast(intersection);
|
|
return intersection;
|
|
} else {
|
|
stack.addLast(rect);
|
|
return rect;
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public ScreenRectangle pop() {
|
|
if (stack.isEmpty())
|
|
throw new IllegalStateException("Scissor stack underflow");
|
|
stack.removeLast();
|
|
return stack.peekLast();
|
|
}
|
|
|
|
@Nullable
|
|
public ScreenRectangle peekLast() {
|
|
return stack.peekLast();
|
|
}
|
|
|
|
public boolean contains(int x, int y) {
|
|
return stack.isEmpty() || stack.peekLast().containsPoint(x, y);
|
|
}
|
|
}
|
|
|
|
// Item rendering
|
|
@Override
|
|
public void drawItem(ItemStackRef stack, int x, int y) {
|
|
drawItem(null, SaturnClient.client.level, stack, x, y, 0);
|
|
}
|
|
|
|
private void drawItem(@Nullable LivingEntity entity, @Nullable Level 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 Level world, ItemStack stack, int x, int y, int seed,
|
|
int z) {
|
|
if (!stack.isEmpty()) {
|
|
//? if >=1.21.7 {
|
|
TrackingItemStackRenderState keyedItemRenderState = new TrackingItemStackRenderState();
|
|
//?} else
|
|
//ItemStackRenderState keyedItemRenderState = new ItemStackRenderState();
|
|
SaturnClient.client.getItemModelResolver().updateForTopItem(keyedItemRenderState, stack,
|
|
ItemDisplayContext.GUI, world,
|
|
entity, seed);
|
|
|
|
try {
|
|
//? if >=26.1 {
|
|
/*this.state.submitItem(new GuiItemRenderState(
|
|
*///?} else
|
|
this.state.submitItem(new GuiItemRenderState(stack.getItem().getName().toString(),
|
|
new Matrix3x2f(this.matrices.stack), keyedItemRenderState, x, y,
|
|
this.scissorStack.peekLast()));
|
|
} catch (Throwable throwable) {
|
|
CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
|
|
CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
|
|
crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
|
|
crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
|
|
crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
|
|
throw new ReportedException(crashReport);
|
|
}
|
|
}
|
|
}
|
|
|
|
@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 sprite, int x, int y, int width, int height, int color) {
|
|
TextureAtlasSprite mcSprite = (TextureAtlasSprite) sprite;
|
|
if (color == 0 || width == 0 || height == 0)
|
|
return;
|
|
|
|
drawTexturedQuad(mcSprite.atlasLocation(), x, x + width, y, y + height,
|
|
mcSprite.getU0(), mcSprite.getU1(), mcSprite.getV0(), mcSprite.getV1(), color);
|
|
}
|
|
|
|
@Override
|
|
public void draw() {
|
|
// No-op for now
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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.submitPicturesInPictureState(new GuiEntityRenderState(entityState, translation, rotation,
|
|
overrideCameraAngle, adjustedX1, adjustedY1, adjustedX2, adjustedY2, adjustedScale,
|
|
this.scissorStack.peekLast()));
|
|
}
|
|
}
|
|
//?} else {
|
|
/*import java.util.ArrayDeque;
|
|
import java.util.Deque;
|
|
import java.util.HashSet;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.function.Consumer;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.joml.Matrix4f;
|
|
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
|
|
import org.saturnclient.common.ref.asset.IdentifierRef;
|
|
import org.saturnclient.common.ref.asset.SpriteRef;
|
|
import org.saturnclient.common.ref.game.ItemStackRef;
|
|
import org.saturnclient.common.ref.render.MatrixStackRef;
|
|
import org.saturnclient.saturnclient.SaturnClient;
|
|
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
|
import org.saturnclient.ui.RenderScope;
|
|
import org.saturnclient.ui.resources.Fonts;
|
|
import org.saturnclient.ui.resources.SvgTexture;
|
|
|
|
import net.minecraft.client.gui.Font;
|
|
import net.minecraft.client.gui.Font.DisplayMode;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
|
import com.mojang.blaze3d.platform.Lighting;
|
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
|
import net.minecraft.client.renderer.RenderType;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.item.ItemStackRenderState;
|
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
|
import com.mojang.blaze3d.platform.Window;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
//? if >=1.21.5
|
|
import net.minecraft.world.item.ItemDisplayContext;
|
|
//? if <1.21.5
|
|
//import net.minecraft.world.item.ItemDisplayContext;
|
|
import net.minecraft.world.item.ItemStack;
|
|
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.world.level.Level;
|
|
|
|
public class RenderScopeImpl implements RenderScope {
|
|
// ----------------------------
|
|
// Fields
|
|
// ----------------------------
|
|
public PoseStack matrices;
|
|
public MultiBufferSource.BufferSource vertexConsumers;
|
|
private ScissorStack scissorStack = new ScissorStack();
|
|
private int opacity = 255 << 24;
|
|
// The glass blurs made for this scope's frame
|
|
private final Set<Integer> capturedBlurs = new HashSet<>();
|
|
private final ItemStackRenderState itemRenderState;
|
|
|
|
// ----------------------------
|
|
// Constructors
|
|
// ----------------------------
|
|
public RenderScopeImpl(GuiGraphics context) {
|
|
this(context.pose(), ((DrawContextAccessor) context).getVertexConsumers());
|
|
}
|
|
|
|
public RenderScopeImpl(PoseStack matrices, MultiBufferSource.BufferSource vertexConsumers) {
|
|
this.matrices = matrices;
|
|
this.vertexConsumers = vertexConsumers;
|
|
this.scissorStack = new ScissorStack();
|
|
this.itemRenderState = new ItemStackRenderState();
|
|
}
|
|
|
|
// ----------------------------
|
|
// Matrix & Transform
|
|
// ----------------------------
|
|
@Override
|
|
public MatrixStackRef getMatrixStack() {
|
|
return (MatrixStackRef) matrices;
|
|
}
|
|
|
|
// ----------------------------
|
|
// Color & Opacity
|
|
// ----------------------------
|
|
@Override
|
|
public void setOpacity(float alpha) {
|
|
this.opacity = (int) (alpha * 255) << 24;
|
|
}
|
|
|
|
@Override
|
|
public int getColor(int color) {
|
|
int originalAlpha = (color >>> 24) & 0xFF;
|
|
int newAlpha = (opacity >>> 24) & 0xFF;
|
|
int mixedAlpha = (originalAlpha * newAlpha) / 255;
|
|
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
|
|
}
|
|
|
|
// ----------------------------
|
|
// Draw / Window Info
|
|
// ----------------------------
|
|
@Override
|
|
public void draw() {
|
|
this.vertexConsumers.endBatch();
|
|
}
|
|
|
|
@Override
|
|
public int getScaledWindowWidth() {
|
|
return SaturnClient.client.getWindow().getGuiScaledWidth();
|
|
}
|
|
|
|
@Override
|
|
public int getScaledWindowHeight() {
|
|
return SaturnClient.client.getWindow().getGuiScaledHeight();
|
|
}
|
|
|
|
public void draw(Consumer<MultiBufferSource> drawer) {
|
|
drawer.accept(this.vertexConsumers);
|
|
this.vertexConsumers.endBatch();
|
|
}
|
|
|
|
// ----------------------------
|
|
// Shapes
|
|
// ----------------------------
|
|
@Override
|
|
public void drawRectangle(int x, int y, int width, int height, int color) {
|
|
if (color == 0)
|
|
return;
|
|
color = getColor(color);
|
|
|
|
Matrix4f matrix4f = this.matrices.last().pose();
|
|
|
|
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(RenderType.gui());
|
|
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setColor(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(RenderType.gui(), x1, y1, x2, y2, z, color);
|
|
}
|
|
|
|
public void fill(RenderType layer, int x1, int y1, int x2, int y2, int color) {
|
|
fill(layer, x1, y1, x2, y2, 0, color);
|
|
}
|
|
|
|
public void fill(RenderType layer, int x1, int y1, int x2, int y2, int z, int color) {
|
|
Matrix4f matrix4f = this.matrices.last().pose();
|
|
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.addVertex(matrix4f, x1, y1, z).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x1, y2, z).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y2, z).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y1, z).setColor(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.pushPose();
|
|
matrices.translate(x, y + i * Fonts.getHeight(), 0);
|
|
matrices.scale(scale, scale, 1.0f);
|
|
Font textRenderer = SaturnClient.client.font;
|
|
textRenderer.drawInBatch((Component) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false,
|
|
matrices.last().pose(), vertexConsumers, DisplayMode.NORMAL, 0, 15728880);
|
|
matrices.popPose();
|
|
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) {
|
|
TextureAtlasSprite sprite = (TextureAtlasSprite) saturnSprite;
|
|
if (color == 0)
|
|
return;
|
|
if (width != 0 && height != 0) {
|
|
drawTexturedQuad(sprite.atlasLocation(), x, x + width, y, y + height,
|
|
sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), 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;
|
|
x2 *= 4;
|
|
y1 *= 4;
|
|
y2 *= 4;
|
|
color = getColor(color);
|
|
|
|
matrices.pushPose();
|
|
matrices.scale(0.25f, 0.25f, 1.0f);
|
|
//? if <1.21.5
|
|
//RenderSystem.setShaderTexture(0, sprite);
|
|
RenderType renderLayer = RenderType.guiTextured(sprite);
|
|
Matrix4f matrix4f = matrices.last().pose();
|
|
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer);
|
|
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(u1, v1).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(u1, v2).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(u2, v2).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(u2, v1).setColor(color);
|
|
matrices.popPose();
|
|
}
|
|
|
|
@Override
|
|
public void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
|
|
int color = getColor(0xFFFFFFFF);
|
|
if (mask == null || color >>> 24 == 0)
|
|
return;
|
|
|
|
if (capturedBlurs.add(blur)) {
|
|
GlassRenderer.captureBackdrop(blur);
|
|
}
|
|
|
|
// In quarter units, as drawTexturedQuad draws
|
|
int x1 = x * 4;
|
|
int x2 = (x + width) * 4;
|
|
int y1 = y * 4;
|
|
int y2 = (y + height) * 4;
|
|
|
|
matrices.pushPose();
|
|
matrices.scale(0.25f, 0.25f, 1.0f);
|
|
Matrix4f matrix4f = matrices.last().pose();
|
|
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GlassRenderer.getLayer((Identifier) (Object) mask, blur));
|
|
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(0, 0).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(0, 1).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(1, 1).setColor(color);
|
|
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(1, 0).setColor(color);
|
|
matrices.popPose();
|
|
}
|
|
|
|
// ----------------------------
|
|
// Items
|
|
// ----------------------------
|
|
@Override
|
|
public void drawItem(ItemStackRef item, int x, int y) {
|
|
drawItem(SaturnClient.client.player, SaturnClient.client.level, item, x, y, 0);
|
|
}
|
|
|
|
private void drawItem(@Nullable LivingEntity entity, @Nullable Level 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 Level world, ItemStack stack, int x, int y, int seed,
|
|
int z) {
|
|
if (stack.isEmpty())
|
|
return;
|
|
|
|
//? if >=1.21.5
|
|
SaturnClient.client.getItemModelResolver().appendItemLayers(itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
|
|
//? if >=1.21.5
|
|
SaturnClient.client.getItemModelResolver().updateForTopItem(this.itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
|
|
//? if <1.21.5
|
|
//SaturnClient.client.getItemModelResolver().updateForTopItem(itemRenderState, stack, ItemDisplayContext.GUI, false, world, entity, seed);
|
|
|
|
this.matrices.pushPose();
|
|
//? if >=1.21.5
|
|
this.matrices.translate((float) (x + 8), (float) (y + 8), (float) (150 + z));
|
|
//? if <1.21.5
|
|
//this.matrices.translate(x + 8, y + 8, 150 + (itemRenderState.isGui3d() ? z : 0));
|
|
|
|
try {
|
|
this.matrices.scale(16.0F, -16.0F, 16.0F);
|
|
boolean bl = !this.itemRenderState.usesBlockLight();
|
|
if (bl) {
|
|
this.draw();
|
|
Lighting.setupForFlatItems();
|
|
}
|
|
|
|
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.NO_OVERLAY);
|
|
this.draw();
|
|
if (bl) {
|
|
Lighting.setupFor3DItems();
|
|
}
|
|
} catch (Throwable throwable) {
|
|
CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
|
|
CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
|
|
crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
|
|
crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
|
|
crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
|
|
throw new ReportedException(crashReport);
|
|
}
|
|
|
|
this.matrices.popPose();
|
|
}
|
|
|
|
// ----------------------------
|
|
// Scissor / Clipping
|
|
// ----------------------------
|
|
@Override
|
|
public void enableScissor(int x1, int y1, int x2, int y2) {
|
|
ScreenRectangle screenRect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1)
|
|
.transformAxisAligned(matrices.last().pose());
|
|
setScissor(scissorStack.push(screenRect));
|
|
}
|
|
|
|
@Override
|
|
public void disableScissor() {
|
|
setScissor(scissorStack.pop());
|
|
}
|
|
|
|
@Override
|
|
public boolean scissorContains(int x, int y) {
|
|
return scissorStack.containsPoint(x, y);
|
|
}
|
|
|
|
private void setScissor(@Nullable ScreenRectangle rect) {
|
|
draw();
|
|
if (rect != null) {
|
|
Window window = SaturnClient.client.getWindow();
|
|
int framebufferHeight = window.getHeight();
|
|
double scaleFactor = window.getGuiScale();
|
|
RenderSystem.enableScissor(
|
|
(int) (rect.left() * scaleFactor),
|
|
(int) (framebufferHeight - rect.bottom() * scaleFactor),
|
|
Math.max(0, (int) (rect.width() * scaleFactor)),
|
|
Math.max(0, (int) (rect.height() * scaleFactor)));
|
|
} else {
|
|
RenderSystem.disableScissor();
|
|
}
|
|
}
|
|
|
|
static class ScissorStack {
|
|
private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
|
|
|
|
public ScreenRectangle push(ScreenRectangle p_281812_) {
|
|
ScreenRectangle screenrectangle = this.stack.peekLast();
|
|
if (screenrectangle != null) {
|
|
ScreenRectangle screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle),
|
|
ScreenRectangle.empty());
|
|
this.stack.addLast(screenrectangle1);
|
|
return screenrectangle1;
|
|
} else {
|
|
this.stack.addLast(p_281812_);
|
|
return p_281812_;
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public ScreenRectangle pop() {
|
|
if (this.stack.isEmpty()) {
|
|
throw new IllegalStateException("Scissor stack underflow");
|
|
} else {
|
|
this.stack.removeLast();
|
|
return this.stack.peekLast();
|
|
}
|
|
}
|
|
|
|
public boolean containsPoint(int p_329411_, int p_333404_) {
|
|
return this.stack.isEmpty() ? true : this.stack.peek().containsPoint(p_329411_, p_333404_);
|
|
}
|
|
}
|
|
}
|
|
*///?}
|