[Editor] Split MapFragment to single views
This commit is contained in:
@@ -1,23 +1,38 @@
|
||||
package com.bartlomiejpluta.base.editor.model.tileset
|
||||
|
||||
import com.bartlomiejpluta.base.editor.model.map.brush.Brush
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.image.PixelFormat
|
||||
import javafx.scene.image.WritableImage
|
||||
import tornadofx.getValue
|
||||
import tornadofx.toObservable
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
|
||||
class TileSet(private val image: Image, val rows: Int, val columns: Int) {
|
||||
val tileWidth = image.width.toInt() / columns
|
||||
val tileHeight = image.height.toInt() / rows
|
||||
val width = tileWidth * columns
|
||||
val height = tileHeight * rows
|
||||
class TileSet(private val image: Image, rows: Int, columns: Int) {
|
||||
val rowsProperty = SimpleIntegerProperty(rows)
|
||||
val rows by rowsProperty
|
||||
|
||||
val tiles: Array<Array<Tile>> =
|
||||
Array(rows) { row -> Array(columns) { column -> cropTile(row, column) } }
|
||||
val columnsProperty = SimpleIntegerProperty(columns)
|
||||
val columns by columnsProperty
|
||||
|
||||
val tileWidthProperty = SimpleIntegerProperty(image.width.toInt() / columns)
|
||||
val tileWidth by tileWidthProperty
|
||||
|
||||
val tileHeightProperty = SimpleIntegerProperty(image.height.toInt() / rows)
|
||||
val tileHeight by tileHeightProperty
|
||||
|
||||
val widthProperty = SimpleIntegerProperty(tileWidth * columns)
|
||||
val width by widthProperty
|
||||
|
||||
val heightProperty = SimpleIntegerProperty(tileHeight * rows)
|
||||
val height by heightProperty
|
||||
|
||||
val tiles = (0 until rows * columns).map { cropTile(it / columns, it % columns) }.toObservable()
|
||||
|
||||
val baseBrush: Brush
|
||||
get() = Brush(arrayOf(arrayOf(tiles[0][0])))
|
||||
get() = Brush(arrayOf(arrayOf(tiles[0])))
|
||||
|
||||
private fun cropTile(row: Int, column: Int): Tile {
|
||||
val reader = image.pixelReader
|
||||
@@ -38,7 +53,11 @@ class TileSet(private val image: Image, val rows: Int, val columns: Int) {
|
||||
return Tile(this, row, column, tile)
|
||||
}
|
||||
|
||||
fun getTile(row: Int, column: Int) = tiles[row.coerceIn(0 until rows)][column.coerceIn(0 until columns)]
|
||||
fun getTile(row: Int, column: Int) = tiles[(row.coerceIn(0 until rows)) * columns + column.coerceIn(0 until columns)]
|
||||
|
||||
fun getTile(id: Int) = tiles[id / columns][id % columns]
|
||||
fun getTile(id: Int) = tiles[id]
|
||||
|
||||
fun forEach(consumer: (row: Int, column: Int, tile: Tile) -> Unit) = tiles.forEachIndexed { id, tile ->
|
||||
consumer(id / columns, id % columns, tile)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.render.canvas.input
|
||||
|
||||
import com.bartlomiejpluta.base.editor.model.tileset.TileSet
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.event.EventType
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
@@ -8,7 +8,7 @@ import javafx.scene.input.MouseEvent
|
||||
class MapMouseEvent(val row: Int, val column: Int, val type: EventType<out MouseEvent>, val button: MouseButton) {
|
||||
|
||||
companion object {
|
||||
fun of(event: MouseEvent, tileSet: TileSet) = MapMouseEvent(
|
||||
fun of(event: MouseEvent, tileSet: TileSetVM) = MapMouseEvent(
|
||||
(event.y / tileSet.tileHeight).toInt(),
|
||||
(event.x / tileSet.tileWidth).toInt(),
|
||||
event.eventType,
|
||||
|
||||
@@ -6,19 +6,17 @@ import com.bartlomiejpluta.base.editor.render.canvas.input.MapMouseEventHandler
|
||||
import com.bartlomiejpluta.base.editor.render.model.Renderable
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import javafx.beans.property.IntegerProperty
|
||||
import javafx.scene.canvas.GraphicsContext
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
|
||||
class MapPainter(
|
||||
private val map: GameMapVM,
|
||||
private val mapVM: GameMapVM,
|
||||
private val brushVM: BrushVM,
|
||||
private val selectedLayer: IntegerProperty,
|
||||
private val paintingCallback: (MapPaintingTrace) -> Unit
|
||||
) : Renderable, MapMouseEventHandler {
|
||||
private val tileWidth = map.tileSet.tileWidth.toDouble()
|
||||
private val tileHeight = map.tileSet.tileHeight.toDouble()
|
||||
private val tileWidth = mapVM.tileSet.tileWidth.toDouble()
|
||||
private val tileHeight = mapVM.tileSet.tileHeight.toDouble()
|
||||
|
||||
private var mouseRow = -1
|
||||
private var mouseColumn = -1
|
||||
@@ -56,10 +54,10 @@ class MapPainter(
|
||||
|
||||
private fun beginTrace(event: MapMouseEvent) {
|
||||
if (event.button == MouseButton.PRIMARY) {
|
||||
currentTrace = MapPaintingTrace(map, "Paint trace").apply {
|
||||
currentTrace = MapPaintingTrace(mapVM, "Paint trace").apply {
|
||||
brushVM.forEach { row, column, tile ->
|
||||
paint(
|
||||
selectedLayer.value,
|
||||
map.selectedLayer,
|
||||
mouseRow - brushVM.centerRow + row,
|
||||
mouseColumn - brushVM.centerColumn + column,
|
||||
tile
|
||||
@@ -74,7 +72,7 @@ class MapPainter(
|
||||
currentTrace?.apply {
|
||||
brushVM.forEach { row, column, tile ->
|
||||
paint(
|
||||
selectedLayer.value,
|
||||
map.selectedLayer,
|
||||
mouseRow - brushVM.centerRow + row,
|
||||
mouseColumn - brushVM.centerColumn + column,
|
||||
tile
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package com.bartlomiejpluta.base.editor.render.canvas.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.MapMouseEventHandler
|
||||
import com.bartlomiejpluta.base.editor.render.model.Renderable
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.scene.canvas.GraphicsContext
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.paint.Color
|
||||
|
||||
class TileSetCanvas(private val tileSet: TileSet, brushVM: BrushVM) : Renderable, MapMouseEventHandler {
|
||||
private val tiles = tileSet.tiles
|
||||
private var selection = TileSetSelection(tileSet, brushVM)
|
||||
class TileSetCanvas(private val tileSetVM: TileSetVM, brushVM: BrushVM) : Renderable, MapMouseEventHandler {
|
||||
private var selection = TileSetSelection(tileSetVM, brushVM)
|
||||
|
||||
private var mouseRow = -1
|
||||
private var mouseColumn = -1
|
||||
@@ -20,22 +19,20 @@ class TileSetCanvas(private val tileSet: TileSet, brushVM: BrushVM) : Renderable
|
||||
override fun render(gc: GraphicsContext) {
|
||||
gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height)
|
||||
|
||||
renderTiles(gc)
|
||||
renderTiles(gc)
|
||||
selection.render(gc)
|
||||
}
|
||||
|
||||
private fun renderTiles(gc: GraphicsContext) {
|
||||
for ((row, columns) in tiles.withIndex()) {
|
||||
for ((column, tile) in columns.withIndex()) {
|
||||
gc.fill = if ((row + column) % 2 == 0) BACKGROUND_COLOR1 else BACKGROUND_COLOR2
|
||||
gc.fillRect(
|
||||
column * tile.image.width,
|
||||
row * tile.image.height,
|
||||
tileSet.tileWidth.toDouble(),
|
||||
tileSet.tileHeight.toDouble()
|
||||
)
|
||||
gc.drawImage(tile.image, column * tile.image.width, row * tile.image.height)
|
||||
}
|
||||
tileSetVM.forEach { row, column, tile ->
|
||||
gc.fill = if ((row + column) % 2 == 0) BACKGROUND_COLOR1 else BACKGROUND_COLOR2
|
||||
gc.fillRect(
|
||||
column * tile.image.width,
|
||||
row * tile.image.height,
|
||||
tileSetVM.tileWidth.toDouble(),
|
||||
tileSetVM.tileHeight.toDouble()
|
||||
)
|
||||
gc.drawImage(tile.image, column * tile.image.width, row * tile.image.height)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.bartlomiejpluta.base.editor.model.tileset.Tile
|
||||
import com.bartlomiejpluta.base.editor.model.tileset.TileSet
|
||||
import com.bartlomiejpluta.base.editor.render.model.Renderable
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.scene.canvas.GraphicsContext
|
||||
import javafx.scene.paint.Color
|
||||
import kotlin.math.abs
|
||||
@@ -12,21 +13,24 @@ import kotlin.math.min
|
||||
|
||||
|
||||
class TileSetSelection(
|
||||
private val tileSet: TileSet,
|
||||
private val tileSetVM: TileSetVM,
|
||||
private val brushVM: BrushVM
|
||||
) : Renderable {
|
||||
private val tileWidth = tileSet.tileWidth.toDouble()
|
||||
private val tileHeight = tileSet.tileHeight.toDouble()
|
||||
|
||||
private var startRow = 0.0
|
||||
private var startColumn = 0.0
|
||||
private var offsetRow = 0.0
|
||||
private var offsetColumn = 0.0
|
||||
private var x = 0.0
|
||||
private var y = 0.0
|
||||
private var width = tileWidth
|
||||
private var height = tileHeight
|
||||
private var width = 0.0
|
||||
private var height = 0.0
|
||||
|
||||
init {
|
||||
tileSetVM.itemProperty.addListener { _, _, tileSet ->
|
||||
width = tileSet.tileWidth.toDouble()
|
||||
height = tileSet.tileHeight.toDouble()
|
||||
}
|
||||
}
|
||||
|
||||
fun begin(row: Double, column: Double) {
|
||||
startRow = row
|
||||
@@ -38,10 +42,10 @@ class TileSetSelection(
|
||||
}
|
||||
|
||||
private fun updateRect(row: Double, column: Double) {
|
||||
x = min(column, startColumn) * tileWidth
|
||||
y = min(row, startRow) * tileHeight
|
||||
width = (offsetColumn + 1) * tileWidth
|
||||
height = (offsetRow + 1) * tileHeight
|
||||
x = min(column, startColumn) * tileSetVM.tileWidth
|
||||
y = min(row, startRow) * tileSetVM.tileHeight
|
||||
width = (offsetColumn + 1) * tileSetVM.tileWidth
|
||||
height = (offsetRow + 1) * tileSetVM.tileHeight
|
||||
}
|
||||
|
||||
fun proceed(row: Double, column: Double) {
|
||||
@@ -62,9 +66,9 @@ class TileSetSelection(
|
||||
val rows = offsetRow.toInt() + 1
|
||||
val columns = offsetColumn.toInt() + 1
|
||||
|
||||
var brushArray = Array<Array<Tile>>(rows) { rowIndex ->
|
||||
Array<Tile>(columns) { columnIndex ->
|
||||
tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex)
|
||||
val brushArray = Array(rows) { rowIndex ->
|
||||
Array(columns) { columnIndex ->
|
||||
tileSetVM.getTile(firstRow + rowIndex, firstColumn + columnIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,21 +6,20 @@ import com.bartlomiejpluta.base.editor.render.canvas.map.MapPainter
|
||||
import com.bartlomiejpluta.base.editor.render.canvas.map.MapPaintingTrace
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import javafx.beans.property.IntegerProperty
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.canvas.Canvas
|
||||
import javafx.scene.input.MouseEvent
|
||||
|
||||
|
||||
class MapPane(
|
||||
map: GameMapVM,
|
||||
mapVM: GameMapVM,
|
||||
private val tileSetVM: TileSetVM,
|
||||
brushVM: BrushVM,
|
||||
selectedLayer: IntegerProperty,
|
||||
paintingCallback: (MapPaintingTrace) -> Unit
|
||||
) : Canvas(), EventHandler<MouseEvent> {
|
||||
private var tileSet = map.tileSet
|
||||
private val painter = MapPainter(map, brushVM, selectedLayer, paintingCallback)
|
||||
private val mapCanvas = MapCanvas(map, painter)
|
||||
private val painter = MapPainter(mapVM, brushVM, paintingCallback)
|
||||
private val mapCanvas = MapCanvas(mapVM, painter)
|
||||
|
||||
init {
|
||||
onMouseMoved = this
|
||||
@@ -28,9 +27,8 @@ class MapPane(
|
||||
onMousePressed = this
|
||||
onMouseReleased = this
|
||||
|
||||
tileSet = map.tileSet
|
||||
width = map.width.toDouble()
|
||||
height = map.height.toDouble()
|
||||
width = mapVM.width.toDouble()
|
||||
height = mapVM.height.toDouble()
|
||||
render()
|
||||
}
|
||||
|
||||
@@ -41,7 +39,7 @@ class MapPane(
|
||||
|
||||
override fun handle(event: MouseEvent?) {
|
||||
if (event != null) {
|
||||
painter.handleMouseInput(MapMouseEvent.of(event, tileSet))
|
||||
painter.handleMouseInput(MapMouseEvent.of(event, tileSetVM))
|
||||
}
|
||||
|
||||
mapCanvas.render(graphicsContext2D)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.bartlomiejpluta.base.editor.view.component.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.tileset.TileSetCanvas
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.canvas.Canvas
|
||||
import javafx.scene.input.MouseEvent
|
||||
|
||||
class TileSetPane(private val tileSet: TileSet, brushVM: BrushVM) : Canvas(), EventHandler<MouseEvent> {
|
||||
private val tileSetCanvas = TileSetCanvas(tileSet, brushVM)
|
||||
class TileSetPane(private val tileSetVM: TileSetVM, brushVM: BrushVM) : Canvas(), EventHandler<MouseEvent> {
|
||||
private val tileSetCanvas = TileSetCanvas(tileSetVM, brushVM)
|
||||
|
||||
init {
|
||||
onMouseMoved = this
|
||||
@@ -17,19 +17,19 @@ class TileSetPane(private val tileSet: TileSet, brushVM: BrushVM) : Canvas(), Ev
|
||||
onMousePressed = this
|
||||
onMouseReleased = this
|
||||
|
||||
width = tileSet.width.toDouble()
|
||||
height = tileSet.height.toDouble()
|
||||
widthProperty().bind(tileSetVM.widthProperty)
|
||||
heightProperty().bind(tileSetVM.heightProperty)
|
||||
|
||||
render()
|
||||
tileSetVM.itemProperty.addListener { _, _, _ -> render() }
|
||||
}
|
||||
|
||||
fun render() {
|
||||
private fun render() {
|
||||
tileSetCanvas.render(graphicsContext2D)
|
||||
}
|
||||
|
||||
override fun handle(event: MouseEvent?) {
|
||||
if (event != null) {
|
||||
tileSetCanvas.handleMouseInput(MapMouseEvent.of(event, tileSet))
|
||||
tileSetCanvas.handleMouseInput(MapMouseEvent.of(event, tileSetVM))
|
||||
}
|
||||
|
||||
tileSetCanvas.render(graphicsContext2D)
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.view.fragment
|
||||
|
||||
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.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.view.component.map.MapPane
|
||||
import com.bartlomiejpluta.base.editor.view.component.tileset.TileSetPane
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import javafx.beans.property.SimpleDoubleProperty
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.scene.control.TableView
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.transform.Scale
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
|
||||
|
||||
class MapFragment : Fragment() {
|
||||
private val undoRedoService: UndoRedoService by di()
|
||||
|
||||
val map: GameMap by param()
|
||||
|
||||
private val brushVM = find<BrushVM>().apply { item = map.tileSet.baseBrush }
|
||||
private val mapVM = find<GameMapVM>().apply { item = map }
|
||||
|
||||
val scaleProperty = SimpleDoubleProperty(1.0)
|
||||
|
||||
private val selectedLayer = SimpleIntegerProperty(0)
|
||||
|
||||
private val mapPane = MapPane(mapVM, brushVM, selectedLayer) { undoRedoService.push(it) }
|
||||
private val tileSetPane = TileSetPane(map.tileSet, brushVM)
|
||||
private var layersPane: TableView<Layer> by singleAssign()
|
||||
|
||||
private val transformation = Scale(1.0, 1.0, 0.0, 0.0).apply {
|
||||
xProperty().bind(scaleProperty)
|
||||
yProperty().bind(scaleProperty)
|
||||
}
|
||||
|
||||
init {
|
||||
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
center = scrollpane {
|
||||
prefWidth = 640.0
|
||||
prefHeight = 480.0
|
||||
isPannable = true
|
||||
|
||||
group {
|
||||
|
||||
// Let the ScrollPane.viewRect only pan on middle button.
|
||||
addEventHandler(MouseEvent.ANY) {
|
||||
if (it.button != MouseButton.MIDDLE) {
|
||||
it.consume()
|
||||
}
|
||||
}
|
||||
|
||||
group {
|
||||
this += mapPane
|
||||
transforms += transformation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
right = drawer(multiselect = true) {
|
||||
item("Layers", expanded = true) {
|
||||
borderpane {
|
||||
layersPane = tableview(mapVM.layers) {
|
||||
column("Layer Name", Layer::nameProperty).makeEditable()
|
||||
|
||||
selectedLayer.bind(selectionModel.selectedIndexProperty())
|
||||
}
|
||||
|
||||
center = layersPane
|
||||
|
||||
bottom = toolbar {
|
||||
button(graphic = FontIcon("fa-plus")) {
|
||||
action {
|
||||
mapVM.item.createTileLayer("Layer ${mapVM.layers.size + 1}")
|
||||
layersPane.selectionModel.select(mapVM.layers.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-chevron-up")) {
|
||||
enableWhen(selectedLayer.greaterThan(0))
|
||||
action {
|
||||
val newIndex = selectedLayer.value - 1
|
||||
mapVM.layers.swap(selectedLayer.value, newIndex)
|
||||
layersPane.selectionModel.select(newIndex)
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-chevron-down")) {
|
||||
enableWhen(
|
||||
selectedLayer.lessThan(mapVM.layers.sizeProperty().minus(1))
|
||||
.and(selectedLayer.greaterThanOrEqualTo(0))
|
||||
)
|
||||
action {
|
||||
val newIndex = selectedLayer.value + 1
|
||||
mapVM.layers.swap(selectedLayer.value, newIndex)
|
||||
layersPane.selectionModel.select(newIndex)
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-trash")) {
|
||||
enableWhen(selectedLayer.greaterThanOrEqualTo(0))
|
||||
action {
|
||||
var index = selectedLayer.value
|
||||
mapVM.layers.removeAt(index)
|
||||
|
||||
if (--index >= 0) {
|
||||
layersPane.selectionModel.select(index)
|
||||
}
|
||||
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item("Tile Set", expanded = true) {
|
||||
scrollpane {
|
||||
maxHeightProperty().bind(this@item.heightProperty())
|
||||
this += tileSetPane
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,7 @@ package com.bartlomiejpluta.base.editor.view.main
|
||||
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
|
||||
import com.bartlomiejpluta.base.editor.controller.map.MapController
|
||||
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
|
||||
import com.bartlomiejpluta.base.editor.view.fragment.MapFragment
|
||||
import javafx.beans.property.SimpleDoubleProperty
|
||||
import com.bartlomiejpluta.base.editor.view.map.MapFragment
|
||||
import javafx.scene.control.TabPane
|
||||
import tornadofx.*
|
||||
|
||||
@@ -14,8 +13,6 @@ class MainView : View() {
|
||||
private val mapController: MapController by di()
|
||||
private val tabPane = TabPane()
|
||||
|
||||
private val mapScale = SimpleDoubleProperty(1.0)
|
||||
|
||||
override val root = borderpane {
|
||||
top = hbox {
|
||||
button("Map 1") {
|
||||
@@ -23,7 +20,6 @@ class MainView : View() {
|
||||
val map = mapController.getMap(1)
|
||||
tabPane += find<MapFragment>(Scope(), MapFragment::map to map).apply {
|
||||
title = "Map 1"
|
||||
scaleProperty.bind(mapScale)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,23 +29,10 @@ class MainView : View() {
|
||||
val map = mapController.getMap(2)
|
||||
tabPane += find<MapFragment>(Scope(), MapFragment::map to map).apply {
|
||||
title = "Map 2"
|
||||
scaleProperty.bind(mapScale)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button("+") {
|
||||
action {
|
||||
mapScale.value += 0.1
|
||||
}
|
||||
}
|
||||
|
||||
button("-") {
|
||||
action {
|
||||
mapScale.value -= 0.1
|
||||
}
|
||||
}
|
||||
|
||||
button("Undo") {
|
||||
action {
|
||||
undoRedoService.undo()
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.bartlomiejpluta.base.editor.view.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.model.map.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import tornadofx.*
|
||||
|
||||
|
||||
class MapFragment : Fragment() {
|
||||
val map: GameMap by param()
|
||||
|
||||
private val mapVM = find<GameMapVM>().apply { item = map }
|
||||
|
||||
private val mapView = find<MapView>()
|
||||
private val layersView = find<MapLayersView>()
|
||||
private val tileSetView = find<TileSetView>()
|
||||
|
||||
|
||||
override val root = borderpane {
|
||||
center = mapView.root
|
||||
|
||||
right = drawer(multiselect = true) {
|
||||
item("Layers", expanded = true) {
|
||||
this += layersView.root
|
||||
}
|
||||
|
||||
item("Tile Set", expanded = true) {
|
||||
this += tileSetView.root.apply {
|
||||
maxHeightProperty().bind(this@item.heightProperty())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.bartlomiejpluta.base.editor.view.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
|
||||
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import javafx.scene.control.TableView
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
|
||||
class MapLayersView : View() {
|
||||
private val mapVM = find<GameMapVM>()
|
||||
|
||||
private var layersPane = TableView(mapVM.layers).apply {
|
||||
column("Layer Name", Layer::nameProperty).makeEditable()
|
||||
|
||||
mapVM.selectedLayerProperty.bind(selectionModel.selectedIndexProperty())
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
center = layersPane
|
||||
|
||||
bottom = toolbar {
|
||||
button(graphic = FontIcon("fa-plus")) {
|
||||
action {
|
||||
mapVM.item.createTileLayer("Layer ${mapVM.layers.size + 1}")
|
||||
layersPane.selectionModel.select(mapVM.layers.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-chevron-up")) {
|
||||
enableWhen(mapVM.selectedLayerProperty.greaterThan(0))
|
||||
action {
|
||||
val newIndex = mapVM.selectedLayer - 1
|
||||
mapVM.layers.swap(mapVM.selectedLayer, newIndex)
|
||||
layersPane.selectionModel.select(newIndex)
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-chevron-down")) {
|
||||
enableWhen(
|
||||
mapVM.selectedLayerProperty.lessThan(mapVM.layers.sizeProperty().minus(1))
|
||||
.and(mapVM.selectedLayerProperty.greaterThanOrEqualTo(0))
|
||||
)
|
||||
action {
|
||||
val newIndex = mapVM.selectedLayer + 1
|
||||
mapVM.layers.swap(mapVM.selectedLayer, newIndex)
|
||||
layersPane.selectionModel.select(newIndex)
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-trash")) {
|
||||
enableWhen(mapVM.selectedLayerProperty.greaterThanOrEqualTo(0))
|
||||
action {
|
||||
var index = mapVM.selectedLayer
|
||||
mapVM.layers.removeAt(index)
|
||||
|
||||
if (--index >= 0) {
|
||||
layersPane.selectionModel.select(index)
|
||||
}
|
||||
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
editor/src/main/kotlin/com/bartlomiejpluta/base/editor/view/map/MapView.kt
Executable file
60
editor/src/main/kotlin/com/bartlomiejpluta/base/editor/view/map/MapView.kt
Executable file
@@ -0,0 +1,60 @@
|
||||
package com.bartlomiejpluta.base.editor.view.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
|
||||
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
|
||||
import com.bartlomiejpluta.base.editor.view.component.map.MapPane
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import javafx.beans.property.SimpleDoubleProperty
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.transform.Scale
|
||||
import tornadofx.View
|
||||
import tornadofx.group
|
||||
import tornadofx.plusAssign
|
||||
import tornadofx.scrollpane
|
||||
|
||||
|
||||
class MapView : View() {
|
||||
private val undoRedoService: UndoRedoService by di()
|
||||
|
||||
val zoomProperty = SimpleDoubleProperty(1.0)
|
||||
private val zoom = Scale(1.0, 1.0, 0.0, 0.0).apply {
|
||||
xProperty().bind(zoomProperty)
|
||||
yProperty().bind(zoomProperty)
|
||||
}
|
||||
|
||||
private val mapVM = find<GameMapVM>()
|
||||
private val brushVM = find<BrushVM>()
|
||||
private val tileSetVM = find<TileSetVM>()
|
||||
|
||||
private val mapPane = MapPane(mapVM, tileSetVM, brushVM) { undoRedoService.push(it) }
|
||||
|
||||
init {
|
||||
brushVM.item = mapVM.tileSet.baseBrush
|
||||
|
||||
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
||||
}
|
||||
|
||||
override val root = scrollpane {
|
||||
prefWidth = 640.0
|
||||
prefHeight = 480.0
|
||||
isPannable = true
|
||||
|
||||
group {
|
||||
|
||||
// Let the ScrollPane.viewRect only pan on middle button.
|
||||
addEventHandler(MouseEvent.ANY) {
|
||||
if (it.button != MouseButton.MIDDLE) {
|
||||
it.consume()
|
||||
}
|
||||
}
|
||||
|
||||
group {
|
||||
this += mapPane
|
||||
transforms += zoom
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.bartlomiejpluta.base.editor.view.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.view.component.tileset.TileSetPane
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.viewmodel.map.TileSetVM
|
||||
import tornadofx.View
|
||||
import tornadofx.plusAssign
|
||||
import tornadofx.scrollpane
|
||||
|
||||
class TileSetView : View() {
|
||||
private val gameMapVM = find<GameMapVM>()
|
||||
private val tileSetVM = find<TileSetVM>()
|
||||
private val brushVM = find<BrushVM>()
|
||||
|
||||
private val tileSetPane = TileSetPane(tileSetVM, brushVM)
|
||||
|
||||
init {
|
||||
tileSetVM.itemProperty.bind(gameMapVM.tileSetProperty)
|
||||
}
|
||||
|
||||
override val root = scrollpane {
|
||||
this += tileSetPane
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.viewmodel.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.model.map.layer.Layer
|
||||
import com.bartlomiejpluta.base.editor.model.map.map.GameMap
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.beans.property.SimpleListProperty
|
||||
import tornadofx.ItemViewModel
|
||||
import tornadofx.getValue
|
||||
@@ -23,6 +24,9 @@ class GameMapVM : ItemViewModel<GameMap>() {
|
||||
|
||||
val heightProperty = bind(GameMap::height)
|
||||
val height by heightProperty
|
||||
|
||||
val selectedLayerProperty = SimpleIntegerProperty(0)
|
||||
val selectedLayer by selectedLayerProperty
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.bartlomiejpluta.base.editor.viewmodel.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.model.tileset.Tile
|
||||
import com.bartlomiejpluta.base.editor.model.tileset.TileSet
|
||||
import javafx.collections.ObservableList
|
||||
import tornadofx.*
|
||||
|
||||
class TileSetVM : ItemViewModel<TileSet>() {
|
||||
val rowsProperty = bind(TileSet::rowsProperty)
|
||||
val rows by rowsProperty
|
||||
|
||||
val columnsProperty = bind(TileSet::columnsProperty)
|
||||
val columns by columnsProperty
|
||||
|
||||
val tileWidthProperty = bind(TileSet::tileWidthProperty)
|
||||
val tileWidth by tileWidthProperty
|
||||
|
||||
val tileHeightProperty = bind(TileSet::tileHeightProperty)
|
||||
val tileHeight by tileHeightProperty
|
||||
|
||||
val widthProperty = bind(TileSet::widthProperty)
|
||||
val width by widthProperty
|
||||
|
||||
val heightProperty = bind(TileSet::heightProperty)
|
||||
val height by heightProperty
|
||||
|
||||
val tiles: ObservableList<Tile> = bind(TileSet::tiles)
|
||||
|
||||
fun getTile(row: Int, column: Int) = item.getTile(row, column)
|
||||
|
||||
fun getTile(id: Int) = item.getTile(id)
|
||||
|
||||
fun forEach(consumer: (row: Int, column: Int, tile: Tile) -> Unit) = item.forEach(consumer)
|
||||
}
|
||||
Reference in New Issue
Block a user