[Editor] Complete full support for auto tiles #3

This commit is contained in:
2022-08-27 00:49:44 +02:00
parent 3fb10a4a5f
commit af5811775b
16 changed files with 108 additions and 137 deletions

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.base.editor.autotile.canvas
import com.bartlomiejpluta.base.editor.map.model.brush.AutoTileBrush
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.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
@@ -21,20 +23,9 @@ class AutoTileSelection(private val editorStateVM: EditorStateVM, private val ga
y = row * height
if (editorStateVM.selectedLayer is AutoTileLayer) {
val autoTile = (editorStateVM.selectedLayer as AutoTileLayer).autoTile
(brushVM.item as AutoTileBrush).id = (1 + row * autoTile.columns + column).toInt() //((column % autoTile.columns).toInt()) + row.toInt() + 1
}
// 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) {

View File

@@ -14,7 +14,7 @@ class AutoTilePaintingCursor(
) : PaintingCursor {
override fun render(gc: GraphicsContext) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange { row, column, centerRow, centerColumn ->
renderTile(gc, row, column, centerRow, centerColumn)
}
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.map.canvas
import com.bartlomiejpluta.base.editor.map.model.brush.AutoTileBrush
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
@@ -39,14 +40,14 @@ class AutoTilePaintingTrace(val map: GameMapVM, override val commandName: String
}
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange { row, column, centerRow, centerColumn ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,
editorStateVM.cursorColumn - centerColumn + column,
when {
brushVM.mode == BrushMode.ERASING_MODE -> 0
mouseEvent.button == MouseButton.PRIMARY -> 1
mouseEvent.button == MouseButton.PRIMARY -> (brushVM.item as AutoTileBrush).id
else -> 0
}
)
@@ -54,14 +55,14 @@ class AutoTilePaintingTrace(val map: GameMapVM, override val commandName: String
}
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange { row, column, centerRow, centerColumn ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,
editorStateVM.cursorColumn - centerColumn + column,
when {
brushVM.mode == BrushMode.ERASING_MODE -> 0
mouseEvent.button == MouseButton.PRIMARY -> 1
mouseEvent.button == MouseButton.PRIMARY -> (brushVM.item as AutoTileBrush).id
else -> 0
}
)

View File

@@ -14,7 +14,7 @@ class PassageAbilityPaintingCursor(
) : PaintingCursor {
override fun render(gc: GraphicsContext) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange() { row, column, centerRow, centerColumn ->
renderTile(gc, row, column, centerRow, centerColumn)
}
}

View File

@@ -40,7 +40,7 @@ class PassageAbilityPaintingTrace(val map: GameMapVM, override val commandName:
}
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange { row, column, centerRow, centerColumn ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,
@@ -55,7 +55,7 @@ class PassageAbilityPaintingTrace(val map: GameMapVM, override val commandName:
}
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
brushVM.item.forEachInRange { row, column, centerRow, centerColumn, ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.map.canvas
import com.bartlomiejpluta.base.editor.map.model.brush.TileBrush
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.tileset.model.Tile
@@ -14,7 +15,7 @@ class TilePaintingCursor(
) : PaintingCursor {
override fun render(gc: GraphicsContext) {
brushVM.forEach { row, column, centerRow, centerColumn, tile ->
(brushVM.item as TileBrush).forEachTileOnBrush { row, column, centerRow, centerColumn, tile ->
renderTile(gc, row, column, centerRow, centerColumn, tile)
}
}

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.map.canvas
import com.bartlomiejpluta.base.editor.map.model.brush.TileBrush
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
@@ -40,7 +41,7 @@ data class TilePaintingTrace(val map: GameMapVM, override val commandName: Strin
}
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, tile ->
(brushVM.item as TileBrush).forEachTileOnBrush { row, column, centerRow, centerColumn, tile ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,
@@ -54,7 +55,7 @@ data class TilePaintingTrace(val map: GameMapVM, override val commandName: Strin
}
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
brushVM.forEach { row, column, centerRow, centerColumn, tile ->
(brushVM.item as TileBrush).forEachTileOnBrush { row, column, centerRow, centerColumn, tile ->
paint(
editorStateVM.selectedLayerIndex,
editorStateVM.cursorRow - centerRow + row,

View File

@@ -0,0 +1,5 @@
package com.bartlomiejpluta.base.editor.map.model.brush
class AutoTileBrush : Brush() {
var id = 0
}

View File

@@ -9,98 +9,27 @@ import tornadofx.getValue
import tornadofx.observableListOf
import tornadofx.setValue
class Brush {
val brush: ObservableList<Tile>
val rowsProperty = SimpleIntegerProperty(0)
var rows by rowsProperty
private set
val columnsProperty = SimpleIntegerProperty(0)
var columns by columnsProperty
private set
val rangeProperty = SimpleIntegerProperty(1)
var range by rangeProperty
private set
abstract class Brush {
val modeProperty = SimpleObjectProperty(BrushMode.PAINTING_MODE)
var mode by modeProperty
private set
val toolProperty = SimpleObjectProperty(BrushTool.DEFAULT)
var tool by toolProperty
private set
private constructor(brushArray: Array<Array<Tile>>) {
rowsProperty.value = brushArray.size
val rangeProperty = SimpleIntegerProperty(1)
var range by rangeProperty
brush = observableListOf()
brushArray.forEach { brush.addAll(it) }
if (rowsProperty.value > 0) {
columns = brush.size / rowsProperty.value
}
}
private constructor(brush: List<Tile>, rows: Int, columns: Int) {
this.rows = rows
this.columns = columns
this.brush = brush.asObservable()
}
fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
return when {
range > 1 || mode == BrushMode.ERASING_MODE -> forEachInRangedBrush(consumer)
else -> forEachInRegularBrush(consumer)
}
}
private fun forEachInRangedBrush(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
fun forEachInRange(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int) -> Unit) {
val center = range / 2
(0 until range).forEach { row ->
(0 until range).forEach { column ->
consumer(row, column, center, center, getTileByMode(brush[0]))
consumer(row, column, center, center)
}
}
}
private fun getTileByMode(tile: Tile) = when (mode!!) {
BrushMode.PAINTING_MODE -> tile
BrushMode.ERASING_MODE -> null
}
private fun forEachInRegularBrush(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
val centerRow = rows / 2
val centerColumn = columns / 2
brush.forEachIndexed { id, tile ->
consumer(id / columns, id % columns, centerRow, centerColumn, getTileByMode(tile))
}
}
private fun clone() = Brush(brush, rows, columns).apply {
this.range = this@Brush.range
this.mode = this@Brush.mode
this.tool = this@Brush.tool
}
fun withRange(range: Int) = clone().apply {
this.range = range
}
fun withMode(mode: BrushMode) = clone().apply {
this.mode = mode
}
fun withTool(tool: BrushTool) = clone().apply {
this.tool = tool
}
companion object {
fun of(brushArray: Array<Array<Tile>>) = Brush(brushArray)
fun of(brushArray: Array<Array<Tile>>) = TileBrush(brushArray)
}
}

View File

@@ -0,0 +1,3 @@
package com.bartlomiejpluta.base.editor.map.model.brush
class EmptyBrush : Brush()

View File

@@ -0,0 +1,3 @@
package com.bartlomiejpluta.base.editor.map.model.brush
class PassageAbilityBrush : Brush()

View File

@@ -0,0 +1,44 @@
package com.bartlomiejpluta.base.editor.map.model.brush
import com.bartlomiejpluta.base.editor.tileset.model.Tile
import tornadofx.observableListOf
class TileBrush(brushArray: Array<Array<Tile>>) : Brush() {
private val brush: List<Tile>
private var columns = 0
private var rows = 0
init {
rows = brushArray.size
brush = observableListOf()
brushArray.forEach { brush.addAll(it) }
if (rows > 0) {
columns = brush.size / rows
}
}
fun forEachTileOnBrush(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
return when {
range > 1 || mode == BrushMode.ERASING_MODE -> forEachInRange { row, column, centerRow, centerColumn ->
consumer(row, column, centerRow, centerColumn, brush[0])
}
else -> forEachInRegularBrush(consumer)
}
}
private fun getTileByMode(tile: Tile) = when (mode!!) {
BrushMode.PAINTING_MODE -> tile
BrushMode.ERASING_MODE -> null
}
private fun forEachInRegularBrush(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
val centerRow = rows / 2
val centerColumn = columns / 2
brush.forEachIndexed { id, tile ->
consumer(id / columns, id % columns, centerRow, centerColumn, getTileByMode(tile))
}
}
}

View File

@@ -53,7 +53,7 @@ class MapToolbarView : View() {
}
editorStateVM.selectedLayerProperty.addListener { _, _, _ ->
brushVM.item = brushVM.withTool(BrushTool.DEFAULT)
brushVM.tool = BrushTool.DEFAULT
}
}
@@ -104,7 +104,7 @@ class MapToolbarView : View() {
enableWhen(isTileLayerSelected.or(isAutoTileLayerSelected).or(isObjectLayerSelected))
action {
brushVM.item = brushVM.withMode(BrushMode.PAINTING_MODE)
brushVM.mode = BrushMode.PAINTING_MODE
brushVM.commit()
}
}
@@ -115,7 +115,7 @@ class MapToolbarView : View() {
enableWhen(isTileLayerSelected.or(isAutoTileLayerSelected).or(isObjectLayerSelected))
action {
brushVM.item = brushVM.withMode(BrushMode.ERASING_MODE)
brushVM.mode = BrushMode.ERASING_MODE
brushVM.commit()
}
}
@@ -130,7 +130,7 @@ class MapToolbarView : View() {
enableWhen(isTileLayerSelected.or(isAutoTileLayerSelected).or(isObjectLayerSelected))
valueProperty().addListener { _, _, newValue ->
brushVM.item = brushVM.withRange(newValue.toInt())
brushVM.range = newValue.toInt()
brushVM.commit()
}
@@ -151,7 +151,7 @@ class MapToolbarView : View() {
visibleWhen(isObjectLayerSelected)
action {
brushVM.item = brushVM.withTool(BrushTool.DEFAULT)
brushVM.tool = BrushTool.DEFAULT
brushVM.commit()
}
}
@@ -162,7 +162,7 @@ class MapToolbarView : View() {
visibleWhen(isObjectLayerSelected)
action {
brushVM.item = brushVM.withTool(BrushTool.PASSAGE)
brushVM.tool = BrushTool.PASSAGE
brushVM.commit()
}
}

View File

@@ -5,6 +5,11 @@ import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
import com.bartlomiejpluta.base.editor.map.canvas.PaintingTrace
import com.bartlomiejpluta.base.editor.map.component.MapPane
import com.bartlomiejpluta.base.editor.map.model.brush.*
import com.bartlomiejpluta.base.editor.map.model.layer.AutoTileLayer
import com.bartlomiejpluta.base.editor.map.model.layer.Layer
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
@@ -40,12 +45,24 @@ class MapView : View() {
}
init {
// brushVM.item = mapVM.tileSet.baseBrush
brushVM.item = EmptyBrush()
brushVM.commit()
editorStateVM.selectedLayerProperty.addListener { _, _, layer ->
brushVM.item = determineBrush(layer)
brushVM.commit()
}
subscribe<RedrawMapRequestEvent> { mapPane.render() }
}
private fun determineBrush(layer: Layer?) : Brush? = when (layer) {
is TileLayer -> TileBrush((arrayOf(arrayOf(layer.tileSetProperty.value.tiles[0]))))
is AutoTileLayer -> AutoTileBrush()
is ObjectLayer -> PassageAbilityBrush()
else -> null
}
private fun pushPaintingTraceToUndoRedoService(trace: PaintingTrace) {
if (trace.executed) {
undoRedoService.push(trace, scope)

View File

@@ -1,36 +1,15 @@
package com.bartlomiejpluta.base.editor.map.viewmodel
import com.bartlomiejpluta.base.editor.map.model.brush.Brush
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
import com.bartlomiejpluta.base.editor.map.model.brush.BrushTool
import com.bartlomiejpluta.base.editor.tileset.model.Tile
import tornadofx.ItemViewModel
import tornadofx.getValue
import tornadofx.*
class BrushVM : ItemViewModel<Brush>(Brush.of(arrayOf(arrayOf()))) {
val brush = bind(Brush::brush)
val rowsProperty = bind(Brush::rowsProperty)
val rows by rowsProperty
val columnsProperty = bind(Brush::columnsProperty)
val columns by columnsProperty
val rangeProperty = bind(Brush::rangeProperty)
val range by rangeProperty
val modeProperty = bind(Brush::modeProperty)
val mode by modeProperty
var mode by modeProperty
val toolProperty = bind(Brush::toolProperty)
val tool by toolProperty
var tool by toolProperty
fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) =
item.forEach(consumer)
fun withRange(range: Int) = item.withRange(range)
fun withMode(mode: BrushMode) = item.withMode(mode)
fun withTool(tool: BrushTool) = item.withTool(tool)
val rangeProperty = bind(Brush::rangeProperty)
var range by rangeProperty
}

View File

@@ -43,9 +43,6 @@ class TileSet(uid: String, name: String, image: Image, rows: Int, columns: Int)
val tiles = (0 until rows * columns).map { cropTile(it / columns, it % columns) }.toObservable()
val baseBrush: Brush
get() = Brush.of(arrayOf(arrayOf(tiles[0])))
private fun cropTile(row: Int, column: Int): Tile {
val reader = image.pixelReader
val buffer = ByteBuffer.allocate(tileWidth * tileHeight * 4)