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 { val returnedColorList = mutableListOf() for (i in 2 downTo 0) { returnedColorList.add( (hex shr (i * 8) and 255) / 255.0F ) } return returnedColorList }