diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/Asset.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/Asset.kt index 2a0eead1..0e63926f 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/Asset.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/Asset.kt @@ -13,4 +13,6 @@ abstract class Asset(directory: ObjectProperty, val uid: String, val sourc val fileProperty = createObjectBinding({ File(directory.value, source) }, directory) val file by fileProperty + + override fun toString() = "${this.javaClass.simpleName}[name=$name, uid=$uid]" } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetFragment.kt index 9b358ad5..cb1758a9 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetFragment.kt @@ -2,12 +2,14 @@ package com.bartlomiejpluta.base.editor.asset.view.select import com.bartlomiejpluta.base.editor.asset.model.Asset import javafx.beans.property.ObjectProperty +import javafx.beans.property.SimpleObjectProperty import javafx.collections.ObservableList import tornadofx.* class SelectGraphicAssetFragment : Fragment("Select Asset") { val assets: ObservableList by param() - val asset: ObjectProperty by param() + + private val asset = SimpleObjectProperty() private val selectGraphicAssetView = find( SelectGraphicAssetView::assets to assets, diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/GraphicAssetParameter.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/GraphicAssetParameter.kt new file mode 100644 index 00000000..787bd84c --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/GraphicAssetParameter.kt @@ -0,0 +1,47 @@ +package com.bartlomiejpluta.base.editor.common.parameter.model + +import com.bartlomiejpluta.base.editor.asset.model.Asset +import com.bartlomiejpluta.base.editor.asset.view.select.SelectGraphicAssetFragment +import javafx.beans.property.SimpleObjectProperty +import javafx.collections.ObservableList +import javafx.scene.control.Label +import javafx.scene.input.MouseButton +import javafx.scene.input.MouseEvent +import tornadofx.Scope +import tornadofx.find +import tornadofx.select + +class GraphicAssetParameter( + key: String, + initialValue: T, + editable: Boolean = true, + assets: ObservableList, + onCommit: (oldValue: T, newValue: T, submit: () -> Unit) -> Unit = { _, _, submit -> submit() } +) : Parameter(key, initialValue, editable, false, onCommit) { + override val editorValueProperty = SimpleObjectProperty(initialValue) + + override val editor = Label(initialValue.name).apply { + textProperty().bind(editorValueProperty.select { it.nameProperty }) + + addEventHandler(MouseEvent.MOUSE_CLICKED) { + if (it.button == MouseButton.PRIMARY) { + find(Scope(), SelectGraphicAssetFragment::assets to assets).apply { + onComplete { asset -> + editorValueProperty.value = asset as T + commit() + } + + openModal(block = true, resizable = false) + } + it.consume() + } + } + } + + override val valueString: String + get() = value.name + + init { + super.init() + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/Parameter.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/Parameter.kt index b18e081c..f1ba198c 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/Parameter.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/common/parameter/model/Parameter.kt @@ -21,7 +21,7 @@ abstract class Parameter( val valueProperty: ObjectProperty = SimpleObjectProperty(initialValue) var value by valueProperty - fun commit() = onCommit(value, editorValueProperty.value, if (autocommit) this::submit else NOOP) + fun commit() = onCommit(value, editorValueProperty.value, if (autocommit) NOOP else this::submit) private fun submit() { value = editorValueProperty.value diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt index 552dafaf..2f707659 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/canvas/MapCanvas.kt @@ -1,9 +1,6 @@ package com.bartlomiejpluta.base.editor.map.canvas -import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer -import com.bartlomiejpluta.base.editor.map.model.layer.Layer -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.* import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM import com.bartlomiejpluta.base.editor.render.model.Renderable @@ -91,6 +88,7 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr is TileLayer -> renderTileLayer(gc, layer) is ObjectLayer -> renderObjectPassageMap(gc, layer) is ColorLayer -> renderColorLayer(gc, layer) + is ImageLayer -> renderImageLayer(gc, layer) } } @@ -132,6 +130,17 @@ class MapCanvas(val map: GameMapVM, private val editorStateVM: EditorStateVM, pr gc.fill = color } + private fun renderImageLayer(gc: GraphicsContext, imageLayer: ImageLayer) { + imageLayer.image?.let { + val alpha = gc.globalAlpha + gc.globalAlpha = imageLayer.alpha / 100.0 + + gc.drawImage(it, 0.0, 0.0) + + gc.globalAlpha = alpha + } + } + private fun renderGrid(gc: GraphicsContext) { if (editorStateVM.showGrid) { gc.drawImage(grid, 0.0, 0.0) diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt new file mode 100644 index 00000000..94f63427 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/ImageLayer.kt @@ -0,0 +1,31 @@ +package com.bartlomiejpluta.base.editor.map.model.layer + +import com.bartlomiejpluta.base.editor.image.asset.ImageAsset +import javafx.beans.binding.Bindings.createObjectBinding +import javafx.beans.property.SimpleObjectProperty +import javafx.beans.property.SimpleStringProperty +import javafx.scene.image.Image +import tornadofx.getValue +import tornadofx.setValue + +class ImageLayer(name: String, imageAsset: ImageAsset, alpha: Int) : Layer { + override val nameProperty = SimpleStringProperty(name) + + override var name by nameProperty + + val imageAssetProperty = SimpleObjectProperty(imageAsset) + var imageAsset by imageAssetProperty + + val imageProperty = createObjectBinding({ + imageAssetProperty.value.file.inputStream().use { fis -> Image(fis) } + }, imageAssetProperty) + + val image by imageProperty + + val alphaProperty = SimpleObjectProperty(alpha) + var alpha by alphaProperty + + override fun resize(rows: Int, columns: Int) { + // We essentially need to do nothing + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ColorLayerParametersBinder.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ColorLayerParametersBinder.kt index b643c5bf..678e7647 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ColorLayerParametersBinder.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ColorLayerParametersBinder.kt @@ -3,12 +3,13 @@ package com.bartlomiejpluta.base.editor.map.parameter.layer import com.bartlomiejpluta.base.editor.common.parameter.model.IntegerParameter import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer +import com.bartlomiejpluta.base.editor.project.model.Project import javafx.collections.ObservableList import org.springframework.stereotype.Component @Component class ColorLayerParametersBinder : LayerParametersBinder { - override fun bind(layer: ColorLayer, parameters: ObservableList>, onCommit: () -> Unit) { + override fun bind(layer: ColorLayer, parameters: ObservableList>, project: Project, onCommit: () -> Unit) { val red = IntegerParameter("red", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() } val green = IntegerParameter("green", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() } val blue = IntegerParameter("blue", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ImageLayerParametersBinder.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ImageLayerParametersBinder.kt new file mode 100644 index 00000000..efa44679 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/ImageLayerParametersBinder.kt @@ -0,0 +1,28 @@ +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.image.asset.ImageAsset +import com.bartlomiejpluta.base.editor.map.model.layer.ImageLayer +import com.bartlomiejpluta.base.editor.project.model.Project +import javafx.collections.ObservableList +import org.springframework.stereotype.Component + +@Component +class ImageLayerParametersBinder : LayerParametersBinder { + + override fun bind(layer: ImageLayer, parameters: ObservableList>, project: Project, onCommit: () -> Unit) { + val image = GraphicAssetParameter("image", layer.imageAsset, true, project.images) { _, _, submit -> + onCommit() + submit() + } + + image.valueProperty.bindBidirectional(layer.imageAssetProperty) + + parameters.addAll(image) + } + + override fun unbind(layer: ImageLayer, parameters: ObservableList>) { + (parameters[0] as GraphicAssetParameter).valueProperty.unbindBidirectional(layer.imageAssetProperty) + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/LayerParametersBinder.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/LayerParametersBinder.kt index 274c916d..25e8313a 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/LayerParametersBinder.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/parameter/layer/LayerParametersBinder.kt @@ -2,9 +2,10 @@ package com.bartlomiejpluta.base.editor.map.parameter.layer import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter import com.bartlomiejpluta.base.editor.map.model.layer.Layer +import com.bartlomiejpluta.base.editor.project.model.Project import javafx.collections.ObservableList interface LayerParametersBinder { - fun bind(layer: T, parameters: ObservableList>, onCommit: () -> Unit) + fun bind(layer: T, parameters: ObservableList>, project: Project, onCommit: () -> Unit) fun unbind(layer: T, parameters: ObservableList>) } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayerParameters.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayerParameters.kt index ab28dabb..bdf5c7f2 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayerParameters.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayerParameters.kt @@ -4,17 +4,22 @@ import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter import com.bartlomiejpluta.base.editor.common.parameter.view.ParametersTableFragment 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.parameter.layer.ColorLayerParametersBinder +import com.bartlomiejpluta.base.editor.map.parameter.layer.ImageLayerParametersBinder import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM +import com.bartlomiejpluta.base.editor.project.context.ProjectContext import tornadofx.View import tornadofx.observableListOf class MapLayerParameters : View() { private val editorStateVM = find() + private val projectContext: ProjectContext by di() // For some reason Spring does not want to autowire a list of beans // of LayerParametersBinder<> type private val colorLayerParametersBinder: ColorLayerParametersBinder by di() + private val imageLayerParametersBinder: ImageLayerParametersBinder by di() private val parameters = observableListOf>() @@ -22,12 +27,14 @@ class MapLayerParameters : View() { editorStateVM.selectedLayerProperty.addListener { _, previousLayer, layer -> when (previousLayer) { is ColorLayer -> colorLayerParametersBinder.unbind(previousLayer, parameters) + is ImageLayer -> imageLayerParametersBinder.unbind(previousLayer, parameters) } parameters.clear() when (layer) { - is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters) { fire(RedrawMapRequestEvent) } + is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters, projectContext.project!!) { fire(RedrawMapRequestEvent) } + is ImageLayer -> imageLayerParametersBinder.bind(layer, parameters, projectContext.project!!) { fire(RedrawMapRequestEvent) } } } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt index aa519d53..d9df9388 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.editor.map.view.editor +import com.bartlomiejpluta.base.editor.asset.view.select.SelectGraphicAssetFragment import com.bartlomiejpluta.base.editor.command.context.UndoableScope import com.bartlomiejpluta.base.editor.command.model.map.CreateLayerCommand import com.bartlomiejpluta.base.editor.command.model.map.MoveLayerCommand @@ -7,12 +8,11 @@ import com.bartlomiejpluta.base.editor.command.model.map.RemoveLayerCommand import com.bartlomiejpluta.base.editor.command.model.map.RenameLayerCommand import com.bartlomiejpluta.base.editor.command.service.UndoRedoService import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent -import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer -import com.bartlomiejpluta.base.editor.map.model.layer.Layer -import com.bartlomiejpluta.base.editor.map.model.layer.ObjectLayer -import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer +import com.bartlomiejpluta.base.editor.image.asset.ImageAsset +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 javafx.scene.control.ListCell import javafx.scene.control.ListView import javafx.scene.control.cell.TextFieldListCell @@ -23,6 +23,8 @@ import tornadofx.* class MapLayersView : View() { private val undoRedoService: UndoRedoService by di() + private val projectContext: ProjectContext by di() + override val scope = super.scope as UndoableScope private val mapVM = find() @@ -79,6 +81,23 @@ class MapLayersView : View() { undoRedoService.push(command, scope) } } + + item("Image Layer", graphic = FontIcon("fa-image")) { + action { + val scope = UndoableScope() + find(scope, SelectGraphicAssetFragment::assets to projectContext.project?.images!!).apply { + onComplete { + val layer = ImageLayer("Layer ${mapVM.layers.size + 1}", it as ImageAsset,100) + val command = CreateLayerCommand(mapVM.item, layer) + command.execute() + layersPane.selectionModel.select(mapVM.layers.size - 1) + undoRedoService.push(command, scope) + } + + openModal(block = true, resizable = false) + } + } + } } button(graphic = FontIcon("fa-chevron-up")) { @@ -164,6 +183,7 @@ class MapLayersView : View() { is TileLayer -> FontIcon("fa-th-large") is ObjectLayer -> FontIcon("fa-cube") is ColorLayer -> FontIcon("fa-paint-brush") + is ImageLayer -> FontIcon("fa-image") else -> throw IllegalStateException("Unknown layer type") } }