From 81005326787d0a98eb7fe8228dad2fd24e721f8d Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 7 Mar 2021 14:02:39 -0500 Subject: [PATCH] Add Terminal GUI scrolling --- .../phycon/block/terminal/TerminalScreen.kt | 54 ++++++++++++++++-- .../block/terminal/TerminalScreenHandler.kt | 42 ++++++++++++-- .../C2STerminalUpdateDisplayedItems.kt | 6 +- .../S2CTerminalUpdateDisplayedItems.kt | 8 ++- .../assets/phycon/textures/gui/terminal.png | Bin 10735 -> 10905 bytes 5 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreen.kt b/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreen.kt index c4fb999..f6a23e5 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreen.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreen.kt @@ -17,6 +17,7 @@ import net.minecraft.text.LiteralText import net.minecraft.text.Text import net.minecraft.text.TranslatableText import net.minecraft.util.Identifier +import net.minecraft.util.math.MathHelper import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.networking.C2STerminalRequestItem import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems @@ -28,6 +29,7 @@ import java.lang.NumberFormatException import kotlin.math.ceil import kotlin.math.floor import kotlin.math.min +import kotlin.math.roundToInt /** * @author shadowfacts @@ -59,6 +61,15 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, } private var dialogChildren = mutableListOf() + private var scrollPosition = 0f + private var isDraggingScrollThumb = false + private val trackMinY = 18 + private val trackHeight = 106 + private val thumbHeight = 15 + private val thumbWidth = 12 + private val scrollThumbTop: Int + get() = trackMinY + (scrollPosition * (trackHeight - thumbHeight)).roundToInt() + private val dialogWidth = 158 private val dialogHeight = 62 @@ -150,7 +161,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, private fun requestUpdatedItems() { val player = MinecraftClient.getInstance().player!! - player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode)) + player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode, scrollPosition)) } override fun tick() { @@ -176,6 +187,9 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, val x = (width - backgroundWidth) / 2 val y = (height - backgroundHeight) / 2 drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight) + + // scroll thumb + drawTexture(matrixStack, x + 232, y + scrollThumbTop, 52, 230, thumbWidth, thumbHeight) } @ExperimentalUnsignedTypes @@ -227,6 +241,16 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt()) } + private fun isPointInsScrollThumb(mouseX: Double, mouseY: Double): Boolean { + val x = (width - backgroundWidth) / 2 + val y = (height - backgroundHeight) / 2 + val thumbMinX = x + 232 + val thumbMaxX = thumbMinX + thumbWidth + val thumbMinY = y + scrollThumbTop + val thumbMaxY = thumbMinY + thumbHeight + return mouseX >= thumbMinX && mouseX < thumbMaxX && mouseY >= thumbMinY && mouseY < thumbMaxY + } + override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) { super.onMouseClick(slot, invSlot, clickData, type) @@ -261,15 +285,25 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, } return false } else { + if (isPointInsScrollThumb(mouseX, mouseY)) { + isDraggingScrollThumb = true + return true + } + return super.mouseClicked(mouseX, mouseY, button) } } - override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean { + override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { if (showingAmountDialog) { return false + } else if (isDraggingScrollThumb) { + scrollPosition = (mouseY.toFloat() - (y + trackMinY) - 7.5f) / (trackHeight - 15) + scrollPosition = MathHelper.clamp(scrollPosition, 0f, 1f) + requestUpdatedItems() + return true } else { - return super.mouseDragged(d, e, i, f, g) + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) } } @@ -284,15 +318,23 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, if (showingAmountDialog) { return false } else { + isDraggingScrollThumb = false + return super.mouseReleased(d, e, i) } } - override fun mouseScrolled(d: Double, e: Double, f: Double): Boolean { + override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean { if (showingAmountDialog) { return false } else { - return super.mouseScrolled(d, e, f) + var newOffsetInRows = handler.currentScrollOffsetInRows() - amount.toInt() + newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, handler.maxScrollOffsetInRows()) + val newScrollPosition = newOffsetInRows / handler.maxScrollOffsetInRows().toFloat() + scrollPosition = newScrollPosition + requestUpdatedItems() + + return super.mouseScrolled(mouseX, mouseY, amount) } } @@ -303,6 +345,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, val oldText = searchBox.text if (searchBox.charTyped(c, i)) { if (searchBox.text != oldText) { + scrollPosition = 0f requestUpdatedItems() } return true @@ -331,6 +374,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, val oldText = searchBox.text if (searchBox.keyPressed(key, j, k)) { if (searchBox.text != oldText) { + scrollPosition = 0f requestUpdatedItems() } return true diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreenHandler.kt b/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreenHandler.kt index 25d4f5b..5137ad9 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreenHandler.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/terminal/TerminalScreenHandler.kt @@ -17,7 +17,10 @@ import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems import net.shadowfacts.phycon.util.SortMode import net.shadowfacts.phycon.util.copyWithCount import java.lang.ref.WeakReference +import kotlin.math.ceil +import kotlin.math.max import kotlin.math.min +import kotlin.math.roundToInt /** * @author shadowfacts @@ -29,10 +32,15 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter val ID = Identifier(PhysicalConnectivity.MODID, "terminal") } + private val rowsDisplayed = 6 + private val fakeInv = FakeInventory(this) private var searchQuery: String = "" var sortMode = SortMode.COUNT_HIGH_FIRST private set + var totalEntries = 0 + private set + private var scrollPosition = 0f private var itemEntries = listOf() set(value) { field = value @@ -96,6 +104,8 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter it.key.name.string.contains(searchQuery, true) } + totalEntries = filtered.size + val sorted = when (sortMode) { SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue } @@ -103,22 +113,46 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter SortMode.ALPHABETICAL -> filtered.sortedBy { it.key.name.string } } - itemEntries = sorted.map { Entry(it.key, it.intValue) } - (player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, sortMode)) + val offsetInItems = currentScrollOffsetInItems() + val end = min(offsetInItems + rowsDisplayed * 9, sorted.size) + itemEntries = sorted.subList(offsetInItems, end).map { Entry(it.key, it.intValue) } + +// itemEntries = sorted.map { Entry(it.key, it.intValue) } + + (player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, sortMode, scrollPosition, totalEntries)) } - fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode) { + fun totalRows(): Int { + return ceil(totalEntries / 9f).toInt() + } + + fun maxScrollOffsetInRows(): Int { + return totalRows() - rowsDisplayed + } + + fun currentScrollOffsetInRows(): Int { + return max(0, (scrollPosition * maxScrollOffsetInRows()).roundToInt()) + } + + fun currentScrollOffsetInItems(): Int { + return currentScrollOffsetInRows() * 9 + } + + fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode, scrollPosition: Float) { this.searchQuery = query this.sortMode = sortMode + this.scrollPosition = scrollPosition netItemsChanged() } - fun receivedUpdatedItemsFromServer(entries: List, query: String, sortMode: SortMode) { + fun receivedUpdatedItemsFromServer(entries: List, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int) { assert(playerInv.player.world.isClient) this.searchQuery = query this.sortMode = sortMode + this.scrollPosition = scrollPosition + this.totalEntries = totalEntries itemEntries = entries } diff --git a/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalUpdateDisplayedItems.kt b/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalUpdateDisplayedItems.kt index f080066..c27da55 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalUpdateDisplayedItems.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalUpdateDisplayedItems.kt @@ -21,7 +21,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver { override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed") - operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode): Packet<*> { + operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode, scrollPosition: Float): Packet<*> { val buf = PacketByteBufs.create() buf.writeIdentifier(terminal.world!!.registryKey.value) @@ -29,6 +29,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver { buf.writeString(query) buf.writeVarInt(sortMode.ordinal) + buf.writeFloat(scrollPosition) return ClientPlayNetworking.createC2SPacket(CHANNEL, buf) } @@ -38,13 +39,14 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver { val pos = buf.readBlockPos() val query = buf.readString() val sortMode = SortMode.values()[buf.readVarInt()] + val scrollPosition = buf.readFloat() server.execute { if (player.world.registryKey.value != dimID) return@execute val screenHandler = player.currentScreenHandler if (screenHandler !is TerminalScreenHandler) return@execute if (screenHandler.terminal.pos != pos) return@execute - screenHandler.sendUpdatedItemsToClient(player, query, sortMode) + screenHandler.sendUpdatedItemsToClient(player, query, sortMode, scrollPosition) } } } diff --git a/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt b/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt index ccc05a1..042d109 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt @@ -17,7 +17,7 @@ import net.shadowfacts.phycon.util.SortMode object S2CTerminalUpdateDisplayedItems: ClientReceiver { override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL - operator fun invoke(terminal: TerminalBlockEntity, entries: List, query: String, sortMode: SortMode): Packet<*> { + operator fun invoke(terminal: TerminalBlockEntity, entries: List, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int): Packet<*> { val buf = PacketByteBufs.create() buf.writeIdentifier(terminal.world!!.registryKey.value) @@ -31,6 +31,8 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver { buf.writeString(query) buf.writeVarInt(sortMode.ordinal) + buf.writeFloat(scrollPosition) + buf.writeInt(totalEntries) return ServerPlayNetworking.createS2CPacket(CHANNEL, buf) } @@ -45,13 +47,15 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver { } val query = buf.readString() val sortMode = SortMode.values()[buf.readVarInt()] + val scrollPosition = buf.readFloat() + val totalEntries = buf.readInt() client.execute { if (client.player!!.world.registryKey.value != dimID) return@execute val screenHandler = client.player!!.currentScreenHandler if (screenHandler !is TerminalScreenHandler) return@execute if (screenHandler.terminal.pos != pos) return@execute - screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode) + screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode, scrollPosition, totalEntries) } } } diff --git a/src/main/resources/assets/phycon/textures/gui/terminal.png b/src/main/resources/assets/phycon/textures/gui/terminal.png index c2d10a7cb8b6d8b3774c58e67ef5ffbdad526f6a..cd530d5574ea5714b5a36cabcee348291a882352 100644 GIT binary patch delta 10573 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 Syi5Q9002n`MNUMnLSTZ?<6Ln7