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.fabric.api.registry.CommandRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.client.MinecraftClient
import net.minecraft.item.BlockItem
import net.minecraft.item.Item
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
*/
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() {
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 ->
val command = CommandManager.literal("uitest").executes {
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
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts
*/
abstract class ExecutableBlock: ProgramBlock {
abstract class ExecutableBlock: ProgramBlock() {
var nextExecutableBlock: ExecutableBlock? = null

View File

@ -1,13 +1,16 @@
package net.shadowfacts.asmr.program
import net.shadowfacts.asmr.program.blocks.StartBlock
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts
*/
class Program {
var startBlock = StartBlock()
var startBlock = StartBlock().apply {
position = Point.ORIGIN
}
val blocks = mutableListOf<ProgramBlock>()
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
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts
*/
interface ProgramBlock {
abstract class ProgramBlock {
val inputs: Array<ProgramBlockInput<*>>
val outputs: Array<ProgramBlockOutput<*>>
var position: Point = Point.ORIGIN
abstract val inputs: Array<ProgramBlockInput<*>>
abstract val outputs: Array<ProgramBlockOutput<*>>
}

View File

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

View File

@ -11,7 +11,7 @@ import net.shadowfacts.asmr.program.ProgramType
class ConstantBlock<Type: Any>(
val type: ProgramType<Type>,
val value: Type
): ProgramBlock {
): ProgramBlock() {
val output = ProgramBlockOutput(type).apply {
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.ProgramBlockOutput
import net.shadowfacts.asmr.program.ProgramType
import net.shadowfacts.cacao.geometry.Point
/**
* @author shadowfacts

View File

@ -8,7 +8,7 @@ import net.shadowfacts.asmr.program.ProgramBlockOutput
/**
* @author shadowfacts
*/
class StartBlock: ProgramBlock {
class StartBlock: ProgramBlock() {
override val inputs: Array<ProgramBlockInput<*>> = arrayOf()
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()

View File

@ -15,7 +15,7 @@ class BinaryOperatorBlock<Type: Any>(
): ExecutableBlock() {
init {
if (type != ProgramType.int && type != ProgramType.float) {
if (type != ProgramType.INT && type != ProgramType.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 fun execute() {
if (type == ProgramType.int) {
if (type == ProgramType.INT) {
val left = left.value as Int
val right = right.value as Int
output.value = when (operation) {
Operation.add -> left + right
Operation.subtract -> left - right
Operation.multiply -> left * right
Operation.divide -> left / right
Operation.ADD -> left + right
Operation.SUBTRACT -> left - right
Operation.MULTIPLY -> left * right
Operation.DIVIDE -> left / right
} as Type
} else if (type == ProgramType.float) {
} else if (type == ProgramType.FLOAT) {
val left = left.value as Float
val right = right.value as Float
output.value = when (operation) {
Operation.add -> left + right
Operation.subtract -> left - right
Operation.multiply -> left * right
Operation.divide -> left / right
Operation.ADD -> left + right
Operation.SUBTRACT -> left - right
Operation.MULTIPLY -> left * right
Operation.DIVIDE -> left / right
} as Type
}
}
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
fun testExecutionFlow() {
val program = Program()
val one = ConstantBlock(ProgramType.int, 3)
program.blocks.add(one)
val two = ConstantBlock(ProgramType.int, 7)
program.blocks.add(two)
val multiply = BinaryOperatorBlock(ProgramType.int, BinaryOperatorBlock.Operation.multiply)
multiply.left.source = one.output
multiply.right.source = two.output
program.blocks.add(multiply)
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.source = one.output
it.right.source = two.output
}
program.startBlock.nextExecutableBlock = multiply