diff options
author | Linnea Gräf <nea@nea.moe> | 2024-10-02 16:44:25 +0200 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-10-02 16:44:25 +0200 |
commit | 67dd2f68d68ae48d7b9881a34502d6c25e335745 (patch) | |
tree | f950229b5a927cdc6912e0dbea8186220bde150a /src | |
parent | a4eac70118fc25334c9352712fe3c7944b8bed1d (diff) | |
download | Firmament-67dd2f68d68ae48d7b9881a34502d6c25e335745.tar.gz Firmament-67dd2f68d68ae48d7b9881a34502d6c25e335745.tar.bz2 Firmament-67dd2f68d68ae48d7b9881a34502d6c25e335745.zip |
Make storage overlay scrollbar draggable
Diffstat (limited to 'src')
4 files changed, 571 insertions, 521 deletions
diff --git a/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java index cda87db..61fdcf8 100644 --- a/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java +++ b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java @@ -27,143 +27,161 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(HandledScreen.class) public class PatchHandledScreen<T extends ScreenHandler> extends Screen implements HasCustomGui { - @Shadow - @Final - protected T handler; - @Shadow - protected int x; - @Shadow - protected int y; - @Unique - public CustomGui override; - @Unique - public boolean hasRememberedSlots = false; - - protected PatchHandledScreen(Text title) { - super(title); - } - - @Nullable - @Override - public CustomGui getCustomGui_Firmament() { - return override; - } - - @Override - public void setCustomGui_Firmament(@Nullable CustomGui gui) { - this.override = gui; - } - - public boolean mouseScrolled_firmament(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); - } - - @Inject(method = "init", at = @At("TAIL")) - private void onInit(CallbackInfo ci) { - if (override != null) { - override.onInit(); - } - } - - @Inject(method = "drawForeground", at = @At("HEAD"), cancellable = true) - private void onDrawForeground(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { - if (override != null && !override.shouldDrawForeground()) - ci.cancel(); - } - - - @Unique - private Slot didBeforeSlotRender; - - @WrapOperation( - method = "render", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/util/collection/DefaultedList;get(I)Ljava/lang/Object;")) - private Object beforeSlotRender(DefaultedList instance, int index, Operation<Object> original, @Local(argsOnly = true) DrawContext context) { - var slot = (Slot) original.call(instance, index); - if (override != null) { - didBeforeSlotRender = slot; - override.beforeSlotRender(context, slot); - } - return slot; - } - - @Inject(method = "render", - at = @At(value = "INVOKE", target = "Lnet/minecraft/util/collection/DefaultedList;size()I")) - private void afterSlotRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (override != null && didBeforeSlotRender != null) { - override.afterSlotRender(context, didBeforeSlotRender); - didBeforeSlotRender = null; - } - } - - @Inject(method = "isClickOutsideBounds", at = @At("HEAD"), cancellable = true) - public void onIsClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable<Boolean> cir) { - if (override != null) { - cir.setReturnValue(override.isClickOutsideBounds(mouseX, mouseY)); - } - } - - @Inject(method = "isPointWithinBounds", at = @At("HEAD"), cancellable = true) - public void onIsPointWithinBounds(int x, int y, int width, int height, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) { - if (override != null) { - cir.setReturnValue(override.isPointWithinBounds(x + this.x, y + this.y, width, height, pointX, pointY)); - } - } - - @Inject(method = "isPointOverSlot", at = @At("HEAD"), cancellable = true) - public void onIsPointOverSlot(Slot slot, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) { - if (override != null) { - cir.setReturnValue(override.isPointOverSlot(slot, this.x, this.y, pointX, pointY)); - } - } - - @Inject(method = "render", at = @At("HEAD")) - public void moveSlots(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (override != null) { - for (Slot slot : handler.slots) { - if (!hasRememberedSlots) { - ((CoordRememberingSlot) slot).rememberCoords_firmament(); - } - override.moveSlot(slot); - } - hasRememberedSlots = true; - } else { - if (hasRememberedSlots) { - for (Slot slot : handler.slots) { - ((CoordRememberingSlot) slot).restoreCoords_firmament(); - } - hasRememberedSlots = false; - } - } - } - - @Inject(at = @At("HEAD"), method = "close", cancellable = true) - private void onVoluntaryExit(CallbackInfo ci) { - if (override != null) { - if (!override.onVoluntaryExit()) - ci.cancel(); - } - } - - @WrapWithCondition(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V")) - public boolean preventDrawingBackground(HandledScreen instance, DrawContext drawContext, float delta, int mouseX, int mouseY) { - if (override != null) { - override.render(drawContext, delta, mouseX, mouseY); - } - return override == null; - } - - @WrapOperation( - method = "mouseClicked", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;mouseClicked(DDI)Z")) - public boolean overrideMouseClicks(HandledScreen instance, double mouseX, double mouseY, int button, - Operation<Boolean> original) { - if (override != null) { - if (override.mouseClick(mouseX, mouseY, button)) - return true; - } - return original.call(instance, mouseX, mouseY, button); - } + @Shadow + @Final + protected T handler; + @Shadow + protected int x; + @Shadow + protected int y; + @Unique + public CustomGui override; + @Unique + public boolean hasRememberedSlots = false; + + protected PatchHandledScreen(Text title) { + super(title); + } + + @Nullable + @Override + public CustomGui getCustomGui_Firmament() { + return override; + } + + @Override + public void setCustomGui_Firmament(@Nullable CustomGui gui) { + this.override = gui; + } + + public boolean mouseScrolled_firmament(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + } + + @Inject(method = "init", at = @At("TAIL")) + private void onInit(CallbackInfo ci) { + if (override != null) { + override.onInit(); + } + } + + @Inject(method = "drawForeground", at = @At("HEAD"), cancellable = true) + private void onDrawForeground(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + if (override != null && !override.shouldDrawForeground()) + ci.cancel(); + } + + + @Unique + private Slot didBeforeSlotRender; + + @WrapOperation( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/util/collection/DefaultedList;get(I)Ljava/lang/Object;")) + private Object beforeSlotRender(DefaultedList instance, int index, Operation<Object> original, @Local(argsOnly = true) DrawContext context) { + var slot = (Slot) original.call(instance, index); + if (override != null) { + didBeforeSlotRender = slot; + override.beforeSlotRender(context, slot); + } + return slot; + } + + @Inject(method = "render", + at = @At(value = "INVOKE", target = "Lnet/minecraft/util/collection/DefaultedList;size()I")) + private void afterSlotRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (override != null && didBeforeSlotRender != null) { + override.afterSlotRender(context, didBeforeSlotRender); + didBeforeSlotRender = null; + } + } + + @Inject(method = "isClickOutsideBounds", at = @At("HEAD"), cancellable = true) + public void onIsClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable<Boolean> cir) { + if (override != null) { + cir.setReturnValue(override.isClickOutsideBounds(mouseX, mouseY)); + } + } + + @Inject(method = "isPointWithinBounds", at = @At("HEAD"), cancellable = true) + public void onIsPointWithinBounds(int x, int y, int width, int height, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) { + if (override != null) { + cir.setReturnValue(override.isPointWithinBounds(x + this.x, y + this.y, width, height, pointX, pointY)); + } + } + + @Inject(method = "isPointOverSlot", at = @At("HEAD"), cancellable = true) + public void onIsPointOverSlot(Slot slot, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) { + if (override != null) { + cir.setReturnValue(override.isPointOverSlot(slot, this.x, this.y, pointX, pointY)); + } + } + + @Inject(method = "render", at = @At("HEAD")) + public void moveSlots(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (override != null) { + for (Slot slot : handler.slots) { + if (!hasRememberedSlots) { + ((CoordRememberingSlot) slot).rememberCoords_firmament(); + } + override.moveSlot(slot); + } + hasRememberedSlots = true; + } else { + if (hasRememberedSlots) { + for (Slot slot : handler.slots) { + ((CoordRememberingSlot) slot).restoreCoords_firmament(); + } + hasRememberedSlots = false; + } + } + } + + @Inject(at = @At("HEAD"), method = "close", cancellable = true) + private void onVoluntaryExit(CallbackInfo ci) { + if (override != null) { + if (!override.onVoluntaryExit()) + ci.cancel(); + } + } + + @WrapWithCondition(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V")) + public boolean preventDrawingBackground(HandledScreen instance, DrawContext drawContext, float delta, int mouseX, int mouseY) { + if (override != null) { + override.render(drawContext, delta, mouseX, mouseY); + } + return override == null; + } + + @WrapOperation( + method = "mouseClicked", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;mouseClicked(DDI)Z")) + public boolean overrideMouseClicks(HandledScreen instance, double mouseX, double mouseY, int button, + Operation<Boolean> original) { + if (override != null) { + if (override.mouseClick(mouseX, mouseY, button)) + return true; + } + return original.call(instance, mouseX, mouseY, button); + } + + @Inject(method = "mouseDragged", at = @At("HEAD"), cancellable = true) + public void overrideMouseDrags(double mouseX, double mouseY, int button, double deltaX, double deltaY, CallbackInfoReturnable<Boolean> cir) { + if (override != null) { + if (override.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) + cir.setReturnValue(true); + } + } + + @Inject( + method = "mouseReleased", + at = @At("HEAD"), cancellable = true) + public void overrideMouseReleases(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) { + if (override != null) { + if (override.mouseReleased(mouseX, mouseY, button)) + cir.setReturnValue(true); + } + } } diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt index d0d9114..fc3c4ef 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt @@ -1,4 +1,3 @@ - package moe.nea.firmament.features.inventory.storageoverlay import me.shedaniel.math.Point @@ -12,87 +11,95 @@ import moe.nea.firmament.mixins.accessor.AccessorHandledScreen import moe.nea.firmament.util.customgui.CustomGui class StorageOverlayCustom( - val handler: StorageBackingHandle, - val screen: GenericContainerScreen, - val overview: StorageOverlayScreen, + val handler: StorageBackingHandle, + val screen: GenericContainerScreen, + val overview: StorageOverlayScreen, ) : CustomGui() { - override fun onVoluntaryExit(): Boolean { - overview.isExiting = true - return super.onVoluntaryExit() - } + override fun onVoluntaryExit(): Boolean { + overview.isExiting = true + return super.onVoluntaryExit() + } + + override fun getBounds(): List<Rectangle> { + return overview.getBounds() + } + + override fun afterSlotRender(context: DrawContext, slot: Slot) { + if (slot.inventory !is PlayerInventory) + context.disableScissor() + } - override fun getBounds(): List<Rectangle> { - return overview.getBounds() - } + override fun beforeSlotRender(context: DrawContext, slot: Slot) { + if (slot.inventory !is PlayerInventory) + overview.createScissors(context) + } - override fun afterSlotRender(context: DrawContext, slot: Slot) { - if (slot.inventory !is PlayerInventory) - context.disableScissor() - } + override fun onInit() { + overview.init(MinecraftClient.getInstance(), screen.width, screen.height) + overview.init() + screen as AccessorHandledScreen + screen.x_Firmament = overview.measurements.x + screen.y_Firmament = overview.measurements.y + screen.backgroundWidth_Firmament = overview.measurements.totalWidth + screen.backgroundHeight_Firmament = overview.measurements.totalHeight + } - override fun beforeSlotRender(context: DrawContext, slot: Slot) { - if (slot.inventory !is PlayerInventory) - overview.createScissors(context) - } + override fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean { + if (!super.isPointOverSlot(slot, xOffset, yOffset, pointX, pointY)) + return false + if (slot.inventory !is PlayerInventory) { + if (!overview.getScrollPanelInner().contains(pointX, pointY)) + return false + } + return true + } - override fun onInit() { - overview.init(MinecraftClient.getInstance(), screen.width, screen.height) - overview.init() - screen as AccessorHandledScreen - screen.x_Firmament = overview.measurements.x - screen.y_Firmament = overview.measurements.y - screen.backgroundWidth_Firmament = overview.measurements.totalWidth - screen.backgroundHeight_Firmament = overview.measurements.totalHeight - } + override fun shouldDrawForeground(): Boolean { + return false + } - override fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean { - if (!super.isPointOverSlot(slot, xOffset, yOffset, pointX, pointY)) - return false - if (slot.inventory !is PlayerInventory) { - if (!overview.getScrollPanelInner().contains(pointX, pointY)) - return false - } - return true - } + override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + return overview.mouseReleased(mouseX, mouseY, button) + } - override fun shouldDrawForeground(): Boolean { - return false - } + override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + return overview.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) + } - override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { - return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot) - } + override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { + return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot) + } - override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) { - overview.drawBackgrounds(drawContext) - overview.drawPages(drawContext, - mouseX, - mouseY, - delta, - (handler as? StorageBackingHandle.Page)?.storagePageSlot, - screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9), - Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament)) - overview.drawScrollBar(drawContext) - } + override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) { + overview.drawBackgrounds(drawContext) + overview.drawPages(drawContext, + mouseX, + mouseY, + delta, + (handler as? StorageBackingHandle.Page)?.storagePageSlot, + screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9), + Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament)) + overview.drawScrollBar(drawContext) + } - override fun moveSlot(slot: Slot) { - val index = slot.index - if (index in 0..<36) { - val (x, y) = overview.getPlayerInventorySlotPosition(index) - slot.x = x - (screen as AccessorHandledScreen).x_Firmament - slot.y = y - screen.y_Firmament - } else { - slot.x = -100000 - slot.y = -100000 - } - } + override fun moveSlot(slot: Slot) { + val index = slot.index + if (index in 0..<36) { + val (x, y) = overview.getPlayerInventorySlotPosition(index) + slot.x = x - (screen as AccessorHandledScreen).x_Firmament + slot.y = y - screen.y_Firmament + } else { + slot.x = -100000 + slot.y = -100000 + } + } - override fun mouseScrolled( - mouseX: Double, - mouseY: Double, - horizontalAmount: Double, - verticalAmount: Double - ): Boolean { - return overview.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount) - } + override fun mouseScrolled( + mouseX: Double, + mouseY: Double, + horizontalAmount: Double, + verticalAmount: Double + ): Boolean { + return overview.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount) + } } diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt index 13c6974..58c894a 100644 --- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt @@ -1,4 +1,3 @@ - package moe.nea.firmament.features.inventory.storageoverlay import me.shedaniel.math.Point @@ -8,289 +7,308 @@ import net.minecraft.client.gui.screen.Screen import net.minecraft.screen.slot.Slot import net.minecraft.text.Text import net.minecraft.util.Identifier -import moe.nea.firmament.annotations.Subscribe -import moe.nea.firmament.events.CommandEvent import moe.nea.firmament.util.MC -import moe.nea.firmament.util.ScreenUtil import moe.nea.firmament.util.assertTrueOr class StorageOverlayScreen : Screen(Text.literal("")) { - companion object { - val PLAYER_WIDTH = 184 - val PLAYER_HEIGHT = 91 - val PLAYER_Y_INSET = 3 - val SLOT_SIZE = 18 - val PADDING = 10 - val PAGE_WIDTH = SLOT_SIZE * 9 - val HOTBAR_X = 12 - val HOTBAR_Y = 67 - val MAIN_INVENTORY_Y = 9 - val SCROLL_BAR_WIDTH = 8 - val SCROLL_BAR_HEIGHT = 16 - } + companion object { + val PLAYER_WIDTH = 184 + val PLAYER_HEIGHT = 91 + val PLAYER_Y_INSET = 3 + val SLOT_SIZE = 18 + val PADDING = 10 + val PAGE_WIDTH = SLOT_SIZE * 9 + val HOTBAR_X = 12 + val HOTBAR_Y = 67 + val MAIN_INVENTORY_Y = 9 + val SCROLL_BAR_WIDTH = 8 + val SCROLL_BAR_HEIGHT = 16 + } + + var isExiting: Boolean = false + var scroll: Float = 0F + var pageWidthCount = StorageOverlay.TConfig.columns + + inner class Measurements { + val innerScrollPanelWidth = PAGE_WIDTH * pageWidthCount + (pageWidthCount - 1) * PADDING + val overviewWidth = innerScrollPanelWidth + 3 * PADDING + SCROLL_BAR_WIDTH + val x = width / 2 - overviewWidth / 2 + val overviewHeight = minOf(3 * 18 * 6, height - PLAYER_HEIGHT - minOf(80, height / 10)) + val innerScrollPanelHeight = overviewHeight - PADDING * 2 + val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2 + val playerX = width / 2 - PLAYER_WIDTH / 2 + val playerY = y + overviewHeight - PLAYER_Y_INSET + val totalWidth = overviewWidth + val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT + } + + var measurements = Measurements() - var isExiting: Boolean = false - var scroll: Float = 0F - var pageWidthCount = StorageOverlay.TConfig.columns + var lastRenderedInnerHeight = 0 + public override fun init() { + super.init() + pageWidthCount = StorageOverlay.TConfig.columns + .coerceAtMost((width - PADDING) / (PAGE_WIDTH + PADDING)) + .coerceAtLeast(1) + measurements = Measurements() + scroll = scroll.coerceAtMost(getMaxScroll()).coerceAtLeast(0F) + } - inner class Measurements { - val innerScrollPanelWidth = PAGE_WIDTH * pageWidthCount + (pageWidthCount - 1) * PADDING - val overviewWidth = innerScrollPanelWidth + 3 * PADDING + SCROLL_BAR_WIDTH - val x = width / 2 - overviewWidth / 2 - val overviewHeight = minOf(3 * 18 * 6, height - PLAYER_HEIGHT - minOf(80, height / 10)) - val innerScrollPanelHeight = overviewHeight - PADDING * 2 - val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2 - val playerX = width / 2 - PLAYER_WIDTH / 2 - val playerY = y + overviewHeight - PLAYER_Y_INSET - val totalWidth = overviewWidth - val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT - } + override fun mouseScrolled( + mouseX: Double, + mouseY: Double, + horizontalAmount: Double, + verticalAmount: Double + ): Boolean { + scroll = (scroll + StorageOverlay.adjustScrollSpeed(verticalAmount)).toFloat() + .coerceAtMost(getMaxScroll()) + .coerceAtLeast(0F) + return true + } - var measurements = Measurements() + fun getMaxScroll() = lastRenderedInnerHeight.toFloat() - getScrollPanelInner().height - var lastRenderedInnerHeight = 0 - public override fun init() { - super.init() - pageWidthCount = StorageOverlay.TConfig.columns - .coerceAtMost((width - PADDING) / (PAGE_WIDTH + PADDING)) - .coerceAtLeast(1) - measurements = Measurements() - } + val playerInventorySprite = Identifier.of("firmament:storageoverlay/player_inventory") + val upperBackgroundSprite = Identifier.of("firmament:storageoverlay/upper_background") + val slotRowSprite = Identifier.of("firmament:storageoverlay/storage_row") + val scrollbarBackground = Identifier.of("firmament:storageoverlay/scroll_bar_background") + val scrollbarKnob = Identifier.of("firmament:storageoverlay/scroll_bar_knob") - override fun mouseScrolled( - mouseX: Double, - mouseY: Double, - horizontalAmount: Double, - verticalAmount: Double - ): Boolean { - scroll = (scroll + StorageOverlay.adjustScrollSpeed(verticalAmount)).toFloat() - .coerceAtMost(getMaxScroll()) - .coerceAtLeast(0F) - return true - } + override fun close() { + isExiting = true + super.close() + } - fun getMaxScroll() = lastRenderedInnerHeight.toFloat() - getScrollPanelInner().height + override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + super.render(context, mouseX, mouseY, delta) + drawBackgrounds(context) + drawPages(context, mouseX, mouseY, delta, null, null, Point()) + drawScrollBar(context) + drawPlayerInventory(context, mouseX, mouseY, delta) + } - val playerInventorySprite = Identifier.of("firmament:storageoverlay/player_inventory") - val upperBackgroundSprite = Identifier.of("firmament:storageoverlay/upper_background") - val slotRowSprite = Identifier.of("firmament:storageoverlay/storage_row") - val scrollbarBackground = Identifier.of("firmament:storageoverlay/scroll_bar_background") - val scrollbarKnob = Identifier.of("firmament:storageoverlay/scroll_bar_knob") + fun getScrollbarPercentage(): Float { + return scroll / getMaxScroll() + } - override fun close() { - isExiting = true - super.close() - } + fun drawScrollBar(context: DrawContext) { + val sbRect = getScrollBarRect() + context.drawGuiTexture( + scrollbarBackground, + sbRect.minX, sbRect.minY, + sbRect.width, sbRect.height, + ) + context.drawGuiTexture( + scrollbarKnob, + sbRect.minX, sbRect.minY + (getScrollbarPercentage() * (sbRect.height - SCROLL_BAR_HEIGHT)).toInt(), + SCROLL_BAR_WIDTH, SCROLL_BAR_HEIGHT + ) + } - override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { - super.render(context, mouseX, mouseY, delta) - drawBackgrounds(context) - drawPages(context, mouseX, mouseY, delta, null, null, Point()) - drawScrollBar(context) - drawPlayerInventory(context, mouseX, mouseY, delta) - } + fun drawBackgrounds(context: DrawContext) { + context.drawGuiTexture(upperBackgroundSprite, + measurements.x, + measurements.y, + 0, + measurements.overviewWidth, + measurements.overviewHeight) + context.drawGuiTexture(playerInventorySprite, + measurements.playerX, + measurements.playerY, + 0, + PLAYER_WIDTH, + PLAYER_HEIGHT) + } - fun getScrollbarPercentage(): Float { - return scroll / getMaxScroll() - } + fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> { + if (int < 9) { + return Pair(measurements.playerX + int * SLOT_SIZE + HOTBAR_X, HOTBAR_Y + measurements.playerY) + } + return Pair( + measurements.playerX + (int % 9) * SLOT_SIZE + HOTBAR_X, + measurements.playerY + (int / 9 - 1) * SLOT_SIZE + MAIN_INVENTORY_Y + ) + } - fun drawScrollBar(context: DrawContext) { - val sbRect = getScrollBarRect() - context.drawGuiTexture( - scrollbarBackground, - sbRect.minX, sbRect.minY, - sbRect.width, sbRect.height, - ) - context.drawGuiTexture( - scrollbarKnob, - sbRect.minX, sbRect.minY + (getScrollbarPercentage() * (sbRect.height - SCROLL_BAR_HEIGHT)).toInt(), - SCROLL_BAR_WIDTH, SCROLL_BAR_HEIGHT - ) - } + fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + val items = MC.player?.inventory?.main ?: return + items.withIndex().forEach { (index, item) -> + val (x, y) = getPlayerInventorySlotPosition(index) + context.drawItem(item, x, y, 0) + context.drawItemInSlot(textRenderer, item, x, y) + } + } - fun drawBackgrounds(context: DrawContext) { - context.drawGuiTexture(upperBackgroundSprite, - measurements.x, - measurements.y, - 0, - measurements.overviewWidth, - measurements.overviewHeight) - context.drawGuiTexture(playerInventorySprite, - measurements.playerX, - measurements.playerY, - 0, - PLAYER_WIDTH, - PLAYER_HEIGHT) - } + fun getScrollBarRect(): Rectangle { + return Rectangle(measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING, + measurements.y + PADDING, + SCROLL_BAR_WIDTH, + measurements.innerScrollPanelHeight) + } - fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> { - if (int < 9) { - return Pair(measurements.playerX + int * SLOT_SIZE + HOTBAR_X, HOTBAR_Y + measurements.playerY) - } - return Pair( - measurements.playerX + (int % 9) * SLOT_SIZE + HOTBAR_X, - measurements.playerY + (int / 9 - 1) * SLOT_SIZE + MAIN_INVENTORY_Y - ) - } + fun getScrollPanelInner(): Rectangle { + return Rectangle(measurements.x + PADDING, + measurements.y + PADDING, + measurements.innerScrollPanelWidth, + measurements.innerScrollPanelHeight) + } - fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { - val items = MC.player?.inventory?.main ?: return - items.withIndex().forEach { (index, item) -> - val (x, y) = getPlayerInventorySlotPosition(index) - context.drawItem(item, x, y, 0) - context.drawItemInSlot(textRenderer, item, x, y) - } - } + fun createScissors(context: DrawContext) { + val rect = getScrollPanelInner() + context.enableScissor( + rect.minX, rect.minY, + rect.maxX, rect.maxY + ) + } - fun getScrollBarRect(): Rectangle { - return Rectangle(measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING, - measurements.y + PADDING, - SCROLL_BAR_WIDTH, - measurements.innerScrollPanelHeight) - } + fun drawPages( + context: DrawContext, mouseX: Int, mouseY: Int, delta: Float, + excluding: StoragePageSlot?, + slots: List<Slot>?, + slotOffset: Point + ) { + createScissors(context) + val data = StorageOverlay.Data.data ?: StorageData() + layoutedForEach(data) { rect, page, inventory -> + drawPage(context, + rect.x, + rect.y, + page, inventory, + if (excluding == page) slots else null, + slotOffset + ) + } + context.disableScissor() + } - fun getScrollPanelInner(): Rectangle { - return Rectangle(measurements.x + PADDING, - measurements.y + PADDING, - measurements.innerScrollPanelWidth, - measurements.innerScrollPanelHeight) - } + var knobGrabbed = false - fun createScissors(context: DrawContext) { - val rect = getScrollPanelInner() - context.enableScissor( - rect.minX, rect.minY, - rect.maxX, rect.maxY - ) - } + override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { + return mouseClicked(mouseX, mouseY, button, null) + } - fun drawPages( - context: DrawContext, mouseX: Int, mouseY: Int, delta: Float, - excluding: StoragePageSlot?, - slots: List<Slot>?, - slotOffset: Point - ) { - createScissors(context) - val data = StorageOverlay.Data.data ?: StorageData() - layoutedForEach(data) { rect, page, inventory -> - drawPage(context, - rect.x, - rect.y, - page, inventory, - if (excluding == page) slots else null, - slotOffset - ) - } - context.disableScissor() - } + override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + if (knobGrabbed) { + knobGrabbed = false + return true + } + return super.mouseReleased(mouseX, mouseY, button) + } - override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { - return mouseClicked(mouseX, mouseY, button, null) - } + override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + if (knobGrabbed) { + val sbRect = getScrollBarRect() + val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight() + scroll = (getMaxScroll() * percentage).toFloat() + mouseScrolled(0.0, 0.0, 0.0, 0.0) + return true + } + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) + } - fun mouseClicked(mouseX: Double, mouseY: Double, button: Int, activePage: StoragePageSlot?): Boolean { - if (getScrollPanelInner().contains(mouseX, mouseY)) { - val data = StorageOverlay.Data.data ?: StorageData() - layoutedForEach(data) { rect, page, _ -> - if (rect.contains(mouseX, mouseY) && activePage != page && button == 0) { - page.navigateTo() - return true - } - } - return false - } - val sbRect = getScrollBarRect() - if (sbRect.contains(mouseX, mouseY)) { - // TODO: support dragging of the mouse and such - val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight() - scroll = (getMaxScroll() * percentage).toFloat() - mouseScrolled(0.0, 0.0, 0.0, 0.0) - return true - } - return false - } + fun mouseClicked(mouseX: Double, mouseY: Double, button: Int, activePage: StoragePageSlot?): Boolean { + if (getScrollPanelInner().contains(mouseX, mouseY)) { + val data = StorageOverlay.Data.data ?: StorageData() + layoutedForEach(data) { rect, page, _ -> + if (rect.contains(mouseX, mouseY) && activePage != page && button == 0) { + page.navigateTo() + return true + } + } + return false + } + val sbRect = getScrollBarRect() + if (sbRect.contains(mouseX, mouseY)) { + val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight() + scroll = (getMaxScroll() * percentage).toFloat() + mouseScrolled(0.0, 0.0, 0.0, 0.0) + knobGrabbed = true + return true + } + return false + } - private inline fun layoutedForEach( - data: StorageData, - func: ( - rectangle: Rectangle, - page: StoragePageSlot, inventory: StorageData.StorageInventory, - ) -> Unit - ) { - var yOffset = -scroll.toInt() - var xOffset = 0 - var maxHeight = 0 - for ((page, inventory) in data.storageInventories.entries) { - val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight } - ?: 18 - maxHeight = maxOf(maxHeight, currentHeight) - val rect = Rectangle( - measurements.x + PADDING + (PAGE_WIDTH + PADDING) * xOffset, - yOffset + measurements.y + PADDING, - PAGE_WIDTH, - currentHeight - ) - func(rect, page, inventory) - xOffset++ - if (xOffset >= pageWidthCount) { - yOffset += maxHeight - xOffset = 0 - maxHeight = 0 - } - } - lastRenderedInnerHeight = maxHeight + yOffset + scroll.toInt() - } + private inline fun layoutedForEach( + data: StorageData, + func: ( + rectangle: Rectangle, + page: StoragePageSlot, inventory: StorageData.StorageInventory, + ) -> Unit + ) { + var yOffset = -scroll.toInt() + var xOffset = 0 + var maxHeight = 0 + for ((page, inventory) in data.storageInventories.entries) { + val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight } + ?: 18 + maxHeight = maxOf(maxHeight, currentHeight) + val rect = Rectangle( + measurements.x + PADDING + (PAGE_WIDTH + PADDING) * xOffset, + yOffset + measurements.y + PADDING, + PAGE_WIDTH, + currentHeight + ) + func(rect, page, inventory) + xOffset++ + if (xOffset >= pageWidthCount) { + yOffset += maxHeight + xOffset = 0 + maxHeight = 0 + } + } + lastRenderedInnerHeight = maxHeight + yOffset + scroll.toInt() + } - fun drawPage( - context: DrawContext, - x: Int, - y: Int, - page: StoragePageSlot, - inventory: StorageData.StorageInventory, - slots: List<Slot>?, - slotOffset: Point, - ): Int { - val inv = inventory.inventory - if (inv == null) { - context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18) - context.drawText(textRenderer, - Text.literal("TODO: open this page"), - x + 4, - y + 4, - -1, - true) - return 18 - } - assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 } - val name = page.defaultName() - context.drawText(textRenderer, Text.literal(name), x + 4, y + 2, - if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true) - context.drawGuiTexture(slotRowSprite, x, y + 4 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE) - inv.stacks.forEachIndexed { index, stack -> - val slotX = (index % 9) * SLOT_SIZE + x + 1 - val slotY = (index / 9) * SLOT_SIZE + y + 4 + textRenderer.fontHeight + 1 - if (slots == null) { - context.drawItem(stack, slotX, slotY) - context.drawItemInSlot(textRenderer, stack, slotX, slotY) - } else { - val slot = slots[index] - slot.x = slotX - slotOffset.x - slot.y = slotY - slotOffset.y - } - } - return inv.rows * SLOT_SIZE + 4 + textRenderer.fontHeight - } + fun drawPage( + context: DrawContext, + x: Int, + y: Int, + page: StoragePageSlot, + inventory: StorageData.StorageInventory, + slots: List<Slot>?, + slotOffset: Point, + ): Int { + val inv = inventory.inventory + if (inv == null) { + context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18) + context.drawText(textRenderer, + Text.literal("TODO: open this page"), + x + 4, + y + 4, + -1, + true) + return 18 + } + assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 } + val name = page.defaultName() + context.drawText(textRenderer, Text.literal(name), x + 4, y + 2, + if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true) + context.drawGuiTexture(slotRowSprite, x, y + 4 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE) + inv.stacks.forEachIndexed { index, stack -> + val slotX = (index % 9) * SLOT_SIZE + x + 1 + val slotY = (index / 9) * SLOT_SIZE + y + 4 + textRenderer.fontHeight + 1 + if (slots == null) { + context.drawItem(stack, slotX, slotY) + context.drawItemInSlot(textRenderer, stack, slotX, slotY) + } else { + val slot = slots[index] + slot.x = slotX - slotOffset.x + slot.y = slotY - slotOffset.y + } + } + return inv.rows * SLOT_SIZE + 4 + textRenderer.fontHeight + } - fun getBounds(): List<Rectangle> { - return listOf( - Rectangle(measurements.x, - measurements.y, - measurements.overviewWidth, - measurements.overviewHeight), - Rectangle(measurements.playerX, - measurements.playerY, - PLAYER_WIDTH, - PLAYER_HEIGHT)) - } + fun getBounds(): List<Rectangle> { + return listOf( + Rectangle(measurements.x, + measurements.y, + measurements.overviewWidth, + measurements.overviewHeight), + Rectangle(measurements.playerX, + measurements.playerY, + PLAYER_WIDTH, + PLAYER_HEIGHT)) + } } diff --git a/src/main/kotlin/util/customgui/CustomGui.kt b/src/main/kotlin/util/customgui/CustomGui.kt index f9094b2..5224448 100644 --- a/src/main/kotlin/util/customgui/CustomGui.kt +++ b/src/main/kotlin/util/customgui/CustomGui.kt @@ -1,4 +1,3 @@ - package moe.nea.firmament.util.customgui import me.shedaniel.math.Rectangle @@ -9,64 +8,72 @@ import moe.nea.firmament.events.HandledScreenPushREIEvent abstract class CustomGui { - abstract fun getBounds(): List<Rectangle> + abstract fun getBounds(): List<Rectangle> + + open fun moveSlot(slot: Slot) { + // TODO: return a Pair maybe? worth an investigation + } + + companion object { + @Subscribe + fun onExclusionZone(event: HandledScreenPushREIEvent) { + val customGui = event.screen.customGui ?: return + event.rectangles.addAll(customGui.getBounds()) + } + } - open fun moveSlot(slot: Slot) { - // TODO: return a Pair maybe? worth an investigation - } + open fun render( + drawContext: DrawContext, + delta: Float, + mouseX: Int, + mouseY: Int + ) { + } - companion object { - @Subscribe - fun onExclusionZone(event: HandledScreenPushREIEvent) { - val customGui = event.screen.customGui ?: return - event.rectangles.addAll(customGui.getBounds()) - } - } + open fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { + return false + } - open fun render( - drawContext: DrawContext, - delta: Float, - mouseX: Int, - mouseY: Int - ) { - } + open fun afterSlotRender(context: DrawContext, slot: Slot) {} + open fun beforeSlotRender(context: DrawContext, slot: Slot) {} + open fun mouseScrolled(mouseX: Double, mouseY: Double, horizontalAmount: Double, verticalAmount: Double): Boolean { + return false + } - open fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { - return false - } + open fun isClickOutsideBounds(mouseX: Double, mouseY: Double): Boolean { + return getBounds().none { it.contains(mouseX, mouseY) } + } - open fun afterSlotRender(context: DrawContext, slot: Slot) {} - open fun beforeSlotRender(context: DrawContext, slot: Slot) {} - open fun mouseScrolled(mouseX: Double, mouseY: Double, horizontalAmount: Double, verticalAmount: Double): Boolean { - return false - } + open fun isPointWithinBounds( + x: Int, + y: Int, + width: Int, + height: Int, + pointX: Double, + pointY: Double, + ): Boolean { + return getBounds().any { it.contains(pointX, pointY) } && + Rectangle(x, y, width, height).contains(pointX, pointY) + } - open fun isClickOutsideBounds(mouseX: Double, mouseY: Double): Boolean { - return getBounds().none { it.contains(mouseX, mouseY) } - } + open fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean { + return isPointWithinBounds(slot.x + xOffset, slot.y + yOffset, 16, 16, pointX, pointY) + } - open fun isPointWithinBounds( - x: Int, - y: Int, - width: Int, - height: Int, - pointX: Double, - pointY: Double, - ): Boolean { - return getBounds().any { it.contains(pointX, pointY) } && - Rectangle(x, y, width, height).contains(pointX, pointY) - } + open fun onInit() {} + open fun shouldDrawForeground(): Boolean { + return true + } - open fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean { - return isPointWithinBounds(slot.x + xOffset, slot.y + yOffset, 16, 16, pointX, pointY) - } + open fun onVoluntaryExit(): Boolean { + return true + } - open fun onInit() {} - open fun shouldDrawForeground(): Boolean { - return true - } + open fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + return false + } - open fun onVoluntaryExit(): Boolean { - return true - } + open fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + return false + } } |