[Editor] Add support for different Tile Sets on each Tile Layer #3
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
package com.bartlomiejpluta.base.editor.asset.view.select
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import javafx.beans.property.BooleanProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.StringProperty
|
||||
import javafx.collections.ObservableList
|
||||
import tornadofx.*
|
||||
|
||||
class SelectGraphicAssetFragment<T : Asset> : Fragment("Select Asset") {
|
||||
val assets: ObservableList<T> by param()
|
||||
val cancelable: BooleanProperty by param(true.toProperty())
|
||||
val comment: StringProperty by param("".toProperty())
|
||||
|
||||
private val asset = SimpleObjectProperty<T>()
|
||||
|
||||
@@ -22,6 +26,12 @@ class SelectGraphicAssetFragment<T : Asset> : Fragment("Select Asset") {
|
||||
}
|
||||
|
||||
override val root = form {
|
||||
if(comment.isNotEmpty.value) {
|
||||
label(comment) {
|
||||
visibleWhen(comment.isNotEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
this += selectGraphicAssetView.root
|
||||
}
|
||||
@@ -37,6 +47,7 @@ class SelectGraphicAssetFragment<T : Asset> : Fragment("Select Asset") {
|
||||
}
|
||||
|
||||
button("Cancel") {
|
||||
visibleWhen(cancelable)
|
||||
action { close() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,17 @@ import com.bartlomiejpluta.base.editor.animation.view.importing.ImportAnimationF
|
||||
import com.bartlomiejpluta.base.editor.animation.viewmodel.AnimationAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset
|
||||
import com.bartlomiejpluta.base.editor.asset.view.select.SelectGraphicAssetFragment
|
||||
import com.bartlomiejpluta.base.editor.asset.viewmodel.GraphicAssetVM
|
||||
import com.bartlomiejpluta.base.editor.audio.view.importing.ImportSoundFragment
|
||||
import com.bartlomiejpluta.base.editor.audio.viewmodel.SoundAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.characterset.view.importing.ImportCharacterSetFragment
|
||||
import com.bartlomiejpluta.base.editor.characterset.viewmodel.CharacterSetAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.code.model.CodeScope
|
||||
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
|
||||
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.Query
|
||||
import com.bartlomiejpluta.base.editor.database.viewmodel.QueryVM
|
||||
import com.bartlomiejpluta.base.editor.characterset.view.importing.ImportCharacterSetFragment
|
||||
import com.bartlomiejpluta.base.editor.characterset.viewmodel.CharacterSetAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.event.SelectMainViewTabEvent
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileNode
|
||||
import com.bartlomiejpluta.base.editor.file.model.ScriptAssetFileNode
|
||||
@@ -26,18 +27,20 @@ import com.bartlomiejpluta.base.editor.image.view.importing.ImportImageFragment
|
||||
import com.bartlomiejpluta.base.editor.image.viewmodel.ImageAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapCreationWizard
|
||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapImportWizard
|
||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapCreationFragment
|
||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapImportFragment
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import com.bartlomiejpluta.base.editor.project.view.ProjectSettingsFragment
|
||||
import com.bartlomiejpluta.base.editor.project.viewmodel.ProjectVM
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import com.bartlomiejpluta.base.editor.tileset.view.importing.ImportTileSetFragment
|
||||
import com.bartlomiejpluta.base.editor.tileset.viewmodel.TileSetAssetDataVM
|
||||
import javafx.scene.control.TextInputDialog
|
||||
import javafx.stage.FileChooser
|
||||
import javafx.stage.StageStyle
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.*
|
||||
import java.io.File
|
||||
@@ -68,10 +71,9 @@ class MainController : Controller() {
|
||||
val vm = GameMapBuilderVM()
|
||||
setInScope(vm, scope)
|
||||
|
||||
find<MapCreationWizard>(scope).apply {
|
||||
find<MapCreationFragment>(scope).apply {
|
||||
onComplete {
|
||||
val tileSet = projectContext.loadTileSet(vm.tileSetAsset.uid)
|
||||
val map = GameMap(tileSet).apply {
|
||||
val map = GameMap(vm.tileWidth.toDouble(), vm.tileHeight.toDouble()).apply {
|
||||
rows = vm.rows
|
||||
columns = vm.columns
|
||||
handler = vm.handler
|
||||
@@ -88,10 +90,28 @@ class MainController : Controller() {
|
||||
val scope = UndoableScope()
|
||||
val vm = GameMapBuilderVM()
|
||||
setInScope(vm, scope)
|
||||
find<MapImportWizard>(scope).apply {
|
||||
find<MapImportFragment>(scope).apply {
|
||||
onComplete {
|
||||
val tileSet = projectContext.loadTileSet(vm.tileSetAsset.uid)
|
||||
val map = projectContext.importMapFromFile(vm.name, vm.handler, File(vm.file), tileSet)
|
||||
val map = projectContext.importMapFromFile(vm.name, vm.handler, File(vm.file)) { name, uid ->
|
||||
var newUid = ""
|
||||
|
||||
find<SelectGraphicAssetFragment<TileSetAsset>>(
|
||||
Scope(),
|
||||
SelectGraphicAssetFragment<TileSetAsset>::assets to projectContext.project?.tileSets!!,
|
||||
SelectGraphicAssetFragment<TileSetAsset>::comment to "You are importing a tile layer which originally was defined\nwith an other Tile Set asset data with UID: [$uid].\nPlease select asset you would like to apply for layer $name.\n".toProperty(),
|
||||
SelectGraphicAssetFragment<TileSetAsset>::cancelable to false.toProperty()
|
||||
).apply {
|
||||
title = "Select Tile Set for layer $name"
|
||||
|
||||
onComplete {
|
||||
newUid = it.uid
|
||||
}
|
||||
|
||||
openModal(block = true, resizable = false, stageStyle = StageStyle.UNDECORATED)
|
||||
}
|
||||
|
||||
newUid
|
||||
}
|
||||
openItems[scope] = GameMapVM(map)
|
||||
}
|
||||
|
||||
@@ -121,11 +141,7 @@ class MainController : Controller() {
|
||||
}
|
||||
|
||||
fun openScript(
|
||||
fsNode: FileNode,
|
||||
line: Int = 1,
|
||||
column: Int = 1,
|
||||
execute: ((String) -> Unit)? = null,
|
||||
saveable: Boolean = true
|
||||
fsNode: FileNode, line: Int = 1, column: Int = 1, execute: ((String) -> Unit)? = null, saveable: Boolean = true
|
||||
) {
|
||||
val findScript = { script: CodeVM -> script.fileNode.absolutePath == fsNode.absolutePath }
|
||||
val updateExistingScope = { scope: CodeScope -> scope.setCaretPosition(line, column) }
|
||||
@@ -170,11 +186,9 @@ class MainController : Controller() {
|
||||
updateViewModel: (VM) -> Unit = {},
|
||||
createItem: () -> Pair<Scope, VM>
|
||||
) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val pair = openItems.entries
|
||||
.filter { (_, item) -> item is VM }
|
||||
.map { (scope, item) -> (scope as S) to (item as VM) }
|
||||
.firstOrNull { (_, item) -> findItem(item) }
|
||||
@Suppress("UNCHECKED_CAST") val pair =
|
||||
openItems.entries.filter { (_, item) -> item is VM }.map { (scope, item) -> (scope as S) to (item as VM) }
|
||||
.firstOrNull { (_, item) -> findItem(item) }
|
||||
|
||||
if (pair == null) {
|
||||
val (scope, item) = createItem()
|
||||
@@ -277,11 +291,7 @@ class MainController : Controller() {
|
||||
width = 300.0
|
||||
contentText = "Widget name"
|
||||
title = "New Widget"
|
||||
}
|
||||
.showAndWait()
|
||||
.map(::WidgetAssetData)
|
||||
.map(projectContext::createWidget)
|
||||
.ifPresent(this::openScript)
|
||||
}.showAndWait().map(::WidgetAssetData).map(projectContext::createWidget).ifPresent(this::openScript)
|
||||
}
|
||||
|
||||
fun importSound() {
|
||||
|
||||
@@ -11,7 +11,6 @@ import javafx.scene.paint.Color
|
||||
|
||||
|
||||
class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, private val painter: MapPainter) : Renderable {
|
||||
var tileSet = map.tileSet
|
||||
private var tileWidth = map.tileWidth
|
||||
private var tileHeight = map.tileHeight
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ class MapPainter(
|
||||
private val editorStateVM: EditorStateVM,
|
||||
private val paintingCallback: (PaintingTrace) -> Unit
|
||||
) : Renderable, MapMouseEventHandler {
|
||||
private val tileWidth = mapVM.tileSet.tileWidth.toDouble()
|
||||
private val tileHeight = mapVM.tileSet.tileHeight.toDouble()
|
||||
private val tileWidth = mapVM.tileWidth.toDouble()
|
||||
private val tileHeight = mapVM.tileHeight.toDouble()
|
||||
|
||||
private var cursor: PaintingCursor? = null
|
||||
private var currentTrace: PaintingTrace? = null
|
||||
|
||||
@@ -47,7 +47,7 @@ class MapPane(
|
||||
|
||||
override fun handle(event: MouseEvent?) {
|
||||
if (event != null) {
|
||||
painter.handleMouseInput(MapMouseEvent.of(event, mapVM.tileSet))
|
||||
painter.handleMouseInput(MapMouseEvent.of(event, mapVM))
|
||||
}
|
||||
|
||||
mapCanvas.render(graphicsContext2D)
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package com.bartlomiejpluta.base.editor.map.model.layer
|
||||
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.Tile
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import javafx.beans.binding.Bindings
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.scene.image.Image
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
import tornadofx.toProperty
|
||||
|
||||
class TileLayer(
|
||||
name: String,
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
tileSetAsset: TileSetAsset,
|
||||
layer: Array<Array<Tile?>> = Array(rows) { Array(columns) { null } }
|
||||
) : Layer {
|
||||
var layer = layer
|
||||
@@ -17,6 +23,21 @@ class TileLayer(
|
||||
override val nameProperty = SimpleStringProperty(name)
|
||||
override var name: String by nameProperty
|
||||
|
||||
val tileSetAssetProperty = tileSetAsset.toProperty()
|
||||
var tileSetAsset by tileSetAssetProperty
|
||||
|
||||
val tileSetProperty = Bindings.createObjectBinding({
|
||||
tileSetAssetProperty.value.file.inputStream().use { fis ->
|
||||
TileSet(
|
||||
tileSetAsset.uid,
|
||||
tileSetAsset.name,
|
||||
Image(fis),
|
||||
tileSetAsset.rows,
|
||||
tileSetAsset.columns
|
||||
)
|
||||
}
|
||||
}, tileSetAssetProperty)
|
||||
|
||||
override fun resize(rows: Int, columns: Int) {
|
||||
layer = Array(rows) { row ->
|
||||
Array(columns) { column ->
|
||||
|
||||
@@ -10,15 +10,12 @@ import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
|
||||
class GameMap(val tileSet: TileSet) {
|
||||
class GameMap(val tileWidth: Double, val tileHeight: Double) {
|
||||
val uidProperty = SimpleStringProperty()
|
||||
var uid by uidProperty
|
||||
|
||||
val layers = FXCollections.observableArrayList(Layer.extractor())
|
||||
|
||||
val tileWidth = tileSet.tileWidth.toDouble()
|
||||
val tileHeight = tileSet.tileHeight.toDouble()
|
||||
|
||||
val rowsProperty = SimpleIntegerProperty(INITIAL_ROWS)
|
||||
var rows by rowsProperty
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.map.model.map
|
||||
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import javafx.beans.property.SimpleDoubleProperty
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
@@ -9,12 +10,15 @@ import tornadofx.setValue
|
||||
import java.io.File
|
||||
|
||||
class GameMapBuilder {
|
||||
val tileSetAssetProperty = SimpleObjectProperty<TileSetAsset>()
|
||||
var tileSetAsset by tileSetAssetProperty
|
||||
|
||||
val nameProperty = SimpleStringProperty("")
|
||||
var name by nameProperty
|
||||
|
||||
val tileWidthProperty = SimpleIntegerProperty(32)
|
||||
var tileWidth by tileWidthProperty
|
||||
|
||||
val tileHeightProperty = SimpleIntegerProperty(32)
|
||||
var tileHeight by tileHeightProperty
|
||||
|
||||
val rowsProperty = SimpleIntegerProperty(20)
|
||||
var rows by rowsProperty
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.bartlomiejpluta.base.editor.map.parameter.layer
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.parameter.model.GraphicAssetParameter
|
||||
import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import javafx.collections.ObservableList
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TileLayerParametersBinder : LayerParametersBinder<TileLayer> {
|
||||
override fun bind(
|
||||
layer: TileLayer,
|
||||
parameters: ObservableList<Parameter<*>>,
|
||||
project: Project,
|
||||
onCommit: () -> Unit
|
||||
) {
|
||||
val tileSet = GraphicAssetParameter("tileSet", layer.tileSetAsset, true, project.tileSets) { _, _, submit ->
|
||||
onCommit()
|
||||
submit()
|
||||
}
|
||||
|
||||
tileSet.bindBidirectional(layer.tileSetAssetProperty)
|
||||
|
||||
parameters.addAll(tileSet)
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package com.bartlomiejpluta.base.editor.map.serial
|
||||
|
||||
import com.bartlomiejpluta.base.editor.common.serial.Deserializer
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import java.io.InputStream
|
||||
|
||||
interface MapDeserializer : Deserializer<GameMap> {
|
||||
fun deserialize(input: InputStream, tileSet: TileSet): GameMap
|
||||
fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String): GameMap
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.bartlomiejpluta.base.editor.map.model.layer.*
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.map.model.obj.MapObject
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.Tile
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import com.bartlomiejpluta.base.proto.GameMapProto
|
||||
@@ -24,25 +25,11 @@ class ProtobufMapDeserializer : MapDeserializer {
|
||||
appContext.getBean(ProjectContext::class.java)
|
||||
}
|
||||
|
||||
override fun deserialize(input: InputStream): GameMap {
|
||||
override fun deserialize(input: InputStream) = deserialize(input) { _, uid -> uid }
|
||||
|
||||
override fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String): GameMap {
|
||||
val proto = GameMapProto.GameMap.parseFrom(input)
|
||||
val tileSet = projectContext.loadTileSet(proto.tileSetUID)
|
||||
val map = GameMap(tileSet)
|
||||
map.uid = proto.uid
|
||||
map.rows = proto.rows
|
||||
map.columns = proto.columns
|
||||
map.handler = proto.handler
|
||||
|
||||
proto.layersList.forEach {
|
||||
map.layers.add(deserializeLayer(map.rows, map.columns, tileSet, it))
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
override fun deserialize(input: InputStream, tileSet: TileSet): GameMap {
|
||||
val proto = GameMapProto.GameMap.parseFrom(input)
|
||||
val map = GameMap(tileSet)
|
||||
val map = GameMap(proto.tileWidth.toDouble(), proto.tileHeight.toDouble())
|
||||
map.uid = proto.uid
|
||||
map.rows = proto.rows
|
||||
map.columns = proto.columns
|
||||
@@ -50,14 +37,14 @@ class ProtobufMapDeserializer : MapDeserializer {
|
||||
|
||||
proto.layersList
|
||||
.filter { it.hasTileLayer() || it.hasObjectLayer() || it.hasColorLayer() }
|
||||
.forEach { map.layers.add(deserializeLayer(map.rows, map.columns, tileSet, it)) }
|
||||
.forEach { map.layers.add(deserializeLayer(map.rows, map.columns, it, replaceTileSet)) }
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
private fun deserializeLayer(rows: Int, columns: Int, tileSet: TileSet, proto: GameMapProto.Layer): Layer {
|
||||
private fun deserializeLayer(rows: Int, columns: Int, proto: GameMapProto.Layer, replaceTileSet: (String, String) -> String): Layer {
|
||||
return when {
|
||||
proto.hasTileLayer() -> deserializeTileLayer(rows, columns, tileSet, proto)
|
||||
proto.hasTileLayer() -> deserializeTileLayer(rows, columns, proto, replaceTileSet)
|
||||
proto.hasObjectLayer() -> deserializeObjectLayer(rows, columns, proto)
|
||||
proto.hasColorLayer() -> deserializeColorLayer(proto)
|
||||
proto.hasImageLayer() -> deserializeImageLayer(proto)
|
||||
@@ -66,8 +53,10 @@ class ProtobufMapDeserializer : MapDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
private fun deserializeTileLayer(rows: Int, columns: Int, tileSet: TileSet, proto: GameMapProto.Layer): Layer {
|
||||
private fun deserializeTileLayer(rows: Int, columns: Int, proto: GameMapProto.Layer, replaceTileSet: (String, String) -> String): Layer {
|
||||
val layer: Array<Array<Tile?>> = Array(rows) { Array(columns) { null } }
|
||||
val tileSetAsset = projectContext.findTileSetAsset(replaceTileSet(proto.name, proto.tileLayer.tilesetUID))
|
||||
val tileSet = projectContext.loadTileSet(tileSetAsset.uid)
|
||||
|
||||
proto.tileLayer.tilesList.forEachIndexed { index, tile ->
|
||||
layer[index / columns][index % columns] = when (tile) {
|
||||
@@ -76,7 +65,7 @@ class ProtobufMapDeserializer : MapDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
return TileLayer(proto.name, rows, columns, layer)
|
||||
return TileLayer(proto.name, rows, columns, tileSetAsset, layer)
|
||||
}
|
||||
|
||||
private fun deserializeObjectLayer(rows: Int, columns: Int, proto: GameMapProto.Layer): Layer {
|
||||
|
||||
@@ -16,7 +16,8 @@ class ProtobufMapSerializer : MapSerializer {
|
||||
protoMap.uid = item.uid
|
||||
protoMap.rows = item.rows
|
||||
protoMap.columns = item.columns
|
||||
protoMap.tileSetUID = item.tileSet.uid
|
||||
protoMap.tileWidth = item.tileWidth.toInt()
|
||||
protoMap.tileHeight = item.tileHeight.toInt()
|
||||
protoMap.handler = item.handler
|
||||
|
||||
item.layers.forEach { layer -> protoMap.addLayers(serializeLayer(layer)) }
|
||||
@@ -28,6 +29,7 @@ class ProtobufMapSerializer : MapSerializer {
|
||||
return when (layer) {
|
||||
is TileLayer -> layer.layer.flatMap { it.asIterable() }
|
||||
.fold(GameMapProto.TileLayer.newBuilder()) { acc, tile -> acc.addTiles((tile?.id?.plus(1)) ?: 0) }
|
||||
.setTilesetUID(layer.tileSetAsset.uid)
|
||||
.build()
|
||||
.let { GameMapProto.Layer.newBuilder().setName(layer.name).setTileLayer(it).build() }
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import com.bartlomiejpluta.base.editor.common.parameter.view.ParametersTableFrag
|
||||
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.ImageLayer
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||
import com.bartlomiejpluta.base.editor.map.parameter.layer.ColorLayerParametersBinder
|
||||
import com.bartlomiejpluta.base.editor.map.parameter.layer.ImageLayerParametersBinder
|
||||
import com.bartlomiejpluta.base.editor.map.parameter.layer.TileLayerParametersBinder
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import tornadofx.View
|
||||
@@ -20,6 +22,7 @@ class MapLayerParameters : View() {
|
||||
// of LayerParametersBinder<> type
|
||||
private val colorLayerParametersBinder: ColorLayerParametersBinder by di()
|
||||
private val imageLayerParametersBinder: ImageLayerParametersBinder by di()
|
||||
private val tileLayerParametersBinder: TileLayerParametersBinder by di()
|
||||
|
||||
private val parameters = observableListOf<Parameter<*>>()
|
||||
|
||||
@@ -29,15 +32,16 @@ class MapLayerParameters : View() {
|
||||
parameters.clear()
|
||||
|
||||
when (layer) {
|
||||
is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
|
||||
fire(
|
||||
RedrawMapRequestEvent
|
||||
)
|
||||
is TileLayer -> tileLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
|
||||
is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
|
||||
is ImageLayer -> imageLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
|
||||
fire(
|
||||
RedrawMapRequestEvent
|
||||
)
|
||||
fire(RedrawMapRequestEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.bartlomiejpluta.base.editor.map.model.layer.*
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.control.ListCell
|
||||
import javafx.scene.control.ListView
|
||||
@@ -55,11 +56,21 @@ class MapLayersView : View() {
|
||||
menubutton(graphic = FontIcon("fa-plus")) {
|
||||
item("Tile Layer", graphic = FontIcon("fa-th-large")) {
|
||||
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)
|
||||
val scope = UndoableScope()
|
||||
find<SelectGraphicAssetFragment<TileSetAsset>>(
|
||||
scope,
|
||||
SelectGraphicAssetFragment<TileSetAsset>::assets to projectContext.project?.tileSets!!
|
||||
).apply {
|
||||
onComplete {
|
||||
val layer = TileLayer("Layer ${mapVM.layers.size + 1}", mapVM.rows, mapVM.columns, it)
|
||||
val command = CreateLayerCommand(mapVM.item, layer)
|
||||
command.execute()
|
||||
layersPane.selectionModel.select(mapVM.layers.size - 1)
|
||||
undoRedoService.push(command, scope)
|
||||
}
|
||||
|
||||
openModal(block = true, resizable = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +175,7 @@ class MapLayersView : View() {
|
||||
override fun fromString(string: String?): Layer = cell.item.apply {
|
||||
string
|
||||
?.takeIf { str -> str != name }
|
||||
?.takeIf { str -> layers.none { it.name == str }}
|
||||
?.takeIf { str -> layers.none { it.name == str } }
|
||||
?.let { onUpdate(this, it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class MapView : View() {
|
||||
}
|
||||
|
||||
init {
|
||||
brushVM.item = mapVM.tileSet.baseBrush
|
||||
// brushVM.item = mapVM.tileSet.baseBrush
|
||||
brushVM.commit()
|
||||
|
||||
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.wizard
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMapBuilder
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil
|
||||
import tornadofx.*
|
||||
|
||||
class MapCreationBasicDataView : View("Basic Data") {
|
||||
class MapCreationFragment : Fragment("Basic Data") {
|
||||
private val mapBuilderVM = find<GameMapBuilderVM>()
|
||||
private var onCompleteConsumer: ((GameMapBuilder) -> Unit)? = null
|
||||
|
||||
override val complete = mapBuilderVM.valid(
|
||||
mapBuilderVM.nameProperty,
|
||||
@@ -14,6 +16,11 @@ class MapCreationBasicDataView : View("Basic Data") {
|
||||
mapBuilderVM.handlerProperty
|
||||
)
|
||||
|
||||
fun onComplete(consumer: (GameMapBuilder) -> Unit) {
|
||||
this.onCompleteConsumer = consumer
|
||||
}
|
||||
|
||||
|
||||
override val root = form {
|
||||
fieldset("Map Settings") {
|
||||
field("Map name") {
|
||||
@@ -23,6 +30,36 @@ class MapCreationBasicDataView : View("Basic Data") {
|
||||
}
|
||||
}
|
||||
|
||||
field("Tile Width") {
|
||||
spinner(min = 1, property = mapBuilderVM.tileWidthProperty, editable = true) {
|
||||
required()
|
||||
editor.textFormatter = TextFieldUtil.integerFormatter(mapBuilderVM.tileWidth)
|
||||
|
||||
validator {
|
||||
if (it?.toInt()?.let { value -> value <= 0 } != false) {
|
||||
error("The tile width must be greater than 0")
|
||||
}
|
||||
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
field("Tile Height") {
|
||||
spinner(min = 1, property = mapBuilderVM.tileHeightProperty, editable = true) {
|
||||
required()
|
||||
editor.textFormatter = TextFieldUtil.integerFormatter(mapBuilderVM.tileHeight)
|
||||
|
||||
validator {
|
||||
if (it?.toInt()?.let { value -> value <= 0 } != false) {
|
||||
error("The tile height must be greater than 0")
|
||||
}
|
||||
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
field("Rows") {
|
||||
spinner(min = 1, max = 100, property = mapBuilderVM.rowsProperty, editable = true) {
|
||||
required()
|
||||
@@ -60,5 +97,25 @@ class MapCreationBasicDataView : View("Basic Data") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buttonbar {
|
||||
button("Create") {
|
||||
action {
|
||||
if (mapBuilderVM.commit()) {
|
||||
onCompleteConsumer?.let { it(mapBuilderVM.item) }
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button("Reset") {
|
||||
action { mapBuilderVM.rollback() }
|
||||
}
|
||||
|
||||
|
||||
button("Cancel") {
|
||||
action { close() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.wizard
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.Wizard
|
||||
|
||||
class MapCreationWizard : Wizard("New Map", "Provide map information") {
|
||||
private val mapBuilderVM = find<GameMapBuilderVM>()
|
||||
|
||||
init {
|
||||
graphic = FontIcon("fa-map").apply {
|
||||
iconSize = 40
|
||||
}
|
||||
|
||||
add(MapCreationBasicDataView::class)
|
||||
add(MapTileSetSelectionView::class)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.wizard
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMapBuilder
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import javafx.beans.binding.Bindings
|
||||
import javafx.stage.FileChooser
|
||||
import tornadofx.*
|
||||
import java.io.File
|
||||
|
||||
class MapImportBasicDataView : View("Basic Data") {
|
||||
class MapImportFragment : Fragment("Basic Data") {
|
||||
private val mapBuilderVM = find<GameMapBuilderVM>()
|
||||
private var onCompleteConsumer: ((GameMapBuilder) -> Unit)? = null
|
||||
|
||||
fun onComplete(consumer: (GameMapBuilder) -> Unit) {
|
||||
this.onCompleteConsumer = consumer
|
||||
}
|
||||
|
||||
override val complete = mapBuilderVM.valid(
|
||||
mapBuilderVM.fileProperty,
|
||||
@@ -61,5 +66,25 @@ class MapImportBasicDataView : View("Basic Data") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buttonbar {
|
||||
button("Create") {
|
||||
action {
|
||||
if (mapBuilderVM.commit()) {
|
||||
onCompleteConsumer?.let { it(mapBuilderVM.item) }
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button("Reset") {
|
||||
action { mapBuilderVM.rollback() }
|
||||
}
|
||||
|
||||
|
||||
button("Cancel") {
|
||||
action { close() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.wizard
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.Wizard
|
||||
|
||||
class MapImportWizard : Wizard("Import Map", "Provide map information") {
|
||||
private val mapBuilderVM = find<GameMapBuilderVM>()
|
||||
|
||||
init {
|
||||
graphic = FontIcon("fa-map").apply {
|
||||
iconSize = 40
|
||||
}
|
||||
|
||||
add(MapImportBasicDataView::class)
|
||||
add(MapTileSetSelectionView::class)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.wizard
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.view.select.SelectGraphicAssetView
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import tornadofx.View
|
||||
|
||||
class MapTileSetSelectionView : View("Tile Set") {
|
||||
private val mapBuilderVM = find<GameMapBuilderVM>()
|
||||
|
||||
private val projectContext: ProjectContext by di()
|
||||
|
||||
private val selectGraphicAssetView = find<SelectGraphicAssetView<TileSetAsset>>(
|
||||
SelectGraphicAssetView<TileSetAsset>::assets to projectContext.project!!.tileSets,
|
||||
SelectGraphicAssetView<TileSetAsset>::asset to mapBuilderVM.tileSetAssetProperty
|
||||
)
|
||||
|
||||
// FIXME
|
||||
// It's kind of ugly solution because for some reason
|
||||
// the custom validator on tileSetsListView does not work here.
|
||||
// Desired solution should use mapBuilderVM.valid(mapBuilderVM.tileSetProperty)
|
||||
// as in the previous step of the wizard as well as the feedback for user
|
||||
// saying, that tile set field is required.
|
||||
override val complete = mapBuilderVM.tileSetAssetProperty.isNotNull
|
||||
|
||||
override val root = selectGraphicAssetView.root
|
||||
}
|
||||
@@ -6,12 +6,15 @@ import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class GameMapBuilderVM : ItemViewModel<GameMapBuilder>(GameMapBuilder()) {
|
||||
val tileSetAssetProperty = bind(GameMapBuilder::tileSetAssetProperty, autocommit = true)
|
||||
var tileSetAsset by tileSetAssetProperty
|
||||
|
||||
val nameProperty = bind(GameMapBuilder::nameProperty, autocommit = true)
|
||||
var name by nameProperty
|
||||
|
||||
val tileWidthProperty = bind(GameMapBuilder::tileWidthProperty, autocommit = true)
|
||||
var tileWidth by tileWidthProperty
|
||||
|
||||
val tileHeightProperty = bind(GameMapBuilder::tileHeightProperty, autocommit = true)
|
||||
var tileHeight by tileHeightProperty
|
||||
|
||||
val rowsProperty = bind(GameMapBuilder::rowsProperty, autocommit = true)
|
||||
var rows by rowsProperty
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@ class GameMapVM(map: GameMap) : ItemViewModel<GameMap>(map) {
|
||||
val uidProperty = bind(GameMap::uidProperty)
|
||||
val uid by uidProperty
|
||||
|
||||
val tileSetProperty = bind(GameMap::tileSet)
|
||||
val tileSet by tileSetProperty
|
||||
|
||||
val rowsProperty = bind(GameMap::rowsProperty)
|
||||
var rows by rowsProperty
|
||||
|
||||
|
||||
@@ -123,9 +123,14 @@ class DefaultProjectContext : ProjectContext {
|
||||
}
|
||||
}
|
||||
|
||||
override fun importMapFromFile(name: String, handler: String, file: File, tileSet: TileSet) =
|
||||
override fun importMapFromFile(
|
||||
name: String,
|
||||
handler: String,
|
||||
file: File,
|
||||
replaceTileSet: (String, String) -> String
|
||||
) =
|
||||
project?.let { project ->
|
||||
val map = file.inputStream().use { mapDeserializer.deserialize(it, tileSet) }
|
||||
val map = file.inputStream().use { mapDeserializer.deserialize(it, replaceTileSet) }
|
||||
UID.next(project.maps.map(Asset::uid)).let { uid ->
|
||||
val asset = GameMapAsset(project, uid, name)
|
||||
map.uid = uid
|
||||
@@ -183,6 +188,11 @@ class DefaultProjectContext : ProjectContext {
|
||||
} ?: throw IllegalStateException("There is no open project in the context")
|
||||
}
|
||||
|
||||
override fun findTileSetAsset(uid: String) = project?.let {
|
||||
it.tileSets.firstOrNull { tileSets -> tileSets.uid == uid }
|
||||
?: throw IllegalStateException("The Tile Set with uid [$uid] does not exist ")
|
||||
} ?: throw IllegalStateException("There is no open project in the context")
|
||||
|
||||
override fun importImage(data: ImageAssetData) {
|
||||
project?.let {
|
||||
UID.next(it.images.map(Asset::uid)).let { uid ->
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.bartlomiejpluta.base.editor.image.asset.ImageAsset
|
||||
import com.bartlomiejpluta.base.editor.image.asset.ImageAssetData
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset
|
||||
import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAssetData
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import javafx.beans.property.ObjectProperty
|
||||
@@ -29,15 +30,17 @@ interface ProjectContext {
|
||||
fun createNewProject(project: Project)
|
||||
|
||||
fun importMap(name: String, map: GameMap)
|
||||
fun importMapFromFile(name: String, handler: String, file: File, tileSet: TileSet): GameMap
|
||||
fun importMapFromFile(name: String, handler: String, file: File, replaceTileSet: (String, String) -> String): GameMap
|
||||
fun loadMap(uid: String): GameMap
|
||||
fun saveMap(map: GameMap)
|
||||
|
||||
fun importTileSet(data: TileSetAssetData)
|
||||
fun loadTileSet(uid: String): TileSet
|
||||
fun findTileSetAsset(uid: String): TileSetAsset
|
||||
|
||||
fun importImage(data: ImageAssetData)
|
||||
fun findImageAsset(uid: String): ImageAsset
|
||||
|
||||
fun loadImage(uid: String): Image
|
||||
|
||||
fun importCharacterSet(data: CharacterSetAssetData)
|
||||
@@ -49,7 +52,6 @@ interface ProjectContext {
|
||||
fun importFont(data: FontAssetData)
|
||||
|
||||
fun createWidget(data: WidgetAssetData): WidgetAsset
|
||||
|
||||
fun importSound(data: SoundAssetData)
|
||||
fun deleteAsset(asset: Asset)
|
||||
fun loadScript(fileNode: FileNode, execute: ((String) -> Unit)?, saveable: Boolean): Code
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.render.input
|
||||
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import javafx.scene.input.MouseEvent
|
||||
|
||||
class MapMouseEvent(val row: Int, val column: Int, val event: MouseEvent) {
|
||||
@@ -8,9 +8,9 @@ class MapMouseEvent(val row: Int, val column: Int, val event: MouseEvent) {
|
||||
val button = event.button
|
||||
|
||||
companion object {
|
||||
fun of(event: MouseEvent, tileSet: TileSet) = MapMouseEvent(
|
||||
(event.y / tileSet.tileHeight).toInt(),
|
||||
(event.x / tileSet.tileWidth).toInt(),
|
||||
fun of(event: MouseEvent, mapVM: GameMapVM) = MapMouseEvent(
|
||||
(event.y / mapVM.tileHeight).toInt(),
|
||||
(event.x / mapVM.tileWidth).toInt(),
|
||||
event
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,38 +1,108 @@
|
||||
package com.bartlomiejpluta.base.editor.tileset.canvas
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||
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.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.tileset.model.TileSet
|
||||
import javafx.scene.canvas.GraphicsContext
|
||||
import javafx.scene.image.WritableImage
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.paint.Color
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class TileSetCanvas(private val gameMapVM: GameMapVM, private val selection: TileSetSelection) : Renderable, MapMouseEventHandler {
|
||||
class TileSetCanvas(private val editorStateVM: EditorStateVM, private val selection: TileSetSelection) : Renderable,
|
||||
MapMouseEventHandler {
|
||||
private var mouseRow = -1
|
||||
private var mouseColumn = -1
|
||||
|
||||
override fun render(gc: GraphicsContext) {
|
||||
gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height)
|
||||
|
||||
renderTiles(gc)
|
||||
selection.render(gc)
|
||||
if (editorStateVM.selectedLayer is TileLayer) {
|
||||
val tileSet = (editorStateVM.selectedLayer as TileLayer).tileSetProperty.value
|
||||
renderBackground(gc)
|
||||
renderTiles(gc, tileSet)
|
||||
renderGrid(gc, tileSet)
|
||||
selection.render(gc)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTiles(gc: GraphicsContext) {
|
||||
gameMapVM.tileSet.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,
|
||||
gameMapVM.tileSet.tileWidth.toDouble(),
|
||||
gameMapVM.tileSet.tileHeight.toDouble()
|
||||
)
|
||||
private fun renderBackground(gc: GraphicsContext) {
|
||||
for (x in 0 until (gc.canvas.width / BACKGROUND_TILE_WIDTH).roundToInt()) {
|
||||
for (y in 0 until (gc.canvas.height / BACKGROUND_TILE_HEIGHT).roundToInt()) {
|
||||
gc.fill = when ((x + y) % 2) {
|
||||
0 -> BACKGROUND_COLOR1
|
||||
else -> BACKGROUND_COLOR2
|
||||
}
|
||||
|
||||
gc.fillRect(x * BACKGROUND_TILE_WIDTH, y * BACKGROUND_TILE_HEIGHT, BACKGROUND_TILE_WIDTH, BACKGROUND_TILE_HEIGHT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTiles(gc: GraphicsContext, tileSet: TileSet) {
|
||||
tileSet.forEach { row, column, tile ->
|
||||
gc.drawImage(tile.image, column * tile.image.width, row * tile.image.height)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderGrid(gc: GraphicsContext, tileSet: TileSet) {
|
||||
gc.stroke = Color.BLACK
|
||||
gc.lineWidth = 0.5
|
||||
|
||||
for (x in 0 until (gc.canvas.width / tileSet.tileWidth).roundToInt()) {
|
||||
gc.strokeLine(x.toDouble() * tileSet.tileWidth, 0.0, x.toDouble() * tileSet.tileWidth, gc.canvas.height)
|
||||
}
|
||||
|
||||
for (y in 0 until (gc.canvas.height / tileSet.tileHeight).roundToInt()) {
|
||||
gc.strokeLine(0.0, y.toDouble() * tileSet.tileHeight, gc.canvas.width, y.toDouble() * tileSet.tileHeight)
|
||||
}
|
||||
|
||||
val w = gc.canvas.width - 1
|
||||
val h = gc.canvas.height - 1
|
||||
|
||||
gc.strokeLine(0.0, 0.0, w, 0.0)
|
||||
gc.strokeLine(w, 0.0, w, h)
|
||||
gc.strokeLine(0.0, h, w, h)
|
||||
gc.strokeLine(0.0, 0.0, 0.0, h)
|
||||
}
|
||||
|
||||
// private fun createGrid(gc: GraphicsContext, chunkWidth: Int, chunkHeight: Int): WritableImage {
|
||||
// val grid = WritableImage(gc.canvas.width.toInt(), gc.canvas.height.toInt())
|
||||
//
|
||||
// val writer = grid.pixelWriter
|
||||
// val color = Color.BLACK
|
||||
// for (x in 0 until grid.width.toInt()) {
|
||||
// for (y in 0 until grid.height.toInt()) {
|
||||
// if (x % chunkWidth == 0) {
|
||||
// writer.setColor(x, y, color)
|
||||
// }
|
||||
//
|
||||
// if (y % chunkHeight == 0) {
|
||||
// writer.setColor(x, y, color)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val lastX = grid.width.toInt() - 1
|
||||
// val lastY = grid.height.toInt() - 1
|
||||
//
|
||||
// for (x in 0 until grid.width.toInt()) {
|
||||
// writer.setColor(x, 0, color)
|
||||
// writer.setColor(x, lastY, color)
|
||||
// }
|
||||
//
|
||||
// for (y in 0 until grid.height.toInt()) {
|
||||
// writer.setColor(0, y, color)
|
||||
// writer.setColor(lastX, y, color)
|
||||
// }
|
||||
//
|
||||
// return grid
|
||||
// }
|
||||
|
||||
override fun handleMouseInput(event: MapMouseEvent) {
|
||||
mouseRow = event.row
|
||||
mouseColumn = event.column
|
||||
@@ -63,7 +133,9 @@ class TileSetCanvas(private val gameMapVM: GameMapVM, private val selection: Til
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BACKGROUND_TILE_WIDTH = 5.0
|
||||
private const val BACKGROUND_TILE_HEIGHT = 5.0
|
||||
private val BACKGROUND_COLOR1 = Color.color(1.0, 1.0, 1.0, 1.0)
|
||||
private val BACKGROUND_COLOR2 = Color.color(0.95, 0.95, 0.95, 0.95)
|
||||
private val BACKGROUND_COLOR2 = Color.color(0.95, 0.95, 0.95, 1.0)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.bartlomiejpluta.base.editor.tileset.canvas
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.brush.Brush
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||
import com.bartlomiejpluta.base.editor.render.model.Renderable
|
||||
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 javafx.scene.canvas.GraphicsContext
|
||||
import javafx.scene.paint.Color
|
||||
@@ -10,15 +12,15 @@ import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class TileSetSelection(private val gameMapVM: GameMapVM, private val brushVM: BrushVM) : Renderable {
|
||||
class TileSetSelection(private val editorStateVM: EditorStateVM, private val gameMapVM: GameMapVM, private val brushVM: BrushVM) : Renderable {
|
||||
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 = gameMapVM.tileSet.tileWidth.toDouble()
|
||||
private var height = gameMapVM.tileSet.tileHeight.toDouble()
|
||||
private var width = gameMapVM.tileWidth.toDouble()
|
||||
private var height = gameMapVM.tileHeight.toDouble()
|
||||
|
||||
|
||||
fun begin(row: Double, column: Double) {
|
||||
@@ -31,10 +33,10 @@ class TileSetSelection(private val gameMapVM: GameMapVM, private val brushVM: Br
|
||||
}
|
||||
|
||||
private fun updateRect(row: Double, column: Double) {
|
||||
x = min(column, startColumn) * gameMapVM.tileSet.tileWidth
|
||||
y = min(row, startRow) * gameMapVM.tileSet.tileHeight
|
||||
width = (offsetColumn + 1) * gameMapVM.tileSet.tileWidth
|
||||
height = (offsetRow + 1) * gameMapVM.tileSet.tileHeight
|
||||
x = min(column, startColumn) * gameMapVM.tileWidth
|
||||
y = min(row, startRow) * gameMapVM.tileHeight
|
||||
width = (offsetColumn + 1) * gameMapVM.tileWidth
|
||||
height = (offsetRow + 1) * gameMapVM.tileHeight
|
||||
}
|
||||
|
||||
fun proceed(row: Double, column: Double) {
|
||||
@@ -55,14 +57,17 @@ class TileSetSelection(private val gameMapVM: GameMapVM, private val brushVM: Br
|
||||
val rows = offsetRow.toInt() + 1
|
||||
val columns = offsetColumn.toInt() + 1
|
||||
|
||||
val brushArray = Array(rows) { rowIndex ->
|
||||
Array(columns) { columnIndex ->
|
||||
gameMapVM.tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex)
|
||||
if (editorStateVM.selectedLayer is TileLayer) {
|
||||
val tileSet = (editorStateVM.selectedLayer as TileLayer).tileSetProperty.value
|
||||
val brushArray = Array(rows) { rowIndex ->
|
||||
Array(columns) { columnIndex ->
|
||||
tileSet.getTile(firstRow + rowIndex, firstColumn + columnIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
brushVM.item = Brush.of(brushArray)
|
||||
brushVM.commit()
|
||||
brushVM.item = Brush.of(brushArray)
|
||||
brushVM.commit()
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(gc: GraphicsContext) {
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
package com.bartlomiejpluta.base.editor.tileset.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.Layer
|
||||
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.tileset.canvas.TileSetCanvas
|
||||
import com.bartlomiejpluta.base.editor.tileset.canvas.TileSetSelection
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.BrushVM
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.canvas.Canvas
|
||||
import javafx.scene.input.MouseEvent
|
||||
import tornadofx.doubleBinding
|
||||
|
||||
class TileSetPane(private val gameMapVM: GameMapVM, brushVM: BrushVM) : Canvas(), EventHandler<MouseEvent> {
|
||||
private val selection = TileSetSelection(gameMapVM, brushVM)
|
||||
private val tileSetCanvas = TileSetCanvas(gameMapVM, selection)
|
||||
class TileSetPane(editorStateVM: EditorStateVM, private val gameMapVM: GameMapVM, brushVM: BrushVM) : Canvas(),
|
||||
EventHandler<MouseEvent> {
|
||||
private val selection = TileSetSelection(editorStateVM, gameMapVM, brushVM)
|
||||
private val tileSetCanvas = TileSetCanvas(editorStateVM, selection)
|
||||
|
||||
init {
|
||||
onMouseMoved = this
|
||||
@@ -19,22 +24,37 @@ class TileSetPane(private val gameMapVM: GameMapVM, brushVM: BrushVM) : Canvas()
|
||||
onMousePressed = this
|
||||
onMouseReleased = this
|
||||
|
||||
width = gameMapVM.tileSet.width.toDouble()
|
||||
height = gameMapVM.tileSet.height.toDouble()
|
||||
updateSize(editorStateVM.selectedLayer)
|
||||
|
||||
editorStateVM.selectedLayerProperty.addListener { _, _, layer ->
|
||||
updateSize(layer)
|
||||
}
|
||||
|
||||
brushVM.itemProperty.addListener { _, _, _ -> render() }
|
||||
|
||||
render()
|
||||
}
|
||||
|
||||
private fun updateSize(layer: Layer?) {
|
||||
if (layer is TileLayer) {
|
||||
val tileSet = layer.tileSetProperty.value
|
||||
width = tileSet.width.toDouble()
|
||||
height = tileSet.height.toDouble()
|
||||
} else {
|
||||
width = 0.0
|
||||
height = 0.0
|
||||
}
|
||||
|
||||
render()
|
||||
}
|
||||
|
||||
private fun render() {
|
||||
tileSetCanvas.render(graphicsContext2D)
|
||||
}
|
||||
|
||||
override fun handle(event: MouseEvent?) {
|
||||
if (event != null) {
|
||||
tileSetCanvas.handleMouseInput(MapMouseEvent.of(event, gameMapVM.tileSet))
|
||||
tileSetCanvas.handleMouseInput(MapMouseEvent.of(event, gameMapVM))
|
||||
}
|
||||
|
||||
tileSetCanvas.render(graphicsContext2D)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.tileset.view.editor
|
||||
|
||||
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.component.TileSetPane
|
||||
import tornadofx.View
|
||||
@@ -10,8 +11,9 @@ import tornadofx.scrollpane
|
||||
class TileSetView : View() {
|
||||
private val gameMapVM = find<GameMapVM>()
|
||||
private val brushVM = find<BrushVM>()
|
||||
private val editorStateVM = find<EditorStateVM>()
|
||||
|
||||
private val tileSetPane = TileSetPane(gameMapVM, brushVM)
|
||||
private val tileSetPane = TileSetPane(editorStateVM, gameMapVM, brushVM)
|
||||
|
||||
override val root = scrollpane {
|
||||
this += tileSetPane
|
||||
|
||||
Reference in New Issue
Block a user