ASMR/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt

170 lines
6.4 KiB
Kotlin

package net.shadowfacts.asmr.ui
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlock
import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput
import net.shadowfacts.cacao.geometry.Axis
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.texture.Texture
import net.shadowfacts.cacao.view.Label
import net.shadowfacts.cacao.view.StackView
import net.shadowfacts.cacao.view.TextureView
import net.shadowfacts.cacao.view.View
import net.shadowfacts.kiwidsl.dsl
import no.birkett.kiwi.Constraint
import kotlin.math.max
/**
* @author shadowfacts
*/
class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distribution.CENTER, spacing = 4.0) {
companion object {
val emptyConnection = Texture(Identifier(ASMR.modid, "textures/gui/programmer/program_connections.png"), u = 0, v = 0)
val executionConnection = Texture(Identifier(ASMR.modid, "textures/gui/programmer/program_connections.png"), u = 7, v = 0)
val parameterConnection = Texture(Identifier(ASMR.modid, "textures/gui/programmer/program_connections.png"), u = 14, v = 0)
}
var incomingExecution: View? = null
var outgoingExeuction: View? = null
val inputViews = mutableMapOf<ProgramBlockInput<*>, View>()
val outputViews = mutableMapOf<ProgramBlockOutput<*>, View>()
var xConstraint: Constraint? = null
var yConstraint: Constraint? = null
override fun wasAdded() {
super.wasAdded()
respondsToDragging = true
backgroundColor = Color.BLACK
zIndex = 10.0
val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
val title = titleStack.addArrangedSubview(Label(block.javaClass.simpleName))
if (block is ExecutableBlock) {
val incomingTexture = if (block.executionFlow.prev == null) emptyConnection else executionConnection
incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0)
val outgoingTexture = if (block.executionFlow.next == null) emptyConnection else executionConnection
outgoingExeuction = titleStack.addArrangedSubview(TextureView(outgoingTexture))
}
solver.dsl {
// we have to constrain the titleStack height, because it's distribution is set to CENTER, so it doesn't do it itself
titleStack.heightAnchor equalTo title.heightAnchor
widthAnchor greaterThanOrEqualTo titleStack.widthAnchor
if (block is ExecutableBlock) {
incomingExecution!!.widthAnchor equalTo incomingExecution!!.heightAnchor
incomingExecution!!.widthAnchor equalTo 7
outgoingExeuction!!.widthAnchor equalTo outgoingExeuction!!.heightAnchor
outgoingExeuction!!.widthAnchor equalTo 7
}
// for (paramView in inputViews.values) {
// paramView.widthAnchor equalTo paramView.heightAnchor
// paramView.widthAnchor equalTo 7
// }
}
for (i in 0 until max(block.inputs.size, block.outputs.size)) {
val hStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
block.inputs.getOrNull(i)?.let { input ->
val inputView = hStack.addArrangedSubview(TextureView(if (input.source == null) emptyConnection else parameterConnection))
inputViews[input] = inputView
val inputLabel = hStack.addArrangedSubview(Label(input.identifier.toString()))
solver.dsl {
hStack.heightAnchor equalTo inputLabel.heightAnchor
inputView.widthAnchor equalTo inputView.heightAnchor
inputView.widthAnchor equalTo 7
}
}
val spacingView = hStack.addArrangedSubview(View())
solver.dsl {
spacingView.widthAnchor equalTo 8
}
block.outputs.getOrNull(i)?.let { output ->
val outputLabel = hStack.addArrangedSubview(Label(output.identifier.toString(), textAlignment = Label.TextAlignment.RIGHT))
val outputView = hStack.addArrangedSubview(TextureView(if (output.destinations.isEmpty()) emptyConnection else parameterConnection))
outputViews[output] = outputView
solver.dsl {
hStack.heightAnchor equalTo outputLabel.heightAnchor
outputView.widthAnchor equalTo outputView.heightAnchor
outputView.widthAnchor equalTo 7
}
}
}
// val pairs = block.inputs.zip(block.outputs)
// val remainingInputs = if (block.inputs.size > block.outputs.size) block.inputs.drop(block.outputs.size) else listOf()
// val remainingOutputs = if (block.outputs.size > block.inputs.size) block.outputs.drop(block.inputs.size) else listOf()
// for ((input, output) in pairs) {
// val hStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
// val inputView = hStack.addArrangedSubview(TextureView(if (input.source == null) emptyConnection else parameterConnection))
// inputViews[input] = inputView
// val inputLabel = hStack.addArrangedSubview(Label(input.identifier.toString()))
// val spacingView = hStack.addArrangedSubview(View())
// hStack.addArrangedSubview(Label(output.identifier.toString()))
//// outputViews[output] = hStack.addArrangedSubview(TextureView(if (output.destinations.isEmpty) emptyConnection else parameterConnection))
//
// solver.dsl {
// hStack.heightAnchor equalTo inputLabel.heightAnchor
//
// inputView.widthAnchor equalTo inputView.heightAnchor
// inputView.widthAnchor equalTo 7
//
// spacingView.widthAnchor equalTo 8
// }
// }
// for (input in remainingInputs) {
// addArrangedSubview(Label(input.identifier.toString()))
// }
// for (output in remainingOutputs) {
// addArrangedSubview(Label(output.identifier.toString(), textAlignment = Label.TextAlignment.RIGHT))
// }
solver.dsl {
for (view in arrangedSubviews.drop(1)) {
widthAnchor.equalTo(view.widthAnchor, strength = STRONG)
}
}
updateDraggingConstraints()
}
override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
block.position += delta
updateDraggingConstraints()
return true
}
private fun updateDraggingConstraints() {
if (xConstraint != null) solver.removeConstraint(xConstraint)
if (yConstraint != null) solver.removeConstraint(yConstraint)
solver.dsl {
xConstraint = (leftAnchor equalTo superview!!.leftAnchor + block.position.x)
yConstraint = (topAnchor equalTo superview!!.topAnchor + block.position.y)
}
window!!.layout()
}
override fun drawContent(mouse: Point, delta: Float) {
super.drawContent(mouse, delta)
}
}