[Editor] Add support for compiled auto tiles in single asset (not yet working selection) #2.5

This commit is contained in:
2022-08-26 23:48:34 +02:00
parent b804178f69
commit 3fb10a4a5f
6 changed files with 249 additions and 33 deletions

View File

@@ -0,0 +1,99 @@
package com.bartlomiejpluta.base.editor.autotile.canvas
import com.bartlomiejpluta.base.editor.autotile.model.AutoTile
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent
import com.bartlomiejpluta.base.editor.render.input.MapMouseEventHandler
import com.bartlomiejpluta.base.editor.render.model.Renderable
import javafx.scene.canvas.GraphicsContext
import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent
import javafx.scene.paint.Color
import kotlin.math.roundToInt
class AutoTileCanvas(private val editorStateVM: EditorStateVM, private val gameMapVM: GameMapVM, private val selection: AutoTileSelection) : Renderable,
MapMouseEventHandler {
private var mouseRow = -1
private var mouseColumn = -1
override fun render(gc: GraphicsContext) {
gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height)
if (editorStateVM.selectedLayer is AutoTileLayer) {
val autoTile = (editorStateVM.selectedLayer as AutoTileLayer).autoTile
renderBackground(gc)
renderTiles(gc, autoTile)
renderGrid(gc, autoTile)
selection.render(gc)
}
}
private fun renderBackground(gc: GraphicsContext) {
for (x in 0 until (gc.canvas.width / BACKGROUND_TILE_WIDTH).roundToInt()) {
for (y in 0 until (gc.canvas.height / BACKGROUND_TILE_HEIGHT).roundToInt()) {
gc.fill = when ((x + y) % 2) {
0 -> BACKGROUND_COLOR1
else -> BACKGROUND_COLOR2
}
gc.fillRect(x * BACKGROUND_TILE_WIDTH, y * BACKGROUND_TILE_HEIGHT, BACKGROUND_TILE_WIDTH, BACKGROUND_TILE_HEIGHT)
}
}
}
private fun renderTiles(gc: GraphicsContext, autoTile: AutoTile) {
autoTile.islandSubTiles.forEachIndexed { i, (topLeft, topRight, bottomLeft, bottomRight) ->
val x = (i % autoTile.columns) * gameMapVM.tileWidth
val y = (i / autoTile.columns) * gameMapVM.tileHeight
gc.drawImage(topLeft, x, y)
gc.drawImage(topRight, x + gameMapVM.tileWidth/2, y)
gc.drawImage(bottomLeft, x, y + gameMapVM.tileHeight/2)
gc.drawImage(bottomRight, x + gameMapVM.tileWidth/2, y + gameMapVM.tileHeight/2)
}
// autoTile.forEach { row, column, tile ->
// gc.drawImage(tile.image, column * tile.image.width, row * tile.image.height)
// }
}
private fun renderGrid(gc: GraphicsContext, autoTile: AutoTile) {
gc.stroke = Color.BLACK
gc.lineWidth = 0.5
for (x in 0 until (gc.canvas.width / autoTile.tileWidth).roundToInt()) {
gc.strokeLine(x.toDouble() * autoTile.tileWidth, 0.0, x.toDouble() * autoTile.tileWidth, gc.canvas.height)
}
for (y in 0 until (gc.canvas.height / autoTile.tileHeight).roundToInt()) {
gc.strokeLine(0.0, y.toDouble() * autoTile.tileHeight, gc.canvas.width, y.toDouble() * autoTile.tileHeight)
}
val w = gc.canvas.width - 1
val h = gc.canvas.height - 1
gc.strokeLine(0.0, 0.0, w, 0.0)
gc.strokeLine(w, 0.0, w, h)
gc.strokeLine(0.0, h, w, h)
gc.strokeLine(0.0, 0.0, 0.0, h)
}
override fun handleMouseInput(event: MapMouseEvent) {
mouseRow = event.row
mouseColumn = event.column
if(event.type == MouseEvent.MOUSE_PRESSED && event.button == MouseButton.PRIMARY) {
selection.select(event.row.toDouble(), event.column.toDouble())
}
}
companion object {
private const val BACKGROUND_TILE_WIDTH = 5.0
private const val BACKGROUND_TILE_HEIGHT = 5.0
private val BACKGROUND_COLOR1 = Color.color(1.0, 1.0, 1.0, 1.0)
private val BACKGROUND_COLOR2 = Color.color(0.95, 0.95, 0.95, 1.0)
}
}

View File

@@ -0,0 +1,52 @@
package com.bartlomiejpluta.base.editor.autotile.canvas
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
import com.bartlomiejpluta.base.editor.render.model.Renderable
import javafx.scene.canvas.GraphicsContext
import javafx.scene.paint.Color
class AutoTileSelection(private val editorStateVM: EditorStateVM, private val gameMapVM: GameMapVM, private val brushVM: BrushVM) :
Renderable {
private var x = 0.0
private var y = 0.0
private var width = gameMapVM.tileWidth.toDouble()
private var height = gameMapVM.tileHeight.toDouble()
fun select(row: Double, column: Double) {
x = column * width
y = row * height
if (editorStateVM.selectedLayer is AutoTileLayer) {
}
// if (editorStateVM.selectedLayer is TileLayer) {
// val tileSet = (editorStateVM.selectedLayer as TileLayer).tileSetProperty.value
// val brushArray = Array(rows) { rowIndex ->
// Array(columns) { columnIndex ->
// tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex)
// }
// }
//
// brushVM.item = Brush.of(brushArray)
// brushVM.commit()
// }
}
override fun render(gc: GraphicsContext) {
gc.fill = SELECTION_FILL_COLOR
gc.fillRect(x, y, width, height)
gc.stroke = SELECTION_STROKE_COLOR
gc.strokeRect(x, y, width, height)
}
companion object {
private val SELECTION_FILL_COLOR = Color.color(0.0, 0.7, 1.0, 0.4)
private val SELECTION_STROKE_COLOR = Color.color(0.0, 0.7, 1.0, 1.0)
}
}

