[Editor] Enable basic Image Layer rendering

This commit is contained in:
2021-02-20 09:45:01 +01:00
parent 5c44f0e5c4
commit f2fe303e31
11 changed files with 161 additions and 13 deletions

View File

@@ -13,4 +13,6 @@ abstract class Asset(directory: ObjectProperty<File>, val uid: String, val sourc
val fileProperty = createObjectBinding({ File(directory.value, source) }, directory) val fileProperty = createObjectBinding({ File(directory.value, source) }, directory)
val file by fileProperty val file by fileProperty
override fun toString() = "${this.javaClass.simpleName}[name=$name, uid=$uid]"
} }

View File

@@ -2,12 +2,14 @@ package com.bartlomiejpluta.base.editor.asset.view.select
import com.bartlomiejpluta.base.editor.asset.model.Asset import com.bartlomiejpluta.base.editor.asset.model.Asset
import javafx.beans.property.ObjectProperty import javafx.beans.property.ObjectProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.collections.ObservableList import javafx.collections.ObservableList
import tornadofx.* import tornadofx.*
class SelectGraphicAssetFragment : Fragment("Select Asset") { class SelectGraphicAssetFragment : Fragment("Select Asset") {
val assets: ObservableList<Asset> by param() val assets: ObservableList<Asset> by param()
val asset: ObjectProperty<Asset> by param()
private val asset = SimpleObjectProperty<Asset>()
private val selectGraphicAssetView = find<SelectGraphicAssetView>( private val selectGraphicAssetView = find<SelectGraphicAssetView>(
SelectGraphicAssetView::assets to assets, SelectGraphicAssetView::assets to assets,

View File

@@ -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<T : Asset>(
key: String,
initialValue: T,
editable: Boolean = true,
assets: ObservableList<T>,
onCommit: (oldValue: T, newValue: T, submit: () -> Unit) -> Unit = { _, _, submit -> submit() }
) : Parameter<T>(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<SelectGraphicAssetFragment>(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()
}
}

View File

@@ -21,7 +21,7 @@ abstract class Parameter<T>(
val valueProperty: ObjectProperty<T> = SimpleObjectProperty(initialValue) val valueProperty: ObjectProperty<T> = SimpleObjectProperty(initialValue)
var value by valueProperty 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() { private fun submit() {
value = editorValueProperty.value value = editorValueProperty.value

View File

@@ -1,9 +1,6 @@
package com.bartlomiejpluta.base.editor.map.canvas package com.bartlomiejpluta.base.editor.map.canvas
import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer import com.bartlomiejpluta.base.editor.map.model.layer.*
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.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
import com.bartlomiejpluta.base.editor.render.model.Renderable 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 TileLayer -> renderTileLayer(gc, layer)
is ObjectLayer -> renderObjectPassageMap(gc, layer) is ObjectLayer -> renderObjectPassageMap(gc, layer)
is ColorLayer -> renderColorLayer(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 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) { private fun renderGrid(gc: GraphicsContext) {
if (editorStateVM.showGrid) { if (editorStateVM.showGrid) {
gc.drawImage(grid, 0.0, 0.0) gc.drawImage(grid, 0.0, 0.0)

View File

@@ -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
}
}

View File

@@ -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.IntegerParameter
import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter
import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer
import com.bartlomiejpluta.base.editor.project.model.Project
import javafx.collections.ObservableList import javafx.collections.ObservableList
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
@Component @Component
class ColorLayerParametersBinder : LayerParametersBinder<ColorLayer> { class ColorLayerParametersBinder : LayerParametersBinder<ColorLayer> {
override fun bind(layer: ColorLayer, parameters: ObservableList<Parameter<*>>, onCommit: () -> Unit) { override fun bind(layer: ColorLayer, parameters: ObservableList<Parameter<*>>, project: Project, onCommit: () -> Unit) {
val red = IntegerParameter("red", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() } val red = IntegerParameter("red", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }
val green = IntegerParameter("green", 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() } val blue = IntegerParameter("blue", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }

View File

@@ -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<ImageLayer> {
override fun bind(layer: ImageLayer, parameters: ObservableList<Parameter<*>>, 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<Parameter<*>>) {
(parameters[0] as GraphicAssetParameter<ImageAsset>).valueProperty.unbindBidirectional(layer.imageAssetProperty)
}
}

View File

@@ -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.common.parameter.model.Parameter
import com.bartlomiejpluta.base.editor.map.model.layer.Layer import com.bartlomiejpluta.base.editor.map.model.layer.Layer
import com.bartlomiejpluta.base.editor.project.model.Project
import javafx.collections.ObservableList import javafx.collections.ObservableList
interface LayerParametersBinder<T : Layer> { interface LayerParametersBinder<T : Layer> {
fun bind(layer: T, parameters: ObservableList<Parameter<*>>, onCommit: () -> Unit) fun bind(layer: T, parameters: ObservableList<Parameter<*>>, project: Project, onCommit: () -> Unit)
fun unbind(layer: T, parameters: ObservableList<Parameter<*>>) fun unbind(layer: T, parameters: ObservableList<Parameter<*>>)
} }

View File

@@ -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.common.parameter.view.ParametersTableFragment
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer 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.ColorLayerParametersBinder
import com.bartlomiejpluta.base.editor.map.parameter.layer.ImageLayerParametersBinder
import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
import tornadofx.View import tornadofx.View
import tornadofx.observableListOf import tornadofx.observableListOf
class MapLayerParameters : View() { class MapLayerParameters : View() {
private val editorStateVM = find<EditorStateVM>() private val editorStateVM = find<EditorStateVM>()
private val projectContext: ProjectContext by di()
// For some reason Spring does not want to autowire a list of beans // For some reason Spring does not want to autowire a list of beans
// of LayerParametersBinder<> type // of LayerParametersBinder<> type
private val colorLayerParametersBinder: ColorLayerParametersBinder by di() private val colorLayerParametersBinder: ColorLayerParametersBinder by di()
private val imageLayerParametersBinder: ImageLayerParametersBinder by di()
private val parameters = observableListOf<Parameter<*>>() private val parameters = observableListOf<Parameter<*>>()
@@ -22,12 +27,14 @@ class MapLayerParameters : View() {
editorStateVM.selectedLayerProperty.addListener { _, previousLayer, layer -> editorStateVM.selectedLayerProperty.addListener { _, previousLayer, layer ->
when (previousLayer) { when (previousLayer) {
is ColorLayer -> colorLayerParametersBinder.unbind(previousLayer, parameters) is ColorLayer -> colorLayerParametersBinder.unbind(previousLayer, parameters)
is ImageLayer -> imageLayerParametersBinder.unbind(previousLayer, parameters)
} }
parameters.clear() parameters.clear()
when (layer) { 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) }
} }
} }
} }

View File

@@ -1,5 +1,6 @@
package com.bartlomiejpluta.base.editor.map.view.editor 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.context.UndoableScope
import com.bartlomiejpluta.base.editor.command.model.map.CreateLayerCommand import com.bartlomiejpluta.base.editor.command.model.map.CreateLayerCommand
import com.bartlomiejpluta.base.editor.command.model.map.MoveLayerCommand 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.model.map.RenameLayerCommand
import com.bartlomiejpluta.base.editor.command.service.UndoRedoService import com.bartlomiejpluta.base.editor.command.service.UndoRedoService
import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent import com.bartlomiejpluta.base.editor.event.RedrawMapRequestEvent
import com.bartlomiejpluta.base.editor.map.model.layer.ColorLayer import com.bartlomiejpluta.base.editor.image.asset.ImageAsset
import com.bartlomiejpluta.base.editor.map.model.layer.Layer import com.bartlomiejpluta.base.editor.map.model.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.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM 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.ListCell
import javafx.scene.control.ListView import javafx.scene.control.ListView
import javafx.scene.control.cell.TextFieldListCell import javafx.scene.control.cell.TextFieldListCell
@@ -23,6 +23,8 @@ import tornadofx.*
class MapLayersView : View() { class MapLayersView : View() {
private val undoRedoService: UndoRedoService by di() private val undoRedoService: UndoRedoService by di()
private val projectContext: ProjectContext by di()
override val scope = super.scope as UndoableScope override val scope = super.scope as UndoableScope
private val mapVM = find<GameMapVM>() private val mapVM = find<GameMapVM>()
@@ -79,6 +81,23 @@ class MapLayersView : View() {
undoRedoService.push(command, scope) undoRedoService.push(command, scope)
} }
} }
item("Image Layer", graphic = FontIcon("fa-image")) {
action {
val scope = UndoableScope()
find<SelectGraphicAssetFragment>(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")) { button(graphic = FontIcon("fa-chevron-up")) {
@@ -164,6 +183,7 @@ class MapLayersView : View() {
is TileLayer -> FontIcon("fa-th-large") is TileLayer -> FontIcon("fa-th-large")
is ObjectLayer -> FontIcon("fa-cube") is ObjectLayer -> FontIcon("fa-cube")
is ColorLayer -> FontIcon("fa-paint-brush") is ColorLayer -> FontIcon("fa-paint-brush")
is ImageLayer -> FontIcon("fa-image")
else -> throw IllegalStateException("Unknown layer type") else -> throw IllegalStateException("Unknown layer type")
} }
} }