From bc621d456ecf707632990442c31f37e49dd87ef5 Mon Sep 17 00:00:00 2001 From: trunksbomb Date: Mon, 23 Mar 2026 18:11:17 -0400 Subject: [PATCH] working on localized tab drawing and then committing that to the screen to help with these weird quirks. --- .../bagtabs/client/BagTabOverlay.java | 272 +++++++++--------- 1 file changed, 133 insertions(+), 139 deletions(-) diff --git a/src/main/java/com/trunksbomb/bagtabs/client/BagTabOverlay.java b/src/main/java/com/trunksbomb/bagtabs/client/BagTabOverlay.java index 60ff329..8ac52e6 100644 --- a/src/main/java/com/trunksbomb/bagtabs/client/BagTabOverlay.java +++ b/src/main/java/com/trunksbomb/bagtabs/client/BagTabOverlay.java @@ -554,31 +554,32 @@ public final class BagTabOverlay { int uOffset = (hovered || selected) ? baseWidth : 0; ResourceLocation baseTexture = tab.baseTexture(); ResourceLocation overlayTexture = tab.overlayTexture(); + final float tintRed = red; + final float tintGreen = green; + final float tintBlue = blue; - RenderSystem.setShaderColor(red, green, blue, 1.0F); - blitRotated(g, baseTexture, tab.x(), tab.y(), tab.width(), tab.height(), uOffset, 0, baseWidth, baseHeight, baseWidth * 2, baseHeight, tab.rotationDegrees()); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - blitRotated(g, overlayTexture, tab.x(), tab.y(), tab.width(), tab.height(), uOffset, 0, baseWidth, baseHeight, baseWidth * 2, baseHeight, tab.rotationDegrees()); - - g.pose().pushPose(); - pushTabTransform(g, tab); - if (dragged || tab.usesFloatingArt()) { - g.fill(1, 0, baseWidth - 1, 1, 0xFF000000); - if (baseHeight > 2) { - g.fill(2, 1, baseWidth - 2, 2, 0x80FFFFFF); + withTabLocalSpace(g, tab, () -> { + RenderSystem.setShaderColor(tintRed, tintGreen, tintBlue, 1.0F); + blitTabLocalTexture(g, baseTexture, uOffset, 0, baseWidth, baseHeight); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + blitTabLocalTexture(g, overlayTexture, uOffset, 0, baseWidth, baseHeight); + if (dragged || tab.usesFloatingArt()) { + g.fill(1, 0, baseWidth - 1, 1, 0xFF000000); + if (baseHeight > 2) { + g.fill(2, 1, baseWidth - 2, 2, 0x80FFFFFF); + } } - } - if (selected) { - renderSelectedIndicator(g, tab, baseWidth, baseHeight); - } - if (!carried.isEmpty()) { - if (INSERTABLE_SLOTS.contains(tab.entry().slot())) { - renderPlusIndicator(g, baseWidth - 7, Math.min(3, Math.max(0, baseHeight - 6))); - } else { - renderXIndicator(g, baseWidth - 7, Math.min(3, Math.max(0, baseHeight - 6))); + if (selected) { + renderSelectedIndicator(g, tab, baseWidth, baseHeight); } - } - g.pose().popPose(); + if (!carried.isEmpty()) { + if (INSERTABLE_SLOTS.contains(tab.entry().slot())) { + renderPlusIndicator(g, baseWidth - 7, Math.min(3, Math.max(0, baseHeight - 6))); + } else { + renderXIndicator(g, baseWidth - 7, Math.min(3, Math.max(0, baseHeight - 6))); + } + } + }); if (tab.showFullnessIndicator() && tab.fullness() >= 0.0F) { renderFullnessIndicator(g, tab, tab.fullness()); @@ -675,84 +676,60 @@ public final class BagTabOverlay { private static void renderNormalFullnessIndicator(GuiGraphics g, RenderedTab tab, float fullness) { int color = interpolateColor(0xFF6CCBFF, 0xFF2E86FF, fullness); - g.pose().pushPose(); - g.pose().translate(0.0F, 0.0F, 10_000.0F); - if (tab.isVertical()) { - int gaugeX = tab.x() + Math.max(0, (tab.width() - NORMAL_FILL_GAUGE_HEIGHT) / 2); - int gaugeY = tab.y() + tab.height() - NORMAL_FILL_GAUGE_WIDTH - 1; - g.pose().pushPose(); - g.pose().translate(gaugeX + (NORMAL_FILL_GAUGE_HEIGHT / 2.0F), gaugeY + (NORMAL_FILL_GAUGE_WIDTH / 2.0F), 0.0F); - g.pose().mulPose(Axis.ZP.rotationDegrees(-90.0F)); - g.blit( - NORMAL_FILL_GAUGE_TEXTURE, - -(NORMAL_FILL_GAUGE_WIDTH / 2), - -(NORMAL_FILL_GAUGE_HEIGHT / 2), - 0, - 0, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT - ); - + withTabLocalSpace(g, tab, () -> { int usableHeight = NORMAL_FILL_GAUGE_HEIGHT - 2; int fillHeight = Math.max(0, Math.min(usableHeight, Math.round(usableHeight * fullness))); - if (fillHeight > 0) { - int localLeft = -(NORMAL_FILL_GAUGE_WIDTH / 2) + 1; - int localTop = -(NORMAL_FILL_GAUGE_HEIGHT / 2) + 1 + (usableHeight - fillHeight); - int localBottom = -(NORMAL_FILL_GAUGE_HEIGHT / 2) + 1 + usableHeight; - g.fill(localLeft, localTop, localLeft + 1, localBottom, color); - } - g.pose().popPose(); - g.pose().popPose(); - return; - } - int gaugeX = tab.x() + tab.width() - NORMAL_FILL_GAUGE_WIDTH - 1; - int gaugeY = isFlippedHorizontalShell(tab) ? tab.y() + tab.height() - NORMAL_FILL_GAUGE_HEIGHT : tab.y(); - boolean flippedVertical = isFlippedHorizontalShell(tab); - if (flippedVertical) { - g.pose().pushPose(); - g.pose().translate(gaugeX + (NORMAL_FILL_GAUGE_WIDTH / 2.0F), gaugeY + (NORMAL_FILL_GAUGE_HEIGHT / 2.0F), 0.0F); - g.pose().scale(1.0F, -1.0F, 1.0F); - g.blit( - NORMAL_FILL_GAUGE_TEXTURE, - -(NORMAL_FILL_GAUGE_WIDTH / 2), - -(NORMAL_FILL_GAUGE_HEIGHT / 2), - 0, - 0, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT - ); - g.pose().popPose(); - } else { - g.blit( - NORMAL_FILL_GAUGE_TEXTURE, - gaugeX, - gaugeY, - 0, - 0, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT, - NORMAL_FILL_GAUGE_WIDTH, - NORMAL_FILL_GAUGE_HEIGHT - ); - } - - int usableHeight = NORMAL_FILL_GAUGE_HEIGHT - 2; - int fillHeight = Math.max(0, Math.min(usableHeight, Math.round(usableHeight * fullness))); - if (fillHeight > 0) { - if (flippedVertical) { - int fillTop = gaugeY + 1 + (usableHeight - fillHeight); - g.fill(gaugeX + 1, fillTop, gaugeX + 2, gaugeY + 1 + usableHeight, color); - } else { - int fillTop = gaugeY + 1 + (usableHeight - fillHeight); - g.fill(gaugeX + 1, fillTop, gaugeX + 2, gaugeY + 1 + usableHeight, color); + if (tab.isVertical()) { + int gaugeX = Math.max(0, (tab.baseTextureWidth() - NORMAL_FILL_GAUGE_HEIGHT) / 2); + int gaugeY = tab.baseTextureHeight() - NORMAL_FILL_GAUGE_WIDTH - 1; + LocalElementTransform transform = LocalElementTransform.identity() + .translate(gaugeX, gaugeY) + .rotate(-90.0F); + withLocalElementTransform(g, 0, 0, NORMAL_FILL_GAUGE_WIDTH, NORMAL_FILL_GAUGE_HEIGHT, transform, () -> { + g.blit( + NORMAL_FILL_GAUGE_TEXTURE, + 0, + 0, + 0, + 0, + NORMAL_FILL_GAUGE_WIDTH, + NORMAL_FILL_GAUGE_HEIGHT, + NORMAL_FILL_GAUGE_WIDTH, + NORMAL_FILL_GAUGE_HEIGHT + ); + if (fillHeight > 0) { + int fillTop = 1 + (usableHeight - fillHeight); + g.fill(1, fillTop, 2, 1 + usableHeight, color); + } + }); + return; } - } - g.pose().popPose(); + + int gaugeX = tab.baseTextureWidth() - NORMAL_FILL_GAUGE_WIDTH - 1; + int gaugeY = isFlippedHorizontalShell(tab) ? tab.baseTextureHeight() - NORMAL_FILL_GAUGE_HEIGHT : 0; + LocalElementTransform transform = LocalElementTransform.identity().translate(gaugeX, gaugeY); + if (isFlippedHorizontalShell(tab)) { + transform = transform.mirrorVertical(); + } + withLocalElementTransform(g, 0, 0, NORMAL_FILL_GAUGE_WIDTH, NORMAL_FILL_GAUGE_HEIGHT, transform, () -> { + g.blit( + NORMAL_FILL_GAUGE_TEXTURE, + 0, + 0, + 0, + 0, + NORMAL_FILL_GAUGE_WIDTH, + NORMAL_FILL_GAUGE_HEIGHT, + NORMAL_FILL_GAUGE_WIDTH, + NORMAL_FILL_GAUGE_HEIGHT + ); + if (fillHeight > 0) { + int fillTop = 1 + (usableHeight - fillHeight); + g.fill(1, fillTop, 2, 1 + usableHeight, color); + } + }); + }); } private static int interpolateColor(int start, int end, float t) { @@ -1079,29 +1056,22 @@ public final class BagTabOverlay { return; } - g.pose().pushPose(); - g.pose().translate(0.0F, 0.0F, 10_000.0F); if (!tab.compact()) { - if (!tab.isVertical()) { - int bookmarkX = tab.x() + 1; - int bookmarkY = isFlippedHorizontalShell(tab) ? tab.y() + tab.height() - BOOKMARK_HEIGHT : tab.y(); - if (isFlippedHorizontalShell(tab)) { - g.blit( - BOOKMARK_TEXTURE, - bookmarkX, - bookmarkY, - 0, - BOOKMARK_HEIGHT, - BOOKMARK_WIDTH, - -BOOKMARK_HEIGHT, - BOOKMARK_WIDTH, - BOOKMARK_HEIGHT - ); + withTabLocalSpace(g, tab, () -> { + LocalElementTransform transform = LocalElementTransform.identity(); + if (!tab.isVertical()) { + transform = transform.translate(1, isFlippedHorizontalShell(tab) ? tab.baseTextureHeight() - BOOKMARK_HEIGHT : 0); + if (isFlippedHorizontalShell(tab)) { + transform = transform.mirrorVertical(); + } } else { + transform = transform.translate(1, 0); + } + withLocalElementTransform(g, 0, 0, BOOKMARK_WIDTH, BOOKMARK_HEIGHT, transform, () -> { g.blit( BOOKMARK_TEXTURE, - bookmarkX, - bookmarkY, + 0, + 0, 0, 0, BOOKMARK_WIDTH, @@ -1109,33 +1079,12 @@ public final class BagTabOverlay { BOOKMARK_WIDTH, BOOKMARK_HEIGHT ); - } - g.pose().popPose(); - return; - } - g.pose().pushPose(); - pushTabTransform(g, tab); - g.blit( - BOOKMARK_TEXTURE, - 1, - 0, - 0, - 0, - BOOKMARK_WIDTH, - BOOKMARK_HEIGHT, - BOOKMARK_WIDTH, - BOOKMARK_HEIGHT - ); - g.pose().popPose(); - g.pose().popPose(); + }); + }); return; } - g.pose().pushPose(); - pushTabTransform(g, tab); - blitScaled(g, BOOKMARK_TEXTURE, 1, 0, 2, 5, 0, 0, BOOKMARK_WIDTH, BOOKMARK_HEIGHT, BOOKMARK_WIDTH, BOOKMARK_HEIGHT); - g.pose().popPose(); - g.pose().popPose(); + withTabLocalSpace(g, tab, () -> blitScaled(g, BOOKMARK_TEXTURE, 1, 0, 2, 5, 0, 0, BOOKMARK_WIDTH, BOOKMARK_HEIGHT, BOOKMARK_WIDTH, BOOKMARK_HEIGHT)); } private static void renderSelectedIndicator(GuiGraphics g, RenderedTab tab, int baseWidth, int baseHeight) { @@ -1642,6 +1591,29 @@ public final class BagTabOverlay { g.pose().popPose(); } + private static void withTabLocalSpace(GuiGraphics g, RenderedTab tab, Runnable draw) { + g.pose().pushPose(); + pushTabTransform(g, tab); + draw.run(); + g.pose().popPose(); + } + + private static void blitTabLocalTexture(GuiGraphics g, ResourceLocation texture, int u, int v, int regionWidth, int regionHeight) { + g.blit(texture, 0, 0, u, v, regionWidth, regionHeight, regionWidth * 2, regionHeight); + } + + private static void withLocalElementTransform(GuiGraphics g, int x, int y, int width, int height, LocalElementTransform transform, Runnable draw) { + g.pose().pushPose(); + g.pose().translate(x + transform.translateX() + (width / 2.0F), y + transform.translateY() + (height / 2.0F), 0.0F); + if (transform.rotationDegrees() != 0.0F) { + g.pose().mulPose(Axis.ZP.rotationDegrees(transform.rotationDegrees())); + } + g.pose().scale(transform.flipHorizontal() ? -1.0F : 1.0F, transform.flipVertical() ? -1.0F : 1.0F, 1.0F); + g.pose().translate(-(width / 2.0F), -(height / 2.0F), 0.0F); + draw.run(); + g.pose().popPose(); + } + private static void pushTabTransform(GuiGraphics g, RenderedTab tab) { g.pose().translate(tab.x() + (tab.width() / 2.0F), tab.y() + (tab.height() / 2.0F), 0.0F); g.pose().mulPose(Axis.ZP.rotationDegrees(tab.rotationDegrees())); @@ -1785,6 +1757,28 @@ public final class BagTabOverlay { } } + private record LocalElementTransform(int translateX, int translateY, boolean flipHorizontal, boolean flipVertical, float rotationDegrees) { + private static LocalElementTransform identity() { + return new LocalElementTransform(0, 0, false, false, 0.0F); + } + + private LocalElementTransform translate(int x, int y) { + return new LocalElementTransform(this.translateX + x, this.translateY + y, this.flipHorizontal, this.flipVertical, this.rotationDegrees); + } + + private LocalElementTransform mirrorHorizontal() { + return new LocalElementTransform(this.translateX, this.translateY, !this.flipHorizontal, this.flipVertical, this.rotationDegrees); + } + + private LocalElementTransform mirrorVertical() { + return new LocalElementTransform(this.translateX, this.translateY, this.flipHorizontal, !this.flipVertical, this.rotationDegrees); + } + + private LocalElementTransform rotate(float degrees) { + return new LocalElementTransform(this.translateX, this.translateY, this.flipHorizontal, this.flipVertical, this.rotationDegrees + degrees); + } + } + private record PendingClick(int slot, double grabOffsetX, double grabOffsetY, boolean pinned) { }