2019-08-09 18:36:12 +00:00
|
|
|
package net.shadowfacts.asmr.ui
|
|
|
|
|
2019-08-10 02:39:01 +00:00
|
|
|
import net.minecraft.util.Identifier
|
|
|
|
import net.shadowfacts.asmr.ASMR
|
|
|
|
import net.shadowfacts.asmr.program.ExecutableBlock
|
2019-08-09 18:36:12 +00:00
|
|
|
import net.shadowfacts.asmr.program.ProgramBlock
|
2019-08-10 04:03:25 +00:00
|
|
|
import net.shadowfacts.asmr.program.ProgramBlockInput
|
|
|
|
import net.shadowfacts.asmr.program.ProgramBlockOutput
|
2019-08-10 02:39:01 +00:00
|
|
|
import net.shadowfacts.cacao.geometry.Axis
|
2019-08-09 18:36:12 +00:00
|
|
|
import net.shadowfacts.cacao.geometry.Point
|
|
|
|
import net.shadowfacts.cacao.util.Color
|
|
|
|
import net.shadowfacts.cacao.util.MouseButton
|
2019-08-10 02:39:01 +00:00
|
|
|
import net.shadowfacts.cacao.util.texture.Texture
|
2019-08-09 18:36:12 +00:00
|
|
|
import net.shadowfacts.cacao.view.Label
|
2019-08-10 02:39:01 +00:00
|
|
|
import net.shadowfacts.cacao.view.StackView
|
|
|
|
import net.shadowfacts.cacao.view.TextureView
|
2019-08-09 18:36:12 +00:00
|
|
|
import net.shadowfacts.cacao.view.View
|
|
|
|
import net.shadowfacts.kiwidsl.dsl
|
|
|
|
import no.birkett.kiwi.Constraint
|
2019-08-10 04:03:25 +00:00
|
|
|
import kotlin.math.max
|
2019-08-09 18:36:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author shadowfacts
|
|
|
|
*/
|
2019-08-10 02:39:01 +00:00
|
|
|
class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distribution.CENTER, spacing = 4.0) {
|
|
|
|
|
|
|
|
companion object {
|
2019-08-10 04:03:25 +00:00
|
|
|
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)
|
2019-08-10 02:39:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var incomingExecution: View? = null
|
|
|
|
var outgoingExeuction: View? = null
|
2019-08-09 18:36:12 +00:00
|
|
|
|
2019-08-11 22:44:22 +00:00
|
|
|
val inputViews = mutableMapOf<ProgramBlockInput<*>, ProgramBlockParamView>()
|
|
|
|
val outputViews = mutableMapOf<ProgramBlockOutput<*>, ProgramBlockParamView>()
|
2019-08-10 04:03:25 +00:00
|
|
|
|
2019-08-09 18:36:12 +00:00
|
|
|
var xConstraint: Constraint? = null
|
|
|
|
var yConstraint: Constraint? = null
|
2019-08-11 02:04:59 +00:00
|
|
|
var didCreateWidthConstraint = false
|
2019-08-09 18:36:12 +00:00
|
|
|
|
|
|
|
override fun wasAdded() {
|
|
|
|
super.wasAdded()
|
|
|
|
|
|
|
|
respondsToDragging = true
|
|
|
|
|
|
|
|
backgroundColor = Color.BLACK
|
2019-08-09 19:23:48 +00:00
|
|
|
zIndex = 10.0
|
2019-08-09 18:36:12 +00:00
|
|
|
|
2019-08-10 02:39:01 +00:00
|
|
|
val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
|
2019-08-11 02:04:59 +00:00
|
|
|
val title = titleStack.addArrangedSubview(Label(block.translateName(), wrappingMode = Label.WrappingMode.NO_WRAP))
|
2019-08-10 02:39:01 +00:00
|
|
|
if (block is ExecutableBlock) {
|
2019-08-10 04:03:25 +00:00
|
|
|
val incomingTexture = if (block.executionFlow.prev == null) emptyConnection else executionConnection
|
2019-08-10 02:39:01 +00:00
|
|
|
incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0)
|
2019-08-10 04:03:25 +00:00
|
|
|
val outgoingTexture = if (block.executionFlow.next == null) emptyConnection else executionConnection
|
2019-08-10 02:39:01 +00:00
|
|
|
outgoingExeuction = titleStack.addArrangedSubview(TextureView(outgoingTexture))
|
|
|
|
}
|
|
|
|
|
2019-08-09 18:36:12 +00:00
|
|
|
solver.dsl {
|
2019-08-10 02:39:01 +00:00
|
|
|
// 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
|
|
|
|
|
|
|
|
if (block is ExecutableBlock) {
|
|
|
|
incomingExecution!!.widthAnchor equalTo incomingExecution!!.heightAnchor
|
|
|
|
incomingExecution!!.widthAnchor equalTo 7
|
|
|
|
outgoingExeuction!!.widthAnchor equalTo outgoingExeuction!!.heightAnchor
|
|
|
|
outgoingExeuction!!.widthAnchor equalTo 7
|
|
|
|
}
|
2019-08-10 04:03:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ->
|
2019-08-11 22:44:22 +00:00
|
|
|
// val inputTexture = if (input.source == null) emptyConnection else parameterConnection
|
|
|
|
// val inputView = hStack.addArrangedSubview(TextureView(inputTexture))
|
|
|
|
val inputView = hStack.addArrangedSubview(ProgramBlockParamView(input))
|
2019-08-10 04:03:25 +00:00
|
|
|
inputViews[input] = inputView
|
2019-08-10 23:21:26 +00:00
|
|
|
val inputLabel = hStack.addArrangedSubview(Label(input.translateName()))
|
2019-08-10 04:03:25 +00:00
|
|
|
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 ->
|
2019-08-10 23:21:26 +00:00
|
|
|
val outputLabel = hStack.addArrangedSubview(Label(output.translateName(), textAlignment = Label.TextAlignment.RIGHT))
|
2019-08-11 22:44:22 +00:00
|
|
|
// val outputTexture = if (output.destinations.isEmpty()) emptyConnection else parameterConnection
|
|
|
|
// val outputView = hStack.addArrangedSubview(TextureView(outputTexture))
|
|
|
|
val outputView = hStack.addArrangedSubview(ProgramBlockParamView(output))
|
2019-08-10 04:03:25 +00:00
|
|
|
outputViews[output] = outputView
|
|
|
|
solver.dsl {
|
|
|
|
hStack.heightAnchor equalTo outputLabel.heightAnchor
|
|
|
|
|
|
|
|
outputView.widthAnchor equalTo outputView.heightAnchor
|
|
|
|
outputView.widthAnchor equalTo 7
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
solver.dsl {
|
2019-08-10 02:39:01 +00:00
|
|
|
for (view in arrangedSubviews.drop(1)) {
|
|
|
|
widthAnchor.equalTo(view.widthAnchor, strength = STRONG)
|
|
|
|
}
|
2019-08-09 18:36:12 +00:00
|
|
|
}
|
|
|
|
|
2019-08-10 04:03:25 +00:00
|
|
|
|
2019-08-09 18:36:12 +00:00
|
|
|
updateDraggingConstraints()
|
|
|
|
}
|
|
|
|
|
2019-08-11 02:04:59 +00:00
|
|
|
override fun didLayout() {
|
|
|
|
super.didLayout()
|
|
|
|
|
|
|
|
// we want to constrain this view's width to be the same as the widest view in the vertical stack,
|
|
|
|
// but we don't know what view that is until after all subviews have been laid-out
|
|
|
|
if (!didCreateWidthConstraint) {
|
|
|
|
didCreateWidthConstraint = true
|
|
|
|
|
|
|
|
arrangedSubviews.maxBy { it.bounds.width }?.let { widestSubview ->
|
|
|
|
solver.dsl {
|
|
|
|
widthAnchor equalTo widestSubview.widthAnchor
|
|
|
|
}
|
|
|
|
window!!.layout()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-09 18:36:12 +00:00
|
|
|
override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
|
|
|
|
block.position += delta
|
|
|
|
updateDraggingConstraints()
|
2019-08-11 02:48:19 +00:00
|
|
|
window!!.layout()
|
2019-08-09 18:36:12 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-10 02:39:01 +00:00
|
|
|
override fun drawContent(mouse: Point, delta: Float) {
|
|
|
|
super.drawContent(mouse, delta)
|
|
|
|
}
|
|
|
|
|
2019-08-09 18:36:12 +00:00
|
|
|
}
|