diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAsset.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAsset.kt new file mode 100644 index 00000000..46cb39d5 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAsset.kt @@ -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) \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt new file mode 100644 index 00000000..2585fbdf --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt @@ -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() + var file by fileProperty + + val rowsProperty = SimpleIntegerProperty() + var rows by rowsProperty + + val columnsProperty = SimpleIntegerProperty() + var columns by columnsProperty +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt new file mode 100644 index 00000000..3c22fc83 --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt @@ -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() + private val imagePreview = SimpleObjectProperty() + + 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() } + } + } + } +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt new file mode 100644 index 00000000..28ee860e --- /dev/null +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt @@ -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()) { + 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 +} \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/AssetTreeCell.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/AssetTreeCell.kt index 91756ee6..78ba9771 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/AssetTreeCell.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/AssetTreeCell.kt @@ -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 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 7951241c..7a7d2c7c 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 @@ -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() diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt index 45646bf8..5e37f723 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt @@ -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") 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 4fc41873..73b76ad0 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 @@ -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(scope).apply { + onComplete { + projectContext.importAnimation(it) + } + + openModal(block = true, resizable = false) + } + } + fun importFont() { val vm = FontAssetDataVM() val scope = Scope() diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt index fd8a0c13..a3ced324 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/DefaultProjectContext.kt @@ -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 -> diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt index 9a70f1d7..6d296208 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/context/ProjectContext.kt @@ -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 diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/model/Project.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/model/Project.kt index 66678132..90ce490b 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/model/Project.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/model/Project.kt @@ -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() val images = observableListOf() val entitySets = observableListOf() + val animations = observableListOf() val fonts = observableListOf() val widgets = observableListOf() - val assetLists = listOf(maps, tileSets, images, entitySets, fonts, widgets) + val assetLists = listOf(maps, tileSets, images, entitySets, animations, fonts, widgets) val mapsDirectoryProperty = SimpleObjectProperty() var mapsDirectory by mapsDirectoryProperty @@ -53,6 +55,10 @@ class Project { var entitySetsDirectory by entitySetsDirectoryProperty private set + val animationsDirectoryProperty = SimpleObjectProperty() + var animationsDirectory by animationsDirectoryProperty + private set + val fontsDirectoryProperty = SimpleObjectProperty() 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" diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectDeserializer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectDeserializer.kt index 58ee8e11..af17acd2 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectDeserializer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectDeserializer.kt @@ -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, diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectSerializer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectSerializer.kt index e3f15486..078679ab 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectSerializer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/project/serial/ProtobufProjectSerializer.kt @@ -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)