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, View>() val outputViews = mutableMapOf, 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) } }