[Editor] Create scaffolding for creating objects in ObjectLayer
This commit is contained in:
@@ -19,6 +19,9 @@ class ImagePositionPaintingTrace(val map: GameMapVM, override val commandName: S
|
|||||||
private var newY = 0.0
|
private var newY = 0.0
|
||||||
private lateinit var layer: ImageLayer
|
private lateinit var layer: ImageLayer
|
||||||
|
|
||||||
|
override var executed = false
|
||||||
|
private set
|
||||||
|
|
||||||
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
this.layerIndex = editorStateVM.selectedLayerIndex
|
this.layerIndex = editorStateVM.selectedLayerIndex
|
||||||
|
|
||||||
@@ -44,6 +47,10 @@ class ImagePositionPaintingTrace(val map: GameMapVM, override val commandName: S
|
|||||||
|
|
||||||
layer.x = newX.toInt()
|
layer.x = newX.toInt()
|
||||||
layer.y = newY.toInt()
|
layer.y = newY.toInt()
|
||||||
|
|
||||||
|
if (dx != 0.0 || dy != 0.0) {
|
||||||
|
executed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
@@ -55,6 +62,10 @@ class ImagePositionPaintingTrace(val map: GameMapVM, override val commandName: S
|
|||||||
|
|
||||||
layer.x = newX.toInt()
|
layer.x = newX.toInt()
|
||||||
layer.y = newY.toInt()
|
layer.y = newY.toInt()
|
||||||
|
|
||||||
|
if (dx != 0.0 || dy != 0.0) {
|
||||||
|
executed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun undo() {
|
override fun undo() {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
|||||||
private fun dispatchLayerRender(gc: GraphicsContext, layer: Layer) {
|
private fun dispatchLayerRender(gc: GraphicsContext, layer: Layer) {
|
||||||
when (layer) {
|
when (layer) {
|
||||||
is TileLayer -> renderTileLayer(gc, layer)
|
is TileLayer -> renderTileLayer(gc, layer)
|
||||||
is ObjectLayer -> renderObjectPassageMap(gc, layer)
|
is ObjectLayer -> renderObjectLayer(gc, layer)
|
||||||
is ColorLayer -> renderColorLayer(gc, layer)
|
is ColorLayer -> renderColorLayer(gc, layer)
|
||||||
is ImageLayer -> renderImageLayer(gc, layer)
|
is ImageLayer -> renderImageLayer(gc, layer)
|
||||||
}
|
}
|
||||||
@@ -120,11 +120,16 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderObjectPassageMap(gc: GraphicsContext, objectLayer: ObjectLayer) {
|
private fun renderObjectLayer(gc: GraphicsContext, objectLayer: ObjectLayer) {
|
||||||
if (editorStateVM.selectedLayer !is ObjectLayer) {
|
if (editorStateVM.selectedLayer !is ObjectLayer) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderObjectPassageMap(gc, objectLayer)
|
||||||
|
renderObjects(gc, objectLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderObjectPassageMap(gc: GraphicsContext, objectLayer: ObjectLayer) {
|
||||||
for ((row, columns) in objectLayer.passageMap.withIndex()) {
|
for ((row, columns) in objectLayer.passageMap.withIndex()) {
|
||||||
for ((column, passage) in columns.withIndex()) {
|
for ((column, passage) in columns.withIndex()) {
|
||||||
PassageAbilitySymbol.render(gc, column * tileWidth, row * tileHeight, tileWidth, tileHeight, passage)
|
PassageAbilitySymbol.render(gc, column * tileWidth, row * tileHeight, tileWidth, tileHeight, passage)
|
||||||
@@ -132,6 +137,26 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderObjects(gc: GraphicsContext, objectLayer: ObjectLayer) {
|
||||||
|
for (mapObject in objectLayer.objects) {
|
||||||
|
val alpha = gc.globalAlpha
|
||||||
|
val fill = gc.fill
|
||||||
|
|
||||||
|
gc.globalAlpha = 0.6
|
||||||
|
gc.fill = OBJECT_COLOR
|
||||||
|
|
||||||
|
gc.fillOval(
|
||||||
|
mapObject.x * tileWidth + OBJECT_MARGIN,
|
||||||
|
mapObject.y * tileHeight + OBJECT_MARGIN,
|
||||||
|
tileWidth - 2 * OBJECT_MARGIN,
|
||||||
|
tileHeight - 2 * OBJECT_MARGIN
|
||||||
|
)
|
||||||
|
|
||||||
|
gc.globalAlpha = alpha
|
||||||
|
gc.fill = fill
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun renderColorLayer(gc: GraphicsContext, colorLayer: ColorLayer) {
|
private fun renderColorLayer(gc: GraphicsContext, colorLayer: ColorLayer) {
|
||||||
val alpha = gc.globalAlpha
|
val alpha = gc.globalAlpha
|
||||||
val color = gc.fill
|
val color = gc.fill
|
||||||
@@ -172,5 +197,8 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
|||||||
companion object {
|
companion object {
|
||||||
private val BACKGROUND_COLOR1 = Color.color(1.0, 1.0, 1.0, 1.0)
|
private val BACKGROUND_COLOR1 = Color.color(1.0, 1.0, 1.0, 1.0)
|
||||||
private val BACKGROUND_COLOR2 = Color.color(0.8, 0.8, 0.8, 1.0)
|
private val BACKGROUND_COLOR2 = Color.color(0.8, 0.8, 0.8, 1.0)
|
||||||
|
|
||||||
|
private val OBJECT_COLOR = Color.WHITE
|
||||||
|
private const val OBJECT_MARGIN = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bartlomiejpluta.base.editor.map.canvas
|
package com.bartlomiejpluta.base.editor.map.canvas
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushTool
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.ImageLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.ImageLayer
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||||
@@ -25,12 +26,18 @@ class MapPainter(
|
|||||||
private var currentTrace: PaintingTrace? = null
|
private var currentTrace: PaintingTrace? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
editorStateVM.selectedLayerProperty.addListener { _, _, layer ->
|
editorStateVM.selectedLayerProperty.addListener { _, _, _ -> updateCursor() }
|
||||||
cursor = when (layer) {
|
brushVM.toolProperty.addListener { _, _, _ -> updateCursor() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCursor() {
|
||||||
|
cursor = when (editorStateVM.selectedLayer) {
|
||||||
is TileLayer -> TilePaintingCursor(tileWidth, tileHeight, editorStateVM, brushVM)
|
is TileLayer -> TilePaintingCursor(tileWidth, tileHeight, editorStateVM, brushVM)
|
||||||
is ObjectLayer -> ObjectPaintingCursor(tileWidth, tileHeight, editorStateVM, brushVM)
|
is ObjectLayer -> when (brushVM.tool) {
|
||||||
|
BrushTool.PASSAGE -> PassageAbilityPaintingCursor(tileWidth, tileHeight, editorStateVM, brushVM)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +65,10 @@ class MapPainter(
|
|||||||
if (currentTrace == null && editorStateVM.selectedLayerIndex >= 0) {
|
if (currentTrace == null && editorStateVM.selectedLayerIndex >= 0) {
|
||||||
currentTrace = when (editorStateVM.selectedLayer) {
|
currentTrace = when (editorStateVM.selectedLayer) {
|
||||||
is TileLayer -> TilePaintingTrace(mapVM, "Paint trace")
|
is TileLayer -> TilePaintingTrace(mapVM, "Paint trace")
|
||||||
is ObjectLayer -> ObjectPaintingTrace(mapVM, "Toggle passage")
|
is ObjectLayer -> when (brushVM.tool) {
|
||||||
|
BrushTool.DEFAULT -> ObjectPaintingTrace(mapVM, "Update object")
|
||||||
|
else -> PassageAbilityPaintingTrace(mapVM, "Toggle passage")
|
||||||
|
}
|
||||||
is ImageLayer -> ImagePositionPaintingTrace(mapVM, "Move Image Layer")
|
is ImageLayer -> ImagePositionPaintingTrace(mapVM, "Move Image Layer")
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +1,108 @@
|
|||||||
package com.bartlomiejpluta.base.editor.map.canvas
|
package com.bartlomiejpluta.base.editor.map.canvas
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
||||||
import com.bartlomiejpluta.base.editor.map.model.enumeration.PassageAbility
|
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.obj.MapObject
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||||
import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent
|
import com.bartlomiejpluta.base.editor.render.input.MapMouseEvent
|
||||||
|
import javafx.collections.ObservableList
|
||||||
import javafx.scene.input.MouseButton
|
import javafx.scene.input.MouseButton
|
||||||
|
|
||||||
class ObjectPaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace {
|
class ObjectPaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace {
|
||||||
private val trace = mutableListOf<Element>()
|
private lateinit var objects: ObservableList<MapObject>
|
||||||
|
private lateinit var event: MapMouseEvent
|
||||||
|
|
||||||
private fun paint(layerIndex: Int, row: Int, column: Int, passageAbility: PassageAbility) {
|
private var newObject: MapObject? = null
|
||||||
if (row >= map.rows || column >= map.columns || row < 0 || column < 0 || layerIndex < 0) {
|
private var formerObject: MapObject? = null
|
||||||
return
|
private var x = 0
|
||||||
}
|
private var y = 0
|
||||||
|
|
||||||
val passageMap = (map.layers[layerIndex] as ObjectLayer).passageMap
|
override var executed = false
|
||||||
val formerPassageAbility = passageMap[row][column]
|
private set
|
||||||
|
|
||||||
if (trace.isEmpty()) {
|
|
||||||
trace += Element(layerIndex, row, column, formerPassageAbility, passageAbility)
|
|
||||||
passageMap[row][column] = passageAbility
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val tileAlreadyPainted =
|
|
||||||
trace.find { it.layerIndex == layerIndex && it.row == row && it.column == column } != null
|
|
||||||
|
|
||||||
if (!tileAlreadyPainted) {
|
|
||||||
trace += Element(layerIndex, row, column, formerPassageAbility, passageAbility)
|
|
||||||
passageMap[row][column] = passageAbility
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
|
x = editorStateVM.cursorColumn
|
||||||
paint(
|
y = editorStateVM.cursorRow
|
||||||
editorStateVM.selectedLayerIndex,
|
|
||||||
editorStateVM.cursorRow - centerRow + row,
|
if (y >= map.rows || x >= map.columns || y < 0 || x < 0 || editorStateVM.selectedLayerIndex < 0) {
|
||||||
editorStateVM.cursorColumn - centerColumn + column,
|
return
|
||||||
when {
|
|
||||||
brushVM.mode == BrushMode.ERASING_MODE -> PassageAbility.ALLOW
|
|
||||||
mouseEvent.button == MouseButton.PRIMARY -> PassageAbility.BLOCK
|
|
||||||
else -> PassageAbility.ALLOW
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
objects = (editorStateVM.selectedLayer as ObjectLayer).objects
|
||||||
|
formerObject = objects.firstOrNull { it.x == x && it.y == y }
|
||||||
|
|
||||||
|
event = mouseEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createOrUpdateObject() {
|
||||||
|
newObject = MapObject(x, y, "")
|
||||||
|
objects.remove(formerObject)
|
||||||
|
objects.add(newObject)
|
||||||
|
executed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun moveObject(newX: Int, newY: Int) {
|
||||||
|
if (newY >= map.rows || newX >= map.columns || newY < 0 || newX < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
formerObject?.let {
|
||||||
|
newObject = MapObject(newX, newY, it.code)
|
||||||
|
objects.remove(formerObject)
|
||||||
|
objects.add(newObject)
|
||||||
|
executed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeObject() {
|
||||||
|
objects.remove(formerObject)
|
||||||
|
executed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
|
|
||||||
paint(
|
|
||||||
editorStateVM.selectedLayerIndex,
|
|
||||||
editorStateVM.cursorRow - centerRow + row,
|
|
||||||
editorStateVM.cursorColumn - centerColumn + column,
|
|
||||||
when {
|
|
||||||
brushVM.mode == BrushMode.ERASING_MODE -> PassageAbility.ALLOW
|
|
||||||
mouseEvent.button == MouseButton.PRIMARY -> PassageAbility.BLOCK
|
|
||||||
else -> PassageAbility.ALLOW
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
|
val newX = editorStateVM.cursorColumn
|
||||||
|
val newY = editorStateVM.cursorRow
|
||||||
|
val dx = newX - x
|
||||||
|
val dy = newY - y
|
||||||
|
|
||||||
|
// Moving
|
||||||
|
if (brushVM.mode == BrushMode.PAINTING_MODE && (dx != 0 || dy != 0)) {
|
||||||
|
moveObject(newX, newY)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating new or updating existing one or removing
|
||||||
|
if (event.event.clickCount > 1 && brushVM.mode == BrushMode.PAINTING_MODE) {
|
||||||
|
when (event.button) {
|
||||||
|
MouseButton.PRIMARY -> createOrUpdateObject()
|
||||||
|
MouseButton.SECONDARY -> removeObject()
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removing
|
||||||
|
if (brushVM.mode == BrushMode.ERASING_MODE) {
|
||||||
|
removeObject()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun undo() {
|
override fun undo() {
|
||||||
trace.forEach {
|
objects.remove(newObject)
|
||||||
(map.layers[it.layerIndex] as ObjectLayer).passageMap[it.row][it.column] = it.formerPassageAbility
|
formerObject?.let(objects::add)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun redo() {
|
override fun redo() {
|
||||||
trace.forEach {
|
objects.remove(formerObject)
|
||||||
(map.layers[it.layerIndex] as ObjectLayer).passageMap[it.row][it.column] = it.passageAbility
|
newObject?.let(objects::add)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val supportedButtons = arrayOf(MouseButton.PRIMARY, MouseButton.SECONDARY)
|
override val supportedButtons = arrayOf(MouseButton.PRIMARY, MouseButton.SECONDARY)
|
||||||
|
|
||||||
companion object {
|
|
||||||
private data class Element(
|
|
||||||
val layerIndex: Int,
|
|
||||||
val row: Int,
|
|
||||||
val column: Int,
|
|
||||||
val formerPassageAbility: PassageAbility,
|
|
||||||
val passageAbility: PassageAbility
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -12,4 +12,6 @@ interface PaintingTrace : Undoable {
|
|||||||
fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent)
|
fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent)
|
||||||
|
|
||||||
val supportedButtons: Array<MouseButton>
|
val supportedButtons: Array<MouseButton>
|
||||||
|
|
||||||
|
val executed: Boolean
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
|||||||
import javafx.scene.canvas.GraphicsContext
|
import javafx.scene.canvas.GraphicsContext
|
||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
|
|
||||||
class ObjectPaintingCursor(
|
class PassageAbilityPaintingCursor(
|
||||||
private val tileWidth: Double,
|
private val tileWidth: Double,
|
||||||
private val tileHeight: Double,
|
private val tileHeight: Double,
|
||||||
private val editorStateVM: EditorStateVM,
|
private val editorStateVM: EditorStateVM,
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.bartlomiejpluta.base.editor.map.canvas
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.enumeration.PassageAbility
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
||||||
|
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.scene.input.MouseButton
|
||||||
|
|
||||||
|
class PassageAbilityPaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace {
|
||||||
|
private val trace = mutableListOf<Element>()
|
||||||
|
|
||||||
|
override var executed = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
private fun paint(layerIndex: Int, row: Int, column: Int, passageAbility: PassageAbility) {
|
||||||
|
if (row >= map.rows || column >= map.columns || row < 0 || column < 0 || layerIndex < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val passageMap = (map.layers[layerIndex] as ObjectLayer).passageMap
|
||||||
|
val formerPassageAbility = passageMap[row][column]
|
||||||
|
|
||||||
|
if (trace.isEmpty()) {
|
||||||
|
trace += Element(layerIndex, row, column, formerPassageAbility, passageAbility)
|
||||||
|
passageMap[row][column] = passageAbility
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val tileAlreadyPainted =
|
||||||
|
trace.find { it.layerIndex == layerIndex && it.row == row && it.column == column } != null
|
||||||
|
|
||||||
|
if (!tileAlreadyPainted) {
|
||||||
|
trace += Element(layerIndex, row, column, formerPassageAbility, passageAbility)
|
||||||
|
passageMap[row][column] = passageAbility
|
||||||
|
executed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beginTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
|
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
|
||||||
|
paint(
|
||||||
|
editorStateVM.selectedLayerIndex,
|
||||||
|
editorStateVM.cursorRow - centerRow + row,
|
||||||
|
editorStateVM.cursorColumn - centerColumn + column,
|
||||||
|
when {
|
||||||
|
brushVM.mode == BrushMode.ERASING_MODE -> PassageAbility.ALLOW
|
||||||
|
mouseEvent.button == MouseButton.PRIMARY -> PassageAbility.BLOCK
|
||||||
|
else -> PassageAbility.ALLOW
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun proceedTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
|
brushVM.forEach { row, column, centerRow, centerColumn, _ ->
|
||||||
|
paint(
|
||||||
|
editorStateVM.selectedLayerIndex,
|
||||||
|
editorStateVM.cursorRow - centerRow + row,
|
||||||
|
editorStateVM.cursorColumn - centerColumn + column,
|
||||||
|
when {
|
||||||
|
brushVM.mode == BrushMode.ERASING_MODE -> PassageAbility.ALLOW
|
||||||
|
mouseEvent.button == MouseButton.PRIMARY -> PassageAbility.BLOCK
|
||||||
|
else -> PassageAbility.ALLOW
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun commitTrace(editorStateVM: EditorStateVM, brushVM: BrushVM, mouseEvent: MapMouseEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun undo() {
|
||||||
|
trace.forEach {
|
||||||
|
(map.layers[it.layerIndex] as ObjectLayer).passageMap[it.row][it.column] = it.formerPassageAbility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun redo() {
|
||||||
|
trace.forEach {
|
||||||
|
(map.layers[it.layerIndex] as ObjectLayer).passageMap[it.row][it.column] = it.passageAbility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val supportedButtons = arrayOf(MouseButton.PRIMARY, MouseButton.SECONDARY)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private data class Element(
|
||||||
|
val layerIndex: Int,
|
||||||
|
val row: Int,
|
||||||
|
val column: Int,
|
||||||
|
val formerPassageAbility: PassageAbility,
|
||||||
|
val passageAbility: PassageAbility
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,9 @@ import javafx.scene.input.MouseButton
|
|||||||
data class TilePaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace {
|
data class TilePaintingTrace(val map: GameMapVM, override val commandName: String) : PaintingTrace {
|
||||||
private val trace = mutableListOf<Element>()
|
private val trace = mutableListOf<Element>()
|
||||||
|
|
||||||
|
override var executed = false
|
||||||
|
private set
|
||||||
|
|
||||||
private 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) {
|
if (row >= map.rows || column >= map.columns || row < 0 || column < 0 || layerIndex < 0) {
|
||||||
return
|
return
|
||||||
@@ -32,6 +35,7 @@ data class TilePaintingTrace(val map: GameMapVM, override val commandName: Strin
|
|||||||
if (!tileAlreadyPainted) {
|
if (!tileAlreadyPainted) {
|
||||||
trace += Element(layerIndex, row, column, formerTile, tile)
|
trace += Element(layerIndex, row, column, formerTile, tile)
|
||||||
layer[row][column] = tile
|
layer[row][column] = tile
|
||||||
|
executed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class Brush {
|
|||||||
var mode by modeProperty
|
var mode by modeProperty
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
val toolProperty = SimpleObjectProperty(BrushTool.DEFAULT)
|
||||||
|
var tool by toolProperty
|
||||||
|
private set
|
||||||
|
|
||||||
private constructor(brushArray: Array<Array<Tile>>) {
|
private constructor(brushArray: Array<Array<Tile>>) {
|
||||||
rowsProperty.value = brushArray.size
|
rowsProperty.value = brushArray.size
|
||||||
|
|
||||||
@@ -81,6 +85,7 @@ class Brush {
|
|||||||
private fun clone() = Brush(brush, rows, columns).apply {
|
private fun clone() = Brush(brush, rows, columns).apply {
|
||||||
this.range = this@Brush.range
|
this.range = this@Brush.range
|
||||||
this.mode = this@Brush.mode
|
this.mode = this@Brush.mode
|
||||||
|
this.tool = this@Brush.tool
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withRange(range: Int) = clone().apply {
|
fun withRange(range: Int) = clone().apply {
|
||||||
@@ -91,6 +96,10 @@ class Brush {
|
|||||||
this.mode = mode
|
this.mode = mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withTool(tool: BrushTool) = clone().apply {
|
||||||
|
this.tool = tool
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun of(brushArray: Array<Array<Tile>>) = Brush(brushArray)
|
fun of(brushArray: Array<Array<Tile>>) = Brush(brushArray)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.bartlomiejpluta.base.editor.map.model.brush
|
||||||
|
|
||||||
|
enum class BrushTool {
|
||||||
|
DEFAULT,
|
||||||
|
|
||||||
|
// Object Layer
|
||||||
|
PASSAGE
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ 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.map.controller.MapController
|
import com.bartlomiejpluta.base.editor.map.controller.MapController
|
||||||
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushTool
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer
|
||||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
||||||
@@ -25,11 +26,9 @@ class MapToolbarView : View() {
|
|||||||
private val brushVM = find<BrushVM>()
|
private val brushVM = find<BrushVM>()
|
||||||
private val editorStateVM = find<EditorStateVM>()
|
private val editorStateVM = find<EditorStateVM>()
|
||||||
|
|
||||||
private val brushMode = ToggleGroup().apply {
|
private val brushMode = ToggleGroup()
|
||||||
brushVM.itemProperty.addListener { _, _, brush ->
|
|
||||||
selectedValueProperty<BrushMode>().value = brush.mode
|
private val objectLayerTool = ToggleGroup()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val isTileLayerSelected = Bindings.createBooleanBinding(
|
private val isTileLayerSelected = Bindings.createBooleanBinding(
|
||||||
{ editorStateVM.selectedLayer is TileLayer },
|
{ editorStateVM.selectedLayer is TileLayer },
|
||||||
@@ -41,6 +40,17 @@ class MapToolbarView : View() {
|
|||||||
editorStateVM.selectedLayerProperty
|
editorStateVM.selectedLayerProperty
|
||||||
)
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
brushVM.itemProperty.addListener { _, _, brush ->
|
||||||
|
brushMode.selectedValueProperty<BrushMode>().value = brush.mode
|
||||||
|
objectLayerTool.selectedValueProperty<BrushTool>().value = brush.tool
|
||||||
|
}
|
||||||
|
|
||||||
|
editorStateVM.selectedLayerProperty.addListener { _, _, _ ->
|
||||||
|
brushVM.item = brushVM.withTool(BrushTool.DEFAULT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val root = toolbar {
|
override val root = toolbar {
|
||||||
button(graphic = FontIcon("fa-floppy-o")) {
|
button(graphic = FontIcon("fa-floppy-o")) {
|
||||||
action {
|
action {
|
||||||
@@ -62,6 +72,8 @@ class MapToolbarView : View() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
separator()
|
||||||
|
|
||||||
togglebutton {
|
togglebutton {
|
||||||
graphic = FontIcon("fa-window-restore")
|
graphic = FontIcon("fa-window-restore")
|
||||||
|
|
||||||
@@ -78,6 +90,8 @@ class MapToolbarView : View() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
separator()
|
||||||
|
|
||||||
togglebutton(value = BrushMode.PAINTING_MODE, group = brushMode) {
|
togglebutton(value = BrushMode.PAINTING_MODE, group = brushMode) {
|
||||||
graphic = FontIcon("fa-paint-brush")
|
graphic = FontIcon("fa-paint-brush")
|
||||||
|
|
||||||
@@ -120,5 +134,31 @@ class MapToolbarView : View() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this += FontIcon("fa-paint-brush").apply { iconSize = 15 }
|
this += FontIcon("fa-paint-brush").apply { iconSize = 15 }
|
||||||
|
|
||||||
|
separator {
|
||||||
|
visibleWhen(isObjectLayerSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
togglebutton(value = BrushTool.DEFAULT, group = objectLayerTool) {
|
||||||
|
graphic = FontIcon("fa-cube")
|
||||||
|
|
||||||
|
visibleWhen(isObjectLayerSelected)
|
||||||
|
|
||||||
|
action {
|
||||||
|
brushVM.item = brushVM.withTool(BrushTool.DEFAULT)
|
||||||
|
brushVM.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
togglebutton(value = BrushTool.PASSAGE, group = objectLayerTool) {
|
||||||
|
graphic = FontIcon("fa-minus-circle")
|
||||||
|
|
||||||
|
visibleWhen(isObjectLayerSelected)
|
||||||
|
|
||||||
|
action {
|
||||||
|
brushVM.item = brushVM.withTool(BrushTool.PASSAGE)
|
||||||
|
brushVM.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.editor.map.view.editor
|
|||||||
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
|
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
|
||||||
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.map.canvas.PaintingTrace
|
||||||
import com.bartlomiejpluta.base.editor.map.component.MapPane
|
import com.bartlomiejpluta.base.editor.map.component.MapPane
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||||
@@ -27,7 +28,7 @@ class MapView : View() {
|
|||||||
|
|
||||||
private val editorStateVM = find<EditorStateVM>()
|
private val editorStateVM = find<EditorStateVM>()
|
||||||
|
|
||||||
private val mapPane = MapPane(mapVM, brushVM, editorStateVM) { undoRedoService.push(it, scope) }
|
private val mapPane = MapPane(mapVM, brushVM, editorStateVM, this::pushPaintingTraceToUndoRedoService)
|
||||||
|
|
||||||
private val zoom = Scale(1.0, 1.0, 0.0, 0.0).apply {
|
private val zoom = Scale(1.0, 1.0, 0.0, 0.0).apply {
|
||||||
xProperty().bind(editorStateVM.zoomProperty)
|
xProperty().bind(editorStateVM.zoomProperty)
|
||||||
@@ -41,6 +42,12 @@ class MapView : View() {
|
|||||||
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pushPaintingTraceToUndoRedoService(trace: PaintingTrace) {
|
||||||
|
if (trace.executed) {
|
||||||
|
undoRedoService.push(trace, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val root = scrollpane {
|
override val root = scrollpane {
|
||||||
prefWidth = 640.0
|
prefWidth = 640.0
|
||||||
prefHeight = 480.0
|
prefHeight = 480.0
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.map.viewmodel
|
|||||||
|
|
||||||
import com.bartlomiejpluta.base.editor.map.model.brush.Brush
|
import com.bartlomiejpluta.base.editor.map.model.brush.Brush
|
||||||
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushMode
|
||||||
|
import com.bartlomiejpluta.base.editor.map.model.brush.BrushTool
|
||||||
import com.bartlomiejpluta.base.editor.tileset.model.Tile
|
import com.bartlomiejpluta.base.editor.tileset.model.Tile
|
||||||
import tornadofx.ItemViewModel
|
import tornadofx.ItemViewModel
|
||||||
import tornadofx.getValue
|
import tornadofx.getValue
|
||||||
@@ -21,9 +22,15 @@ class BrushVM : ItemViewModel<Brush>(Brush.of(arrayOf(arrayOf()))) {
|
|||||||
val modeProperty = bind(Brush::modeProperty)
|
val modeProperty = bind(Brush::modeProperty)
|
||||||
val mode by modeProperty
|
val mode by modeProperty
|
||||||
|
|
||||||
fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) = item.forEach(consumer)
|
val toolProperty = bind(Brush::toolProperty)
|
||||||
|
val tool by toolProperty
|
||||||
|
|
||||||
|
fun forEach(consumer: (row: Int, column: Int, centerRow: Int, centerColumn: Int, tile: Tile?) -> Unit) =
|
||||||
|
item.forEach(consumer)
|
||||||
|
|
||||||
fun withRange(range: Int) = item.withRange(range)
|
fun withRange(range: Int) = item.withRange(range)
|
||||||
|
|
||||||
fun withMode(mode: BrushMode) = item.withMode(mode)
|
fun withMode(mode: BrushMode) = item.withMode(mode)
|
||||||
|
|
||||||
|
fun withTool(tool: BrushTool) = item.withTool(tool)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user