Initial ShadowUI work

This commit is contained in:
Shadowfacts 2019-06-21 16:22:23 -04:00
parent 24abf51f8d
commit 215949eabe
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 225 additions and 0 deletions

View File

@ -1,11 +1,27 @@
package net.shadowfacts.asmr
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.registry.CommandRegistry
import net.minecraft.client.MinecraftClient
import net.minecraft.server.command.CommandManager
object ASMR: ModInitializer {
override fun onInitialize() {
println("hello fabric")
CommandRegistry.INSTANCE.register(false) { dispatcher ->
val command = CommandManager.literal("uitest").executes {
try {
MinecraftClient.getInstance().openScreen(UITest())
} catch (e: Throwable) {
e.printStackTrace()
}
1
}
dispatcher.register(command)
}
}
}

View File

@ -0,0 +1,54 @@
package net.shadowfacts.asmr
import net.shadowfacts.kiwidsl.dsl
import net.shadowfacts.shadowui.UIScreen
import net.shadowfacts.shadowui.UIView
import net.shadowfacts.shadowui.util.Color
class UITest: UIScreen() {
init {
val red = UIView().apply {
backgroundColor = Color(0xff0000)
addView(this)
}
val green = UIView().apply {
backgroundColor = Color(0x00ff00)
addView(this)
}
val blue = UIView().apply {
backgroundColor = Color(0x0000ff)
addView(this)
}
val purple = UIView().apply {
backgroundColor = Color(0x800080)
green.addSubview(this)
}
solver.dsl {
red.leftAnchor equalTo 0
red.widthAnchor equalTo 200
red.topAnchor equalTo 0
red.heightAnchor equalTo 100
green.leftAnchor equalTo (red.leftAnchor + red.widthAnchor + 20)
green.widthAnchor equalTo red.widthAnchor
green.topAnchor equalTo 0
green.heightAnchor equalTo (red.heightAnchor + 100)
blue.leftAnchor equalTo green.leftAnchor
blue.widthAnchor equalTo green.widthAnchor
blue.topAnchor equalTo (green.topAnchor + green.heightAnchor)
blue.heightAnchor equalTo 50
purple.widthAnchor equalTo 100
purple.heightAnchor equalTo 100
purple.centerXAnchor equalTo green.centerXAnchor
purple.centerYAnchor equalTo green.centerYAnchor
}
layout()
}
}

View File

@ -0,0 +1,11 @@
package net.shadowfacts.shadowui
import no.birkett.kiwi.Variable
class LayoutVariable(val owner: UIView, val property: String): Variable("LayoutVariable") {
override fun getName() = "$owner.$property"
override fun toString() = "LayoutVariable(name=$name, value=$value)"
}

View File

@ -0,0 +1,28 @@
package net.shadowfacts.shadowui
import net.minecraft.client.gui.screen.Screen
import net.minecraft.network.chat.TextComponent
import no.birkett.kiwi.Solver
open class UIScreen: Screen(TextComponent("UIScreen")) {
val solver = Solver()
val views = mutableListOf<UIView>()
fun addView(view: UIView) {
views.add(view)
view.solver = solver
view.wasAdded()
}
fun layout() {
solver.updateVariables()
views.forEach(UIView::didLayout)
}
override fun render(mouseX: Int, mouseY: Int, delta: Float) {
views.forEach(UIView::draw)
}
}

View File

@ -0,0 +1,79 @@
package net.shadowfacts.shadowui
import com.mojang.blaze3d.platform.GlStateManager
import net.shadowfacts.kiwidsl.dsl
import net.shadowfacts.shadowui.geometry.UIRect
import net.shadowfacts.shadowui.util.Color
import net.shadowfacts.shadowui.util.RenderHelper
import no.birkett.kiwi.Solver
class UIView {
lateinit var solver: Solver
// in the coordinate system of the screen
val leftAnchor = LayoutVariable(this, "left")
val rightAnchor = LayoutVariable(this, "right")
val topAnchor = LayoutVariable(this, "top")
val bottomAnchor = LayoutVariable(this, "bottom")
val widthAnchor = LayoutVariable(this, "width")
val heightAnchor = LayoutVariable(this, "height")
val centerXAnchor = LayoutVariable(this, "centerX")
val centerYAnchor = LayoutVariable(this, "centerY")
// The rectangle for this view in the coordinate system of the parent view.
lateinit var frame: UIRect
// The rectangle for this view in its own coordinate system.
lateinit var bounds: UIRect
var backgroundColor = Color(0xff0000)
var parent: UIView? = null
val subviews = mutableListOf<UIView>()
fun addSubview(view: UIView) {
subviews.add(view)
view.parent = this
view.solver = solver
view.wasAdded()
}
fun wasAdded() {
createInternalConstraints()
}
fun createInternalConstraints() {
solver.dsl {
rightAnchor equalTo (leftAnchor + widthAnchor)
bottomAnchor equalTo (topAnchor + heightAnchor)
centerXAnchor equalTo (leftAnchor + widthAnchor / 2)
centerYAnchor equalTo (topAnchor + heightAnchor / 2)
}
}
fun didLayout() {
subviews.forEach(UIView::didLayout)
val parentLeft = parent?.leftAnchor?.value ?: 0.0
val parentTop = parent?.topAnchor?.value ?: 0.0
frame = UIRect(leftAnchor.value - parentLeft, topAnchor.value - parentTop, widthAnchor.value, heightAnchor.value)
bounds = UIRect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
}
fun draw() {
GlStateManager.pushMatrix()
GlStateManager.translated(frame.left, frame.top, 0.0)
RenderHelper.fill(bounds, backgroundColor)
drawContent()
subviews.forEach(UIView::draw)
GlStateManager.popMatrix()
}
fun drawContent() {}
}

View File

@ -0,0 +1,15 @@
package net.shadowfacts.shadowui.geometry
data class UIRect(val left: Double, val top: Double, val width: Double, val height: Double) {
val right: Double
get() = left + width
val bottom: Double
get() = top + height
val midX: Double
get() = left + width / 2
val midY: Double
get() = top + height / 2
}

View File

@ -0,0 +1,10 @@
package net.shadowfacts.shadowui.util
data class Color(val red: Int, val green: Int, val blue: Int, val alpha: Int = 255) {
constructor(rgb: Int, alpha: Int = 255): this(rgb shr 16, (rgb shr 8) and 255, rgb and 255, alpha)
val argb: Int
get() = ((alpha and 255) shl 24) or ((red and 255) shl 16) or ((green and 255) shl 8) or (blue and 255)
}

View File

@ -0,0 +1,12 @@
package net.shadowfacts.shadowui.util
import net.minecraft.client.gui.DrawableHelper
import net.shadowfacts.shadowui.geometry.UIRect
object RenderHelper {
fun fill(rect: UIRect, color: Color) {
DrawableHelper.fill(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb)
}
}