package fr.username404.snowygui.gui import com.mojang.blaze3d.vertex.* import fr.username404.snowygui.Snowy import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.utils.RenderingUtil import fr.username404.snowygui.utils.RenderingUtil.colorEnd import net.minecraft.client.gui.components.events.GuiEventListener fun interface Renderable { 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 fun isWithinBounds(coordinateX: Double, coordinateY: Double, offsetWidth: Double = 0.0, offsetHeight: Double = 0.0): Boolean = (coordinateX in x..(x + width + offsetWidth)) && (coordinateY in y..(y + height + offsetHeight)) @JvmField protected var focused = false override fun isFocused() = focused override fun setFocused(boolean: Boolean) { focused = boolean } 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) } } } open 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 } abstract class ColoredElement( x: Double, y: Double, width: Int, height: Int, open val color: Int = Colors.TRANSPARENT.hexValue, protected var opacity: Float, ) : Element(x, y, width, height) { 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) = colorEnd(color, opacity) protected fun defaultRectFunc() = RenderingUtil.drawRectangle(x, y, height, width, color, opacity) } 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 }