From 76c26ed367ca2a0c3e6ef5e4a64e076c05ad9bef Mon Sep 17 00:00:00 2001 From: Dragon-Seeker Date: Sat, 9 Nov 2024 15:09:02 -0600 Subject: [PATCH 1/3] Adjust tooltip rendering to after rendering of the screen to prevent being covered by other rendering elements --- .../io/wispforest/owo/compat/rei/ReiUIAdapter.java | 9 +++++++-- .../wispforest/owo/ui/base/BaseOwoHandledScreen.java | 5 +++++ .../java/io/wispforest/owo/ui/base/BaseOwoScreen.java | 5 +++++ .../java/io/wispforest/owo/ui/core/OwoUIAdapter.java | 11 +++++++++-- src/main/java/io/wispforest/owo/ui/layers/Layers.java | 4 ++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java b/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java index 28f8b7ad..01c88e5e 100644 --- a/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java +++ b/src/main/java/io/wispforest/owo/compat/rei/ReiUIAdapter.java @@ -29,8 +29,13 @@ public ReiUIAdapter(Rectangle bounds, BiFunction rootComponen this.adapter = OwoUIAdapter.createWithoutScreen(bounds.x, bounds.y, bounds.width, bounds.height, rootComponentMaker); this.adapter.inspectorZOffset = 900; - if (MinecraftClient.getInstance().currentScreen != null) { - ScreenEvents.remove(MinecraftClient.getInstance().currentScreen).register(screen -> this.adapter.dispose()); + var screenWithREI = MinecraftClient.getInstance().currentScreen; + + if (screenWithREI != null) { + ScreenEvents.remove(screenWithREI).register(screen -> this.adapter.dispose()); + ScreenEvents.afterRender(screenWithREI).register((screen, drawContext, mouseX, mouseY, tickDelta) -> { + this.adapter.drawTooltip(drawContext, mouseX, mouseY, tickDelta); + }); } } diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java index 5237a228..2ff6d0c9 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java @@ -7,6 +7,7 @@ import io.wispforest.owo.ui.util.DisposableScreen; import io.wispforest.owo.ui.util.UIErrorToast; import io.wispforest.owo.util.pond.OwoSlotExtension; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; @@ -82,6 +83,10 @@ protected void init() { this.build(this.uiAdapter.rootComponent); this.uiAdapter.inflateAndMount(); + + ScreenEvents.afterRender(this).register((screen, drawContext, mouseX, mouseY, tickDelta) -> { + if (this.uiAdapter != null) this.uiAdapter.drawTooltip(drawContext, mouseX, mouseY, tickDelta); + }); } catch (Exception error) { Owo.LOGGER.warn("Could not initialize owo screen", error); UIErrorToast.report(error); diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java index 4d5c4762..f68801a2 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoScreen.java @@ -8,6 +8,7 @@ import io.wispforest.owo.ui.inject.GreedyInputComponent; import io.wispforest.owo.ui.util.DisposableScreen; import io.wispforest.owo.ui.util.UIErrorToast; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; @@ -91,6 +92,10 @@ protected void init() { this.build(this.uiAdapter.rootComponent); this.uiAdapter.inflateAndMount(); + + ScreenEvents.afterRender(this).register((screen, drawContext, mouseX, mouseY, tickDelta) -> { + if (this.uiAdapter != null) this.uiAdapter.drawTooltip(drawContext, mouseX, mouseY, tickDelta); + }); } catch (Exception error) { Owo.LOGGER.warn("Could not initialize owo screen", error); UIErrorToast.report(error); diff --git a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java index 9c7d98ae..0f225e92 100644 --- a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java +++ b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java @@ -180,8 +180,6 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic GlStateManager._disableScissorTest(); RenderSystem.disableDepthTest(); - this.rootComponent.drawTooltip(owoContext, mouseX, mouseY, partialTicks, delta); - final var hovered = this.rootComponent.childAt(mouseX, mouseY); if (!disposed && hovered != null) { this.cursorAdapter.applyStyle(hovered.cursorStyle()); @@ -200,6 +198,15 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic } } + public void drawTooltip(DrawContext context, int mouseX, int mouseY, float partialTicks) { + if (!(context instanceof OwoUIDrawContext)) context = OwoUIDrawContext.of(context); + var owoContext = (OwoUIDrawContext) context; + + final var delta = MinecraftClient.getInstance().getRenderTickCounter().getLastFrameDuration(); + + this.rootComponent.drawTooltip(owoContext, mouseX, mouseY, partialTicks, delta); + } + @Override public boolean isMouseOver(double mouseX, double mouseY) { return this.rootComponent.isInBoundingBox(mouseX, mouseY); diff --git a/src/main/java/io/wispforest/owo/ui/layers/Layers.java b/src/main/java/io/wispforest/owo/ui/layers/Layers.java index e340082a..6b1a0aac 100644 --- a/src/main/java/io/wispforest/owo/ui/layers/Layers.java +++ b/src/main/java/io/wispforest/owo/ui/layers/Layers.java @@ -94,6 +94,10 @@ public static Layer add(BiFu for (var instance : getInstances(screen)) { instance.adapter.render(context, mouseX, mouseY, tickDelta); } + + for (var instance : getInstances(screen)) { + instance.adapter.drawTooltip(context, mouseX, mouseY, tickDelta); + } }); ScreenMouseEvents.allowMouseClick(screeen).register((screen, mouseX, mouseY, button) -> { From 5787c9657fea3d40894b07a4a871eb8a3395ef71 Mon Sep 17 00:00:00 2001 From: Dragon-Seeker Date: Sat, 9 Nov 2024 15:11:15 -0600 Subject: [PATCH 2/3] Reimplement Z offset forBaseOwoHandledScreen to fix issues with hover and item rendering --- .../owo/mixin/ui/HandledScreenMixin.java | 14 ------- .../owo/ui/base/BaseOwoHandledScreen.java | 41 +++++++++++++++++++ src/main/resources/owo.accesswidener | 6 ++- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/wispforest/owo/mixin/ui/HandledScreenMixin.java b/src/main/java/io/wispforest/owo/mixin/ui/HandledScreenMixin.java index 8fc57f01..4878e907 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/HandledScreenMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/HandledScreenMixin.java @@ -64,20 +64,6 @@ private void clearSlotScissors(DrawContext context, Slot slot, CallbackInfo ci) GlStateManager._disableScissorTest(); } - // TODO: [1.21.2-Porting] Figure out f such is still needed and how to handle such -// @Inject(method = "drawSlotHighlight", at = @At(value = "HEAD")) -// private static void enableSlotDepth(DrawContext context, int x, int y, int z, CallbackInfo ci) { -// if (!owo$inOwoScreen) return; -// RenderSystem.enableDepthTest(); -// context.getMatrices().translate(0, 0, 300); -// } -// -// @Inject(method = "drawSlotHighlight", at = @At("TAIL")) -// private static void clearSlotDepth(DrawContext context, int x, int y, int z, CallbackInfo ci) { -// if (!owo$inOwoScreen) return; -// context.getMatrices().translate(0, 0, -300); -// } - @ModifyVariable(method = "mouseClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;", ordinal = 0), ordinal = 3) private int doNoThrow(int slotId, @Local() Slot slot) { return (((Object) this instanceof BaseOwoHandledScreen) && slot != null) ? slot.id : slotId; diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java index 2ff6d0c9..ab806ffb 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java @@ -13,6 +13,7 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; import net.minecraft.text.Text; @@ -330,4 +331,44 @@ public void updateY(int y) { ((SlotAccessor) this.slot).owo$setY(y - BaseOwoHandledScreen.this.y); } } + + @Override + protected void drawSlotHighlightBack(DrawContext context) { + context.translate(0, 0, getOffsetAmount(true)); + + super.drawSlotHighlightBack(context); + } + + @Override + protected void drawSlotHighlightFront(DrawContext context) { + super.drawSlotHighlightFront(context); + + context.translate(0, 0, -getOffsetAmount(true)); + } + + @Override + protected void drawItem(DrawContext context, ItemStack stack, int x, int y, @Nullable String amountText) { + var offset = getOffsetAmount(false); + + context.translate(0, 0, offset); + + super.drawItem(context, stack, x, y, amountText); + + context.translate(0, 0, -offset); + } + + @Override + protected void drawMouseoverTooltip(DrawContext context, int x, int y) { + var offset = getOffsetAmount(false); + + context.translate(0, 0, offset); + + super.drawMouseoverTooltip(context, x, y); + + context.translate(0, 0, offset); + } + + protected int getOffsetAmount(boolean slotRendering) { + return 300; + } } diff --git a/src/main/resources/owo.accesswidener b/src/main/resources/owo.accesswidener index 29dc5223..15f60296 100644 --- a/src/main/resources/owo.accesswidener +++ b/src/main/resources/owo.accesswidener @@ -9,4 +9,8 @@ transitive-accessible class net/minecraft/item/ItemGroup$EntriesImpl transitive-accessible class net/minecraft/client/gui/DrawContext$ScissorStack transitive-extendable method net/minecraft/client/gui/widget/CheckboxWidget (IIILnet/minecraft/text/Text;Lnet/minecraft/client/font/TextRenderer;ZLnet/minecraft/client/gui/widget/CheckboxWidget$Callback;)V -accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter \ No newline at end of file +accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter + +extendable method net/minecraft/client/gui/screen/ingame/HandledScreen drawSlotHighlightBack (Lnet/minecraft/client/gui/DrawContext;)V +extendable method net/minecraft/client/gui/screen/ingame/HandledScreen drawSlotHighlightFront (Lnet/minecraft/client/gui/DrawContext;)V +extendable method net/minecraft/client/gui/screen/ingame/HandledScreen drawItem (Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V \ No newline at end of file From ae3e0c2ff9e195f6c60b63d248a2ac4264603e15 Mon Sep 17 00:00:00 2001 From: glisco Date: Thu, 12 Dec 2024 00:53:41 +0100 Subject: [PATCH 3/3] [ui] add documentation to new delayed tooltip rendering, clean up and improve implementation of handled screen changes --- .../owo/ui/base/BaseOwoHandledScreen.java | 99 +++++++++++-------- .../wispforest/owo/ui/core/OwoUIAdapter.java | 13 +++ 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java index ab806ffb..8028fde6 100644 --- a/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java +++ b/src/main/java/io/wispforest/owo/ui/base/BaseOwoHandledScreen.java @@ -267,6 +267,63 @@ public void dispose() { @Override protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {} + @Override + protected void drawSlotHighlightBack(DrawContext context) { + context.push().translate(0, 0, this.getLayerZOffset(HandledScreenLayer.SLOT)); + super.drawSlotHighlightBack(context); + } + + @Override + protected void drawSlotHighlightFront(DrawContext context) { + super.drawSlotHighlightFront(context); + context.pop(); + } + + @Override + protected void drawItem(DrawContext context, ItemStack stack, int x, int y, @Nullable String amountText) { + context.push().translate(0, 0, this.getLayerZOffset(HandledScreenLayer.CURSOR_ITEM)); + super.drawItem(context, stack, x, y, amountText); + context.pop(); + } + + @Override + protected void drawMouseoverTooltip(DrawContext context, int x, int y) { + context.push().translate(0, 0, this.getLayerZOffset(HandledScreenLayer.ITEM_TOOLTIP)); + super.drawMouseoverTooltip(context, x, y); + context.pop(); + } + + /** + * Return the z-offset to apply to rendering the given {@code layer} + */ + protected int getLayerZOffset(HandledScreenLayer layer) { + return layer == HandledScreenLayer.CURSOR_ITEM ? -6900 : 300; + } + + /** + * Different layers of handled screen rendering, the z-offset + * of which can be adjusted in an owo screen using {@link #getLayerZOffset(HandledScreenLayer)} + */ + protected enum HandledScreenLayer { + /** + * The items in all slots, along with the highlight + * of the hovered slot + */ + SLOT, + + /** + * The item currently held by the cursor. More specifically, any item + * rendered through the {@link #drawItem(DrawContext, ItemStack, int, int, String)} method + */ + CURSOR_ITEM, + + /** + * The tooltip of an item in a slot. More specifically, any tooltip + * rendered through {@link #drawMouseoverTooltip(DrawContext, int, int)} + */ + ITEM_TOOLTIP + } + public class SlotComponent extends BaseComponent { protected final Slot slot; @@ -331,44 +388,4 @@ public void updateY(int y) { ((SlotAccessor) this.slot).owo$setY(y - BaseOwoHandledScreen.this.y); } } - - @Override - protected void drawSlotHighlightBack(DrawContext context) { - context.translate(0, 0, getOffsetAmount(true)); - - super.drawSlotHighlightBack(context); - } - - @Override - protected void drawSlotHighlightFront(DrawContext context) { - super.drawSlotHighlightFront(context); - - context.translate(0, 0, -getOffsetAmount(true)); - } - - @Override - protected void drawItem(DrawContext context, ItemStack stack, int x, int y, @Nullable String amountText) { - var offset = getOffsetAmount(false); - - context.translate(0, 0, offset); - - super.drawItem(context, stack, x, y, amountText); - - context.translate(0, 0, -offset); - } - - @Override - protected void drawMouseoverTooltip(DrawContext context, int x, int y) { - var offset = getOffsetAmount(false); - - context.translate(0, 0, offset); - - super.drawMouseoverTooltip(context, x, y); - - context.translate(0, 0, offset); - } - - protected int getOffsetAmount(boolean slotRendering) { - return 300; - } -} +} \ No newline at end of file diff --git a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java index 0f225e92..5e6fe7e4 100644 --- a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java +++ b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java @@ -26,6 +26,12 @@ * even if you choose to not use {@link io.wispforest.owo.ui.base.BaseOwoScreen} * you can always simply add it as a widget and get most of the functionality * working out of the box + *

+ * To draw the UI tree managed by this adapter, call {@link OwoUIAdapter#render(DrawContext, int, int, float)}. + * Note that this does not draw the current tooltip of the UI - this must be done separately + * by invoking {@link #drawTooltip(DrawContext, int, int, float)}. If in a scenario with multiple adapters + * or other sources rendering UI elements to the screen, it is generally desirable to delay tooltip + * drawing until after all UI is drawn to avoid layering issues. * * @see io.wispforest.owo.ui.base.BaseOwoScreen */ @@ -198,6 +204,13 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic } } + /** + * Draw the current tooltip of the UI managed by this adapter. This method + * must not be called without a previous, corresponding call to {@link #render(DrawContext, int, int, float)} + * + * + * @since 0.12.19 + */ public void drawTooltip(DrawContext context, int mouseX, int mouseY, float partialTicks) { if (!(context instanceof OwoUIDrawContext)) context = OwoUIDrawContext.of(context); var owoContext = (OwoUIDrawContext) context;