[Editor] Make layer operations undoable

This commit is contained in:
2021-02-06 10:00:20 +01:00
parent 1374f2843b
commit 9c1373434e
8 changed files with 124 additions and 37 deletions

View File

@@ -0,0 +1,23 @@
package com.bartlomiejpluta.base.editor.command.model.map
import com.bartlomiejpluta.base.editor.command.model.base.Command
import com.bartlomiejpluta.base.editor.command.model.base.Undoable
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
import com.bartlomiejpluta.base.editor.model.map.map.GameMap
class CreateLayerCommand(private val map: GameMap, private val layer: Layer): Undoable, Command {
override fun execute() {
map.layers += layer
}
override fun undo() {
map.layers -= layer
}
override fun redo() {
execute()
}
override val commandName = "Create map layer"
}

View File

@@ -0,0 +1,22 @@
package com.bartlomiejpluta.base.editor.command.model.map
import com.bartlomiejpluta.base.editor.command.model.base.Command
import com.bartlomiejpluta.base.editor.command.model.base.Undoable
import com.bartlomiejpluta.base.editor.model.map.map.GameMap
import tornadofx.swap
class MoveLayerCommand(private val map: GameMap, private val currentIndex: Int, private val newIndex: Int) : Undoable, Command {
override fun execute() {
map.layers.swap(currentIndex, newIndex)
}
override fun undo() {
map.layers.swap(newIndex, currentIndex)
}
override fun redo() {
execute()
}
override val commandName = "Move layer"
}

View File

@@ -0,0 +1,26 @@
package com.bartlomiejpluta.base.editor.command.model.map
import com.bartlomiejpluta.base.editor.command.model.base.Command
import com.bartlomiejpluta.base.editor.command.model.base.Undoable
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
import com.bartlomiejpluta.base.editor.model.map.map.GameMap
import kotlin.math.min
class RemoveLayerCommand(private val map: GameMap, private val layerIndex: Int) : Undoable, Command {
private var layer: Layer? = null
override fun execute() {
layer = map.layers.removeAt(layerIndex)
}
override fun undo() {
map.layers.add(layerIndex, layer)
layer = null
}
override fun redo() {
execute()
}
override val commandName = "Remove layer"
}

View File

@@ -0,0 +1,23 @@
package com.bartlomiejpluta.base.editor.command.model.map
import com.bartlomiejpluta.base.editor.command.model.base.Command
import com.bartlomiejpluta.base.editor.command.model.base.Undoable
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
class RenameLayerCommand(private val layer: Layer, private val newName: String) : Undoable, Command {
private val formerName = layer.name
override fun execute() {
layer.name = newName
}
override fun undo() {
layer.name = formerName
}
override fun redo() {
execute()
}
override val commandName = "Rename layer"
}

View File

@@ -3,6 +3,6 @@ package com.bartlomiejpluta.base.editor.model.map.layer
import javafx.beans.property.StringProperty
interface Layer {
val name: String
var name: String
val nameProperty: StringProperty
}

View File

