[Editor] Refactor brush code #2

This commit is contained in:
2021-02-07 13:42:19 +01:00
parent 6028ae27fb
commit 47d85ddc7e
5 changed files with 68 additions and 60 deletions

View File

@@ -14,21 +14,19 @@ class Brush {
val rowsProperty = SimpleIntegerProperty(this, "", 0) val rowsProperty = SimpleIntegerProperty(this, "", 0)
var rows by rowsProperty var rows by rowsProperty
private set
val columnsProperty = SimpleIntegerProperty(0) val columnsProperty = SimpleIntegerProperty(0)
var columns by columnsProperty var columns by columnsProperty
private set
val centerRowProperty = SimpleIntegerProperty(0)
var centerRow by centerRowProperty
val centerColumnProperty = SimpleIntegerProperty(0)
var centerColumn by centerColumnProperty
val brushRangeProperty = SimpleIntegerProperty(1) val brushRangeProperty = SimpleIntegerProperty(1)
var brushRange by brushRangeProperty var brushRange by brushRangeProperty
private set
val modeProperty = SimpleObjectProperty(BrushMode.PAINTING_MODE) val modeProperty = SimpleObjectProperty(BrushMode.PAINTING_MODE)
var mode by modeProperty var mode by modeProperty
private set
private constructor(brushArray: Array<Array<Tile>>) { private constructor(brushArray: Array<Array<Tile>>) {
rowsProperty.value = brushArray.size rowsProperty.value = brushArray.size
@@ -40,9 +38,6 @@ class Brush {
if (rowsProperty.value > 0) { if (rowsProperty.value > 0) {
columns = brush.size / rowsProperty.value columns = brush.size / rowsProperty.value
} }
centerRow = rows / 2
centerColumn = columns / 2
} }
private constructor(brush: List<Tile>, rows: Int, columns: Int) { private constructor(brush: List<Tile>, rows: Int, columns: Int) {
@@ -50,32 +45,53 @@ class Brush {
this.columns = columns this.columns = columns
this.brush = brush.asObservable() this.brush = brush.asObservable()
centerRow = rows / 2
centerColumn = columns / 2
} }
fun forEach(consumer: (row: Int, column: Int, tile: Tile?) -> Unit) { fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) {
brush.forEachIndexed { id, tile -> return when {
consumer(id / columns, id % columns, when(mode) { brushRange > 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) {
val center = brushRange / 2
(0 until brushRange).forEach { row ->
(0 until brushRange).forEach { column ->
consumer(row, column, center, center, getTileByMode(brush[0]))
}
}
}
private fun getTileByMode(tile: Tile) = when (mode) {
BrushMode.PAINTING_MODE -> tile BrushMode.PAINTING_MODE -> tile
BrushMode.ERASING_MODE -> null 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))
} }
} }
fun withBrushRange(range: Int) = Brush(Array(range) { Array(range) { brush[0] } }).apply { private fun clone() = Brush(brush, rows, columns).apply {
brushRange = range brushRange = this@Brush.brushRange
mode = this@Brush.mode mode = this@Brush.mode
} }
fun withErasingMode() = Brush(brush, rows, columns).apply { fun withBrushRange(range: Int) = clone().apply {
brushRange = this@Brush.brushRange brushRange = range
}
fun withErasingMode() = clone().apply {
mode = BrushMode.ERASING_MODE mode = BrushMode.ERASING_MODE
} }
fun withPaintingMode() = Brush(brush, rows, columns).apply { fun withPaintingMode() = clone().apply {
brushRange = this@Brush.brushRange
mode = BrushMode.PAINTING_MODE mode = BrushMode.PAINTING_MODE
} }

View File

@@ -27,17 +27,21 @@ class MapPainter(
val alpha = gc.globalAlpha val alpha = gc.globalAlpha
gc.globalAlpha = 0.4 gc.globalAlpha = 0.4
brushVM.forEach { row, column, tile -> tile?.let { renderTile(gc, it, column, row) } } brushVM.forEach { row, column, centerRow, centerColumn, tile ->
tile?.let {
renderTile(gc, it, column, row, centerRow, centerColumn)
}
}
gc.globalAlpha = alpha gc.globalAlpha = alpha
} }
private fun renderTile(gc: GraphicsContext, tile: Tile, column: Int, row: Int) { private fun renderTile(gc: GraphicsContext, tile: Tile, column: Int, row: Int, centerRow: Int, centerColumn: Int) {
gc.drawImage( gc.drawImage(
tile.image, tile.image,
tileWidth * (mouseColumn - brushVM.centerColumn + column), tileWidth * (mouseColumn - centerColumn + column),
tileHeight * (mouseRow - brushVM.centerRow + row) tileHeight * (mouseRow - centerRow + row)
) )
} }
@@ -55,13 +59,8 @@ class MapPainter(
private fun beginTrace(event: MapMouseEvent) { private fun beginTrace(event: MapMouseEvent) {
if (event.button == MouseButton.PRIMARY && mapVM.selectedLayer >= 0) { if (event.button == MouseButton.PRIMARY && mapVM.selectedLayer >= 0) {
currentTrace = MapPaintingTrace(mapVM, "Paint trace").apply { currentTrace = MapPaintingTrace(mapVM, "Paint trace").apply {
brushVM.forEach { row, column, tile -> brushVM.forEach { row, column, centerRow, centerColumn, tile ->
paint( paint(map.selectedLayer, mouseRow - centerRow + row, mouseColumn - centerColumn + column, tile)
map.selectedLayer,
mouseRow - brushVM.centerRow + row,
mouseColumn - brushVM.centerColumn + column,
tile
)
} }
} }
} }
@@ -70,13 +69,8 @@ class MapPainter(
private fun proceedTrace(event: MapMouseEvent) { private fun proceedTrace(event: MapMouseEvent) {
if (event.button == MouseButton.PRIMARY) { if (event.button == MouseButton.PRIMARY) {
currentTrace?.apply { currentTrace?.apply {
brushVM.forEach { row, column, tile -> brushVM.forEach { row, column, centerRow, centerColumn, tile ->
paint( paint(map.selectedLayer, mouseRow - centerRow + row, mouseColumn - centerColumn + column, tile)
map.selectedLayer,
mouseRow - brushVM.centerRow + row,
mouseColumn - brushVM.centerColumn + column,
tile
)
} }
} }
} }

View File

@@ -26,11 +26,12 @@ class TileSetPane(private val gameMapVM: GameMapVM, brushVM: BrushVM) : Canvas()
// when brush range (size) is increased to 2 or more // when brush range (size) is increased to 2 or more
// (because the range-increased brush can only include // (because the range-increased brush can only include
// the tile of one type). // the tile of one type).
brushVM.brushRangeProperty.addListener { _, _, newValue -> brushVM.itemProperty.addListener { _, _, brush ->
if (newValue.toInt() > 1) { if (brush.brushRange > 1) {
selection.shrinkToTopLeftTile() selection.shrinkToTopLeftTile()
render()
} }
render()
} }
render() render()

View File

@@ -8,7 +8,9 @@ import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
import javafx.scene.control.ToggleGroup import javafx.scene.control.ToggleGroup
import org.kordamp.ikonli.javafx.FontIcon import org.kordamp.ikonli.javafx.FontIcon
import org.slf4j.LoggerFactory
import tornadofx.* import tornadofx.*
import java.util.*
import kotlin.math.max import kotlin.math.max
class MapToolbarView : View() { class MapToolbarView : View() {
@@ -20,8 +22,8 @@ class MapToolbarView : View() {
private val brushVM = find<BrushVM>() private val brushVM = find<BrushVM>()
private val brushMode = ToggleGroup().apply { private val brushMode = ToggleGroup().apply {
brushVM.erasingProperty.addListener { _, _, newValue -> brushVM.itemProperty.addListener { _, _, brush ->
selectedValueProperty<BrushMode>().value = newValue selectedValueProperty<BrushMode>().value = brush.mode
} }
} }
@@ -101,8 +103,8 @@ class MapToolbarView : View() {
brushVM.item = brushVM.withBrushRange(newValue.toInt()) brushVM.item = brushVM.withBrushRange(newValue.toInt())
} }
brushVM.brushRangeProperty.addListener { _, _, newValue -> brushVM.itemProperty.addListener { _, _, brush ->
value = newValue.toDouble() value = brush.brushRange.toDouble()
} }
} }

View File

@@ -2,7 +2,8 @@ package com.bartlomiejpluta.base.editor.viewmodel.map
import com.bartlomiejpluta.base.editor.model.map.brush.Brush import com.bartlomiejpluta.base.editor.model.map.brush.Brush
import com.bartlomiejpluta.base.editor.model.tileset.Tile import com.bartlomiejpluta.base.editor.model.tileset.Tile
import tornadofx.* import tornadofx.ItemViewModel
import tornadofx.getValue
class BrushVM : ItemViewModel<Brush>(Brush.of(arrayOf(arrayOf()))) { class BrushVM : ItemViewModel<Brush>(Brush.of(arrayOf(arrayOf()))) {
val brush = bind(Brush::brush) val brush = bind(Brush::brush)
@@ -13,19 +14,13 @@ class BrushVM : ItemViewModel<Brush>(Brush.of(arrayOf(arrayOf()))) {
val columnsProperty = bind(Brush::columnsProperty) val columnsProperty = bind(Brush::columnsProperty)
val columns by columnsProperty val columns by columnsProperty
val centerRowProperty = bind(Brush::centerRowProperty)
val centerRow by centerRowProperty
val centerColumnProperty = bind(Brush::centerColumnProperty)
val centerColumn by centerColumnProperty
val brushRangeProperty = bind(Brush::brushRangeProperty) val brushRangeProperty = bind(Brush::brushRangeProperty)
var brushRange by brushRangeProperty val brushRange by brushRangeProperty
val erasingProperty = bind(Brush::modeProperty) val modeProperty = bind(Brush::modeProperty)
var erasing by erasingProperty val mode by modeProperty
fun forEach(consumer: (row: Int, column: Int, tile: Tile?) -> Unit) = item.forEach(consumer) fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) = item.forEach(consumer)
fun withBrushRange(range: Int) = item.withBrushRange(range) fun withBrushRange(range: Int) = item.withBrushRange(range)