SnowyGUI/common/src/main/kotlin/fr/username404/snowygui/gui/Element.kt

81 lines
3.2 KiB
Kotlin

package fr.username404.snowygui.gui
import com.mojang.blaze3d.vertex.*
import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.Colors
import net.minecraft.client.gui.components.events.GuiEventListener
import org.lwjgl.opengl.GL20
fun interface Renderable {
companion object Rendering {
@JvmStatic val tessellator: Tesselator = Tesselator.getInstance()
@JvmStatic val buffer: BufferBuilder = tessellator.builder
fun ColoredElement.defaultRectFunc() {
with(buffer) {
begin(GL20.GL_QUADS, DefaultVertexFormat.POSITION_COLOR)
vertex(x, y + height, 0.0).colorEnd()
vertex(x + width, y + height, 0.0).colorEnd()
vertex(x + width, y, 0.0).colorEnd()
vertex(x, y, 0.0).colorEnd()
tessellator.end()
}
}
}
fun render(poseStack: PoseStack?)
}
abstract class Element(
@JvmField val xOrigin: Double, @JvmField val yOrigin: Double,
val originalWidth: Int, val originalHeight: Int
): Renderable, GuiEventListener {
open var width = originalWidth; open var height = originalHeight
open var x = xOrigin; open var y = yOrigin
internal fun withinBounds(coordinateX: Double, coordinateY: Double, offsetWidth: Double = 0.0, offsetHeight: Double = 0.0): Boolean =
((coordinateX >= this.x) && (coordinateX <= (this.x + this.width + offsetWidth))) and ((coordinateY >= this.y) && (coordinateY <= (this.y + this.height + offsetHeight)))
companion object {
private var caughtError: Boolean = false
fun fromRenderable(r: Renderable, x: Double, y: Double, width: Int, height: Int): Element {
return object: Element(x, y, width, height) {
override fun render(poseStack: PoseStack?) = r.render(poseStack)
}
}
}
fun display(stack: PoseStack? = null) {
if (!hidden && !caughtError) try {
render(stack)
} catch (t: Throwable) {
with(Snowy.logs) {
error("An element from snowy threw an error: \n\t$t")
debug("\t${t.stackTraceToString()}")
warn("Rendering of snowy UI elements will now be disabled to avoid further errors.")
caughtError = true
}
}
}
var hidden: Boolean = false; internal set
}
abstract class ColoredElement(
x: Double, y: Double, width: Int, height: Int,
color: Colors = Colors.TRANSPARENT, protected var opacity: Float,
) : Element(x, y, width, height) {
open var color = color; protected set
companion object {
@JvmStatic protected fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer {
with(hextoRGB(color)) {
return this@colorIt.color(get(0), get(1), get(2), opacity)
}
}
}
internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color.hexValue) = colorIt(color, opacity).endVertex()
}
fun hextoRGB(hex: Int): MutableList<Float> {
val returnedColorList = mutableListOf<Float>()
for (i in 2 downTo 0) {
returnedColorList.add(
(hex shr (i * 8) and 255) / 255.0F
)
}
return returnedColorList
}