View File

@@ -0,0 +1,61 @@
package com.bartlomiejpluta.base.editor.autotile.component
import com.bartlomiejpluta.base.editor.autotile.canvas.AutoTileCanvas
import com.bartlomiejpluta.base.editor.autotile.canvas.AutoTileSelection
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.model.layer.Layer
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent
import javafx.event.EventHandler
import javafx.scene.canvas.Canvas
import javafx.scene.input.MouseEvent
class AutoTilePane(editorStateVM: EditorStateVM, private val gameMapVM: GameMapVM, brushVM: BrushVM) : Canvas(),
EventHandler<MouseEvent> {
private val selection = AutoTileSelection(editorStateVM, gameMapVM, brushVM)
private val autoTileCanvas = AutoTileCanvas(editorStateVM, gameMapVM, selection)
init {
onMouseMoved = this
onMouseDragged = this
onMousePressed = this
onMouseReleased = this
updateSize(editorStateVM.selectedLayer)
editorStateVM.selectedLayerProperty.addListener { _, _, layer ->
updateSize(layer)
}
brushVM.itemProperty.addListener { _, _, _ -> render() }
render()
}
private fun updateSize(layer: Layer?) {
if (layer is AutoTileLayer) {
val tileSet = layer.autoTile
width = (tileSet.tileWidth * tileSet.columns).toDouble()
height = (tileSet.tileHeight * tileSet.rows).toDouble()
} else {
width = 0.0
height = 0.0
}
render()
}
private fun render() {
autoTileCanvas.render(graphicsContext2D)
}
override fun handle(event: MouseEvent?) {
if (event != null) {
autoTileCanvas.handleMouseInput(MapMouseEvent.of(event, gameMapVM))
}
autoTileCanvas.render(graphicsContext2D)
}
}

View File

@@ -0,0 +1,21 @@
package com.bartlomiejpluta.base.editor.autotile.view.editor
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
import com.bartlomiejpluta.base.editor.autotile.component.AutoTilePane
import tornadofx.View
import tornadofx.plusAssign
import tornadofx.scrollpane
class AutoTileView : View() {
private val gameMapVM = find<GameMapVM>()
private val brushVM = find<BrushVM>()
private val editorStateVM = find<EditorStateVM>()
private val autoTilePane = AutoTilePane(editorStateVM, gameMapVM, brushVM)
override val root = scrollpane {
this += autoTilePane
}
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.map.view.editor
import com.bartlomiejpluta.base.editor.autotile.view.editor.AutoTileView
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
@@ -8,6 +9,7 @@ import com.bartlomiejpluta.base.editor.main.component.EditorTab.Companion.REDO_S
import com.bartlomiejpluta.base.editor.main.component.EditorTab.Companion.SAVE_SHORTCUT
import com.bartlomiejpluta.base.editor.main.component.EditorTab.Companion.UNDO_SHORTCUT
import com.bartlomiejpluta.base.editor.map.controller.MapController
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
@@ -29,6 +31,7 @@ class MapFragment : EditorFragment() {
private val mapView = find<MapView>()
private val layersView = find<MapLayersView>()
private val tileSetView = find<TileSetView>()
private val autoTileView = find<AutoTileView>()
private val toolbarView = find<MapToolbarView>()
private val statusBarView = find<MapStatusBarView>()
private val layerParameters = find<MapLayerParameters>()
@@ -39,6 +42,11 @@ class MapFragment : EditorFragment() {
editorStateVM.selectedLayerProperty
)
private val isAutoTileLayerSelected = Bindings.createBooleanBinding(
{ editorStateVM.selectedLayer is AutoTileLayer },
editorStateVM.selectedLayerProperty
)
override val root = borderpane {
top = toolbarView.root
@@ -59,6 +67,14 @@ class MapFragment : EditorFragment() {
}
}
item("Auto Tile", expanded = false) {
enableWhen(isAutoTileLayerSelected)
this += autoTileView.root.apply {
maxHeightProperty().bind(this@item.heightProperty())
}
}
item("Layer Parameters", expanded = false) {
this += layerParameters
}

View File

@@ -70,39 +70,6 @@ class TileSetCanvas(private val editorStateVM: EditorStateVM, private val select
gc.strokeLine(0.0, 0.0, 0.0, h)
}
// private fun createGrid(gc: GraphicsContext, chunkWidth: Int, chunkHeight: Int): WritableImage {
// val grid = WritableImage(gc.canvas.width.toInt(), gc.canvas.height.toInt())
//
// val writer = grid.pixelWriter
// val color = Color.BLACK
// for (x in 0 until grid.width.toInt()) {
// for (y in 0 until grid.height.toInt()) {
// if (x % chunkWidth == 0) {
// writer.setColor(x, y, color)
// }
//
// if (y % chunkHeight == 0) {
// writer.setColor(x, y, color)
// }
// }
// }
//
// val lastX = grid.width.toInt() - 1
// val lastY = grid.height.toInt() - 1
//
// for (x in 0 until grid.width.toInt()) {
// writer.setColor(x, 0, color)
// writer.setColor(x, lastY, color)
// }
//
// for (y in 0 until grid.height.toInt()) {
// writer.setColor(0, y, color)
// writer.setColor(lastX, y, color)
// }
//
// return grid
// }
override fun handleMouseInput(event: MapMouseEvent) {
mouseRow = event.row
mouseColumn = event.column