Start manager block & programming UI

This commit is contained in:
Shadowfacts 2019-08-08 22:44:19 -04:00
parent 200a9eea27
commit 946ebd7d9c
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
14 changed files with 228 additions and 30 deletions

View File

@ -2,17 +2,36 @@ package net.shadowfacts.asmr
import net.fabricmc.api.ModInitializer import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.registry.CommandRegistry import net.fabricmc.fabric.api.registry.CommandRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.item.BlockItem
import net.minecraft.item.Item
import net.minecraft.server.command.CommandManager import net.minecraft.server.command.CommandManager
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
import net.shadowfacts.asmr.manager.ManagerBlock
import net.shadowfacts.asmr.manager.ManagerBlockEntity
import net.shadowfacts.asmr.util.register
import java.util.function.Supplier
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
object ASMR: ModInitializer { object ASMR: ModInitializer {
const val modid = "asmr"
val managerBlock = ManagerBlock()
val managerBlockItem = BlockItem(managerBlock, Item.Settings())
val managerEntityType = BlockEntityType.Builder.create(Supplier { ManagerBlockEntity() }, managerBlock).build(null)
override fun onInitialize() { override fun onInitialize() {
println("hello fabric") println("hello fabric")
Registry.BLOCK.register(managerBlock, Identifier(modid, "manager"))
Registry.ITEM.register(managerBlockItem, Identifier(modid, "manager"))
Registry.BLOCK_ENTITY.register(managerEntityType, Identifier(modid, "manager"))
CommandRegistry.INSTANCE.register(false) { dispatcher -> CommandRegistry.INSTANCE.register(false) { dispatcher ->
val command = CommandManager.literal("uitest").executes { val command = CommandManager.literal("uitest").executes {
try { try {

View File

@ -0,0 +1,46 @@
package net.shadowfacts.asmr.manager
import net.fabricmc.api.EnvType
import net.fabricmc.api.Environment
import net.minecraft.block.Block
import net.minecraft.block.BlockEntityProvider
import net.minecraft.block.BlockState
import net.minecraft.block.Material
import net.minecraft.block.entity.BlockEntity
import net.minecraft.client.MinecraftClient
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.Hand
import net.minecraft.util.hit.BlockHitResult
import net.minecraft.util.math.BlockPos
import net.minecraft.world.BlockView
import net.minecraft.world.World
import net.shadowfacts.asmr.ui.ManagerViewController
import net.shadowfacts.cacao.CacaoScreen
import net.shadowfacts.cacao.Window
/**
* @author shadowfacts
*/
class ManagerBlock: Block(Settings.of(Material.METAL)), BlockEntityProvider {
@Deprecated("")
override fun activate(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult?): Boolean {
if (world.isClient) {
openManagerUI(world.getBlockEntity(pos) as ManagerBlockEntity)
}
return true
}
@Environment(EnvType.CLIENT)
private fun openManagerUI(managerBlockEntity: ManagerBlockEntity) {
val vc = ManagerViewController(managerBlockEntity)
val screen = CacaoScreen()
val window = screen.addWindow(Window(vc))
MinecraftClient.getInstance().openScreen(screen)
}
override fun createBlockEntity(world: BlockView): BlockEntity {
return ManagerBlockEntity()
}
}

View File

@ -0,0 +1,45 @@
package net.shadowfacts.asmr.manager
import net.minecraft.block.entity.BlockEntity
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.Program
import net.shadowfacts.asmr.program.ProgramType.Companion.INT
import net.shadowfacts.asmr.program.blocks.ConstantBlock
import net.shadowfacts.asmr.program.blocks.PrintBlock
import net.shadowfacts.asmr.program.blocks.math.BinaryOperatorBlock
import net.shadowfacts.asmr.program.blocks.math.BinaryOperatorBlock.Operation.DIVIDE
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts
*/
class ManagerBlockEntity: BlockEntity(ASMR.managerEntityType) {
val program = Program()
init {
val left = program.addBlock(ConstantBlock(INT, 36)) {
it.position = Point(0.0, 60.0)
}
val right = program.addBlock(ConstantBlock(INT, 9)) {
it.position = Point(0.0, 120.0)
}
val divide = program.addBlock(BinaryOperatorBlock(INT, DIVIDE)) {
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.source = divide.output
it.position = Point(240.0, 0.0)
}
program.startBlock.nextExecutableBlock = divide
divide.nextExecutableBlock = print
}
fun activate() {
program.execute()
}
}

View File

@ -1,9 +1,11 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.shadowfacts.cacao.geometry.Point
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class ExecutableBlock: ProgramBlock { abstract class ExecutableBlock: ProgramBlock() {
var nextExecutableBlock: ExecutableBlock? = null var nextExecutableBlock: ExecutableBlock? = null

View File

@ -1,13 +1,16 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.shadowfacts.asmr.program.blocks.StartBlock import net.shadowfacts.asmr.program.blocks.StartBlock
import net.shadowfacts.cacao.geometry.Point
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class Program { class Program {
var startBlock = StartBlock() var startBlock = StartBlock().apply {
position = Point.ORIGIN
}
val blocks = mutableListOf<ProgramBlock>() val blocks = mutableListOf<ProgramBlock>()
fun execute() { fun execute() {
@ -19,4 +22,10 @@ class Program {
} }
} }
fun <Block: ProgramBlock> addBlock(block: Block, init: (Block) -> Unit = {}): Block {
init(block)
blocks.add(block)
return block
}
} }

View File

@ -1,11 +1,15 @@
package net.shadowfacts.asmr.program package net.shadowfacts.asmr.program
import net.shadowfacts.cacao.geometry.Point
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
interface ProgramBlock { abstract class ProgramBlock {
val inputs: Array<ProgramBlockInput<*>> var position: Point = Point.ORIGIN
val outputs: Array<ProgramBlockOutput<*>>
abstract val inputs: Array<ProgramBlockInput<*>>
abstract val outputs: Array<ProgramBlockOutput<*>>
} }

View File

@ -5,8 +5,8 @@ package net.shadowfacts.asmr.program
*/ */
class ProgramType<Type> { class ProgramType<Type> {
companion object { companion object {
val int = ProgramType<Int>() val INT = ProgramType<Int>()
val float = ProgramType<Float>() val FLOAT = ProgramType<Float>()
val string = ProgramType<String>() val STRING = ProgramType<String>()
} }
} }

View File

@ -11,7 +11,7 @@ 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() {
val output = ProgramBlockOutput(type).apply { val output = ProgramBlockOutput(type).apply {
value = this@ConstantBlock.value value = this@ConstantBlock.value

View File

@ -4,6 +4,7 @@ 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
import net.shadowfacts.asmr.program.ProgramType import net.shadowfacts.asmr.program.ProgramType
import net.shadowfacts.cacao.geometry.Point
/** /**
* @author shadowfacts * @author shadowfacts

View File

@ -8,7 +8,7 @@ import net.shadowfacts.asmr.program.ProgramBlockOutput
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class StartBlock: ProgramBlock { class StartBlock: ProgramBlock() {
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

@ -15,7 +15,7 @@ class BinaryOperatorBlock<Type: Any>(
): ExecutableBlock() { ): ExecutableBlock() {
init { init {
if (type != ProgramType.int && type != ProgramType.float) { if (type != ProgramType.INT && type != ProgramType.FLOAT) {
throw RuntimeException("BinaryOperatorBlock type must be int or float") throw RuntimeException("BinaryOperatorBlock type must be int or float")
} }
} }
@ -29,29 +29,29 @@ class BinaryOperatorBlock<Type: Any>(
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output) override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output)
override fun execute() { override fun execute() {
if (type == ProgramType.int) { if (type == ProgramType.INT) {
val left = left.value as Int val left = left.value as Int
val right = right.value as Int val right = right.value as Int
output.value = when (operation) { output.value = when (operation) {
Operation.add -> left + right Operation.ADD -> left + right
Operation.subtract -> left - right Operation.SUBTRACT -> left - right
Operation.multiply -> left * right Operation.MULTIPLY -> left * right
Operation.divide -> left / right Operation.DIVIDE -> left / right
} as Type } as Type
} else if (type == ProgramType.float) { } else if (type == ProgramType.FLOAT) {
val left = left.value as Float val left = left.value as Float
val right = right.value as Float val right = right.value as Float
output.value = when (operation) { output.value = when (operation) {
Operation.add -> left + right Operation.ADD -> left + right
Operation.subtract -> left - right Operation.SUBTRACT -> left - right
Operation.multiply -> left * right Operation.MULTIPLY -> left * right
Operation.divide -> left / right Operation.DIVIDE -> left / right
} as Type } as Type
} }
} }
enum class Operation { enum class Operation {
add, subtract, multiply, divide ADD, SUBTRACT, MULTIPLY, DIVIDE
} }
} }

View File

@ -0,0 +1,63 @@
package net.shadowfacts.asmr.ui
import net.shadowfacts.asmr.manager.ManagerBlockEntity
import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.geometry.Size
import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.texture.NinePatchTexture
import net.shadowfacts.cacao.view.Label
import net.shadowfacts.cacao.view.NinePatchView
import net.shadowfacts.cacao.view.View
import net.shadowfacts.cacao.viewcontroller.ViewController
/**
* @author shadowfacts
*/
class ManagerViewController(val managerBlockEntity: ManagerBlockEntity): ViewController() {
lateinit var panel: View
override fun viewDidLoad() {
panel = view.addSubview(View())
val background = panel.addSubview(NinePatchView(NinePatchTexture.PANEL_BG))
val label = panel.addSubview(Label("test label"))
createConstraints {
panel.widthAnchor equalTo (view.widthAnchor - 40)
panel.heightAnchor equalTo (view.heightAnchor - 40)
panel.centerXAnchor equalTo view.centerXAnchor
panel.centerYAnchor equalTo view.centerYAnchor
background.leftAnchor equalTo panel.leftAnchor
background.rightAnchor equalTo panel.rightAnchor
background.topAnchor equalTo panel.topAnchor
background.bottomAnchor equalTo panel.bottomAnchor
label.centerXAnchor equalTo view.centerXAnchor
label.centerYAnchor equalTo view.centerYAnchor
}
createProgramView()
}
private fun createProgramView() {
val program = managerBlockEntity.program
program.blocks.forEach {
val blockView = panel.addSubview(View())
blockView.backgroundColor = Color.BLACK
val title = blockView.addSubview(Label(it.javaClass.simpleName))
createConstraints {
blockView.widthAnchor equalTo (title.widthAnchor + 8)
blockView.heightAnchor equalTo (title.heightAnchor + 8)
blockView.leftAnchor equalTo (panel.leftAnchor + 4 + it.position.x)
blockView.topAnchor equalTo (panel.topAnchor + 4 + it.position.y)
title.leftAnchor equalTo (blockView.leftAnchor + 4)
title.topAnchor equalTo (blockView.topAnchor + 4)
}
}
}
}

View File

@ -0,0 +1,11 @@
package net.shadowfacts.asmr.util
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
/**
* @author shadowfacts
*/
fun <T> Registry<T>.register(obj: T, identifier: Identifier) {
Registry.register(this, identifier, obj)
}

View File

@ -13,14 +13,12 @@ class ProgramTests {
@Test @Test
fun testExecutionFlow() { fun testExecutionFlow() {
val program = Program() val program = Program()
val one = ConstantBlock(ProgramType.int, 3) val one = program.addBlock(ConstantBlock(ProgramType.INT, 3))
program.blocks.add(one) val two = program.addBlock(ConstantBlock(ProgramType.INT, 7))
val two = ConstantBlock(ProgramType.int, 7) val multiply = program.addBlock(BinaryOperatorBlock(ProgramType.INT, BinaryOperatorBlock.Operation.MULTIPLY)) {
program.blocks.add(two) it.left.source = one.output
val multiply = BinaryOperatorBlock(ProgramType.int, BinaryOperatorBlock.Operation.multiply) it.right.source = two.output
multiply.left.source = one.output }
multiply.right.source = two.output
program.blocks.add(multiply)
program.startBlock.nextExecutableBlock = multiply program.startBlock.nextExecutableBlock = multiply