[Editor] Replace map brush-related callbacks with Brush model

This commit is contained in:
2021-02-05 17:30:49 +01:00
parent d18a38347c
commit 8f3fca3f4b
8 changed files with 74 additions and 59 deletions

View File

@@ -0,0 +1,41 @@
package com.bartlomiejpluta.base.editor.model.map.brush
import com.bartlomiejpluta.base.editor.model.tileset.Tile
import javafx.beans.property.SimpleIntegerProperty
import tornadofx.*
class Brush {
val brush = observableListOf<Tile>()
val rowsProperty = SimpleIntegerProperty(this, "", 0)
var rows by rowsProperty
val columnsProperty = SimpleIntegerProperty(0)
var columns by columnsProperty
val centerRowProperty = SimpleIntegerProperty(0)
var centerRow by centerRowProperty
val centerColumnProperty = SimpleIntegerProperty(0)
var centerColumn by centerColumnProperty
fun updateBrush(newBrush: Array<Array<Tile>>) {
brush.clear()
columns = 0
rowsProperty.value = newBrush.size
newBrush.forEach { brush.addAll(it) }
if(rowsProperty.value > 0) {
columns = brush.size / rowsProperty.value
}
centerRow = rows/2
centerColumn = columns/2
}
fun tileAt(row: Int, column: Int) = brush[row * columns + column]
fun forEach(consumer: (row: Int, column: Int, tile: Tile) -> Unit) {
brush.forEachIndexed { id, tile ->
consumer(id / columns, id % columns, tile)
}
}
}

View File

