/* * 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 strata = new ArrayList(); private int firstStratumAfterBlur = Integer.MAX_VALUE; private Node current; private final Set itemModelIdentities = new HashSet(); 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 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 getItemModelIdentities() { return this.itemModelIdentities; } public void forEachElement(Consumer 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 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 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 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 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 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 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 elementStates; public @Nullable List glyphStates; public @Nullable List itemStates; public @Nullable List textStates; public @Nullable List picturesInPictureStates; private Node(@Nullable Node parent) { this.parent = parent; } public void submitItem(GuiItemRenderState itemState) { if (this.itemStates == null) { this.itemStates = new ArrayList(); } this.itemStates.add(itemState); } public void submitText(GuiTextRenderState textState) { if (this.textStates == null) { this.textStates = new ArrayList(); } this.textStates.add(textState); } public void submitPicturesInPictureState(PictureInPictureRenderState picturesInPictureState) { if (this.picturesInPictureStates == null) { this.picturesInPictureStates = new ArrayList(); } this.picturesInPictureStates.add(picturesInPictureState); } public void submitGuiElement(GuiElementRenderState blitState) { if (this.elementStates == null) { this.elementStates = new ArrayList(); } this.elementStates.add(blitState); } public void submitGlyph(GuiElementRenderState glyphState) { if (this.glyphStates == null) { this.glyphStates = new ArrayList(); } this.glyphStates.add(glyphState); } } public static enum TraverseRange { ALL, BEFORE_BLUR, AFTER_BLUR; } }