Compare commits

..

No commits in common. "6045800d11db1eece82e46179e7088d31612a3ae" and "37835b578db991aaac4137b56dd8ab99b8bc375e" have entirely different histories.

18 changed files with 46 additions and 237 deletions

View File

@ -25,17 +25,17 @@ class ManagerBlockEntity: BlockEntity(ASMR.managerEntityType) {
it.position = Point(0.0, 120.0)
}
val divide = program.addBlock(BinaryOperatorBlock(INT, DIVIDE)) {
it.left.link(from = left.output)
it.right.link(from = right.output)
it.left.source = left.output
it.right.source = right.output
it.position = Point(120.0, 0.0)
}
val print = program.addBlock(PrintBlock(INT)) {
it.input.link(from = divide.output)
it.input.source = divide.output
it.position = Point(240.0, 0.0)
}
program.startBlock.executionFlow.link(divide)
divide.executionFlow.link(print)
program.startBlock.nextExecutableBlock = divide
divide.nextExecutableBlock = print
}
fun activate() {

View File

@ -1,11 +1,13 @@
package net.shadowfacts.asmr.program
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts
*/
abstract class ExecutableBlock: ProgramBlock() {
open val executionFlow = ExecutionFlow(this)
var nextExecutableBlock: ExecutableBlock? = null
abstract fun execute()

View File

@ -1,16 +0,0 @@
package net.shadowfacts.asmr.program
/**
* @author shadowfacts
*/
open class ExecutionFlow(val block: ExecutableBlock) {
open var next: ExecutableBlock? = null
open var prev: ExecutableBlock? = null
fun link(next: ExecutableBlock) {
this.next = next
next.executionFlow.prev = block
}
}

View File

@ -11,14 +11,14 @@ class Program {
var startBlock = StartBlock().apply {
position = Point.ORIGIN
}
val blocks = mutableListOf<ProgramBlock>(startBlock)
val blocks = mutableListOf<ProgramBlock>()
fun execute() {
var currentBlock: ExecutableBlock? = startBlock.executionFlow.next
var currentBlock: ExecutableBlock? = startBlock.nextExecutableBlock
while (currentBlock != null) {
currentBlock.execute()
currentBlock = currentBlock.executionFlow.next
currentBlock = currentBlock.nextExecutableBlock
}
}

View File

@ -1,29 +1,15 @@
package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier
/**
* @author shadowfacts
*/
class ProgramBlockInput<Type: Any>(
val identifier: Identifier,
val type: ProgramType<Type>,
val block: ProgramBlock,
source: ProgramBlockOutput<Type>? = null
var source: ProgramBlockOutput<Type>? = null
) {
var source: ProgramBlockOutput<Type>? = source
internal set
val value: Type?
get() = source?.value
fun link(from: ProgramBlockOutput<Type>) {
from.link(to = this)
}
fun unlink() {
source?.unlink(to = this)
}
}

View File

@ -1,29 +1,13 @@
package net.shadowfacts.asmr.program
import net.minecraft.util.Identifier
/**
* @author shadowfacts
*/
class ProgramBlockOutput<Type: Any>(
val identifier: Identifier,
val type: ProgramType<Type>,
val block: ProgramBlock
) {
lateinit var value: Type
private val _destinations = mutableListOf<ProgramBlockInput<Type>>()
val destinations: List<ProgramBlockInput<Type>> = _destinations
fun link(to: ProgramBlockInput<Type>) {
to.source = this
_destinations.add(to)
}
fun unlink(to: ProgramBlockInput<Type>) {
to.source = null
_destinations.remove(to)
}
}

View File

@ -1,7 +1,5 @@
package net.shadowfacts.asmr.program.blocks
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.ProgramBlock
import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput
@ -15,7 +13,7 @@ class ConstantBlock<Type: Any>(
val value: Type
): ProgramBlock() {
val output = ProgramBlockOutput(Identifier(ASMR.modid, "constant_output"), type, this).apply {
val output = ProgramBlockOutput(type, this).apply {
value = this@ConstantBlock.value
}

View File

@ -1,8 +1,9 @@
package net.shadowfacts.asmr.program.blocks
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.*
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput
import net.shadowfacts.asmr.program.ProgramType
import net.shadowfacts.cacao.geometry.Point
/**
@ -12,7 +13,7 @@ class PrintBlock<Type: Any>(
val type: ProgramType<Type>
): ExecutableBlock() {
val input = ProgramBlockInput(Identifier(ASMR.modid, "print_input"), type, this)
val input = ProgramBlockInput(type, this)
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(input)
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()

View File

@ -1,18 +1,18 @@
package net.shadowfacts.asmr.program.blocks
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlock
import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput
/**
* @author shadowfacts
*/
class StartBlock: ExecutableBlock() {
class StartBlock: ProgramBlock() {
override val inputs: Array<ProgramBlockInput<*>> = arrayOf()
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()
override fun execute() {
}
var nextExecutableBlock: ExecutableBlock? = null
}

View File

@ -1,7 +1,5 @@
package net.shadowfacts.asmr.program.blocks.math
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlockInput
import net.shadowfacts.asmr.program.ProgramBlockOutput
@ -22,10 +20,10 @@ class BinaryOperatorBlock<Type: Any>(
}
}
val left = ProgramBlockInput(Identifier(ASMR.modid, "left_operand"), type, this)
val right = ProgramBlockInput(Identifier(ASMR.modid, "right_operand"), type, this)
val left = ProgramBlockInput(type, this)
val right = ProgramBlockInput(type, this)
val output = ProgramBlockOutput(Identifier(ASMR.modid, "result"), type, this)
val output = ProgramBlockOutput(type, this)
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(left, right)
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output)

View File

@ -1,40 +1,18 @@
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>()
class ProgramBlockView(val block: ProgramBlock): View() {
var xConstraint: Constraint? = null
var yConstraint: Constraint? = null
@ -47,103 +25,15 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
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))
}
val title = addSubview(Label(block.javaClass.simpleName))
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
// }
widthAnchor equalTo (title.widthAnchor + 8)
heightAnchor equalTo (title.heightAnchor + 8)
title.centerXAnchor equalTo centerXAnchor
title.centerYAnchor equalTo centerYAnchor
}
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()
}
@ -163,8 +53,4 @@ class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distri
window!!.layout()
}
override fun drawContent(mouse: Point, delta: Float) {
super.drawContent(mouse, delta)
}
}

