feat: Add border to selected storage page

This commit is contained in:
Linnea Gräf
2025-06-08 00:03:38 +02:00
parent d8472888c0
commit 576dd477bb
3 changed files with 116 additions and 69 deletions

View File

@@ -27,6 +27,7 @@ object StorageOverlay : FirmamentFeature {
object TConfig : ManagedConfig(identifier, Category.INVENTORY) { object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val alwaysReplace by toggle("always-replace") { true } val alwaysReplace by toggle("always-replace") { true }
val outlineActiveStoragePage by toggle("outline-active-page") { false }
val columns by integer("rows", 1, 10) { 3 } val columns by integer("rows", 1, 10) { 3 }
val height by integer("height", 80, 3000) { 3 * 18 * 6 } val height by integer("height", 80, 3000) { 3 * 18 * 6 }
val scrollSpeed by integer("scroll-speed", 1, 50) { 10 } val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
@@ -101,7 +102,8 @@ object StorageOverlay : FirmamentFeature {
screen.customGui = StorageOverlayCustom( screen.customGui = StorageOverlayCustom(
currentHandler ?: return, currentHandler ?: return,
screen, screen,
storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return)) storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return)
)
} }
fun rememberContent(handler: StorageBackingHandle?) { fun rememberContent(handler: StorageBackingHandle?) {

View File

@@ -47,7 +47,8 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val PLAYER_Y_INSET = 3 val PLAYER_Y_INSET = 3
val SLOT_SIZE = 18 val SLOT_SIZE = 18
val PADDING = 10 val PADDING = 10
val PAGE_WIDTH = SLOT_SIZE * 9 val PAGE_SLOTS_WIDTH = SLOT_SIZE * 9
val PAGE_WIDTH = PAGE_SLOTS_WIDTH + 4
val HOTBAR_X = 12 val HOTBAR_X = 12
val HOTBAR_Y = 67 val HOTBAR_Y = 67
val MAIN_INVENTORY_Y = 9 val MAIN_INVENTORY_Y = 9
@@ -68,7 +69,8 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val x = width / 2 - overviewWidth / 2 val x = width / 2 - overviewWidth / 2
val overviewHeight = minOf( val overviewHeight = minOf(
height - PLAYER_HEIGHT - minOf(80, height / 10), height - PLAYER_HEIGHT - minOf(80, height / 10),
StorageOverlay.TConfig.height) StorageOverlay.TConfig.height
)
val innerScrollPanelHeight = overviewHeight - PADDING * 2 val innerScrollPanelHeight = overviewHeight - PADDING * 2
val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2 val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2
val playerX = width / 2 - PLAYER_WIDTH / 2 val playerX = width / 2 - PLAYER_WIDTH / 2
@@ -100,6 +102,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
coerceScroll(StorageOverlay.adjustScrollSpeed(verticalAmount).toFloat()) coerceScroll(StorageOverlay.adjustScrollSpeed(verticalAmount).toFloat())
return true return true
} }
fun coerceScroll(offset: Float) { fun coerceScroll(offset: Float) {
scroll = (scroll + offset) scroll = (scroll + offset)
.coerceAtMost(getMaxScroll()) .coerceAtMost(getMaxScroll())
@@ -159,11 +162,16 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val guiContext = GuiContext(EmptyComponent()) val guiContext = GuiContext(EmptyComponent())
private val knobStub = EmptyComponent() private val knobStub = EmptyComponent()
val editButton = FirmButtonComponent(TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string), action = ::editPages) val editButton = FirmButtonComponent(
TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string),
action = ::editPages
)
val searchText = Property.of("") // TODO: sync with REI val searchText = Property.of("") // TODO: sync with REI
val searchField = TextFieldComponent(searchText, 100, GetSetter.constant(true), val searchField = TextFieldComponent(
tr("firmament.storage-overlay.search.suggestion", "Search...").string, searchText, 100, GetSetter.constant(true),
IMinecraft.instance.defaultFontRenderer) tr("firmament.storage-overlay.search.suggestion", "Search...").string,
IMinecraft.instance.defaultFontRenderer
)
val controlComponent = PanelComponent( val controlComponent = PanelComponent(
ColumnComponent( ColumnComponent(
searchField, searchField,
@@ -186,25 +194,31 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
controllerBackground, controllerBackground,
measurements.controlX, measurements.controlX,
measurements.controlY, measurements.controlY,
CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT) CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT
)
context.drawMCComponentInPlace( context.drawMCComponentInPlace(
controlComponent, controlComponent,
measurements.controlX, measurements.controlY, measurements.controlX, measurements.controlY,
CONTROL_WIDTH, CONTROL_HEIGHT, CONTROL_WIDTH, CONTROL_HEIGHT,
mouseX, mouseY) mouseX, mouseY
)
} }
fun drawBackgrounds(context: DrawContext) { fun drawBackgrounds(context: DrawContext) {
context.drawGuiTexture(upperBackgroundSprite, context.drawGuiTexture(
measurements.x, upperBackgroundSprite,
measurements.y, measurements.x,
measurements.overviewWidth, measurements.y,
measurements.overviewHeight) measurements.overviewWidth,
context.drawGuiTexture(playerInventorySprite, measurements.overviewHeight
measurements.playerX, )
measurements.playerY, context.drawGuiTexture(
PLAYER_WIDTH, playerInventorySprite,
PLAYER_HEIGHT) measurements.playerX,
measurements.playerY,
PLAYER_WIDTH,
PLAYER_HEIGHT
)
} }
fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> { fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> {
@@ -227,17 +241,21 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
} }
fun getScrollBarRect(): Rectangle { fun getScrollBarRect(): Rectangle {
return Rectangle(measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING, return Rectangle(
measurements.y + PADDING, measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING,
SCROLL_BAR_WIDTH, measurements.y + PADDING,
measurements.innerScrollPanelHeight) SCROLL_BAR_WIDTH,
measurements.innerScrollPanelHeight
)
} }
fun getScrollPanelInner(): Rectangle { fun getScrollPanelInner(): Rectangle {
return Rectangle(measurements.x + PADDING, return Rectangle(
measurements.y + PADDING, measurements.x + PADDING,
measurements.innerScrollPanelWidth, measurements.y + PADDING,
measurements.innerScrollPanelHeight) measurements.innerScrollPanelWidth,
measurements.innerScrollPanelHeight
)
} }
fun createScissors(context: DrawContext) { fun createScissors(context: DrawContext) {
@@ -257,12 +275,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
createScissors(context) createScissors(context)
val data = StorageOverlay.Data.data ?: StorageData() val data = StorageOverlay.Data.data ?: StorageData()
layoutedForEach(data) { rect, page, inventory -> layoutedForEach(data) { rect, page, inventory ->
drawPage(context, drawPage(
rect.x, context,
rect.y, rect.x,
page, inventory, rect.y,
if (excluding == page) slots else null, page, inventory,
slotOffset if (excluding == page) slots else null,
slotOffset
) )
} }
context.disableScissor() context.disableScissor()
@@ -282,11 +301,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
knobGrabbed = false knobGrabbed = false
return true return true
} }
if (clickMCComponentInPlace(controlComponent, if (clickMCComponentInPlace(
measurements.controlX, measurements.controlY, controlComponent,
CONTROL_WIDTH, CONTROL_HEIGHT, measurements.controlX, measurements.controlY,
mouseX.toInt(), mouseY.toInt(), CONTROL_WIDTH, CONTROL_HEIGHT,
MouseEvent.Click(button, false)) mouseX.toInt(), mouseY.toInt(),
MouseEvent.Click(button, false)
)
) return true ) return true
return super.mouseReleased(mouseX, mouseY, button) return super.mouseReleased(mouseX, mouseY, button)
} }
@@ -322,11 +343,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
knobGrabbed = true knobGrabbed = true
return true return true
} }
if (clickMCComponentInPlace(controlComponent, if (clickMCComponentInPlace(
measurements.controlX, measurements.controlY, controlComponent,
CONTROL_WIDTH, CONTROL_HEIGHT, measurements.controlX, measurements.controlY,
mouseX.toInt(), mouseY.toInt(), CONTROL_WIDTH, CONTROL_HEIGHT,
MouseEvent.Click(button, true)) mouseX.toInt(), mouseY.toInt(),
MouseEvent.Click(button, true)
)
) return true ) return true
return false return false
} }
@@ -420,7 +443,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val filter = getFilteredPages() val filter = getFilteredPages()
for ((page, inventory) in data.storageInventories.entries) { for ((page, inventory) in data.storageInventories.entries) {
if (page !in filter) continue if (page !in filter) continue
val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight } val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 6 + textRenderer.fontHeight }
?: 18 ?: 18
maxHeight = maxOf(maxHeight, currentHeight) maxHeight = maxOf(maxHeight, currentHeight)
val rect = Rectangle( val rect = Rectangle(
@@ -452,22 +475,35 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
val inv = inventory.inventory val inv = inventory.inventory
if (inv == null) { if (inv == null) {
context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18) context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18)
context.drawText(textRenderer, context.drawText(
Text.literal("TODO: open this page"), textRenderer,
x + 4, Text.literal("TODO: open this page"),
y + 4, x + 4,
-1, y + 4,
true) -1,
true
)
return 18 return 18
} }
assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 } assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 }
val name = page.defaultName() val name = page.defaultName()
context.drawText(textRenderer, Text.literal(name), x + 4, y + 2, val pageHeight = inv.rows * SLOT_SIZE + 8 + textRenderer.fontHeight
if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true) if (slots != null && StorageOverlay.TConfig.outlineActiveStoragePage)
context.drawGuiTexture(slotRowSprite, x, y + 4 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE) context.drawBorder(x, y + 3 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE + 4, 0xFFFF00FF.toInt())
context.drawText(
textRenderer, Text.literal(name), x + 6, y + 3,
if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true
)
context.drawGuiTexture(
slotRowSprite,
x + 2,
y + 5 + textRenderer.fontHeight,
PAGE_SLOTS_WIDTH,
inv.rows * SLOT_SIZE
)
inv.stacks.forEachIndexed { index, stack -> inv.stacks.forEachIndexed { index, stack ->
val slotX = (index % 9) * SLOT_SIZE + x + 1 val slotX = (index % 9) * SLOT_SIZE + x + 3
val slotY = (index / 9) * SLOT_SIZE + y + 4 + textRenderer.fontHeight + 1 val slotY = (index / 9) * SLOT_SIZE + y + 5 + textRenderer.fontHeight + 1
val fakeSlot = FakeSlot(stack, slotX, slotY) val fakeSlot = FakeSlot(stack, slotX, slotY)
if (slots == null) { if (slots == null) {
SlotRenderEvents.Before.publish(SlotRenderEvents.Before(context, fakeSlot)) SlotRenderEvents.Before.publish(SlotRenderEvents.Before(context, fakeSlot))
@@ -480,22 +516,29 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
slot.y = slotY - slotOffset.y slot.y = slotY - slotOffset.y
} }
} }
return inv.rows * SLOT_SIZE + 4 + textRenderer.fontHeight return pageHeight + 6
} }
fun getBounds(): List<Rectangle> { fun getBounds(): List<Rectangle> {
return listOf( return listOf(
Rectangle(measurements.x, Rectangle(
measurements.y, measurements.x,
measurements.overviewWidth, measurements.y,
measurements.overviewHeight), measurements.overviewWidth,
Rectangle(measurements.playerX, measurements.overviewHeight
measurements.playerY, ),
PLAYER_WIDTH, Rectangle(
PLAYER_HEIGHT), measurements.playerX,
Rectangle(measurements.controlX, measurements.playerY,
measurements.controlY, PLAYER_WIDTH,
CONTROL_WIDTH, PLAYER_HEIGHT
CONTROL_HEIGHT)) ),
Rectangle(
measurements.controlX,
measurements.controlY,
CONTROL_WIDTH,
CONTROL_HEIGHT
)
)
} }
} }