@@ -10,8 +10,7 @@ import com.bartlomiejpluta.base.editor.render.model.Renderable
import javafx.scene.canvas.GraphicsContext import javafx.scene.canvas.GraphicsContext
class MapCanvas(val map: GameMap, private val paintingCallback: (MapPaintingTrace) -> Unit) : Renderable, class MapCanvas(val map: GameMap, private val painter: MapPainter) : Renderable {
MapMouseEventHandler {
var tileSet = map.tileSet var tileSet = map.tileSet
private var layers = map.layers private var layers = map.layers
private var rows = map.rows private var rows = map.rows
@@ -21,11 +20,6 @@ class MapCanvas(val map: GameMap, private val paintingCallback: (MapPaintingTrac
private var mapWidth = map.width.toDouble() private var mapWidth = map.width.toDouble()
private var mapHeight = map.height.toDouble() private var mapHeight = map.height.toDouble()
private var brush = MapBrush(map, arrayOf(arrayOf(tileSet.getTile(0, 0))), paintingCallback)
fun setBrush(brush: Array<Array<Tile>>) {
this.brush = MapBrush(map, brush, paintingCallback)
}
override fun render(gc: GraphicsContext) { override fun render(gc: GraphicsContext) {
gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height); gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height);
@@ -33,7 +27,7 @@ class MapCanvas(val map: GameMap, private val paintingCallback: (MapPaintingTrac
layers.forEach { dispatchLayerRender(gc, it) } layers.forEach { dispatchLayerRender(gc, it) }
renderGrid(gc) renderGrid(gc)
brush.render(gc) painter.render(gc)
} }
private fun dispatchLayerRender(gc: GraphicsContext, layer: Layer) { private fun dispatchLayerRender(gc: GraphicsContext, layer: Layer) {
@@ -63,8 +57,4 @@ class MapCanvas(val map: GameMap, private val paintingCallback: (MapPaintingTrac
gc.strokeLine(column * tileWidth, 0.0, column * tileWidth, mapHeight) gc.strokeLine(column * tileWidth, 0.0, column * tileWidth, mapHeight)
} }
} }
override fun handleMouseInput(event: MapMouseEvent) {
brush.handleMouseInput(event)
}
} }

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.render.canvas.map package com.bartlomiejpluta.base.editor.render.canvas.map
import com.bartlomiejpluta.base.editor.model.map.brush.Brush
import com.bartlomiejpluta.base.editor.model.map.map.GameMap import com.bartlomiejpluta.base.editor.model.map.map.GameMap
import com.bartlomiejpluta.base.editor.model.tileset.Tile import com.bartlomiejpluta.base.editor.model.tileset.Tile
import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent
@@ -9,39 +10,24 @@ import javafx.scene.canvas.GraphicsContext
import javafx.scene.input.MouseButton import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
class MapBrush( class MapPainter(
private val map: GameMap, private val map: GameMap,
private val brush: Array<Array<Tile>>, private val brush: Brush,
private val paintingCallback: (MapPaintingTrace) -> Unit private val paintingCallback: (MapPaintingTrace) -> Unit
) : Renderable, MapMouseEventHandler { ) : Renderable, MapMouseEventHandler {
private val tileWidth = map.tileSet.tileWidth.toDouble() private val tileWidth = map.tileSet.tileWidth.toDouble()
private val tileHeight = map.tileSet.tileHeight.toDouble() private val tileHeight = map.tileSet.tileHeight.toDouble()
private val centerRow: Int
private val centerColumn: Int
private var mouseRow = -1 private var mouseRow = -1
private var mouseColumn = -1 private var mouseColumn = -1
private var currentTrace: MapPaintingTrace? = null private var currentTrace: MapPaintingTrace? = null
init {
if (brush.isEmpty() || brush[0].isEmpty()) {
throw IllegalStateException("Brush size must be at least 1x1")
}
centerRow = brush.size / 2
centerColumn = brush[0].size / 2
}
override fun render(gc: GraphicsContext) { override fun render(gc: GraphicsContext) {
val alpha = gc.globalAlpha val alpha = gc.globalAlpha
gc.globalAlpha = 0.4 gc.globalAlpha = 0.4
for ((row, columns) in brush.withIndex()) { brush.forEach { row, column, tile -> renderTile(gc, tile, column, row) }
for ((column, tile) in columns.withIndex()) {
renderTile(gc, tile, column, row)
}
}
gc.globalAlpha = alpha gc.globalAlpha = alpha
@@ -50,8 +36,8 @@ class MapBrush(
private fun renderTile(gc: GraphicsContext, tile: Tile, column: Int, row: Int) { private fun renderTile(gc: GraphicsContext, tile: Tile, column: Int, row: Int) {
gc.drawImage( gc.drawImage(
tile.image, tile.image,
tileWidth * (mouseColumn - centerColumn + column), tileWidth * (mouseColumn - brush.centerColumn + column),
tileHeight * (mouseRow - centerRow + row) tileHeight * (mouseRow - brush.centerRow + row)
) )
} }
@@ -69,10 +55,8 @@ class MapBrush(
private fun beginTrace(event: MapMouseEvent) { private fun beginTrace(event: MapMouseEvent) {
if (event.button == MouseButton.PRIMARY) { if (event.button == MouseButton.PRIMARY) {
currentTrace = MapPaintingTrace(map, "Paint trace").apply { currentTrace = MapPaintingTrace(map, "Paint trace").apply {
for ((row, columns) in brush.withIndex()) { brush.forEach { row, column, tile ->
for ((column, tile) in columns.withIndex()) { paint(0, mouseRow - brush.centerRow + row, mouseColumn - brush.centerColumn + column, tile)
paint(0, mouseRow - centerRow + row, mouseColumn - centerColumn + column, tile)
}
} }
} }
} }
@@ -81,10 +65,8 @@ class MapBrush(
private fun proceedTrace(event: MapMouseEvent) { private fun proceedTrace(event: MapMouseEvent) {
if (event.button == MouseButton.PRIMARY) { if (event.button == MouseButton.PRIMARY) {
currentTrace?.apply { currentTrace?.apply {
for ((row, columns) in brush.withIndex()) { brush.forEach { row, column, tile ->
for ((column, tile) in columns.withIndex()) { paint(0, mouseRow - brush.centerRow + row, mouseColumn - brush.centerColumn + column, tile)
paint(0, mouseRow - centerRow + row, mouseColumn - centerColumn + column, tile)
}
} }
} }
} }

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.render.canvas.tileset package com.bartlomiejpluta.base.editor.render.canvas.tileset
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 com.bartlomiejpluta.base.editor.model.tileset.TileSet import com.bartlomiejpluta.base.editor.model.tileset.TileSet
import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent
@@ -10,9 +11,9 @@ import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
import javafx.scene.paint.Color import javafx.scene.paint.Color
class TileSetCanvas(private val tileSet: TileSet, selectionCallback: (Array<Array<Tile>>) -> Unit) : Renderable, MapMouseEventHandler { class TileSetCanvas(private val tileSet: TileSet, brush: Brush) : Renderable, MapMouseEventHandler {
private val tiles = tileSet.tiles private val tiles = tileSet.tiles
private var selection = TileSetSelection(tileSet, selectionCallback) private var selection = TileSetSelection(tileSet, brush)
private var mouseRow = -1 private var mouseRow = -1
private var mouseColumn = -1 private var mouseColumn = -1

View File

@@ -1,23 +1,18 @@
package com.bartlomiejpluta.base.editor.render.canvas.tileset package com.bartlomiejpluta.base.editor.render.canvas.tileset
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 com.bartlomiejpluta.base.editor.model.tileset.TileSet import com.bartlomiejpluta.base.editor.model.tileset.TileSet
import com.bartlomiejpluta.base.editor.render.model.Renderable import com.bartlomiejpluta.base.editor.render.model.Renderable
import javafx.collections.ObservableList
import javafx.scene.canvas.GraphicsContext import javafx.scene.canvas.GraphicsContext
import javafx.scene.paint.Color import javafx.scene.paint.Color
import org.apache.commons.logging.LogFactory
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import tornadofx.observableListOf
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min import kotlin.math.min
class TileSetSelection( class TileSetSelection(
private val tileSet: TileSet, private val tileSet: TileSet,
private val selectionCallback: (Array<Array<Tile>>) -> Unit private val brush: Brush
) : Renderable { ) : Renderable {
private val tileWidth = tileSet.tileWidth.toDouble() private val tileWidth = tileSet.tileWidth.toDouble()
private val tileHeight = tileSet.tileHeight.toDouble() private val tileHeight = tileSet.tileHeight.toDouble()
@@ -66,13 +61,13 @@ class TileSetSelection(
val rows = offsetRow.toInt() + 1 val rows = offsetRow.toInt() + 1
val columns = offsetColumn.toInt() + 1 val columns = offsetColumn.toInt() + 1
var brush = Array<Array<Tile>>(rows) { rowIndex -> var brushArray = Array<Array<Tile>>(rows) { rowIndex ->
Array<Tile>(columns) { columnIndex -> Array<Tile>(columns) { columnIndex ->
tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex) tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex)
} }
} }
selectionCallback(brush) brush.updateBrush(brushArray)
} }
override fun render(gc: GraphicsContext) { override fun render(gc: GraphicsContext) {

View File

@@ -4,15 +4,18 @@ import com.bartlomiejpluta.base.editor.model.map.map.GameMap
import com.bartlomiejpluta.base.editor.model.tileset.Tile import com.bartlomiejpluta.base.editor.model.tileset.Tile
import com.bartlomiejpluta.base.editor.render.canvas.map.MapCanvas import com.bartlomiejpluta.base.editor.render.canvas.map.MapCanvas
import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent
import com.bartlomiejpluta.base.editor.model.map.brush.Brush
import com.bartlomiejpluta.base.editor.render.canvas.map.MapPainter
import com.bartlomiejpluta.base.editor.render.canvas.map.MapPaintingTrace import com.bartlomiejpluta.base.editor.render.canvas.map.MapPaintingTrace
import javafx.event.EventHandler import javafx.event.EventHandler
import javafx.scene.canvas.Canvas import javafx.scene.canvas.Canvas
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
class MapPane(map: GameMap, paintingCallback: (MapPaintingTrace) -> Unit) : Canvas(), EventHandler<MouseEvent> { class MapPane(map: GameMap, brush: Brush, paintingCallback: (MapPaintingTrace) -> Unit) : Canvas(), EventHandler<MouseEvent> {
private var tileSet = map.tileSet private var tileSet = map.tileSet
private val mapCanvas = MapCanvas(map, paintingCallback) private val painter = MapPainter(map, brush, paintingCallback)
private val mapCanvas = MapCanvas(map, painter)
init { init {
onMouseMoved = this onMouseMoved = this
@@ -26,7 +29,6 @@ class MapPane(map: GameMap, paintingCallback: (MapPaintingTrace) -> Unit) : Canv
render() render()
} }
fun setBrush(brush: Array<Array<Tile>>) = mapCanvas.setBrush(brush)
fun render() { fun render() {
mapCanvas.render(graphicsContext2D) mapCanvas.render(graphicsContext2D)
@@ -34,7 +36,7 @@ class MapPane(map: GameMap, paintingCallback: (MapPaintingTrace) -> Unit) : Canv
override fun handle(event: MouseEvent?) { override fun handle(event: MouseEvent?) {
if (event != null) { if (event != null) {
mapCanvas.handleMouseInput(MapMouseEvent.of(event, tileSet)) painter.handleMouseInput(MapMouseEvent.of(event, tileSet))
} }
mapCanvas.render(graphicsContext2D) mapCanvas.render(graphicsContext2D)

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.view.component.tileset package com.bartlomiejpluta.base.editor.view.component.tileset
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 com.bartlomiejpluta.base.editor.model.tileset.TileSet import com.bartlomiejpluta.base.editor.model.tileset.TileSet
import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEvent
@@ -8,8 +9,8 @@ import javafx.event.EventHandler
import javafx.scene.canvas.Canvas import javafx.scene.canvas.Canvas
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
class TileSetPane(private val tileSet: TileSet, selectionCallback: (Array<Array<Tile>>) -> Unit) : Canvas(), EventHandler<MouseEvent> { class TileSetPane(private val tileSet: TileSet, brush: Brush) : Canvas(), EventHandler<MouseEvent> {
private val tileSetCanvas = TileSetCanvas(tileSet, selectionCallback) private val tileSetCanvas = TileSetCanvas(tileSet, brush)
init { init {
onMouseMoved = this onMouseMoved = this

View File

@@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.editor.view.fragment
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
import com.bartlomiejpluta.base.editor.model.map.map.GameMap import com.bartlomiejpluta.base.editor.model.map.map.GameMap
import com.bartlomiejpluta.base.editor.model.map.brush.Brush
import com.bartlomiejpluta.base.editor.view.component.map.MapPane import com.bartlomiejpluta.base.editor.view.component.map.MapPane
import com.bartlomiejpluta.base.editor.view.component.tileset.TileSetPane import com.bartlomiejpluta.base.editor.view.component.tileset.TileSetPane
import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleDoubleProperty
@@ -14,11 +15,13 @@ import tornadofx.*
class MapFragment : Fragment() { class MapFragment : Fragment() {
private val undoRedoService: UndoRedoService by di() private val undoRedoService: UndoRedoService by di()
private val brush = Brush()
val scaleProperty = SimpleDoubleProperty(1.0) val scaleProperty = SimpleDoubleProperty(1.0)
val map: GameMap by param() val map: GameMap by param()
private val mapPane = MapPane(map) { undoRedoService.push(it) } private val mapPane = MapPane(map, brush) { undoRedoService.push(it) }
private val tileSetPane = TileSetPane(map.tileSet) { mapPane.setBrush(it) } private val tileSetPane = TileSetPane(map.tileSet, brush)
private val transformation = Scale(1.0, 1.0, 0.0, 0.0).apply { private val transformation = Scale(1.0, 1.0, 0.0, 0.0).apply {
xProperty().bind(scaleProperty) xProperty().bind(scaleProperty)