From 78e11029e53074e3d623df7ba871baba28e83b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Wed, 17 Feb 2021 08:13:55 +0100 Subject: [PATCH] [Editor] Add support for object and image layers in editor --- .../base/editor/map/canvas/MapCanvas.kt | 6 +- .../base/editor/map/canvas/MapPainter.kt | 63 +++++++------------ .../base/editor/map/canvas/PaintingCursor.kt | 5 ++ .../base/editor/map/canvas/PaintingTrace.kt | 11 ++++ .../editor/map/canvas/TilePaintingCursor.kt | 39 ++++++++++++ ...pPaintingTrace.kt => TilePaintingTrace.kt} | 35 +++++++++-- .../base/editor/map/component/MapPane.kt | 8 +-- .../base/editor/map/model/layer/ImageLayer.kt | 15 +++++ .../base/editor/map/model/layer/Layer.kt | 2 - .../editor/map/model/layer/ObjectLayer.kt | 15 +++++ .../base/editor/map/model/layer/TileLayer.kt | 4 -- .../editor/map/view/editor/MapFragment.kt | 12 ++++ .../editor/map/view/editor/MapLayersView.kt | 62 ++++++++++++------ .../editor/map/viewmodel/EditorStateVM.kt | 7 ++- 14 files changed, 209 insertions(+), 75 deletions(-) create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingCursor.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingTrace.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingCursor.kt rename editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/{MapPaintingTrace.kt => TilePaintingTrace.kt} (56%) create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ObjectLayer.kt diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt index 22970525..7444ed3a 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt @@ -2,9 +2,9 @@ package com.bartlomiejpluta.base.editor.map.canvas import com.bartlomiejpluta.base.editor.map.model.layer.Layer import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer -import com.bartlomiejpluta.base.editor.render.model.Renderable import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM +import com.bartlomiejpluta.base.editor.render.model.Renderable import javafx.scene.canvas.GraphicsContext import javafx.scene.paint.Color @@ -27,7 +27,7 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr } private fun renderSelectedLayer(gc: GraphicsContext) { - map.layers.getOrNull(editorStateVM.selectedLayer) ?. let { dispatchLayerRender(gc, it) } + map.layers.getOrNull(editorStateVM.selectedLayerIndex)?.let { dispatchLayerRender(gc, it) } } private fun renderCover(gc: GraphicsContext) { @@ -40,7 +40,7 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr } private fun renderUnderlyingLayers(gc: GraphicsContext) { - for(layer in map.layers.dropLast(if(editorStateVM.selectedLayer < 0) 0 else map.layers.size - editorStateVM.selectedLayer)) { + for (layer in map.layers.dropLast(if (editorStateVM.selectedLayerIndex < 0) 0 else map.layers.size - editorStateVM.selectedLayerIndex)) { dispatchLayerRender(gc, layer) } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPainter.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPainter.kt index b3eb6f1a..74c2abbf 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPainter.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPainter.kt @@ -1,57 +1,46 @@ package com.bartlomiejpluta.base.editor.map.canvas -import com.bartlomiejpluta.base.editor.tileset.model.Tile -import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent -import com.bartlomiejpluta.base.editor.render.input.MapMouseEventHandler -import com.bartlomiejpluta.base.editor.render.model.Renderable +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 +import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent +import com.bartlomiejpluta.base.editor.render.input.MapMouseEventHandler +import com.bartlomiejpluta.base.editor.render.model.Renderable import javafx.scene.canvas.GraphicsContext import javafx.scene.input.MouseButton import javafx.scene.input.MouseEvent -import javafx.scene.paint.Color class MapPainter( private val mapVM: GameMapVM, private val brushVM: BrushVM, private val editorStateVM: EditorStateVM, - private val paintingCallback: (MapPaintingTrace) -> Unit + private val paintingCallback: (PaintingTrace) -> Unit ) : Renderable, MapMouseEventHandler { private val tileWidth = mapVM.tileSet.tileWidth.toDouble() private val tileHeight = mapVM.tileSet.tileHeight.toDouble() - private var currentTrace: MapPaintingTrace? = null + private var cursor: PaintingCursor? = null + private var currentTrace: PaintingTrace? = null + + init { + editorStateVM.selectedLayerProperty.addListener { _, _, layer -> + cursor = when (layer) { + is TileLayer -> TilePaintingCursor(tileWidth, tileHeight, editorStateVM, brushVM) + else -> null + } + } + } override fun render(gc: GraphicsContext) { val alpha = gc.globalAlpha gc.globalAlpha = 0.4 - brushVM.forEach { row, column, centerRow, centerColumn, tile -> - renderTile(gc, row, column, centerRow, centerColumn, tile) - } + cursor?.render(gc) gc.globalAlpha = alpha } - private fun renderTile(gc: GraphicsContext, row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) { - val x = tileWidth * (editorStateVM.cursorColumn - centerColumn + column) - val y = tileHeight * (editorStateVM.cursorRow - centerRow + row) - - when { - tile != null -> renderPaintingBrushTile(gc, tile, x, y) - else -> renderEraserTile(gc, x, y) - } - } - - private fun renderPaintingBrushTile(gc: GraphicsContext, tile: Tile, x: Double, y: Double) = - gc.drawImage(tile.image, x, y) - - private fun renderEraserTile(gc: GraphicsContext, x: Double, y: Double) { - gc.fill = Color.WHITE - gc.fillRect(x, y, tileWidth, tileHeight) - } - override fun handleMouseInput(event: MapMouseEvent) { editorStateVM.cursorRowProperty.value = event.row editorStateVM.cursorColumnProperty.value = event.column @@ -64,28 +53,24 @@ class MapPainter( } private fun beginTrace(event: MapMouseEvent) { - if (event.button == MouseButton.PRIMARY && editorStateVM.selectedLayer >= 0) { - currentTrace = MapPaintingTrace(mapVM, "Paint trace").apply { - brushVM.forEach { row, column, centerRow, centerColumn, tile -> - paint(editorStateVM.selectedLayer, editorStateVM.cursorRow - centerRow + row, editorStateVM.cursorColumn - centerColumn + column, tile) - } - } + if (event.button == MouseButton.PRIMARY && editorStateVM.selectedLayerIndex >= 0) { + currentTrace = when (editorStateVM.selectedLayer) { + is TileLayer -> TilePaintingTrace(mapVM, "Paint trace") + else -> null + }?.apply { beginTrace(editorStateVM, brushVM) } } } private fun proceedTrace(event: MapMouseEvent) { if (event.button == MouseButton.PRIMARY) { - currentTrace?.apply { - brushVM.forEach { row, column, centerRow, centerColumn, tile -> - paint(editorStateVM.selectedLayer, editorStateVM.cursorRow - centerRow + row, editorStateVM.cursorColumn - centerColumn + column, tile) - } - } + currentTrace?.proceedTrace(editorStateVM, brushVM) } } private fun commitTrace(event: MapMouseEvent) { if (event.button == MouseButton.PRIMARY) { currentTrace?.let { + it.commitTrace(editorStateVM, brushVM) paintingCallback(it) currentTrace = null } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingCursor.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingCursor.kt new file mode 100644 index 00000000..99b7363a --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingCursor.kt @@ -0,0 +1,5 @@ +package com.bartlomiejpluta.base.editor.map.canvas + +import com.bartlomiejpluta.base.editor.render.model.Renderable + +interface PaintingCursor : Renderable \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingTrace.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingTrace.kt new file mode 100644 index 00000000..29f67f86 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/PaintingTrace.kt @@ -0,0 +1,11 @@ +package com.bartlomiejpluta.base.editor.map.canvas + +import com.bartlomiejpluta.base.editor.command.model.base.Undoable +import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM +import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM + +interface PaintingTrace : Undoable { + fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) + fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) + fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingCursor.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingCursor.kt new file mode 100644 index 00000000..4d6648e1 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingCursor.kt @@ -0,0 +1,39 @@ +package com.bartlomiejpluta.base.editor.map.canvas + +import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM +import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM +import com.bartlomiejpluta.base.editor.tileset.model.Tile +import javafx.scene.canvas.GraphicsContext +import javafx.scene.paint.Color + +class TilePaintingCursor( + private val tileWidth: Double, + private val tileHeight: Double, + private val editorStateVM: EditorStateVM, + private val brushVM: BrushVM +) : PaintingCursor { + + override fun render(gc: GraphicsContext) { + brushVM.forEach { row, column, centerRow, centerColumn, tile -> + renderTile(gc, row, column, centerRow, centerColumn, tile) + } + } + + private fun renderTile(gc: GraphicsContext, row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) { + val x = tileWidth * (editorStateVM.cursorColumn - centerColumn + column) + val y = tileHeight * (editorStateVM.cursorRow - centerRow + row) + + when { + tile != null -> renderPaintingBrushTile(gc, tile, x, y) + else -> renderEraserTile(gc, x, y) + } + } + + private fun renderPaintingBrushTile(gc: GraphicsContext, tile: Tile, x: Double, y: Double) = + gc.drawImage(tile.image, x, y) + + private fun renderEraserTile(gc: GraphicsContext, x: Double, y: Double) { + gc.fill = Color.WHITE + gc.fillRect(x, y, tileWidth, tileHeight) + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPaintingTrace.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingTrace.kt similarity index 56% rename from editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPaintingTrace.kt rename to editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingTrace.kt index e3614581..ce593d65 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapPaintingTrace.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/TilePaintingTrace.kt @@ -1,15 +1,16 @@ package com.bartlomiejpluta.base.editor.map.canvas -import com.bartlomiejpluta.base.editor.command.model.base.Undoable import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer -import com.bartlomiejpluta.base.editor.tileset.model.Tile +import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM +import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM +import com.bartlomiejpluta.base.editor.tileset.model.Tile -data class MapPaintingTrace(val map: GameMapVM, override val commandName: String) : Undoable { +data class TilePaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace { private val trace = mutableListOf() - fun paint(layerIndex: Int, row: Int, column: Int, tile: Tile?) { + private fun paint(layerIndex: Int, row: Int, column: Int, tile: Tile?) { if (row >= map.rows || column >= map.columns || row < 0 || column < 0 || layerIndex < 0) { return } @@ -32,6 +33,32 @@ data class MapPaintingTrace(val map: GameMapVM, override val commandName: String } } + override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) { + brushVM.forEach { row, column, centerRow, centerColumn, tile -> + paint( + editorStateVM.selectedLayerIndex, + editorStateVM.cursorRow - centerRow + row, + editorStateVM.cursorColumn - centerColumn + column, + tile + ) + } + } + + override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) { + brushVM.forEach { row, column, centerRow, centerColumn, tile -> + paint( + editorStateVM.selectedLayerIndex, + editorStateVM.cursorRow - centerRow + row, + editorStateVM.cursorColumn - centerColumn + column, + tile + ) + } + } + + override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM) { + + } + override fun undo() { trace.forEach { (map.layers[it.layerIndex] as TileLayer).layer[it.row][it.column] = it.formerTile diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/component/MapPane.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/component/MapPane.kt index 314c94e1..29b2790f 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/component/MapPane.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/component/MapPane.kt @@ -2,11 +2,11 @@ package com.bartlomiejpluta.base.editor.map.component import com.bartlomiejpluta.base.editor.map.canvas.MapCanvas import com.bartlomiejpluta.base.editor.map.canvas.MapPainter -import com.bartlomiejpluta.base.editor.map.canvas.MapPaintingTrace -import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent +import com.bartlomiejpluta.base.editor.map.canvas.PaintingTrace import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM +import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent import javafx.event.EventHandler import javafx.scene.canvas.Canvas import javafx.scene.input.MouseEvent @@ -15,7 +15,7 @@ class MapPane( private val mapVM: GameMapVM, brushVM: BrushVM, editorStateVM: EditorStateVM, - paintingCallback: (MapPaintingTrace) -> Unit + paintingCallback: (PaintingTrace) -> Unit ) : Canvas(), EventHandler { private val painter = MapPainter(mapVM, brushVM, editorStateVM, paintingCallback) private val mapCanvas = MapCanvas(mapVM, editorStateVM, painter) @@ -33,7 +33,7 @@ class MapPane( mapVM.item.columnsProperty.addListener { _, _, _ -> render() } editorStateVM.showGridProperty.addListener { _, _, _ -> render() } - editorStateVM.selectedLayerProperty.addListener { _, _, _ -> render() } + editorStateVM.selectedLayerIndexProperty.addListener { _, _, _ -> render() } editorStateVM.coverUnderlyingLayersProperty.addListener { _, _, _ -> render() } render() diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt new file mode 100644 index 00000000..a4ff62f9 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt @@ -0,0 +1,15 @@ +package com.bartlomiejpluta.base.editor.map.model.layer + +import javafx.beans.property.SimpleStringProperty +import tornadofx.getValue +import tornadofx.setValue + +class ImageLayer(name: String) : Layer { + override val nameProperty = SimpleStringProperty(name) + + override fun resize(rows: Int, columns: Int) { + // We essentially need to do nothing + } + + override var name by nameProperty +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt index 80e09f83..123dc395 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt @@ -10,8 +10,6 @@ interface Layer { fun resize(rows: Int, columns: Int) - fun clone(): Layer - companion object { fun extractor() = Callback> { arrayOf(it.nameProperty) } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ObjectLayer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ObjectLayer.kt new file mode 100644 index 00000000..c32ef90a --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ObjectLayer.kt @@ -0,0 +1,15 @@ +package com.bartlomiejpluta.base.editor.map.model.layer + +import javafx.beans.property.SimpleStringProperty +import tornadofx.getValue +import tornadofx.setValue + +class ObjectLayer(name: String) : Layer { + override val nameProperty = SimpleStringProperty(name) + + override fun resize(rows: Int, columns: Int) { + // We essentially need to do nothing + } + + override var name by nameProperty +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/TileLayer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/TileLayer.kt index 273eb3fe..bf7795ee 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/TileLayer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/TileLayer.kt @@ -24,8 +24,4 @@ class TileLayer( } } } - - override fun clone() = TileLayer(name, 0, 0).apply { - layer = this@TileLayer.layer - } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapFragment.kt index 9ebe07c4..2e2399a7 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapFragment.kt @@ -1,19 +1,29 @@ package com.bartlomiejpluta.base.editor.map.view.editor import com.bartlomiejpluta.base.editor.command.context.UndoableScope +import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer +import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.tileset.view.editor.TileSetView +import javafx.beans.binding.Bindings import tornadofx.* class MapFragment : Fragment() { override val scope = super.scope as UndoableScope + private val editorStateVM = find() + private val mapView = find() private val layersView = find() private val tileSetView = find() private val toolbarView = find() private val statusBarView = find() + private val isTileLayerSelected = Bindings.createBooleanBinding( + { editorStateVM.selectedLayer is TileLayer }, + editorStateVM.selectedLayerProperty + ) + override val root = borderpane { top = toolbarView.root @@ -25,6 +35,8 @@ class MapFragment : Fragment() { } item("Tile Set", expanded = true) { + enableWhen(isTileLayerSelected) + this += tileSetView.root.apply { maxHeightProperty().bind(this@item.heightProperty()) } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt index 9fe3b80c..95e6f372 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt @@ -7,11 +7,12 @@ 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.map.model.layer.ImageLayer 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.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM -import javafx.beans.value.ObservableValue import javafx.scene.control.ListCell import javafx.scene.control.ListView import javafx.scene.control.cell.TextFieldListCell @@ -40,28 +41,51 @@ class MapLayersView : View() { } } - editorStateVM.selectedLayerProperty.bind(selectionModel.selectedIndexProperty()) + editorStateVM.selectedLayerIndexProperty.bind(selectionModel.selectedIndexProperty()) + editorStateVM.selectedLayerProperty.bind(selectionModel.selectedItemProperty()) } override val root = borderpane { center = layersPane bottom = toolbar { - button(graphic = FontIcon("fa-plus")) { - action { - val tileLayer = TileLayer("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) + menubutton(graphic = FontIcon("fa-plus")) { + item("Tile Layer", graphic = FontIcon("fa-th")) { + action { + val layer = TileLayer("Layer ${mapVM.layers.size + 1}", mapVM.rows, mapVM.columns) + val command = CreateLayerCommand(mapVM.item, layer) + command.execute() + layersPane.selectionModel.select(mapVM.layers.size - 1) + undoRedoService.push(command, scope) + } + } + + item("Object Layer", graphic = FontIcon("fa-cube")) { + action { + val layer = ObjectLayer("Layer ${mapVM.layers.size + 1}") + val command = CreateLayerCommand(mapVM.item, layer) + command.execute() + layersPane.selectionModel.select(mapVM.layers.size - 1) + undoRedoService.push(command, scope) + } + } + + item("Image Layer", graphic = FontIcon("fa-image")) { + action { + val layer = ImageLayer("Layer ${mapVM.layers.size + 1}") + val command = CreateLayerCommand(mapVM.item, layer) + command.execute() + layersPane.selectionModel.select(mapVM.layers.size - 1) + undoRedoService.push(command, scope) + } } } button(graphic = FontIcon("fa-chevron-up")) { - enableWhen(editorStateVM.selectedLayerProperty.greaterThan(0)) + enableWhen(editorStateVM.selectedLayerIndexProperty.greaterThan(0)) action { - val newIndex = editorStateVM.selectedLayer - 1 - val command = MoveLayerCommand(mapVM.item, editorStateVM.selectedLayer, newIndex) + val newIndex = editorStateVM.selectedLayerIndex - 1 + val command = MoveLayerCommand(mapVM.item, editorStateVM.selectedLayerIndex, newIndex) command.execute() layersPane.selectionModel.select(newIndex) fire(RedrawMapRequestEvent) @@ -71,12 +95,12 @@ class MapLayersView : View() { button(graphic = FontIcon("fa-chevron-down")) { enableWhen( - editorStateVM.selectedLayerProperty.lessThan(mapVM.layers.sizeProperty().minus(1)) - .and(editorStateVM.selectedLayerProperty.greaterThanOrEqualTo(0)) + editorStateVM.selectedLayerIndexProperty.lessThan(mapVM.layers.sizeProperty().minus(1)) + .and(editorStateVM.selectedLayerIndexProperty.greaterThanOrEqualTo(0)) ) action { - val newIndex = editorStateVM.selectedLayer + 1 - val command = MoveLayerCommand(mapVM.item, editorStateVM.selectedLayer, newIndex) + val newIndex = editorStateVM.selectedLayerIndex + 1 + val command = MoveLayerCommand(mapVM.item, editorStateVM.selectedLayerIndex, newIndex) command.execute() layersPane.selectionModel.select(newIndex) fire(RedrawMapRequestEvent) @@ -85,9 +109,9 @@ class MapLayersView : View() { } button(graphic = FontIcon("fa-trash")) { - enableWhen(editorStateVM.selectedLayerProperty.greaterThanOrEqualTo(0)) + enableWhen(editorStateVM.selectedLayerIndexProperty.greaterThanOrEqualTo(0)) action { - var index = editorStateVM.selectedLayer + var index = editorStateVM.selectedLayerIndex val command = RemoveLayerCommand(mapVM.item, index) command.execute() @@ -138,6 +162,8 @@ class MapLayersView : View() { graphic = when (item) { is TileLayer -> FontIcon("fa-th") + is ObjectLayer -> FontIcon("fa-cube") + is ImageLayer -> FontIcon("fa-image") else -> throw IllegalStateException("Unknown layer type") } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/viewmodel/EditorStateVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/viewmodel/EditorStateVM.kt index bc1fa45b..9cd79882 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/viewmodel/EditorStateVM.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/viewmodel/EditorStateVM.kt @@ -1,14 +1,19 @@ package com.bartlomiejpluta.base.editor.map.viewmodel +import com.bartlomiejpluta.base.editor.map.model.layer.Layer import javafx.beans.property.SimpleBooleanProperty import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleIntegerProperty +import javafx.beans.property.SimpleObjectProperty import tornadofx.ViewModel import tornadofx.getValue import tornadofx.setValue class EditorStateVM : ViewModel() { - val selectedLayerProperty = SimpleIntegerProperty(0) + val selectedLayerIndexProperty = SimpleIntegerProperty(0) + var selectedLayerIndex by selectedLayerIndexProperty + + val selectedLayerProperty = SimpleObjectProperty() var selectedLayer by selectedLayerProperty val showGridProperty = SimpleBooleanProperty(true)