[Editor] Enable serialization/deserialization of auto tile layer

This commit is contained in:
2022-08-26 18:41:17 +02:00
parent 36f68a6056
commit 6fb0a0a24b
7 changed files with 127 additions and 34 deletions

View File

@@ -8,6 +8,7 @@ import com.bartlomiejpluta.base.editor.asset.view.select.SelectGraphicAssetFragm
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.autotile.asset.AutoTileAsset
import com.bartlomiejpluta.base.editor.autotile.view.importing.ImportAutoTileFragment
import com.bartlomiejpluta.base.editor.autotile.viewmodel.AutoTileAssetDataVM
import com.bartlomiejpluta.base.editor.characterset.view.importing.ImportCharacterSetFragment
@@ -94,32 +95,54 @@ class MainController : Controller() {
setInScope(vm, scope)
find<MapImportFragment>(scope).apply {
onComplete {
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
}
val map = projectContext.importMapFromFile(vm.name, vm.handler, File(vm.file), ::askForNewTileSetAsset, ::askForNewAutoTileAsset)
openItems[scope] = GameMapVM(map)
}
openModal(block = true, resizable = false)
}
}
private fun askForNewTileSetAsset(name: String, uid: String): String {
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)
}
return newUid
}
private fun askForNewAutoTileAsset(name: String, uid: String): String {
var newUid = ""
find<SelectGraphicAssetFragment<AutoTileAsset>>(
Scope(),
SelectGraphicAssetFragment<AutoTileAsset>::assets to projectContext.project?.autoTiles!!,
SelectGraphicAssetFragment<AutoTileAsset>::comment to "You are importing a tile layer which originally was defined\nwith an other Auto Tile asset data with UID: [$uid].\nPlease select asset you would like to apply for layer $name.\n".toProperty(),
SelectGraphicAssetFragment<AutoTileAsset>::cancelable to false.toProperty()
).apply {
title = "Select Auto Tile for layer $name"
onComplete {
newUid = it.uid
}
openModal(block = true, resizable = false, stageStyle = StageStyle.UNDECORATED)
}
return newUid
}
fun openProject() {
chooseFile(

View File

@@ -0,0 +1,44 @@
package com.bartlomiejpluta.base.editor.map.model.layer
import com.bartlomiejpluta.base.editor.autotile.asset.AutoTileAsset
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 AutoTileLayer(
name: String,
rows: Int,
columns: Int,
autoTileAsset: AutoTileAsset,
layer: Array<Array<Boolean>> = Array(rows) { Array(columns) { false } }
) : Layer {
var layer = layer
private set
val autoTileAssetProperty = autoTileAsset.toProperty()
var autoTileAsset by autoTileAssetProperty
// val autoTileProperty = Bindings.createObjectBinding({
// autoTileAsset.file.inputStream().use { fis ->
// // create AutoTile
// }
// }, autoTileAssetProperty)
override val nameProperty = SimpleStringProperty(name)
override fun resize(rows: Int, columns: Int) {
layer = Array(rows) { row ->
Array(columns) { column ->
layer.getOrNull(row)?.getOrNull(column) ?: false
}
}
}
override var name: String by nameProperty
}

View File

@@ -7,5 +7,5 @@ import com.bartlomiejpluta.base.editor.tileset.model.TileSet
import java.io.InputStream
interface MapDeserializer : Deserializer<GameMap> {
fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String): GameMap
fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String, replaceAutoTile: (String, String) -> String): GameMap
}

View File