@@ -2,7 +2,7 @@ package com.bartlomiejpluta.base.editor.model.map.layer
import com.bartlomiejpluta.base.editor.model.tileset.Tile
import javafx.beans.property.SimpleStringProperty
import tornadofx.getValue
import tornadofx.*
class TileLayer(name: String, val layer: Array<Array<Tile?>>) : Layer {
@@ -10,5 +10,9 @@ class TileLayer(name: String, val layer: Array<Array<Tile?>>) : Layer {
override val nameProperty = SimpleStringProperty(name)
override val name: String by nameProperty
override var name: String by nameProperty
companion object {
fun empty(name: String, rows: Int ,columns: Int) = TileLayer(name, Array(rows) { Array(columns) { null } })
}
}

View File

@@ -1,7 +1,6 @@
package com.bartlomiejpluta.base.editor.model.map.map
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
import com.bartlomiejpluta.base.editor.model.map.layer.TileLayer
import com.bartlomiejpluta.base.editor.model.tileset.TileSet
import tornadofx.observableListOf
@@ -12,32 +11,4 @@ class GameMap(val tileSet: TileSet, val rows: Int, val columns: Int) {
val width = columns * tileSet.tileWidth
val height = columns * tileSet.tileWidth
fun createTileLayer(name: String, tile: Int) = createTileLayer(name).apply {
val layerId = layers.size - 1
for (row in 0 until rows) {
for (column in 0 until columns) {
setTile(layerId, row, column, tile)
}
}
}
fun createTileLayer(name: String, tileRow: Int, tileColumn: Int) = createTileLayer(name).apply {
val layerId = layers.size - 1
for (row in 0 until rows) {
for (column in 0 until columns) {
setTile(layerId, row, column, tileRow, tileColumn)
}
}
}
fun createTileLayer(name: String) = apply { layers.add(TileLayer(name, Array(rows) { Array(columns) { null } })) }
fun setTile(layer: Int, row: Int, column: Int, tile: Int) = apply {
(layers[layer] as TileLayer).setTile(row, column, tileSet.getTile(tile))
}
fun setTile(layer: Int, row: Int, column: Int, tileRow: Int, tileColumn: Int) = apply {
(layers[layer] as TileLayer).setTile(row, column, tileSet.getTile(tileRow, tileColumn))
}
}

View File

@@ -1,9 +1,14 @@
package com.bartlomiejpluta.base.editor.view.map
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
import com.bartlomiejpluta.base.editor.command.model.map.CreateLayerCommand
import com.bartlomiejpluta.base.editor.command.model.map.MoveLayerCommand
import com.bartlomiejpluta.base.editor.command.model.map.RemoveLayerCommand
import com.bartlomiejpluta.base.editor.command.model.map.RenameLayerCommand
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
import com.bartlomiejpluta.base.editor.model.map.layer.TileLayer
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
import javafx.scene.control.TableView
import org.kordamp.ikonli.javafx.FontIcon
@@ -17,7 +22,11 @@ class MapLayersView : View() {
private val mapVM = find<GameMapVM>()
private var layersPane = TableView(mapVM.layers).apply {
column("Layer Name", Layer::nameProperty).makeEditable()
column("Layer Name", Layer::nameProperty).makeEditable().setOnEditCommit {
val command = RenameLayerCommand(it.rowValue, it.newValue)
command.execute()
undoRedoService.push(command, scope)
}
mapVM.selectedLayerProperty.bind(selectionModel.selectedIndexProperty())
}
@@ -28,8 +37,11 @@ class MapLayersView : View() {
bottom = toolbar {
button(graphic = FontIcon("fa-plus")) {
action {
mapVM.item.createTileLayer("Layer ${mapVM.layers.size + 1}")
val tileLayer = TileLayer.empty("Layer ${mapVM.layers.size + 1}", mapVM.rows, mapVM.columns)
val command = CreateLayerCommand(mapVM.item, tileLayer)
command.execute()
layersPane.selectionModel.select(mapVM.layers.size - 1)
undoRedoService.push(command, scope)
}
}
@@ -37,9 +49,11 @@ class MapLayersView : View() {
enableWhen(mapVM.selectedLayerProperty.greaterThan(0))
action {
val newIndex = mapVM.selectedLayer - 1
mapVM.layers.swap(mapVM.selectedLayer, newIndex)
val command = MoveLayerCommand(mapVM.item, mapVM.selectedLayer, newIndex)
command.execute()
layersPane.selectionModel.select(newIndex)
fire(RedrawMapRequestEvent)
undoRedoService.push(command, scope)
}
}
@@ -50,9 +64,11 @@ class MapLayersView : View() {
)
action {
val newIndex = mapVM.selectedLayer + 1
mapVM.layers.swap(mapVM.selectedLayer, newIndex)
val command = MoveLayerCommand(mapVM.item, mapVM.selectedLayer, newIndex)
command.execute()
layersPane.selectionModel.select(newIndex)
fire(RedrawMapRequestEvent)
undoRedoService.push(command, scope)
}
}
@@ -60,13 +76,15 @@ class MapLayersView : View() {
enableWhen(mapVM.selectedLayerProperty.greaterThanOrEqualTo(0))
action {
var index = mapVM.selectedLayer
mapVM.layers.removeAt(index)
val command = RemoveLayerCommand(mapVM.item, index)
command.execute()
if (--index >= 0) {
layersPane.selectionModel.select(index)
}
fire(RedrawMapRequestEvent)
undoRedoService.push(command, scope)
}
}
}