From 12d9d6d7dfe0178ca9d187a372c27b2ba12ca624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Fri, 12 Feb 2021 09:21:37 +0100 Subject: [PATCH] [Editor] Enable storing Tile Sets and loading Game Maps with them --- .../editor/map/serial/ProtobufMapDeserializer.kt | 13 ++++++++----- .../editor/map/serial/ProtobufMapSerializer.kt | 1 + .../map/view/wizard/MapTileSetSelectionView.kt | 16 +++++++++++----- .../project/context/DefaultProjectContext.kt | 15 +++++++++++++++ .../editor/project/context/ProjectContext.kt | 2 ++ .../base/editor/tileset/model/TileSet.kt | 6 +++++- proto/src/main/proto/map.proto | 3 ++- 7 files changed, 44 insertions(+), 12 deletions(-) diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapDeserializer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapDeserializer.kt index 3ec82719..0c124dd5 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapDeserializer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapDeserializer.kt @@ -3,27 +3,30 @@ package com.bartlomiejpluta.base.editor.map.serial import com.bartlomiejpluta.base.editor.map.model.layer.Layer import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer import com.bartlomiejpluta.base.editor.map.model.map.GameMap +import com.bartlomiejpluta.base.editor.project.context.ProjectContext 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.stereotype.Component -import tornadofx.ResourceLookup import java.io.InputStream @Component class ProtobufMapDeserializer : MapDeserializer { - private val resources = ResourceLookup(this) - private val tileset = TileSet("Test TileSet", resources.image("/textures/tileset.png"), 160, 8) + + @Autowired + private lateinit var projectContext: ProjectContext override fun deserialize(input: InputStream): GameMap { - val map = GameMap(tileset) 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 proto.layersList.forEach { - map.layers.add(deserializeLayer(map.rows, map.columns, tileset, it)) + map.layers.add(deserializeLayer(map.rows, map.columns, tileSet, it)) } return map diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapSerializer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapSerializer.kt index 6a98b8c8..084e2f40 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapSerializer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/serial/ProtobufMapSerializer.kt @@ -15,6 +15,7 @@ class ProtobufMapSerializer : MapSerializer { protoMap.uid = item.uid protoMap.rows = item.rows protoMap.columns = item.columns + protoMap.tileSetUID = item.tileSet.uid item.layers.forEach { layer -> protoMap.addLayers(serializeLayer(layer)) } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/wizard/MapTileSetSelectionView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/wizard/MapTileSetSelectionView.kt index 23b59869..a5e42775 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/wizard/MapTileSetSelectionView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/wizard/MapTileSetSelectionView.kt @@ -1,6 +1,8 @@ package com.bartlomiejpluta.base.editor.map.view.wizard +import com.bartlomiejpluta.base.editor.asset.model.Asset import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM +import com.bartlomiejpluta.base.editor.project.context.ProjectContext import com.bartlomiejpluta.base.editor.tileset.model.TileSet import javafx.scene.control.ListView import tornadofx.* @@ -10,11 +12,15 @@ class MapTileSetSelectionView : View("Tile Set") { private var tileSetsListView: ListView by singleAssign() - // TODO(Fetch it from project assets) - private val tileSets = listOf( - TileSet("Big TileSet", resources.image("/textures/tileset.png"), 160, 8), - TileSet("Mage City", resources.image("/textures/magecity.png"), 44, 8) - ).asObservable() + private val projectContext: ProjectContext by di() + + // FIXME + // Because of loading all the images at once and storing them in cache + // this solution is not best efficient. It could be better to store images + // in the local cache, scoped to this view. + private val tileSets = + projectContext.project?.tileSets?.map(Asset::uid)?.map(projectContext::loadTileSet)?.asObservable() + ?: throw IllegalStateException("There is no open project in the context") // FIXME diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt index 96a1163a..f3dd1400 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt @@ -10,9 +10,11 @@ import com.bartlomiejpluta.base.editor.project.serial.ProjectDeserializer import com.bartlomiejpluta.base.editor.project.serial.ProjectSerializer import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAsset import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAssetBuilder +import com.bartlomiejpluta.base.editor.tileset.model.TileSet import com.bartlomiejpluta.base.editor.util.uid.UID import javafx.beans.property.ObjectProperty import javafx.beans.property.SimpleObjectProperty +import javafx.scene.image.Image import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component import tornadofx.getValue @@ -23,6 +25,7 @@ import java.io.FileOutputStream @Component class DefaultProjectContext : ProjectContext { + private val tileSetCache = mutableMapOf() @Autowired private lateinit var projectSerializer: ProjectSerializer @@ -42,6 +45,7 @@ class DefaultProjectContext : ProjectContext { init { projectProperty.addListener { _, _, newProject -> newProject?.mkdirs() + tileSetCache.clear() } } @@ -94,4 +98,15 @@ class DefaultProjectContext : ProjectContext { } } } + + override fun loadTileSet(uid: String) = tileSetCache.getOrPut(uid) { + project?.let { + val asset = it.tileSets.first { tileSet -> tileSet.uid == uid } + ?: throw IllegalStateException("The Tile Set with uid [$uid] does not exist ") + + val image = File(it.tileSetsDirectory, asset.source).inputStream().use { fis -> Image(fis) } + + TileSet(uid, asset.name, image, asset.rows, asset.columns) + } ?: throw IllegalStateException("There is no open project in the context") + } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt index cfad4e5a..871b2018 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt @@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.editor.project.context import com.bartlomiejpluta.base.editor.map.model.map.GameMap import com.bartlomiejpluta.base.editor.project.model.Project import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAssetBuilder +import com.bartlomiejpluta.base.editor.tileset.model.TileSet import javafx.beans.property.ObjectProperty import java.io.File @@ -17,4 +18,5 @@ interface ProjectContext { fun loadMap(uid: String): GameMap fun importTileSet(builder: TileSetAssetBuilder) + fun loadTileSet(uid: String): TileSet } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/model/TileSet.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/model/TileSet.kt index 8917caa7..729db2f6 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/model/TileSet.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/model/TileSet.kt @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.editor.tileset.model import com.bartlomiejpluta.base.editor.map.model.brush.Brush +import javafx.beans.property.ReadOnlyStringWrapper import javafx.beans.property.SimpleIntegerProperty import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleStringProperty @@ -12,7 +13,10 @@ import tornadofx.toObservable import java.nio.ByteBuffer -class TileSet(name: String, image: Image, rows: Int, columns: Int) { +class TileSet(uid: String, name: String, image: Image, rows: Int, columns: Int) { + val uidProperty = ReadOnlyStringWrapper(uid) + val uid by uidProperty + val nameProperty = SimpleStringProperty(name) val name by nameProperty diff --git a/proto/src/main/proto/map.proto b/proto/src/main/proto/map.proto index 1bc3c510..4bff3be0 100644 --- a/proto/src/main/proto/map.proto +++ b/proto/src/main/proto/map.proto @@ -7,7 +7,8 @@ message GameMap { required string uid = 1; required uint32 rows = 2; required uint32 columns = 3; - repeated Layer layers = 4; + required string tileSetUID = 4; + repeated Layer layers = 5; } message Layer {