From e66f45ac7ea014bcf579b7a3d56033d082ebb763 Mon Sep 17 00:00:00 2001 From: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:07:59 +0100 Subject: Improvement: HoverTips improvements (#821) Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> --- .../utils/renderables/RenderLineTooltips.kt | 309 ++++++++++----------- .../skyhanni/utils/renderables/Renderable.kt | 36 ++- 2 files changed, 168 insertions(+), 177 deletions(-) (limited to 'src/main/java/at/hannibal2/skyhanni/utils/renderables') diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderLineTooltips.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderLineTooltips.kt index ec39dc7af..1f3267a62 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderLineTooltips.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderLineTooltips.kt @@ -1,6 +1,9 @@ package at.hannibal2.skyhanni.utils.renderables import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.Minecraft import net.minecraft.client.gui.ScaledResolution @@ -14,180 +17,152 @@ import java.awt.Color object RenderLineTooltips { fun drawHoveringText( - posX: Int, posY: Int, tips: List, stack: ItemStack? = null, + posX: Int, posY: Int, + tips: List, + stack: ItemStack? = null, + borderColor: LorenzColor? = null, + snapsToTopIfToLong: Boolean = true, mouseX: Int = Utils.getMouseX(), mouseY: Int = Utils.getMouseY(), ) { - if (tips.isNotEmpty()) { - var textLines = tips - val x = mouseX + 12 - posX - val y = mouseY - 10 - posY - val color: Char = stack?.getLore()?.lastOrNull()?.take(4)?.get(1) - ?: Utils.getPrimaryColourCode(textLines[0]) - val colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(color) - val borderColorStart = Color(colourInt).darker().rgb and 0x00FFFFFF or (200 shl 24) - val font = Minecraft.getMinecraft().fontRendererObj - val scaled = ScaledResolution(Minecraft.getMinecraft()) - GlStateManager.disableRescaleNormal() - RenderHelper.disableStandardItemLighting() - GlStateManager.disableLighting() - GlStateManager.enableDepth() - var tooltipTextWidth = 0 - for (textLine in textLines) { - val textLineWidth = font.getStringWidth(textLine) - if (textLineWidth > tooltipTextWidth) { - tooltipTextWidth = textLineWidth - } - } - var needsWrap = false - var titleLinesCount = 1 - var tooltipX = x - if (tooltipX + tooltipTextWidth + 4 > scaled.scaledWidth) { - tooltipX = x - 16 - tooltipTextWidth - if (tooltipX < 4) { - tooltipTextWidth = if (x > scaled.scaledWidth / 2) { - x - 12 - 8 - } else { - scaled.scaledWidth - 16 - x - } - needsWrap = true - } - } - if (needsWrap) { - var wrappedTooltipWidth = 0 - val wrappedTextLines = mutableListOf() - for (i in textLines.indices) { - val textLine = textLines[i] - val wrappedLine = font.listFormattedStringToWidth(textLine, tooltipTextWidth) - if (i == 0) { - titleLinesCount = wrappedLine.size - } - for (line in wrappedLine) { - val lineWidth = font.getStringWidth(line) - if (lineWidth > wrappedTooltipWidth) { - wrappedTooltipWidth = lineWidth - } - wrappedTextLines.add(line) - } - } - tooltipTextWidth = wrappedTooltipWidth - textLines = wrappedTextLines.toList() - tooltipX = if (x > scaled.scaledWidth / 2) { - x - 16 - tooltipTextWidth - } else { - x + 12 - } - } - var tooltipY = y - 12 - var tooltipHeight = 8 - if (textLines.size > 1) { - tooltipHeight += (textLines.size - 1) * 10 - if (textLines.size > titleLinesCount) { - tooltipHeight += 2 - } - } + if (tips.isEmpty()) return + + val (xTranslate, yTranslate, _) = RenderUtils.absoluteTranslation + + val x = mouseX - posX + 12 + val y = mouseY - posY - if (tips.size > 1) 2 else -7 + val color: Char = borderColor?.chatColorCode ?: stack?.getLore()?.lastOrNull()?.take(4)?.get(1) + ?: 'f' + val colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(color) + val borderColorStart = Color(colourInt).darker().rgb and 0x00FFFFFF or (200 shl 24) + val scaled = ScaledResolution(Minecraft.getMinecraft()) + + val tooltipTextWidth = tips.maxOf { it.width } + val tooltipHeight = tips.sumOf { it.height } - if (tooltipY + tooltipHeight + 6 > scaled.scaledHeight) { - tooltipY = scaled.scaledHeight - tooltipHeight - 6 + val tooltipY = when { + y + yTranslate < 16 -> -yTranslate + 4 // Limit Top + y + yTranslate + tooltipHeight > scaled.scaledHeight -> { + if (snapsToTopIfToLong && tooltipHeight + 8 > scaled.scaledHeight) + -yTranslate + 4 // Snap to Top if to Long + else + scaled.scaledHeight - tooltipHeight - 4 - yTranslate // Limit Bottom } - val zLevel = 300 - val backgroundColor = -0xfeffff0 - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY - 4, - tooltipX + tooltipTextWidth + 3, - tooltipY - 3, - backgroundColor, - backgroundColor - ) - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY + tooltipHeight + 3, - tooltipX + tooltipTextWidth + 3, - tooltipY + tooltipHeight + 4, - backgroundColor, - backgroundColor - ) - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY - 3, - tooltipX + tooltipTextWidth + 3, - tooltipY + tooltipHeight + 3, - backgroundColor, - backgroundColor - ) - drawGradientRect( - zLevel, - tooltipX - 4, - tooltipY - 3, - tooltipX - 3, - tooltipY + tooltipHeight + 3, - backgroundColor, - backgroundColor - ) - drawGradientRect( - zLevel, - tooltipX + tooltipTextWidth + 3, - tooltipY - 3, - tooltipX + tooltipTextWidth + 4, - tooltipY + tooltipHeight + 3, - backgroundColor, - backgroundColor - ) - val borderColorEnd = borderColorStart and 0xFEFEFE shr 1 or (borderColorStart and -0x1000000) - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY - 3 + 1, - tooltipX - 3 + 1, - tooltipY + tooltipHeight + 3 - 1, - borderColorStart, - borderColorEnd - ) - drawGradientRect( - zLevel, - tooltipX + tooltipTextWidth + 2, - tooltipY - 3 + 1, - tooltipX + tooltipTextWidth + 3, - tooltipY + tooltipHeight + 3 - 1, - borderColorStart, - borderColorEnd - ) - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY - 3, - tooltipX + tooltipTextWidth + 3, - tooltipY - 3 + 1, - borderColorStart, - borderColorStart - ) - drawGradientRect( - zLevel, - tooltipX - 3, - tooltipY + tooltipHeight + 2, - tooltipX + tooltipTextWidth + 3, - tooltipY + tooltipHeight + 3, - borderColorEnd, - borderColorEnd - ) - GlStateManager.disableDepth() - for (lineNumber in textLines.indices) { - val line = textLines[lineNumber] - font.drawStringWithShadow(line, 1f + tooltipX.toFloat(), 1f + tooltipY.toFloat(), -1) - if (lineNumber + 1 == titleLinesCount) { - tooltipY += 2 - } - tooltipY += 10 + + else -> { + y - 12 // normal } - GlStateManager.enableLighting() - GlStateManager.enableDepth() - RenderHelper.enableStandardItemLighting() - GlStateManager.enableRescaleNormal() } + val tooltipX = if (x + tooltipTextWidth + 4 + xTranslate > scaled.scaledWidth) { + scaled.scaledWidth - tooltipTextWidth - 4 - xTranslate // Limit Right + } else { + x // normal + } + + GlStateManager.disableRescaleNormal() + RenderHelper.disableStandardItemLighting() + GlStateManager.enableDepth() + + val zLevel = 300 + val backgroundColor = -0xfeffff0 + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 4, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3, + backgroundColor, + backgroundColor + ) + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY + tooltipHeight + 3, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 4, + backgroundColor, + backgroundColor + ) + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ) + drawGradientRect( + zLevel, + tooltipX - 4, + tooltipY - 3, + tooltipX - 3, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ) + drawGradientRect( + zLevel, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 4, + tooltipY + tooltipHeight + 3, + backgroundColor, + backgroundColor + ) + val borderColorEnd = borderColorStart and 0xFEFEFE shr 1 or (borderColorStart and -0x1000000) + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3 + 1, + tooltipX - 3 + 1, + tooltipY + tooltipHeight + 3 - 1, + borderColorStart, + borderColorEnd + ) + drawGradientRect( + zLevel, + tooltipX + tooltipTextWidth + 2, + tooltipY - 3 + 1, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3 - 1, + borderColorStart, + borderColorEnd + ) + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY - 3, + tooltipX + tooltipTextWidth + 3, + tooltipY - 3 + 1, + borderColorStart, + borderColorStart + ) + drawGradientRect( + zLevel, + tooltipX - 3, + tooltipY + tooltipHeight + 2, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3, + borderColorEnd, + borderColorEnd + ) + GlStateManager.disableDepth() + GlStateManager.translate(tooltipX.toFloat(), tooltipY.toFloat(), 0f) + + var yTranslateSum = 0 + for (line in tips) { + line.renderXAligned(tooltipX, tooltipY, tooltipTextWidth) + val yShift = line.height + GlStateManager.translate(0f, yShift.toFloat(), 0f) + yTranslateSum += yShift + } + + GlStateManager.translate(-tooltipX.toFloat(), -tooltipY.toFloat() + yTranslateSum.toFloat(), 0f) + GlStateManager.enableLighting() + GlStateManager.enableDepth() + RenderHelper.enableStandardItemLighting() + GlStateManager.enableRescaleNormal() GlStateManager.disableLighting() } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt index 0874d1cf2..8a57ded54 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.features.chroma.ChromaShaderManager import at.hannibal2.skyhanni.features.chroma.ChromaType import at.hannibal2.skyhanni.utils.ColorUtils import at.hannibal2.skyhanni.utils.ColorUtils.darker +import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzLogger import at.hannibal2.skyhanni.utils.NEUItems.renderOnScreen import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment @@ -96,12 +97,17 @@ interface Renderable { } fun clickAndHover( - text: String, - tips: List, + text: Any, + tips: List, bypassChecks: Boolean = false, onClick: () -> Unit, + onHover: () -> Unit = {}, ): Renderable { - return clickable(hoverTips(text, tips, bypassChecks = bypassChecks), onClick, bypassChecks = bypassChecks) + return clickable( + hoverTips(text, tips, bypassChecks = bypassChecks, onHover = onHover), + onClick, + bypassChecks = bypassChecks + ) } fun clickable( @@ -134,34 +140,44 @@ interface Renderable { } fun hoverTips( - text: String, - tips: List, + content: Any, + tips: List, indexes: List = listOf(), stack: ItemStack? = null, + color: LorenzColor? = null, bypassChecks: Boolean = false, + snapsToTopIfToLong: Boolean = true, condition: () -> Boolean = { true }, + onHover: () -> Unit = {}, ): Renderable { - val render = string(text) + val render = fromAny(content) ?: string("Error") return object : Renderable { override val width = render.width override val height = render.height override val horizontalAlign = render.horizontalAlign override val verticalAlign = render.verticalAlign + val tipsRender = tips.mapNotNull { fromAny(it) } + override fun render(posX: Int, posY: Int) { render.render(posX, posY) if (isHovered(posX, posY)) { if (condition() && shouldAllowLink(true, bypassChecks)) { + onHover.invoke() list[Pair(posX, posY)] = indexes GlStateManager.pushMatrix() GlStateManager.translate(0F, 0F, 400F) RenderLineTooltips.drawHoveringText( - posX, posY, tips, - stack, - currentRenderPassMousePosition?.first ?: Utils.getMouseX(), - currentRenderPassMousePosition?.second ?: Utils.getMouseY(), + posX = posX, + posY = posY, + tips = tipsRender, + stack = stack, + borderColor = color, + snapsToTopIfToLong = snapsToTopIfToLong, + mouseX = currentRenderPassMousePosition?.first ?: Utils.getMouseX(), + mouseY = currentRenderPassMousePosition?.second ?: Utils.getMouseY(), ) GlStateManager.popMatrix() } -- cgit