[Editor] Add support for Animations
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.animation.asset
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
|
||||
class AnimationAsset(project: Project, uid: String, source: String, name: String, val rows: Int, val columns: Int) :
|
||||
Asset(project.animationsDirectoryProperty, uid, source, name)
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.bartlomiejpluta.base.editor.animation.asset
|
||||
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
import java.io.File
|
||||
|
||||
class AnimationAssetData {
|
||||
val nameProperty = SimpleStringProperty()
|
||||
var name by nameProperty
|
||||
|
||||
val fileProperty = SimpleObjectProperty<File>()
|
||||
var file by fileProperty
|
||||
|
||||
val rowsProperty = SimpleIntegerProperty()
|
||||
var rows by rowsProperty
|
||||
|
||||
val columnsProperty = SimpleIntegerProperty()
|
||||
var columns by columnsProperty
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.bartlomiejpluta.base.editor.animation.view.importing
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
|
||||
import com.bartlomiejpluta.base.editor.animation.viewmodel.AnimationAssetDataVM
|
||||
import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.scene.Cursor
|
||||
import javafx.scene.image.Image
|
||||
import javafx.stage.FileChooser
|
||||
import tornadofx.*
|
||||
|
||||
class ImportAnimationFragment : Fragment("Import Animation") {
|
||||
private val dataVM = find<AnimationAssetDataVM>()
|
||||
private val imagePreview = SimpleObjectProperty<Image?>()
|
||||
|
||||
private var onCompleteConsumer: ((AnimationAssetData) -> Unit)? = null
|
||||
|
||||
init {
|
||||
dataVM.fileProperty.addListener { _, _, file ->
|
||||
when (file) {
|
||||
null -> imagePreview.value = null
|
||||
else -> file.inputStream().use { imagePreview.value = Image(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onComplete(consumer: (AnimationAssetData) -> Unit) {
|
||||
this.onCompleteConsumer = consumer
|
||||
}
|
||||
|
||||
override val root = form {
|
||||
prefHeight = 480.0
|
||||
|
||||
fieldset("Import Animation") {
|
||||
hbox {
|
||||
vbox {
|
||||
scrollpane {
|
||||
prefWidth = 300.0
|
||||
prefHeightProperty().bind(this@form.heightProperty())
|
||||
imageview(imagePreview)
|
||||
tooltip = tooltip("Click to choose Animation file")
|
||||
cursor = Cursor.HAND
|
||||
|
||||
setOnMouseClicked {
|
||||
dataVM.file = chooseFile(
|
||||
title = "Select Animation",
|
||||
filters = arrayOf(FileChooser.ExtensionFilter("PNG Images (*.png)", "*.png"))
|
||||
).getOrNull(0)
|
||||
}
|
||||
|
||||
dataVM.validationContext.addValidator(this@vbox, dataVM.fileProperty) {
|
||||
when {
|
||||
it == null -> error("This field is required")
|
||||
!it.exists() -> error("The file must exist")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vbox {
|
||||
paddingLeft = 20.0
|
||||
|
||||
field("Animation Name") {
|
||||
textfield(dataVM.nameProperty) {
|
||||
required()
|
||||
trimWhitespace()
|
||||
}
|
||||
}
|
||||
|
||||
field("Animation Rows") {
|
||||
spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.rowsProperty, editable = true) {
|
||||
required()
|
||||
editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.rows)
|
||||
}
|
||||
}
|
||||
|
||||
field("Animation Columns") {
|
||||
spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.columnsProperty, editable = true) {
|
||||
required()
|
||||
editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.columns)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buttonbar {
|
||||
button("Import") {
|
||||
action {
|
||||
if (dataVM.commit()) {
|
||||
onCompleteConsumer?.let { it(dataVM.item) }
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button("Reset") {
|
||||
action { dataVM.rollback() }
|
||||
}
|
||||
|
||||
|
||||
button("Cancel") {
|
||||
action { close() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.bartlomiejpluta.base.editor.animation.viewmodel
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
|
||||
import tornadofx.ItemViewModel
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class AnimationAssetDataVM : ItemViewModel<AnimationAssetData>(AnimationAssetData()) {
|
||||
val nameProperty = bind(AnimationAssetData::nameProperty)
|
||||
var name by nameProperty
|
||||
|
||||
val fileProperty = bind(AnimationAssetData::fileProperty)
|
||||
var file by fileProperty
|
||||
|
||||
val rowsProperty = bind(AnimationAssetData::rowsProperty)
|
||||
var rows by rowsProperty
|
||||
|
||||
val columnsProperty = bind(AnimationAssetData::columnsProperty)
|
||||
var columns by columnsProperty
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.asset.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAsset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.asset.model.AssetCategory
|
||||
import com.bartlomiejpluta.base.editor.entityset.asset.EntitySet
|
||||
@@ -72,6 +73,7 @@ class AssetTreeCell(renameAsset: (asset: Asset, name: String) -> Asset, deleteAs
|
||||
is TileSetAsset -> FontIcon("fa-th")
|
||||
is ImageAsset -> FontIcon("fa-image")
|
||||
is EntitySet -> FontIcon("fa-male")
|
||||
is AnimationAsset -> FontIcon("fa-film")
|
||||
is FontAsset -> FontIcon("fa-font")
|
||||
is WidgetAsset -> FontIcon("fa-tachometer")
|
||||
else -> null
|
||||
|
||||
@@ -32,6 +32,10 @@ class AssetsListView : View() {
|
||||
menuitem("Import Entity Set...") { mainController.importEntitySet() }
|
||||
}
|
||||
|
||||
private val animations = AssetCategory("Animations").apply {
|
||||
menuitem("Import Animation...") { mainController.importAnimation() }
|
||||
}
|
||||
|
||||
private val fonts = AssetCategory("Fonts").apply {
|
||||
menuitem("Import Font...") { mainController.importFont() }
|
||||
}
|
||||
@@ -46,6 +50,7 @@ class AssetsListView : View() {
|
||||
tileSets,
|
||||
images,
|
||||
entitySet,
|
||||
animations,
|
||||
fonts,
|
||||
widgets
|
||||
)
|
||||
@@ -59,6 +64,7 @@ class AssetsListView : View() {
|
||||
Bindings.bindContent(tileSets.items, it.tileSets)
|
||||
Bindings.bindContent(images.items, it.images)
|
||||
Bindings.bindContent(entitySet.items, it.entitySets)
|
||||
Bindings.bindContent(animations.items, it.animations)
|
||||
Bindings.bindContent(fonts.items, it.fonts)
|
||||
Bindings.bindContent(widgets.items, it.widgets)
|
||||
root.root.expandAll()
|
||||
|
||||
@@ -27,6 +27,7 @@ class DefaultProjectAssembler : ProjectAssembler {
|
||||
packager.pack(project.tileSetsDirectory, targetJar, "BOOT-INF/classes/project/tilesets")
|
||||
packager.pack(project.imagesDirectory, targetJar, "BOOT-INF/classes/project/images")
|
||||
packager.pack(project.entitySetsDirectory, targetJar, "BOOT-INF/classes/project/entsets")
|
||||
packager.pack(project.animationsDirectory, targetJar, "BOOT-INF/classes/project/animations")
|
||||
packager.pack(project.fontsDirectory, targetJar, "BOOT-INF/classes/project/fonts")
|
||||
packager.pack(project.widgetsDirectory, targetJar, "BOOT-INF/classes/project/widgets")
|
||||
packager.copy(project.projectFile, targetJar, "BOOT-INF/classes/project")
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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.code.model.Code
|
||||
import com.bartlomiejpluta.base.editor.code.model.CodeScope
|
||||
@@ -172,6 +174,20 @@ class MainController : Controller() {
|
||||
}
|
||||
}
|
||||
|
||||
fun importAnimation() {
|
||||
val vm = AnimationAssetDataVM()
|
||||
val scope = Scope()
|
||||
setInScope(vm, scope)
|
||||
|
||||
find<ImportAnimationFragment>(scope).apply {
|
||||
onComplete {
|
||||
projectContext.importAnimation(it)
|
||||
}
|
||||
|
||||
openModal(block = true, resizable = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun importFont() {
|
||||
val vm = FontAssetDataVM()
|
||||
val scope = Scope()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.project.context
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAsset
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.code.model.Code
|
||||
import com.bartlomiejpluta.base.editor.code.model.CodeType
|
||||
@@ -181,6 +183,19 @@ class DefaultProjectContext : ProjectContext {
|
||||
}
|
||||
}
|
||||
|
||||
override fun importAnimation(data: AnimationAssetData) {
|
||||
project?.let {
|
||||
UID.next(it.animations.map(Asset::uid)).let { uid ->
|
||||
val source = "$uid.${data.file.extension}"
|
||||
val targetFile = File(it.animationsDirectory, source)
|
||||
data.file.copyTo(targetFile)
|
||||
it.animations += AnimationAsset(it, uid, source, data.name, data.rows, data.columns)
|
||||
|
||||
save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun importFont(data: FontAssetData) {
|
||||
project?.let {
|
||||
UID.next(it.fonts.map(Asset::uid)).let { uid ->
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.project.context
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.code.model.Code
|
||||
import com.bartlomiejpluta.base.editor.entityset.asset.EntitySetAssetData
|
||||
@@ -38,6 +39,8 @@ interface ProjectContext {
|
||||
|
||||
fun importEntitySet(data: EntitySetAssetData)
|
||||
|
||||
fun importAnimation(data: AnimationAssetData)
|
||||
|
||||
fun importFont(data: FontAssetData)
|
||||
|
||||
fun createWidget(data: WidgetAssetData): WidgetAsset
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.project.model
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAsset
|
||||
import com.bartlomiejpluta.base.editor.entityset.asset.EntitySet
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
|
||||
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAsset
|
||||
@@ -32,10 +33,11 @@ class Project {
|
||||
val tileSets = observableListOf<TileSetAsset>()
|
||||
val images = observableListOf<ImageAsset>()
|
||||
val entitySets = observableListOf<EntitySet>()
|
||||
val animations = observableListOf<AnimationAsset>()
|
||||
val fonts = observableListOf<FontAsset>()
|
||||
val widgets = observableListOf<WidgetAsset>()
|
||||
|
||||
val assetLists = listOf(maps, tileSets, images, entitySets, fonts, widgets)
|
||||
val assetLists = listOf(maps, tileSets, images, entitySets, animations, fonts, widgets)
|
||||
|
||||
val mapsDirectoryProperty = SimpleObjectProperty<File>()
|
||||
var mapsDirectory by mapsDirectoryProperty
|
||||
@@ -53,6 +55,10 @@ class Project {
|
||||
var entitySetsDirectory by entitySetsDirectoryProperty
|
||||
private set
|
||||
|
||||
val animationsDirectoryProperty = SimpleObjectProperty<File>()
|
||||
var animationsDirectory by animationsDirectoryProperty
|
||||
private set
|
||||
|
||||
val fontsDirectoryProperty = SimpleObjectProperty<File>()
|
||||
var fontsDirectory by fontsDirectoryProperty
|
||||
private set
|
||||
@@ -95,6 +101,7 @@ class Project {
|
||||
tileSetsDirectory = File(it, TILE_SETS_DIR)
|
||||
imagesDirectory = File(it, IMAGES_DIR)
|
||||
entitySetsDirectory = File(it, ENTITY_SETS_DIR)
|
||||
animationsDirectory = File(it, ANIMATIONS_DIR)
|
||||
fontsDirectory = File(it, FONTS_DIR)
|
||||
widgetsDirectory = File(it, WIDGETS_DIR)
|
||||
codeDirectory = File(it, CODE_DIR)
|
||||
@@ -112,6 +119,7 @@ class Project {
|
||||
tileSetsDirectory?.mkdirs()
|
||||
imagesDirectory?.mkdirs()
|
||||
entitySetsDirectory?.mkdirs()
|
||||
animationsDirectory?.mkdirs()
|
||||
fontsDirectory?.mkdirs()
|
||||
widgetsDirectory?.mkdirs()
|
||||
codeDirectory?.mkdirs()
|
||||
@@ -125,6 +133,7 @@ class Project {
|
||||
const val TILE_SETS_DIR = "tilesets"
|
||||
const val IMAGES_DIR = "images"
|
||||
const val ENTITY_SETS_DIR = "entsets"
|
||||
const val ANIMATIONS_DIR = "animations"
|
||||
const val FONTS_DIR = "fonts"
|
||||
const val WIDGETS_DIR = "widgets"
|
||||
const val CODE_DIR = "code"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.project.serial
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAsset
|
||||
import com.bartlomiejpluta.base.editor.entityset.asset.EntitySet
|
||||
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAsset
|
||||
import com.bartlomiejpluta.base.editor.gui.widget.asset.WidgetAsset
|
||||
@@ -23,6 +24,7 @@ class ProtobufProjectDeserializer : ProjectDeserializer {
|
||||
project.tileSets.addAll(proto.tileSetsList.map { deserializeTileSet(project, it) })
|
||||
project.images.addAll(proto.imagesList.map { deserializeImage(project, it) })
|
||||
project.entitySets.addAll(proto.entitySetsList.map { deserializeEntitySet(project, it) })
|
||||
project.animations.addAll(proto.animationsList.map { deserializeAnimation(project, it) })
|
||||
project.fonts.addAll(proto.fontsList.map { deserializeFont(project, it) })
|
||||
project.widgets.addAll(proto.widgetsList.map { deserializeWidget(project, it) })
|
||||
|
||||
@@ -60,6 +62,15 @@ class ProtobufProjectDeserializer : ProjectDeserializer {
|
||||
columns = entitySetAsset.columns
|
||||
)
|
||||
|
||||
private fun deserializeAnimation(project: Project, animationAsset: ProjectProto.AnimationAsset) = AnimationAsset(
|
||||
project = project,
|
||||
uid = animationAsset.uid,
|
||||
source = animationAsset.source,
|
||||
name = animationAsset.name,
|
||||
rows = animationAsset.rows,
|
||||
columns = animationAsset.columns
|
||||
)
|
||||
|
||||
private fun deserializeFont(project: Project, fontAsset: ProjectProto.FontAsset) = FontAsset(
|
||||
project = project,
|
||||
uid = fontAsset.uid,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bartlomiejpluta.base.editor.project.serial
|
||||
|
||||
import com.bartlomiejpluta.base.editor.animation.asset.AnimationAsset
|
||||
import com.bartlomiejpluta.base.editor.entityset.asset.EntitySet
|
||||
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAsset
|
||||
import com.bartlomiejpluta.base.editor.gui.widget.asset.WidgetAsset
|
||||
@@ -22,6 +23,7 @@ class ProtobufProjectSerializer : ProjectSerializer {
|
||||
proto.addAllTileSets(item.tileSets.map(this::serializeTileSet))
|
||||
proto.addAllImages(item.images.map(this::serializeImage))
|
||||
proto.addAllEntitySets(item.entitySets.map(this::serializeEntitySet))
|
||||
proto.addAllAnimations(item.animations.map(this::serializeAnimation))
|
||||
proto.addAllFonts(item.fonts.map(this::serializeFont))
|
||||
proto.addAllWidgets(item.widgets.map(this::serializeWidget))
|
||||
proto.build().writeTo(output)
|
||||
@@ -55,6 +57,14 @@ class ProtobufProjectSerializer : ProjectSerializer {
|
||||
.setColumns(entitySet.columns)
|
||||
.build()
|
||||
|
||||
private fun serializeAnimation(animation: AnimationAsset) = ProjectProto.AnimationAsset.newBuilder()
|
||||
.setUid(animation.uid)
|
||||
.setSource(animation.source)
|
||||
.setName(animation.name)
|
||||
.setRows(animation.rows)
|
||||
.setColumns(animation.columns)
|
||||
.build()
|
||||
|
||||
private fun serializeFont(font: FontAsset) = ProjectProto.FontAsset.newBuilder()
|
||||
.setUid(font.uid)
|
||||
.setSource(font.source)
|
||||
|
||||
Reference in New Issue
Block a user