View File

@@ -279,6 +279,8 @@
"firmament.config.storage-overlay.inverse-scroll.description": "Invert the mouse wheel scrolling in Firmament's storage overlay.", "firmament.config.storage-overlay.inverse-scroll.description": "Invert the mouse wheel scrolling in Firmament's storage overlay.",
"firmament.config.storage-overlay.margin": "Margin", "firmament.config.storage-overlay.margin": "Margin",
"firmament.config.storage-overlay.margin.description": "Margin inside of the storage overview.", "firmament.config.storage-overlay.margin.description": "Margin inside of the storage overview.",
"firmament.config.storage-overlay.outline-active-page": "Outline Active Page",
"firmament.config.storage-overlay.outline-active-page.description": "Put a border around the selected storage page in the storage overlay.",
"firmament.config.storage-overlay.padding": "Padding", "firmament.config.storage-overlay.padding": "Padding",
"firmament.config.storage-overlay.padding.description": "Padding inside of the storage overview.", "firmament.config.storage-overlay.padding.description": "Padding inside of the storage overview.",
"firmament.config.storage-overlay.rows": "Columns", "firmament.config.storage-overlay.rows": "Columns",
@@ -397,5 +399,5 @@
"firmament.warp-util.mark-excluded": "Firmament: Tried to warp to %s, but it was not unlocked. I will avoid warping there again.", "firmament.warp-util.mark-excluded": "Firmament: Tried to warp to %s, but it was not unlocked. I will avoid warping there again.",
"firmament.warp-util.no-warp-found": "Could not find an unlocked warp in %s", "firmament.warp-util.no-warp-found": "Could not find an unlocked warp in %s",
"firmament.waypoint.temporary": "Temporary Waypoint: %s", "firmament.waypoint.temporary": "Temporary Waypoint: %s",
"firmanent.config.edit": "Edit" "zzzzzzzzz.lastentry": "Here so every real firmament entry has a trailing ,"
} }