From 742093a2d1dfc593a9652dfa5d7c469a62f9abd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Tue, 23 Aug 2022 12:21:10 +0200 Subject: [PATCH] [Editor] Implement possibility to preview graphic assets --- .../component/GraphicAssetPreviewFragment.kt | 14 ++ .../component/GraphicAssetPreviewView.kt | 131 ++++++++++++++++++ .../base/editor/asset/model/GraphicAsset.kt | 17 +++ .../editor/asset/view/list/AssetsListView.kt | 2 + .../editor/asset/viewmodel/GraphicAssetVM.kt | 12 ++ .../editor/main/controller/MainController.kt | 13 ++ .../base/editor/main/view/MainView.kt | 14 ++ 7 files changed, 203 insertions(+) create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewFragment.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewView.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/GraphicAsset.kt create mode 100644 editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/viewmodel/GraphicAssetVM.kt diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewFragment.kt new file mode 100644 index 00000000..f31f48e8 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewFragment.kt @@ -0,0 +1,14 @@ +package com.bartlomiejpluta.base.editor.asset.component + +import com.bartlomiejpluta.base.editor.main.component.EditorFragment +import javafx.scene.input.KeyEvent + +class GraphicAssetPreviewFragment : EditorFragment() { + private val preview = find() + + override val root = preview.root + + override fun handleShortcut(event: KeyEvent) { + + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewView.kt new file mode 100644 index 00000000..3b00a252 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetPreviewView.kt @@ -0,0 +1,131 @@ +package com.bartlomiejpluta.base.editor.asset.component + +import com.bartlomiejpluta.base.editor.asset.viewmodel.GraphicAssetVM +import javafx.beans.binding.Bindings +import javafx.beans.property.SimpleIntegerProperty +import javafx.scene.image.Image +import javafx.scene.image.WritableImage +import javafx.scene.input.MouseEvent +import javafx.scene.paint.Color +import javafx.scene.text.TextAlignment +import tornadofx.* +import kotlin.math.max + +class GraphicAssetPreviewView : View() { + private val vm = find() + private val image = Image(vm.fileProperty.value.inputStream()) + private val rows = vm.rowsProperty.value + private val columns = vm.columnsProperty.value + private val chunkWidth = (image.width / columns).toInt() + private val chunkHeight = (image.height / rows).toInt() + private val mouseColumn = SimpleIntegerProperty(0) + private val mouseRow = SimpleIntegerProperty(0) + private val singleChunk = rows == 1 && columns == 1 + + override val root = borderpane { + center = scrollpane { + canvas(image.width + OFFSET_X, image.height + OFFSET_Y) { + addEventHandler(MouseEvent.ANY) { + mouseColumn.value = max(0, (it.x / chunkWidth).toInt() - 1) + mouseRow.value = max(0, (it.y / chunkHeight).toInt() - 1) + } + + graphicsContext2D.drawImage(createBackgroundImage(), OFFSET_X, OFFSET_Y) + graphicsContext2D.drawImage(image, OFFSET_X, OFFSET_Y) + + if(!singleChunk) { + graphicsContext2D.textAlign = TextAlignment.LEFT + for (i in 0 until columns) { + graphicsContext2D.fillText(i.toString(), OFFSET_X + chunkWidth * i + INDEX_OFFSET_X, OFFSET_Y - 5.0) + } + + graphicsContext2D.textAlign = TextAlignment.RIGHT + for (i in 0 until rows) { + graphicsContext2D.fillText(i.toString(), OFFSET_X - 5.0, OFFSET_Y + chunkHeight * i + INDEX_OFFSET_Y) + } + } + + if(!singleChunk) graphicsContext2D.drawImage(createGrid(), OFFSET_X, OFFSET_Y) + } + } + + bottom = label( + if (singleChunk) Bindings.format( + "Width: %d, Height: %d", + image.width.toInt(), + image.height.toInt() + ) + else Bindings.format( + "Rows: %d, Columns: %d, Chunk width: %d, Chunk height: %d, Cursor: %d, %d", + rows, + columns, + chunkWidth, + chunkHeight, + mouseRow, + mouseColumn + ) + ) + } + + private fun createBackgroundImage(): WritableImage { + val background = WritableImage(image.width.toInt(), image.height.toInt()) + + val writer = background.pixelWriter + for (x in 0 until background.width.toInt()) { + for (y in 0 until background.height.toInt()) { + val color = when (((x / BACKGROUND_TILE_WIDTH) + (y / BACKGROUND_TILE_HEIGHT)) % 2) { + 0 -> BACKGROUND_COLOR1 + else -> BACKGROUND_COLOR2 + } + + writer.setColor(x, y, color) + } + } + + return background + } + + private fun createGrid(): WritableImage { + val grid = WritableImage(image.width.toInt(), image.height.toInt()) + + val writer = grid.pixelWriter + val color = Color.BLACK + for (x in 0 until grid.width.toInt()) { + for (y in 0 until grid.height.toInt()) { + if (x % chunkWidth == 0) { + writer.setColor(x, y, color) + } + + if (y % chunkHeight == 0) { + writer.setColor(x, y, color) + } + } + } + + val lastX = grid.width.toInt() - 1 + val lastY = grid.height.toInt() - 1 + + for (x in 0 until grid.width.toInt()) { + writer.setColor(x, 0, color) + writer.setColor(x, lastY, color) + } + + for (y in 0 until grid.height.toInt()) { + writer.setColor(0, y, color) + writer.setColor(lastX, y, color) + } + + return grid + } + + companion object { + private const val BACKGROUND_TILE_WIDTH = 5 + private const val BACKGROUND_TILE_HEIGHT = 5 + private val BACKGROUND_COLOR1 = Color.color(1.0, 1.0, 1.0, 1.0) + private val BACKGROUND_COLOR2 = Color.color(0.95, 0.95, 0.95, 1.0) + private const val OFFSET_X = 30.0 + private const val OFFSET_Y = 30.0 + private const val INDEX_OFFSET_X = 0.0 + private const val INDEX_OFFSET_Y = 10.0 + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/GraphicAsset.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/GraphicAsset.kt new file mode 100644 index 00000000..f06269a8 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/model/GraphicAsset.kt @@ -0,0 +1,17 @@ +package com.bartlomiejpluta.base.editor.asset.model + +import javafx.beans.property.ObjectProperty +import javafx.beans.property.SimpleIntegerProperty +import java.io.File + +abstract class GraphicAsset( + directory: ObjectProperty, + uid: String, + source: String, + name: String, + val rows: Int, + val columns: Int +) : Asset(directory, uid, source, name) { + val rowsProperty = SimpleIntegerProperty(rows) + val columnsProperty = SimpleIntegerProperty(columns) +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/list/AssetsListView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/list/AssetsListView.kt index b6677b0b..bbb73154 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/list/AssetsListView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/list/AssetsListView.kt @@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.editor.asset.view.list import com.bartlomiejpluta.base.editor.asset.component.AssetTreeCell import com.bartlomiejpluta.base.editor.asset.model.Asset import com.bartlomiejpluta.base.editor.asset.model.AssetCategory +import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset import com.bartlomiejpluta.base.editor.file.model.ScriptAssetFileNode import com.bartlomiejpluta.base.editor.main.controller.MainController import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset @@ -106,6 +107,7 @@ class AssetsListView : View() { when (val item = selectionModel?.selectedItem?.value) { is GameMapAsset -> mainController.openMap(item.uid) is ScriptAssetFileNode -> mainController.openScript(item) + is GraphicAsset -> mainController.openGraphicAsset(item) } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/viewmodel/GraphicAssetVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/viewmodel/GraphicAssetVM.kt new file mode 100644 index 00000000..87af0e3f --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/viewmodel/GraphicAssetVM.kt @@ -0,0 +1,12 @@ +package com.bartlomiejpluta.base.editor.asset.viewmodel + +import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset +import javafx.beans.property.SimpleIntegerProperty +import tornadofx.ItemViewModel + +class GraphicAssetVM(asset: GraphicAsset) : ItemViewModel(asset) { + val nameProperty = bind(GraphicAsset::nameProperty) + val fileProperty = bind(GraphicAsset::file) + val rowsProperty = bind(GraphicAsset::rowsProperty) + val columnsProperty = bind(GraphicAsset::columnsProperty) +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/controller/MainController.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/controller/MainController.kt index 52722b49..e98b2bb7 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/controller/MainController.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/controller/MainController.kt @@ -3,6 +3,8 @@ package com.bartlomiejpluta.base.editor.main.controller import com.bartlomiejpluta.base.editor.animation.view.importing.ImportAnimationFragment import com.bartlomiejpluta.base.editor.animation.viewmodel.AnimationAssetDataVM import com.bartlomiejpluta.base.editor.asset.model.Asset +import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset +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.code.model.CodeScope @@ -151,6 +153,17 @@ class MainController : Controller() { } } + fun openGraphicAsset(asset: GraphicAsset) { + val findItem = { a: GraphicAssetVM -> a.fileProperty.value.absolutePath == asset.file.absolutePath } + openItem(findItem) { + val vm = GraphicAssetVM(asset) + val scope = Scope() + setInScope(vm, scope) + + scope to vm + } + } + private inline fun , S : Scope> openItem( findItem: (item: VM) -> Boolean, updateExistingScope: (S) -> Unit = {}, diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/view/MainView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/view/MainView.kt index f22c0da9..7bfe174d 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/view/MainView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/main/view/MainView.kt @@ -1,6 +1,8 @@ package com.bartlomiejpluta.base.editor.main.view +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetPreviewFragment import com.bartlomiejpluta.base.editor.asset.view.list.AssetsListView +import com.bartlomiejpluta.base.editor.asset.viewmodel.GraphicAssetVM import com.bartlomiejpluta.base.editor.code.view.build.BuildLogsView import com.bartlomiejpluta.base.editor.code.view.editor.CodeEditorFragment import com.bartlomiejpluta.base.editor.code.view.list.ScriptFilesView @@ -173,6 +175,18 @@ class MainView : View("BASE Game Editor") { } } + is GraphicAssetVM -> { + setInScope(vm, scope) + + EditorTab(find(scope), FontIcon("fa-file-image-o")).apply { + textProperty().bind(vm.nameProperty) + + setOnClosed { + mainController.openItems.remove(scope) + } + } + } + else -> throw IllegalStateException("Unsupported tab item") }