[Editor] Enable creating snapshots when map is being saved
Because the new map creation is done in different place than saving already existing maps, there is a bug that no snapshot is created when new map is created. The snapshots only are created when map is saved (Save via button with floppy disk icon in Map View toolbar).
This commit is contained in:
@@ -15,4 +15,8 @@ abstract class Asset(directory: ObjectProperty<File>, val uid: String, val sourc
|
||||
val file by fileProperty
|
||||
|
||||
override fun toString() = "${this.javaClass.simpleName}[name=$name, uid=$uid]"
|
||||
|
||||
open fun delete() {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.bartlomiejpluta.base.editor.asset.model
|
||||
|
||||
import javafx.beans.binding.Bindings.createObjectBinding
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import tornadofx.getValue
|
||||
import java.io.File
|
||||
|
||||
abstract class GraphicAsset(
|
||||
assetDirectory: ObjectProperty<File>,
|
||||
graphicDirectory: ObjectProperty<File>,
|
||||
uid: String,
|
||||
assetSource: String,
|
||||
val graphicSource: String,
|
||||
name: String
|
||||
) : Asset(assetDirectory, uid, assetSource, name) {
|
||||
|
||||
constructor(directory: ObjectProperty<File>, uid: String, source: String, name: String)
|
||||
: this(directory, directory, uid, source, source, name)
|
||||
|
||||
val graphicFileProperty = createObjectBinding({ File(graphicDirectory.value, graphicSource) }, graphicDirectory)
|
||||
val graphicFile by graphicFileProperty
|
||||
|
||||
override fun delete() {
|
||||
super.delete()
|
||||
graphicFile.delete()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.image.asset
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
|
||||
class ImageAsset(project: Project, uid: String, source: String, name: String) :
|
||||
Asset(project.imagesDirectoryProperty, uid, source, name)
|
||||
GraphicAsset(project.imagesDirectoryProperty, uid, source, name)
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.map.asset
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
|
||||
class GameMapAsset(project: Project, uid: String, name: String) :
|
||||
Asset(project.mapsDirectoryProperty, uid, "$uid.dat", name)
|
||||
GraphicAsset(project.mapsDirectoryProperty, project.mapsDirectoryProperty, uid, "$uid.dat", "$uid.png", name)
|
||||
@@ -70,6 +70,11 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
||||
override fun render(gc: GraphicsContext) {
|
||||
gc.clearRect(0.0, 0.0, gc.canvas.width, gc.canvas.height)
|
||||
|
||||
if (editorStateVM.takingSnapshot) {
|
||||
renderForPhoto(gc)
|
||||
return
|
||||
}
|
||||
|
||||
renderBackground(gc)
|
||||
renderUnderlyingLayers(gc)
|
||||
renderCover(gc)
|
||||
@@ -78,6 +83,10 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr
|
||||
painter.render(gc)
|
||||
}
|
||||
|
||||
private fun renderForPhoto(gc: GraphicsContext) {
|
||||
map.layers.forEach { dispatchLayerRender(gc, it) }
|
||||
}
|
||||
|
||||
private fun renderSelectedLayer(gc: GraphicsContext) {
|
||||
map.layers.getOrNull(editorStateVM.selectedLayerIndex)?.let { dispatchLayerRender(gc, it) }
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.map.controller
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import javafx.scene.image.Image
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.Controller
|
||||
|
||||
@@ -9,7 +10,7 @@ import tornadofx.Controller
|
||||
class MapController : Controller() {
|
||||
private val projectContext: ProjectContext by di()
|
||||
|
||||
fun saveMap(map: GameMap) {
|
||||
projectContext.saveMap(map)
|
||||
fun saveMap(map: GameMap, image: Image) {
|
||||
projectContext.saveMap(map, image)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.bartlomiejpluta.base.editor.map.view.editor
|
||||
|
||||
import com.bartlomiejpluta.base.editor.command.context.UndoableScope
|
||||
import com.bartlomiejpluta.base.editor.map.controller.MapController
|
||||
import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.tileset.view.editor.TileSetView
|
||||
import javafx.beans.binding.Bindings
|
||||
import tornadofx.*
|
||||
@@ -11,12 +13,15 @@ import tornadofx.*
|
||||
class MapFragment : Fragment() {
|
||||
override val scope = super.scope as UndoableScope
|
||||
|
||||
private val mapController: MapController by di()
|
||||
|
||||
private val editorStateVM = find<EditorStateVM>()
|
||||
private val mapVM = find<GameMapVM>()
|
||||
|
||||
private val mapView = find<MapView>()
|
||||
private val layersView = find<MapLayersView>()
|
||||
private val tileSetView = find<TileSetView>()
|
||||
private val toolbarView = find<MapToolbarView>()
|
||||
private val toolbarView = find<MapToolbarView>(MapToolbarView::onSaveMap to this::saveMap)
|
||||
private val statusBarView = find<MapStatusBarView>()
|
||||
private val layerParameters = find<MapLayerParameters>()
|
||||
|
||||
@@ -25,6 +30,10 @@ class MapFragment : Fragment() {
|
||||
editorStateVM.selectedLayerProperty
|
||||
)
|
||||
|
||||
private fun saveMap() {
|
||||
mapController.saveMap(mapVM.item, mapView.snapshot())
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
top = toolbarView.root
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ class MapToolbarView : View() {
|
||||
private val undoRedoService: UndoRedoService by di()
|
||||
private val mapController: MapController by di()
|
||||
|
||||
val onSaveMap: () -> Unit by param()
|
||||
|
||||
override val scope = super.scope as UndoableScope
|
||||
|
||||
private val mapVM = find<GameMapVM>()
|
||||
@@ -45,7 +47,7 @@ class MapToolbarView : View() {
|
||||
button(graphic = FontIcon("fa-floppy-o")) {
|
||||
shortcut("Ctrl+S")
|
||||
action {
|
||||
mapController.saveMap(mapVM.item)
|
||||
onSaveMap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.bartlomiejpluta.base.editor.map.component.MapPane
|
||||
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.image.Image
|
||||
import javafx.scene.input.MouseButton
|
||||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.transform.Scale
|
||||
@@ -41,6 +42,16 @@ class MapView : View() {
|
||||
subscribe<RedrawMapRequestEvent> { mapPane.render() }
|
||||
}
|
||||
|
||||
fun snapshot(): Image {
|
||||
editorStateVM.takingSnapshot = true
|
||||
mapPane.render()
|
||||
|
||||
return mapPane.snapshot(null, null).also {
|
||||
editorStateVM.takingSnapshot = false
|
||||
mapPane.render()
|
||||
}
|
||||
}
|
||||
|
||||
override val root = scrollpane {
|
||||
prefWidth = 640.0
|
||||
prefHeight = 480.0
|
||||
|
||||
@@ -30,4 +30,7 @@ class EditorStateVM : ViewModel() {
|
||||
|
||||
val cursorColumnProperty = SimpleIntegerProperty(-1)
|
||||
val cursorColumn by cursorColumnProperty
|
||||
|
||||
val takingSnapshotProperty = SimpleBooleanProperty(false)
|
||||
var takingSnapshot by takingSnapshotProperty
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.bartlomiejpluta.base.editor.project.serial.ProjectSerializer
|
||||
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 com.bartlomiejpluta.base.editor.util.fx.ImageUtil
|
||||
import com.bartlomiejpluta.base.editor.util.uid.UID
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
@@ -24,6 +25,7 @@ import tornadofx.setValue
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import kotlin.math.min
|
||||
|
||||
@Component
|
||||
class DefaultProjectContext : ProjectContext {
|
||||
@@ -88,11 +90,14 @@ class DefaultProjectContext : ProjectContext {
|
||||
File(it.mapsDirectory, asset.source).inputStream().use { fis -> mapDeserializer.deserialize(fis) }
|
||||
} ?: throw IllegalStateException("There is no open project in the context")
|
||||
|
||||
override fun saveMap(map: GameMap) {
|
||||
override fun saveMap(map: GameMap, image: Image) {
|
||||
project?.let {
|
||||
val asset = it.maps.firstOrNull { asset -> asset.uid == map.uid }
|
||||
?: throw IllegalStateException("The map with uid [${map.uid}] does not exist ")
|
||||
|
||||
val thumbnail = ImageUtil.scale(image, min(200, map.width.toInt()), min(200, map.height.toInt()), true)
|
||||
|
||||
ImageUtil.save(thumbnail, asset.graphicFile)
|
||||
File(it.mapsDirectory, asset.source).outputStream().use { fos -> mapSerializer.serialize(map, fos) }
|
||||
}
|
||||
}
|
||||
@@ -151,7 +156,7 @@ class DefaultProjectContext : ProjectContext {
|
||||
it.assetLists.firstOrNull { assets -> assets.remove(asset) }
|
||||
?: throw IllegalStateException("The asset does not belong to any of the assets lists")
|
||||
|
||||
asset.file.delete()
|
||||
asset.delete()
|
||||
} ?: throw IllegalStateException("There is no open project in the context")
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ interface ProjectContext {
|
||||
|
||||
fun importMap(name: String, map: GameMap)
|
||||
fun loadMap(uid: String): GameMap
|
||||
fun saveMap(map: GameMap)
|
||||
fun saveMap(map: GameMap, image: Image)
|
||||
|
||||
fun importTileSet(data: TileSetAssetData)
|
||||
fun loadTileSet(uid: String): TileSet
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.tileset.asset
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
|
||||
class TileSetAsset(project: Project, uid: String, source: String, name: String, val rows: Int, val columns: Int) :
|
||||
Asset(project.tileSetsDirectoryProperty, uid, source, name)
|
||||
GraphicAsset(project.tileSetsDirectoryProperty, uid, source, name)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.bartlomiejpluta.base.editor.util.fx
|
||||
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.image.ImageView
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.File
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
object ImageUtil {
|
||||
fun scale(source: Image, targetWidth: Int, targetHeight: Int, preserveRatio: Boolean) = ImageView(source).apply {
|
||||
this.isSmooth = false
|
||||
this.isPreserveRatio = preserveRatio
|
||||
this.fitWidth = targetWidth.toDouble()
|
||||
this.fitHeight = targetHeight.toDouble()
|
||||
}.snapshot(null, null)
|
||||
|
||||
fun save(image: Image, file: File) {
|
||||
val buffered = BufferedImage(image.width.toInt(), image.height.toInt(), BufferedImage.TYPE_INT_ARGB)
|
||||
val reader = image.pixelReader
|
||||
for (x in 0 until image.width.toInt()) {
|
||||
for (y in 0 until image.height.toInt()) {
|
||||
buffered.setRGB(x, y, reader.getArgb(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
ImageIO.write(buffered, file.extension, file)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user