From 56bc870ac5a25fe29ac268287a55169cbac487bd Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Fri, 9 Aug 2019 22:39:01 -0400 Subject: [PATCH] More programmer UI work --- .../asmr/program/ProgramBlockInput.kt | 3 + .../asmr/program/ProgramBlockOutput.kt | 3 + .../asmr/program/blocks/ConstantBlock.kt | 4 +- .../asmr/program/blocks/PrintBlock.kt | 4 +- .../blocks/math/BinaryOperatorBlock.kt | 8 ++- .../shadowfacts/asmr/ui/ProgramBlockView.kt | 63 ++++++++++++++++-- .../shadowfacts/asmr/ui/ProgramCanvasView.kt | 33 ++++++--- .../kotlin/net/shadowfacts/cacao/Window.kt | 3 +- .../net/shadowfacts/cacao/util/Color.kt | 1 + .../shadowfacts/cacao/util/RenderHelper.kt | 2 +- .../net/shadowfacts/cacao/view/StackView.kt | 2 +- .../gui/programmer/execution_flow.png | Bin 0 -> 889 bytes 12 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 src/main/resources/assets/asmr/textures/gui/programmer/execution_flow.png diff --git a/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockInput.kt b/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockInput.kt index 8058ba5..89bc2fd 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockInput.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockInput.kt @@ -1,9 +1,12 @@ package net.shadowfacts.asmr.program +import net.minecraft.util.Identifier + /** * @author shadowfacts */ class ProgramBlockInput( + val identifier: Identifier, val type: ProgramType, val block: ProgramBlock, var source: ProgramBlockOutput? = null diff --git a/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockOutput.kt b/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockOutput.kt index 0a4b3da..c4cc0c6 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockOutput.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/program/ProgramBlockOutput.kt @@ -1,9 +1,12 @@ package net.shadowfacts.asmr.program +import net.minecraft.util.Identifier + /** * @author shadowfacts */ class ProgramBlockOutput( + val identifier: Identifier, val type: ProgramType, val block: ProgramBlock ) { diff --git a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/ConstantBlock.kt b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/ConstantBlock.kt index 0914baa..193cd27 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/ConstantBlock.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/ConstantBlock.kt @@ -1,5 +1,7 @@ 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 @@ -13,7 +15,7 @@ class ConstantBlock( val value: Type ): ProgramBlock() { - val output = ProgramBlockOutput(type, this).apply { + val output = ProgramBlockOutput(Identifier(ASMR.modid, "constant_output"), type, this).apply { value = this@ConstantBlock.value } diff --git a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/PrintBlock.kt b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/PrintBlock.kt index 25c2ef0..9acf0ef 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/PrintBlock.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/PrintBlock.kt @@ -1,5 +1,7 @@ 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.ProgramBlockInput import net.shadowfacts.asmr.program.ProgramBlockOutput @@ -13,7 +15,7 @@ class PrintBlock( val type: ProgramType ): ExecutableBlock() { - val input = ProgramBlockInput(type, this) + val input = ProgramBlockInput(Identifier(ASMR.modid, "print_input"), type, this) override val inputs: Array> = arrayOf(input) override val outputs: Array> = arrayOf() diff --git a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/math/BinaryOperatorBlock.kt b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/math/BinaryOperatorBlock.kt index 554f215..98cf2b5 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/program/blocks/math/BinaryOperatorBlock.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/program/blocks/math/BinaryOperatorBlock.kt @@ -1,5 +1,7 @@ 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 @@ -20,10 +22,10 @@ class BinaryOperatorBlock( } } - val left = ProgramBlockInput(type, this) - val right = ProgramBlockInput(type, this) + val left = ProgramBlockInput(Identifier(ASMR.modid, "left_operand"), type, this) + val right = ProgramBlockInput(Identifier(ASMR.modid, "right_operand"), type, this) - val output = ProgramBlockOutput(type, this) + val output = ProgramBlockOutput(Identifier(ASMR.modid, "result"), type, this) override val inputs: Array> = arrayOf(left, right) override val outputs: Array> = arrayOf(output) diff --git a/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt b/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt index 3df2ee0..3540c0b 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt @@ -1,10 +1,17 @@ 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.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 @@ -12,7 +19,15 @@ import no.birkett.kiwi.Constraint /** * @author shadowfacts */ -class ProgramBlockView(val block: ProgramBlock): View() { +class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distribution.CENTER, spacing = 4.0) { + + companion object { + val executionFlowInactiveTexture = Texture(Identifier(ASMR.modid, "textures/gui/programmer/execution_flow.png"), u = 0, v = 0) + val executionFlowActiveTexture = Texture(Identifier(ASMR.modid, "textures/gui/programmer/execution_flow.png"), u = 7, v = 0) + } + + var incomingExecution: View? = null + var outgoingExeuction: View? = null var xConstraint: Constraint? = null var yConstraint: Constraint? = null @@ -25,13 +40,45 @@ class ProgramBlockView(val block: ProgramBlock): View() { backgroundColor = Color.BLACK zIndex = 10.0 - val title = addSubview(Label(block.javaClass.simpleName)) + val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER)) + val title = titleStack.addArrangedSubview(Label(block.javaClass.simpleName)) + if (block is ExecutableBlock) { + val incomingTexture = executionFlowInactiveTexture + incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0) + val outgoingTexture = if (block.nextExecutableBlock == null) executionFlowInactiveTexture else executionFlowActiveTexture + outgoingExeuction = titleStack.addArrangedSubview(TextureView(outgoingTexture)) + } + + 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, spacing = 8.0)) + hStack.addArrangedSubview(Label(input.identifier.toString())) + hStack.addArrangedSubview(Label(output.identifier.toString())) + } + for (input in remainingInputs) { + addArrangedSubview(Label(input.identifier.toString())) + } + for (output in remainingOutputs) { + addArrangedSubview(Label(output.identifier.toString(), textAlignment = Label.TextAlignment.RIGHT)) + } solver.dsl { - widthAnchor equalTo (title.widthAnchor + 8) - heightAnchor equalTo (title.heightAnchor + 8) - title.centerXAnchor equalTo centerXAnchor - title.centerYAnchor equalTo centerYAnchor + // 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 (view in arrangedSubviews.drop(1)) { + widthAnchor.equalTo(view.widthAnchor, strength = STRONG) + } } updateDraggingConstraints() @@ -53,4 +100,8 @@ class ProgramBlockView(val block: ProgramBlock): View() { window!!.layout() } + override fun drawContent(mouse: Point, delta: Float) { + super.drawContent(mouse, delta) + } + } \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramCanvasView.kt b/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramCanvasView.kt index c3906b7..f767bac 100644 --- a/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramCanvasView.kt +++ b/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramCanvasView.kt @@ -1,5 +1,6 @@ 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 @@ -28,17 +29,29 @@ 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) - RenderHelper.drawLine(start, end, zIndex, 5f, Color.WHITE) - } + for ((block, view) in blocks) { + (block as? ExecutableBlock)?.nextExecutableBlock?.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(0x00ff00)) + } + } + +// for (input in block.inputs) { +// if (input.source == null) continue +// 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) +// +// RenderHelper.drawLine(start, end, zIndex, 5f, Color.WHITE) +// } } } diff --git a/src/main/kotlin/net/shadowfacts/cacao/Window.kt b/src/main/kotlin/net/shadowfacts/cacao/Window.kt index 89cde6b..c060406 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/Window.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/Window.kt @@ -186,14 +186,13 @@ 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) - lateinit var prevView: View + var prevView: View? = null 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 } diff --git a/src/main/kotlin/net/shadowfacts/cacao/util/Color.kt b/src/main/kotlin/net/shadowfacts/cacao/util/Color.kt index 6a113bd..c0c9116 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/util/Color.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/util/Color.kt @@ -26,6 +26,7 @@ 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 GREEN = Color(0x00ff00) } } \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt index 35addcc..f041167 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/util/RenderHelper.kt @@ -117,7 +117,7 @@ object RenderHelper { } private fun BufferBuilder.color(color: Color): BufferBuilder { - color(color.alpha, color.red, color.green, color.blue) + color(color.red, color.green, color.blue, color.alpha) return this } diff --git a/src/main/kotlin/net/shadowfacts/cacao/view/StackView.kt b/src/main/kotlin/net/shadowfacts/cacao/view/StackView.kt index 12a55ed..a24f317 100644 --- a/src/main/kotlin/net/shadowfacts/cacao/view/StackView.kt +++ b/src/main/kotlin/net/shadowfacts/cacao/view/StackView.kt @@ -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]. */ -class StackView( +open class StackView( val axis: Axis, val distribution: Distribution = Distribution.FILL, val spacing: Double = 0.0 diff --git a/src/main/resources/assets/asmr/textures/gui/programmer/execution_flow.png b/src/main/resources/assets/asmr/textures/gui/programmer/execution_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..49edb93b2693740c3d355eb9a0d41f341f27332a GIT binary patch literal 889 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$5xX)7d$|)7e>}peR2rGbfdS zL1SX=L|c!;4l+mMqnCzi@x4`eG-07tq`=fiD?&A#S_8DVyhF(Ei@t>N|Ux|D4qdK0A-o;i``EWG}9r ze^v?9xN_8XC@{`H;#2D+&ZEvoRmLGRGimTK;+4bg=^z%uF>*h(CZkk#7NMmEbtE8RXkv9W6mv<(2tqR;{ z|9sP-%I?ikYd3$h{mFfpH8*wUYZLbghm@u%I5qTGX{|WqG$*WAL|F2cf7Oq6+5H}R zGh;*zigXsRiB5XV{=fPD-C0LhdYWs_VX2DG`JF7n@s4S2TW-Dl?XuS_95&41QOD!6 znT+QzF}I3(!y$2pO>dp`tUc^8?--o@ccpmri7a@jFV^_o_}4NUft{?suHU(L>$gQM z!=@{tzt}7+SdMv3+57I}yMXfi|MN1xe`oeKEt)RI#yb%hEo@2N?k+$Y2!1;6t_M<_ z1s;*b3=De8Ak0{?)V>TT$X?><>&pI^gNvDwGtnb{DljI?JY5_^DsH{KX~=h2frs_N z`&H$B>kh2EtLow@y0ZAvcQ+pHNxU<>CcX2UbZ*%yE%v>>JGvOZf1P*I-sshg55^aF z?{;@vmvrDP_W_@OrmqY4JX>jR^hq?B<$+?{HU<%f2lDe7LQU8I{ynwsWYH@|8F8IR p6Q+lXe!cr^FX)4uI}*Wxe0i12R)Pon+CY)Q;OXk;vd$@?2>|WO3Z?)6 literal 0 HcmV?d00001