From 7d05332a90aedce9e4b8eb24cd962e1ae172fd7b Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 20 Aug 2023 20:19:54 +0700 Subject: [PATCH] Update hover check code to properly determine hover status in case of overlapping panels --- .../mc/otm/client/screen/MatteryScreen.kt | 10 +-- .../otm/client/screen/panels/EditablePanel.kt | 85 ++++++++++++------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt index ef2495a9f..cdb1be997 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt @@ -104,7 +104,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit RenderSystem.depthFunc(GL11.GL_ALWAYS) graphics.renderItemDecorations( - font, + super.font, itemstack, 1, 1, @@ -533,7 +533,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit override fun mouseReleased(p_97812_: Double, p_97813_: Double, p_97814_: Int): Boolean { if (lastDragSlot != null) { - if (isQuickCrafting) { + if (super.isQuickCrafting) { returnSlot = lastDragSlot val ret = super.mouseReleased(p_97812_, p_97813_, p_97814_) returnSlot = null @@ -644,7 +644,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit // dark background this.renderBackground(graphics) - hoveredSlot = null + super.hoveredSlot = null var hovered = false for (panel in panels) { @@ -692,7 +692,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit val i2 = if (draggingItem.isEmpty) 8 else 16 var overrideCount: String? = null - if (isQuickCrafting && quickCraftSlots.size > 1) { + if (super.isQuickCrafting && super.quickCraftSlots.size > 1) { itemstack = itemstack.copy() itemstack.count = quickCraftingRemainder @@ -706,7 +706,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit } if (menu.carried.isEmpty) { - val hoveredSlot = hoveredSlot + val hoveredSlot = super.hoveredSlot if (hoveredSlot != null && hoveredSlot.hasItem()) { this.renderTooltip(graphics, mouseX, mouseY) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt index 3742af760..d8360abcd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt @@ -25,6 +25,9 @@ import ru.dbotthepony.mc.otm.client.render.popScissorRect import ru.dbotthepony.mc.otm.client.render.pushScissorRect import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.input.QueryUserPanel +import ru.dbotthepony.mc.otm.core.collect.any +import ru.dbotthepony.mc.otm.core.collect.concatIterators +import ru.dbotthepony.mc.otm.core.collect.flatMap import java.util.* import kotlin.collections.ArrayList import kotlin.math.roundToInt @@ -260,9 +263,18 @@ open class EditablePanel @JvmOverloads constructor( private val childrenInternal = ArrayList>() private val visibleChildrenInternal = ArrayList>() + val children: List> = Collections.unmodifiableList(childrenInternal) val visibleChildren: List> = Collections.unmodifiableList(visibleChildrenInternal) + val allPanels: Iterator> get() { + return concatIterators(listOf(this).iterator(), childrenInternal.iterator().flatMap { it.allPanels }) + } + + val allVisiblePanels: Iterator> get() { + return concatIterators(listOf(this).iterator(), visibleChildrenInternal.iterator().flatMap { it.allVisiblePanels }) + } + var layoutInvalidated = true private set var boundsInvalidated = true @@ -649,6 +661,9 @@ open class EditablePanel @JvmOverloads constructor( var absoluteY = 0f private set + /** + * If this exact panel is hovered. Panel is not considered hovered if any of its children are hovered + */ var isHovered = false private set(value) { if (value == field) { @@ -661,6 +676,13 @@ open class EditablePanel @JvmOverloads constructor( onHoverUpdate(old, value) } + /** + * If this panel or any of its children are hovered + */ + val isEverHovered: Boolean get() { + return isHovered || visibleChildrenInternal.any { it.isEverHovered } + } + fun unsetHovered() { isHovered = false @@ -772,7 +794,7 @@ open class EditablePanel @JvmOverloads constructor( } protected open fun shouldRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean { - return isHovered || isGrabbingMouseInput() + return isEverHovered || isGrabbingMouseInput() } fun isVisible(): Boolean { @@ -835,16 +857,6 @@ open class EditablePanel @JvmOverloads constructor( if (parent == null) { absoluteX = x absoluteY = y - } else { - if ((x < 0f || y < 0f || x + width > parent.width || y + height > parent.height) && parent.parent == null) { - // no op - we updated ourselves in tickHover - } else { - isHovered = parent.isHovered && - mouseX >= absoluteX && - mouseX < absoluteX + width && - mouseY >= absoluteY && - mouseY < absoluteY + height - } } } @@ -893,35 +905,50 @@ open class EditablePanel @JvmOverloads constructor( } } - open fun tickHover(mouseX: Float, mouseY: Float): Boolean { - if (isRemoved) { - return false + fun updateAbsolutePosition() { + val parent = parent + + if (parent == null) { + absoluteX = x + absoluteY = y + } else { + absoluteX = parent.absoluteX + x + parent.xOffset + absoluteY = parent.absoluteY + y + parent.yOffset } - if ((childrenRectHeight > height || childrenRectWidth > width || childrenRectX < 0 || childrenRectY < 0) && parent == null) { + for (child in visibleChildrenInternal) { + child.updateAbsolutePosition() + } + } + + fun tickHover(mouseX: Float, mouseY: Float): Boolean { + if (isRemoved) + return false + + if (parent == null) + updateAbsolutePosition() + + if (mouseX in absoluteX ..< absoluteX + childrenRectWidth.coerceAtLeast(width) && mouseY in absoluteY ..< absoluteY + childrenRectHeight.coerceAtLeast(height)) { var hit = false - for (child in childrenInternal) { - if (child.tickHover(mouseX, mouseY)) { + for (child in visibleChildrenInternal) { + if (hit) { + child.unsetHovered() + } else if (child.tickHover(mouseX, mouseY)) { hit = true } } - isHovered = mouseX >= absoluteX && - mouseX <= absoluteX + width && - mouseY >= absoluteY && - mouseY <= absoluteY + height + isHovered = + !hit && + mouseX in absoluteX ..< absoluteX + width && + mouseY in absoluteY ..< absoluteY + height return hit || isHovered + } else { + unsetHovered() + return false } - - isHovered = - mouseX >= absoluteX && - mouseX <= absoluteX + width && - mouseY >= absoluteY && - mouseY <= absoluteY + height - - return isHovered } fun findSlot(mouseX: Float, mouseY: Float): Pair {