313 lines
11 KiB
Java
313 lines
11 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* org.joml.Matrix3x2f
|
|
* org.joml.Matrix3x2fc
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.client.gui.render.state;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.function.Consumer;
|
|
import net.minecraft.SharedConstants;
|
|
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
|
import net.minecraft.client.gui.render.TextureSetup;
|
|
import net.minecraft.client.gui.render.state.BlitRenderState;
|
|
import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiElementRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiItemRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiTextRenderState;
|
|
import net.minecraft.client.gui.render.state.ScreenArea;
|
|
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
|
|
import net.minecraft.client.renderer.RenderPipelines;
|
|
import org.joml.Matrix3x2f;
|
|
import org.joml.Matrix3x2fc;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class GuiRenderState {
|
|
private static final int DEBUG_RECTANGLE_COLOR = 0x774444FF;
|
|
private final List<Node> strata = new ArrayList<Node>();
|
|
private int firstStratumAfterBlur = Integer.MAX_VALUE;
|
|
private Node current;
|
|
private final Set<Object> itemModelIdentities = new HashSet<Object>();
|
|
private @Nullable ScreenRectangle lastElementBounds;
|
|
|
|
public GuiRenderState() {
|
|
this.nextStratum();
|
|
}
|
|
|
|
public void nextStratum() {
|
|
this.current = new Node(null);
|
|
this.strata.add(this.current);
|
|
}
|
|
|
|
public void blurBeforeThisStratum() {
|
|
if (this.firstStratumAfterBlur != Integer.MAX_VALUE) {
|
|
throw new IllegalStateException("Can only blur once per frame");
|
|
}
|
|
this.firstStratumAfterBlur = this.strata.size() - 1;
|
|
}
|
|
|
|
public void up() {
|
|
if (this.current.up == null) {
|
|
this.current.up = new Node(this.current);
|
|
}
|
|
this.current = this.current.up;
|
|
}
|
|
|
|
public void submitItem(GuiItemRenderState itemState) {
|
|
if (!this.findAppropriateNode(itemState)) {
|
|
return;
|
|
}
|
|
this.itemModelIdentities.add(itemState.itemStackRenderState().getModelIdentity());
|
|
this.current.submitItem(itemState);
|
|
this.sumbitDebugRectangleIfEnabled(itemState.bounds());
|
|
}
|
|
|
|
public void submitText(GuiTextRenderState textState) {
|
|
if (!this.findAppropriateNode(textState)) {
|
|
return;
|
|
}
|
|
this.current.submitText(textState);
|
|
this.sumbitDebugRectangleIfEnabled(textState.bounds());
|
|
}
|
|
|
|
public void submitPicturesInPictureState(PictureInPictureRenderState picturesInPictureState) {
|
|
if (!this.findAppropriateNode(picturesInPictureState)) {
|
|
return;
|
|
}
|
|
this.current.submitPicturesInPictureState(picturesInPictureState);
|
|
this.sumbitDebugRectangleIfEnabled(picturesInPictureState.bounds());
|
|
}
|
|
|
|
public void submitGuiElement(GuiElementRenderState blitState) {
|
|
if (!this.findAppropriateNode(blitState)) {
|
|
return;
|
|
}
|
|
this.current.submitGuiElement(blitState);
|
|
this.sumbitDebugRectangleIfEnabled(blitState.bounds());
|
|
}
|
|
|
|
private void sumbitDebugRectangleIfEnabled(@Nullable ScreenRectangle bounds) {
|
|
if (!SharedConstants.DEBUG_RENDER_UI_LAYERING_RECTANGLES || bounds == null) {
|
|
return;
|
|
}
|
|
this.up();
|
|
this.current.submitGuiElement(new ColoredRectangleRenderState(RenderPipelines.GUI, TextureSetup.noTexture(), (Matrix3x2fc)new Matrix3x2f(), 0, 0, 10000, 10000, 0x774444FF, 0x774444FF, bounds));
|
|
}
|
|
|
|
private boolean findAppropriateNode(ScreenArea screenArea) {
|
|
ScreenRectangle bounds = screenArea.bounds();
|
|
if (bounds == null) {
|
|
return false;
|
|
}
|
|
if (this.lastElementBounds != null && this.lastElementBounds.encompasses(bounds)) {
|
|
this.up();
|
|
} else {
|
|
this.navigateToAboveHighestElementWithIntersectingBounds(bounds);
|
|
}
|
|
this.lastElementBounds = bounds;
|
|
return true;
|
|
}
|
|
|
|
private void navigateToAboveHighestElementWithIntersectingBounds(ScreenRectangle bounds) {
|
|
Node node = this.strata.getLast();
|
|
while (node.up != null) {
|
|
node = node.up;
|
|
}
|
|
boolean found = false;
|
|
while (!found) {
|
|
boolean bl = found = this.hasIntersection(bounds, node.elementStates) || this.hasIntersection(bounds, node.itemStates) || this.hasIntersection(bounds, node.textStates) || this.hasIntersection(bounds, node.picturesInPictureStates);
|
|
if (node.parent == null) break;
|
|
if (found) continue;
|
|
node = node.parent;
|
|
}
|
|
this.current = node;
|
|
if (found) {
|
|
this.up();
|
|
}
|
|
}
|
|
|
|
private boolean hasIntersection(ScreenRectangle bounds, @Nullable List<? extends ScreenArea> states) {
|
|
if (states != null) {
|
|
for (ScreenArea screenArea : states) {
|
|
ScreenRectangle existingBounds = screenArea.bounds();
|
|
if (existingBounds == null || !existingBounds.intersects(bounds)) continue;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void submitBlitToCurrentLayer(BlitRenderState blitState) {
|
|
this.current.submitGuiElement(blitState);
|
|
}
|
|
|
|
public void submitGlyphToCurrentLayer(GuiElementRenderState glyphState) {
|
|
this.current.submitGlyph(glyphState);
|
|
}
|
|
|
|
public Set<Object> getItemModelIdentities() {
|
|
return this.itemModelIdentities;
|
|
}
|
|
|
|
public void forEachElement(Consumer<GuiElementRenderState> consumer, TraverseRange range) {
|
|
this.traverse((Node node) -> {
|
|
if (node.elementStates == null && node.glyphStates == null) {
|
|
return;
|
|
}
|
|
if (node.elementStates != null) {
|
|
for (GuiElementRenderState elementState : node.elementStates) {
|
|
consumer.accept(elementState);
|
|
}
|
|
}
|
|
if (node.glyphStates != null) {
|
|
for (GuiElementRenderState glyphState : node.glyphStates) {
|
|
consumer.accept(glyphState);
|
|
}
|
|
}
|
|
}, range);
|
|
}
|
|
|
|
public void forEachItem(Consumer<GuiItemRenderState> consumer) {
|
|
Node currentBackup = this.current;
|
|
this.traverse((Node node) -> {
|
|
if (node.itemStates != null) {
|
|
this.current = node;
|
|
for (GuiItemRenderState itemState : node.itemStates) {
|
|
consumer.accept(itemState);
|
|
}
|
|
}
|
|
}, TraverseRange.ALL);
|
|
this.current = currentBackup;
|
|
}
|
|
|
|
public void forEachText(Consumer<GuiTextRenderState> consumer) {
|
|
Node currentBackup = this.current;
|
|
this.traverse((Node node) -> {
|
|
if (node.textStates != null) {
|
|
for (GuiTextRenderState textState : node.textStates) {
|
|
this.current = node;
|
|
consumer.accept(textState);
|
|
}
|
|
}
|
|
}, TraverseRange.ALL);
|
|
this.current = currentBackup;
|
|
}
|
|
|
|
public void forEachPictureInPicture(Consumer<PictureInPictureRenderState> consumer) {
|
|
Node currentBackup = this.current;
|
|
this.traverse((Node node) -> {
|
|
if (node.picturesInPictureStates != null) {
|
|
this.current = node;
|
|
for (PictureInPictureRenderState pictureInPictureState : node.picturesInPictureStates) {
|
|
consumer.accept(pictureInPictureState);
|
|
}
|
|
}
|
|
}, TraverseRange.ALL);
|
|
this.current = currentBackup;
|
|
}
|
|
|
|
public void sortElements(Comparator<GuiElementRenderState> comparator) {
|
|
this.traverse((Node node) -> {
|
|
if (node.elementStates != null) {
|
|
if (SharedConstants.DEBUG_SHUFFLE_UI_RENDERING_ORDER) {
|
|
Collections.shuffle(node.elementStates);
|
|
}
|
|
node.elementStates.sort(comparator);
|
|
}
|
|
}, TraverseRange.ALL);
|
|
}
|
|
|
|
private void traverse(Consumer<Node> consumer, TraverseRange range) {
|
|
int startIndex = 0;
|
|
int endIndex = this.strata.size();
|
|
if (range == TraverseRange.BEFORE_BLUR) {
|
|
endIndex = Math.min(this.firstStratumAfterBlur, this.strata.size());
|
|
} else if (range == TraverseRange.AFTER_BLUR) {
|
|
startIndex = this.firstStratumAfterBlur;
|
|
}
|
|
for (int i = startIndex; i < endIndex; ++i) {
|
|
Node stratum = this.strata.get(i);
|
|
this.traverse(stratum, consumer);
|
|
}
|
|
}
|
|
|
|
private void traverse(Node node, Consumer<Node> consumer) {
|
|
consumer.accept(node);
|
|
if (node.up != null) {
|
|
this.traverse(node.up, consumer);
|
|
}
|
|
}
|
|
|
|
public void reset() {
|
|
this.itemModelIdentities.clear();
|
|
this.strata.clear();
|
|
this.firstStratumAfterBlur = Integer.MAX_VALUE;
|
|
this.nextStratum();
|
|
}
|
|
|
|
private static class Node {
|
|
public final @Nullable Node parent;
|
|
public @Nullable Node up;
|
|
public @Nullable List<GuiElementRenderState> elementStates;
|
|
public @Nullable List<GuiElementRenderState> glyphStates;
|
|
public @Nullable List<GuiItemRenderState> itemStates;
|
|
public @Nullable List<GuiTextRenderState> textStates;
|
|
public @Nullable List<PictureInPictureRenderState> picturesInPictureStates;
|
|
|
|
private Node(@Nullable Node parent) {
|
|
this.parent = parent;
|
|
}
|
|
|
|
public void submitItem(GuiItemRenderState itemState) {
|
|
if (this.itemStates == null) {
|
|
this.itemStates = new ArrayList<GuiItemRenderState>();
|
|
}
|
|
this.itemStates.add(itemState);
|
|
}
|
|
|
|
public void submitText(GuiTextRenderState textState) {
|
|
if (this.textStates == null) {
|
|
this.textStates = new ArrayList<GuiTextRenderState>();
|
|
}
|
|
this.textStates.add(textState);
|
|
}
|
|
|
|
public void submitPicturesInPictureState(PictureInPictureRenderState picturesInPictureState) {
|
|
if (this.picturesInPictureStates == null) {
|
|
this.picturesInPictureStates = new ArrayList<PictureInPictureRenderState>();
|
|
}
|
|
this.picturesInPictureStates.add(picturesInPictureState);
|
|
}
|
|
|
|
public void submitGuiElement(GuiElementRenderState blitState) {
|
|
if (this.elementStates == null) {
|
|
this.elementStates = new ArrayList<GuiElementRenderState>();
|
|
}
|
|
this.elementStates.add(blitState);
|
|
}
|
|
|
|
public void submitGlyph(GuiElementRenderState glyphState) {
|
|
if (this.glyphStates == null) {
|
|
this.glyphStates = new ArrayList<GuiElementRenderState>();
|
|
}
|
|
this.glyphStates.add(glyphState);
|
|
}
|
|
}
|
|
|
|
public static enum TraverseRange {
|
|
ALL,
|
|
BEFORE_BLUR,
|
|
AFTER_BLUR;
|
|
|
|
}
|
|
}
|
|
|