View File

@ -1,6 +1,5 @@
package net.shadowfacts.asmr.ui
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.Program
import net.shadowfacts.asmr.program.ProgramBlock
import net.shadowfacts.cacao.geometry.Point
@ -29,44 +28,17 @@ class ProgramCanvasView(val program: Program): View() {
override fun drawContent(mouse: Point, delta: Float) {
super.drawContent(mouse, delta)
blocks.keys.forEach { block ->
block.inputs
.filter { it.source != null }
.forEach { input ->
val start = block.position
val source = input.source!!
val sourcePosition = source.block.position
val end = Point(sourcePosition.x + blocks[source.block]!!.bounds.width, sourcePosition.y)
for ((block, view) in blocks) {
(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 end = incoming.convert(outgoing.bounds.center, to = this)
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)
RenderHelper.drawLine(start, end, zIndex, 5f, Color.RED)
}
RenderHelper.drawLine(start, end, zIndex, 5f, Color.WHITE)
}
}
// 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

@ -186,13 +186,14 @@ class Window(
return currentlyDraggedView.mouseDragged(startPoint, delta, mouseButton)
} else if (startPoint in viewController.view.frame) {
val startInView = Point(startPoint.x - viewController.view.frame.left, startPoint.y - viewController.view.frame.top)
var prevView: View? = null
lateinit var prevView: View
var view = viewController.view.subviewsAtPoint(startInView).maxBy(View::zIndex)
while (view != null && !view.respondsToDragging) {
prevView = view
val pointInView = viewController.view.convert(startInView, to = view)
view = view.subviewsAtPoint(pointInView).maxBy(View::zIndex)
}
// this.currentlyDraggedView = viewController.view.subviewsAtPoint(startInView).maxBy(View::zIndex)
this.currentDragReceiver = view ?: prevView
return this.currentDragReceiver?.mouseDragged(startPoint, delta, mouseButton) ?: false
}

View File

@ -26,9 +26,6 @@ data class Color(val red: Int, val green: Int, val blue: Int, val alpha: Int = 2
val CLEAR = Color(0, alpha = 0)
val WHITE = Color(0xffffff)
val BLACK = Color(0)
val RED = Color(0xff0000)
val GREEN = Color(0x00ff00)
val BLUE = Color(0x0000ff)
}
}

View File

@ -117,7 +117,7 @@ object RenderHelper {
}
private fun BufferBuilder.color(color: Color): BufferBuilder {
color(color.red, color.green, color.blue, color.alpha)
color(color.alpha, color.red, color.green, color.blue)
return this
}

View File

@ -19,7 +19,7 @@ import java.util.*
* @param distribution The mode by which this stack lays out its children along the axis perpendicular to the
* primary [axis].
*/
open class StackView(
class StackView(
val axis: Axis,
val distribution: Distribution = Distribution.FILL,
val spacing: Double = 0.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

View File

@ -16,11 +16,11 @@ class ProgramTests {
val one = program.addBlock(ConstantBlock(ProgramType.INT, 3))
val two = program.addBlock(ConstantBlock(ProgramType.INT, 7))
val multiply = program.addBlock(BinaryOperatorBlock(ProgramType.INT, BinaryOperatorBlock.Operation.MULTIPLY)) {
it.left.link(from = one.output)
it.right.link(from = two.output)
it.left.source = one.output
it.right.source = two.output
}
program.startBlock.executionFlow.link(multiply)
program.startBlock.nextExecutableBlock = multiply
program.execute()