[Editor] Make layer operations undoable
This commit is contained in:
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 } })
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user