Compare commits

..

No commits in common. "971c41ed2fde1e1708fa9e8b5b80e9187791f85b" and "6045800d11db1eece82e46179e7088d31612a3ae" have entirely different histories.

11 changed files with 84 additions and 115 deletions

View File

@ -1,11 +1,9 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class ExecutableBlock(identifier: Identifier): ProgramBlock(identifier) { abstract class ExecutableBlock: ProgramBlock() {
open val executionFlow = ExecutionFlow(this) open val executionFlow = ExecutionFlow(this)

View File

@ -1,21 +1,15 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier
import net.minecraft.util.Language
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class ProgramBlock(val identifier: Identifier) { abstract class ProgramBlock {
var position: Point = Point.ORIGIN var position: Point = Point.ORIGIN
abstract val inputs: Array<ProgramBlockInput<*>> abstract val inputs: Array<ProgramBlockInput<*>>
abstract val outputs: Array<ProgramBlockOutput<*>> abstract val outputs: Array<ProgramBlockOutput<*>>
fun translateName(): String {
return Language.getInstance().translate("programblock.${identifier.namespace}.${identifier.path}")
}
} }

View File

@ -1,7 +1,6 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.Language
/** /**
* @author shadowfacts * @author shadowfacts
@ -27,8 +26,4 @@ class ProgramBlockInput<Type: Any>(
source?.unlink(to = this) source?.unlink(to = this)
} }
fun translateName(): String {
return Language.getInstance().translate("programblock.param.${identifier.namespace}.${identifier.path}")
}
} }

View File

@ -1,7 +1,6 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.Language
/** /**
* @author shadowfacts * @author shadowfacts
@ -27,8 +26,4 @@ class ProgramBlockOutput<Type: Any>(
_destinations.remove(to) _destinations.remove(to)
} }
fun translateName(): String {
return Language.getInstance().translate("programblock.param.${identifier.namespace}.${identifier.path}")
}
} }

View File

@ -13,11 +13,9 @@ import net.shadowfacts.asmr.program.ProgramType
class ConstantBlock<Type: Any>( class ConstantBlock<Type: Any>(
val type: ProgramType<Type>, val type: ProgramType<Type>,
val value: Type val value: Type
): ProgramBlock( ): ProgramBlock() {
Identifier(ASMR.modid, "constant")
) {
val output = ProgramBlockOutput(Identifier(ASMR.modid, "constant.output"), type, this).apply { val output = ProgramBlockOutput(Identifier(ASMR.modid, "constant_output"), type, this).apply {
value = this@ConstantBlock.value value = this@ConstantBlock.value
} }

View File

@ -10,11 +10,9 @@ import net.shadowfacts.cacao.geometry.Point
*/ */
class PrintBlock<Type: Any>( class PrintBlock<Type: Any>(
val type: ProgramType<Type> val type: ProgramType<Type>
): ExecutableBlock( ): ExecutableBlock() {
Identifier(ASMR.modid, "print")
) {
val input = ProgramBlockInput(Identifier(ASMR.modid, "print.input"), type, this) val input = ProgramBlockInput(Identifier(ASMR.modid, "print_input"), type, this)
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(input) override val inputs: Array<ProgramBlockInput<*>> = arrayOf(input)
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf() override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()

View File

@ -1,7 +1,5 @@
package net.shadowfacts.asmr.program.blocks package net.shadowfacts.asmr.program.blocks
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.ExecutableBlock import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlockInput import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput import net.shadowfacts.asmr.program.ProgramBlockOutput
@ -9,9 +7,7 @@ import net.shadowfacts.asmr.program.ProgramBlockOutput
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class StartBlock: ExecutableBlock( class StartBlock: ExecutableBlock() {
Identifier(ASMR.modid, "start")
) {
override val inputs: Array<ProgramBlockInput<*>> = arrayOf() override val inputs: Array<ProgramBlockInput<*>> = arrayOf()
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf() override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()

View File

@ -14,9 +14,7 @@ import java.lang.RuntimeException
class BinaryOperatorBlock<Type: Any>( class BinaryOperatorBlock<Type: Any>(
val type: ProgramType<Type>, val type: ProgramType<Type>,
val operation: Operation val operation: Operation
): ExecutableBlock( ): ExecutableBlock() {
Identifier(ASMR.modid, "binary_operator")
) {
init { init {
if (type != ProgramType.INT && type != ProgramType.FLOAT) { if (type != ProgramType.INT && type != ProgramType.FLOAT) {
@ -24,10 +22,10 @@ class BinaryOperatorBlock<Type: Any>(
} }
} }
val left = ProgramBlockInput(Identifier(ASMR.modid, "binary_operator.left_operand"), type, this) val left = ProgramBlockInput(Identifier(ASMR.modid, "left_operand"), type, this)
val right = ProgramBlockInput(Identifier(ASMR.modid, "binary_operator.right_operand"), type, this) val right = ProgramBlockInput(Identifier(ASMR.modid, "right_operand"), type, this)
val output = ProgramBlockOutput(Identifier(ASMR.modid, "binary_operator.result"), type, this) val output = ProgramBlockOutput(Identifier(ASMR.modid, "result"), type, this)
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(left, right) override val inputs: Array<ProgramBlockInput<*>> = arrayOf(left, right)
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output) override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output)

View File

@ -38,7 +38,6 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
var xConstraint: Constraint? = null var xConstraint: Constraint? = null
var yConstraint: Constraint? = null var yConstraint: Constraint? = null
var didCreateWidthConstraint = false
override fun wasAdded() { override fun wasAdded() {
super.wasAdded() super.wasAdded()
@ -49,7 +48,7 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
zIndex = 10.0 zIndex = 10.0
val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER)) val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
val title = titleStack.addArrangedSubview(Label(block.translateName(), wrappingMode = Label.WrappingMode.NO_WRAP)) val title = titleStack.addArrangedSubview(Label(block.javaClass.simpleName))
if (block is ExecutableBlock) { if (block is ExecutableBlock) {
val incomingTexture = if (block.executionFlow.prev == null) emptyConnection else executionConnection val incomingTexture = if (block.executionFlow.prev == null) emptyConnection else executionConnection
incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0) incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0)
@ -60,6 +59,7 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
solver.dsl { solver.dsl {
// we have to constrain the titleStack height, because it's distribution is set to CENTER, so it doesn't do it itself // 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 titleStack.heightAnchor equalTo title.heightAnchor
widthAnchor greaterThanOrEqualTo titleStack.widthAnchor
if (block is ExecutableBlock) { if (block is ExecutableBlock) {
incomingExecution!!.widthAnchor equalTo incomingExecution!!.heightAnchor incomingExecution!!.widthAnchor equalTo incomingExecution!!.heightAnchor
@ -67,16 +67,21 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
outgoingExeuction!!.widthAnchor equalTo outgoingExeuction!!.heightAnchor outgoingExeuction!!.widthAnchor equalTo outgoingExeuction!!.heightAnchor
outgoingExeuction!!.widthAnchor equalTo 7 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)) { for (i in 0 until max(block.inputs.size, block.outputs.size)) {
val hStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER)) val hStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
block.inputs.getOrNull(i)?.let { input -> block.inputs.getOrNull(i)?.let { input ->
val inputTexture = if (input.source == null) emptyConnection else parameterConnection val inputView = hStack.addArrangedSubview(TextureView(if (input.source == null) emptyConnection else parameterConnection))
val inputView = hStack.addArrangedSubview(TextureView(inputTexture))
inputViews[input] = inputView inputViews[input] = inputView
val inputLabel = hStack.addArrangedSubview(Label(input.translateName())) val inputLabel = hStack.addArrangedSubview(Label(input.identifier.toString()))
solver.dsl { solver.dsl {
hStack.heightAnchor equalTo inputLabel.heightAnchor hStack.heightAnchor equalTo inputLabel.heightAnchor
@ -91,9 +96,8 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
} }
block.outputs.getOrNull(i)?.let { output -> block.outputs.getOrNull(i)?.let { output ->
val outputLabel = hStack.addArrangedSubview(Label(output.translateName(), textAlignment = Label.TextAlignment.RIGHT)) val outputLabel = hStack.addArrangedSubview(Label(output.identifier.toString(), textAlignment = Label.TextAlignment.RIGHT))
val outputTexture = if (output.destinations.isEmpty()) emptyConnection else parameterConnection val outputView = hStack.addArrangedSubview(TextureView(if (output.destinations.isEmpty()) emptyConnection else parameterConnection))
val outputView = hStack.addArrangedSubview(TextureView(outputTexture))
outputViews[output] = outputView outputViews[output] = outputView
solver.dsl { solver.dsl {
hStack.heightAnchor equalTo outputLabel.heightAnchor hStack.heightAnchor equalTo outputLabel.heightAnchor
@ -104,6 +108,35 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
} }
} }
// 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 { solver.dsl {
for (view in arrangedSubviews.drop(1)) { for (view in arrangedSubviews.drop(1)) {
widthAnchor.equalTo(view.widthAnchor, strength = STRONG) widthAnchor.equalTo(view.widthAnchor, strength = STRONG)
@ -114,27 +147,9 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
updateDraggingConstraints() updateDraggingConstraints()
} }
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()
}
}
}
override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean { override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
block.position += delta block.position += delta
updateDraggingConstraints() updateDraggingConstraints()
window!!.layout()
return true return true
} }
@ -145,6 +160,7 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
xConstraint = (leftAnchor equalTo superview!!.leftAnchor + block.position.x) xConstraint = (leftAnchor equalTo superview!!.leftAnchor + block.position.x)
yConstraint = (topAnchor equalTo superview!!.topAnchor + block.position.y) yConstraint = (topAnchor equalTo superview!!.topAnchor + block.position.y)
} }
window!!.layout()
} }
override fun drawContent(mouse: Point, delta: Float) { override fun drawContent(mouse: Point, delta: Float) {

View File

@ -13,11 +13,7 @@ import net.shadowfacts.cacao.view.View
*/ */
class ProgramCanvasView(val program: Program): View() { class ProgramCanvasView(val program: Program): View() {
private lateinit var blocks: Map<ProgramBlock, ProgramBlockView> lateinit var blocks: Map<ProgramBlock, ProgramBlockView>
// map of starting block to (start, end) points
private val executionFlowStartLinks = mutableMapOf<ExecutableBlock, Pair<Point, Point>>()
private val parameterLinks = mutableMapOf<ProgramBlock, Pair<Point, Point>>()
override fun wasAdded() { override fun wasAdded() {
super.wasAdded() super.wasAdded()
@ -30,52 +26,48 @@ class ProgramCanvasView(val program: Program): View() {
} }
} }
private fun updateBlockLinks() { override fun drawContent(mouse: Point, delta: Float) {
for ((startBlock, startView) in blocks) { super.drawContent(mouse, delta)
(startBlock as? ExecutableBlock)?.executionFlow?.next?.let { endBlock ->
blocks[endBlock]?.let { endView ->
val outgoing = startView.outgoingExeuction!! for ((block, view) in blocks) {
val incoming = endView.incomingExecution!! (block as? ExecutableBlock)?.executionFlow?.next?.let { next ->
blocks[next]?.let { nextView ->
val outgoing = view.outgoingExeuction!!
val incoming = nextView.incomingExecution!!
val start = outgoing.convert(outgoing.bounds.center, to = this) val start = outgoing.convert(outgoing.bounds.center, to = this)
val end = incoming.convert(outgoing.bounds.center, to = this) val end = incoming.convert(outgoing.bounds.center, to = this)
executionFlowStartLinks[startBlock] = start to end
}
}
for (output in startBlock.outputs) {
val outputView = startView.outputViews[output] ?: continue
val start = outputView.convert(outputView.bounds.center, to = this)
for (destination in output.destinations) {
val endView = blocks[destination.block] ?: continue
val inputView = endView.inputViews[destination] ?: continue
val end = inputView.convert(inputView.bounds.center, to = this)
parameterLinks[startBlock] = start to end
}
}
}
}
override fun didLayout() {
super.didLayout()
// we can't calculate the link points until layout is completed and all of the views have concrete positions/sizes
updateBlockLinks()
}
override fun drawContent(mouse: Point, delta: Float) {
super.drawContent(mouse, delta)
for ((start, end) in executionFlowStartLinks.values) {
RenderHelper.drawLine(start, end, zIndex, 5f, Color.GREEN) RenderHelper.drawLine(start, end, zIndex, 5f, Color.GREEN)
} }
}
for (input in block.inputs) {
if (input.source == null) continue
val source = input.source!!
blocks[source.block]?.let { sourceView ->
view.inputViews[input]?.let { inputView ->
sourceView.outputViews[source]?.let { outputView ->
val start = inputView.convert(inputView.bounds.center, to = this)
val end = outputView.convert(outputView.bounds.center, to = this)
for ((start, end) in parameterLinks.values) {
RenderHelper.drawLine(start, end, zIndex, 5f, Color.RED) RenderHelper.drawLine(start, end, zIndex, 5f, Color.RED)
} }
} }
}
// val start = block.position
// val sourcePosition = source.block.position
// val end = Point(sourcePosition.x + blocks[source.block]!!.bounds.width, sourcePosition.y)
// val inputView = view.inputViews[input]
// val outputView =
//
// RenderHelper.drawLine(start, end, zIndex, 5f, Color.RED)
}
}
}
} }

View File

@ -1,11 +0,0 @@
{
"programblock.asmr.start": "Start",
"programblock.asmr.constant": "Constant",
"programblock.param.asmr.constant.output": "Output",
"programblock.asmr.print": "Print",
"programblock.param.asmr.print.input": "Print Value",
"programblock.asmr.binary_operator": "Binary Math Operator",
"programblock.param.asmr.binary_operator.left_operand": "Left Operand",
"programblock.param.asmr.binary_operator.right_operand": "Right Operand",
"programblock.param.asmr.binary_operator.result": "Result"
}