diff --git a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt index 2d3a7fc..1265288 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt @@ -8,6 +8,8 @@ import net.minecraft.client.render.* import net.minecraft.client.sound.PositionedSoundInstance import net.minecraft.client.util.math.MatrixStack import net.minecraft.sound.SoundEvent +import net.minecraft.text.OrderedText +import net.minecraft.text.Text import net.minecraft.util.math.Matrix4f import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Rect @@ -20,7 +22,7 @@ import org.lwjgl.opengl.GL11 * * @author shadowfacts */ -object RenderHelper { +object RenderHelper: DrawableHelper() { val disabled = (System.getProperty("cacao.drawing.disabled") ?: "false").toBoolean() @@ -35,7 +37,7 @@ object RenderHelper { */ fun fill(matrixStack: MatrixStack, rect: Rect, color: Color) { if (disabled) return - DrawableHelper.fill(matrixStack, rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb) + fill(matrixStack, rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb) } /** @@ -85,6 +87,87 @@ object RenderHelper { BufferRenderer.draw(bufferBuilder) } + fun drawTooltip(matrixStack: MatrixStack, text: Text, mouse: Point) { + drawTooltip(matrixStack, listOf(text.asOrderedText()), mouse) + } + + fun drawTooltip(matrixStack: MatrixStack, texts: List, mouse: Point) { + drawTooltip(matrixStack, texts.map(Text::asOrderedText), mouse) + } + + // Based on Screen.renderOrderedTooltip + @JvmName("drawOrderedTooltip") + fun drawTooltip(matrixStack: MatrixStack, texts: List, mouse: Point) { + if (disabled) return + if (texts.isEmpty()) return + + val client = MinecraftClient.getInstance() + val textRenderer = client.textRenderer + + val maxWidth = texts.maxOf(textRenderer::getWidth) + + var x = mouse.x.toInt() + 12 + var y = mouse.y.toInt() - 12 + var p = 8 + if (texts.size > 1) { + p += 2 + (texts.size - 1) * 8 + } + + if (x + maxWidth > client.window.scaledWidth) { + x -= 28 + maxWidth + } + + if (y + p + 6 > client.window.scaledHeight) { + y = client.window.scaledHeight - p - 6 + } + + matrixStack.push() + val q = -267386864 + val r = 1347420415 + val s = 1344798847 + val t = 1 + val tessellator = Tessellator.getInstance() + val buffer = tessellator.buffer + buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR) + val matrix = matrixStack.peek().model + val z = 400 + fillGradient(matrix, buffer, x - 3, y - 4, x + maxWidth + 3, y - 3, z, q, q) + fillGradient(matrix, buffer, x - 3, y + p + 3, x + maxWidth + 3, y + p + 4, z, q, q) + fillGradient(matrix, buffer, x - 3, y - 3, x + maxWidth + 3, y + p + 3, z, q, q) + fillGradient(matrix, buffer, x - 4, y - 3, x - 3, y + p + 3, z, q, q) + fillGradient(matrix, buffer, x + maxWidth + 3, y - 3, x + maxWidth + 4, y + p + 3, z, q, q) + fillGradient(matrix, buffer, x - 3, y - 3 + 1, x - 3 + 1, y + p + 3 - 1, z, r, s) + fillGradient(matrix, buffer, x + maxWidth + 2, y - 3 + 1, x + maxWidth + 3, y + p + 3 - 1, z, r, s) + fillGradient(matrix, buffer, x - 3, y - 3, x + maxWidth + 3, y - 3 + 1, z, r, r) + fillGradient(matrix, buffer, x - 3, y + p + 2, x + maxWidth + 3, y + p + 3, z, s, s) + RenderSystem.enableDepthTest() + RenderSystem.disableTexture() + RenderSystem.enableBlend() + RenderSystem.defaultBlendFunc() + RenderSystem.shadeModel(7425) + buffer.end() + BufferRenderer.draw(buffer) + RenderSystem.shadeModel(7424) + RenderSystem.disableBlend() + RenderSystem.enableTexture() + val immediate = VertexConsumerProvider.immediate(buffer) + + matrixStack.translate(0.0, 0.0, 400.0) + + for (i in texts.indices) { + val text = texts[i] + textRenderer.draw(text, x.toFloat(), y.toFloat(), -1, true, matrix, immediate, false, 0, 15728880) + + if (i == 0) { + y += 2 + } + + y += 10 + } + + immediate.draw() + matrixStack.pop() + } /** * @see org.lwjgl.opengl.GL11.glPushMatrix diff --git a/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/TabViewController.kt b/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/TabViewController.kt index 40bb218..7c02b02 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/TabViewController.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/TabViewController.kt @@ -1,5 +1,6 @@ package net.shadowfacts.cacao.viewcontroller +import net.minecraft.client.util.math.MatrixStack import net.minecraft.text.Text import net.minecraft.util.Identifier import net.shadowfacts.cacao.geometry.Axis @@ -139,6 +140,14 @@ class TabViewController( override fun getCurrentBackground(mouse: Point) = backgroundView + override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) { + super.draw(matrixStack, mouse, delta) + + if (mouse in bounds && tab.tooltip != null) { + window!!.drawTooltip(listOf(tab.tooltip!!)) + } + } + override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean { if (selected) return false else return super.mouseClicked(point, mouseButton) diff --git a/src/main/kotlin/net/shadowfacts/cacao/window/Window.kt b/src/main/kotlin/net/shadowfacts/cacao/window/Window.kt index d0650bb..aa539c1 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/window/Window.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/window/Window.kt @@ -1,17 +1,20 @@ package net.shadowfacts.cacao.window import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.Text import net.shadowfacts.cacao.AbstractCacaoScreen import net.shadowfacts.cacao.CacaoScreen import net.shadowfacts.cacao.Responder import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.util.MouseButton +import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.view.View import net.shadowfacts.cacao.viewcontroller.ViewController import net.shadowfacts.kiwidsl.dsl import no.birkett.kiwi.Constraint import no.birkett.kiwi.Solver import no.birkett.kiwi.Variable +import java.lang.RuntimeException /** * A Window is the object at the top of a Cacao view hierarchy. It occupies the entirety of the Minecraft screen size @@ -88,6 +91,8 @@ open class Window( private var currentDragReceiver: View? = null + private var currentDeferredTooltip: List? = null + init { createInternalConstraints() } @@ -168,8 +173,21 @@ open class Window( * @param delta The time elapsed since the last frame. */ open fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) { + currentDeferredTooltip = null + val mouseInView = Point(mouse.x - viewController.view.frame.left, mouse.y - viewController.view.frame.top) viewController.view.draw(matrixStack, mouseInView, delta) + + if (currentDeferredTooltip != null) { + RenderHelper.drawTooltip(matrixStack, currentDeferredTooltip!!, mouse) + } + } + + fun drawTooltip(text: List) { + if (currentDeferredTooltip != null) { + throw RuntimeException("Deferred tooltip already registered for current frame") + } + currentDeferredTooltip = text } /**