@@ -6,9 +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
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext
@@ -25,9 +23,9 @@ class ProtobufMapDeserializer : MapDeserializer {
appContext.getBean(ProjectContext::class.java)
}
override fun deserialize(input: InputStream) = deserialize(input) { _, uid -> uid }
override fun deserialize(input: InputStream) = deserialize(input, { _, uid -> uid }, { _, uid -> uid })
override fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String): GameMap {
override fun deserialize(input: InputStream, replaceTileSet: (String, String) -> String, replaceAutoTile: (String, String) -> String): GameMap {
val proto = GameMapProto.GameMap.parseFrom(input)
val map = GameMap(proto.tileWidth.toDouble(), proto.tileHeight.toDouble())
map.uid = proto.uid
@@ -36,15 +34,16 @@ class ProtobufMapDeserializer : MapDeserializer {
map.handler = proto.handler
proto.layersList
.filter { it.hasTileLayer() || it.hasObjectLayer() || it.hasColorLayer() }
.forEach { map.layers.add(deserializeLayer(map.rows, map.columns, it, replaceTileSet)) }
.filter { it.hasTileLayer() || it.hasAutoTileLayer() || it.hasObjectLayer() || it.hasColorLayer() }
.forEach { map.layers.add(deserializeLayer(map.rows, map.columns, it, replaceTileSet, replaceAutoTile)) }
return map
}
private fun deserializeLayer(rows: Int, columns: Int, proto: GameMapProto.Layer, replaceTileSet: (String, String) -> String): Layer {
private fun deserializeLayer(rows: Int, columns: Int, proto: GameMapProto.Layer, replaceTileSet: (String, String) -> String, replaceAutoTile: (String, String) -> String): Layer {
return when {
proto.hasTileLayer() -> deserializeTileLayer(rows, columns, proto, replaceTileSet)
proto.hasAutoTileLayer() -> deserializeAutoTileLayer(rows, columns, proto, replaceAutoTile)
proto.hasObjectLayer() -> deserializeObjectLayer(rows, columns, proto)
proto.hasColorLayer() -> deserializeColorLayer(proto)
proto.hasImageLayer() -> deserializeImageLayer(proto)
@@ -68,6 +67,17 @@ class ProtobufMapDeserializer : MapDeserializer {
return TileLayer(proto.name, rows, columns, tileSetAsset, layer)
}
private fun deserializeAutoTileLayer(rows: Int, columns: Int, proto: GameMapProto.Layer, replaceTileSet: (String, String) -> String): AutoTileLayer {
val layer: Array<Array<Boolean>> = Array(rows) { Array(columns) { false } }
val autoTile = projectContext.findAutoTileAsset(replaceTileSet(proto.name, proto.autoTileLayer.autotileUID))
proto.autoTileLayer.tilesList.forEachIndexed { index, tile ->
layer[index / columns][index % columns] = tile
}
return AutoTileLayer(proto.name, rows, columns, autoTile, layer)
}
private fun deserializeObjectLayer(rows: Int, columns: Int, proto: GameMapProto.Layer): Layer {
val passageMap: Array<Array<PassageAbility>> = Array(rows) { Array(columns) { PassageAbility.ALLOW } }

View File

@@ -33,6 +33,12 @@ class ProtobufMapSerializer : MapSerializer {
.build()
.let { GameMapProto.Layer.newBuilder().setName(layer.name).setTileLayer(it).build() }
is AutoTileLayer -> layer.layer.flatMap { it.asIterable() }
.fold(GameMapProto.AutoTileLayer.newBuilder()) { acc, tile -> acc.addTiles(tile) }
.setAutotileUID(layer.autoTileAsset.uid)
.build()
.let { GameMapProto.Layer.newBuilder().setName(layer.name).setAutoTileLayer(it).build() }
is ObjectLayer -> layer.passageMap.flatMap { it.asIterable() }
.fold(GameMapProto.ObjectLayer.newBuilder()) { acc, passage ->
acc.addPassageMap(

View File

@@ -129,10 +129,11 @@ class DefaultProjectContext : ProjectContext {
name: String,
handler: String,
file: File,
replaceTileSet: (String, String) -> String
replaceTileSet: (String, String) -> String,
replaceAutoTile: (String, String) -> String,
) =
project?.let { project ->
val map = file.inputStream().use { mapDeserializer.deserialize(it, replaceTileSet) }
val map = file.inputStream().use { mapDeserializer.deserialize(it, replaceTileSet, replaceAutoTile) }
UID.next(project.maps.map(Asset::uid)).let { uid ->
val asset = GameMapAsset(project, uid, name)
map.uid = uid
@@ -208,6 +209,11 @@ class DefaultProjectContext : ProjectContext {
?: throw IllegalStateException("The Tile Set with uid [$uid] does not exist ")
} ?: throw IllegalStateException("There is no open project in the context")
override fun findAutoTileAsset(uid: String) = project?.let {
it.autoTiles.firstOrNull { autoTile -> autoTile.uid == uid }
?: throw IllegalStateException("The Auto Tile 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 ->

View File

@@ -3,9 +3,10 @@ package com.bartlomiejpluta.base.editor.project.context
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
import com.bartlomiejpluta.base.editor.asset.model.Asset
import com.bartlomiejpluta.base.editor.audio.asset.SoundAssetData
import com.bartlomiejpluta.base.editor.autotile.asset.AutoTileAsset
import com.bartlomiejpluta.base.editor.autotile.asset.AutoTileAssetData
import com.bartlomiejpluta.base.editor.code.model.Code
import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAssetData
import com.bartlomiejpluta.base.editor.code.model.Code
import com.bartlomiejpluta.base.editor.file.model.FileNode
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAssetData
import com.bartlomiejpluta.base.editor.gui.widget.asset.WidgetAsset
@@ -31,15 +32,18 @@ interface ProjectContext {
fun createNewProject(project: Project)
fun importMap(name: String, map: GameMap)
fun importMapFromFile(name: String, handler: String, file: File, replaceTileSet: (String, String) -> String): GameMap
fun importMapFromFile(name: String, handler: String, file: File, replaceTileSet: (String, String) -> String, replaceAutoTile: (String, String) -> String,
): GameMap
fun loadMap(uid: String): GameMap
fun saveMap(map: GameMap)
fun importTileSet(data: TileSetAssetData)
fun loadTileSet(uid: String): TileSet
fun importAutoTile(data: AutoTileAssetData)
fun findTileSetAsset(uid: String): TileSetAsset
fun importAutoTile(data: AutoTileAssetData)
fun findAutoTileAsset(uid: String): AutoTileAsset
fun importImage(data: ImageAssetData)
fun findImageAsset(uid: String): ImageAsset