[Editor] Improve generating asset index class for map assets
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package com.bartlomiejpluta.base.editor.code.build.generator
|
||||
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||
import com.bartlomiejpluta.base.editor.map.serial.MapDeserializer
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import com.squareup.javapoet.*
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.*
|
||||
import javax.lang.model.element.Modifier
|
||||
|
||||
@Component
|
||||
@@ -14,13 +17,16 @@ class AssetMapCodeGenerator : CodeGenerator {
|
||||
@Autowired
|
||||
private lateinit var projectContext: ProjectContext
|
||||
|
||||
@Autowired
|
||||
private lateinit var mapDeserializer: MapDeserializer
|
||||
|
||||
override fun generate() {
|
||||
projectContext.project?.let(::generateAssetClasses)
|
||||
}
|
||||
|
||||
private fun generateAssetClasses(project: Project) {
|
||||
listOf(
|
||||
generateAssetClass("maps", project.maps),
|
||||
generateMapAssetClass("maps", project.maps),
|
||||
generateAssetClass("tilesets", project.tileSets),
|
||||
generateAssetClass("charsets", project.characterSets),
|
||||
generateAssetClass("images", project.images),
|
||||
@@ -44,11 +50,13 @@ class AssetMapCodeGenerator : CodeGenerator {
|
||||
.classBuilder(className)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
.addField(
|
||||
FieldSpec.builder(ParameterizedTypeName.get(
|
||||
ClassName.get(java.util.Map::class.java),
|
||||
ClassName.get(String::class.java),
|
||||
className
|
||||
), "_map", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
|
||||
FieldSpec.builder(
|
||||
ParameterizedTypeName.get(
|
||||
ClassName.get(java.util.Map::class.java),
|
||||
ClassName.get(String::class.java),
|
||||
className
|
||||
), "_map", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL
|
||||
)
|
||||
.initializer("new \$T<>()", java.util.HashMap::class.java)
|
||||
.build()
|
||||
)
|
||||
@@ -91,8 +99,176 @@ class AssetMapCodeGenerator : CodeGenerator {
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getAssetName(asset: Asset) = asset.name
|
||||
private fun generateMapAssetClass(name: String, assets: List<GameMapAsset>): TypeSpec {
|
||||
val className = ClassName.get("A", name)
|
||||
val mapLayers = assets
|
||||
.map { asset -> asset to mapDeserializer.deserialize(asset.file.inputStream()) }
|
||||
.associate { (asset, map) -> asset to map.layers }
|
||||
|
||||
val abstractAssetClassName = ClassName.get("", "GameMapAsset")
|
||||
|
||||
return TypeSpec
|
||||
.classBuilder(className)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
.addField(
|
||||
FieldSpec.builder(
|
||||
ParameterizedTypeName.get(
|
||||
ClassName.get(java.util.Map::class.java),
|
||||
ClassName.get(String::class.java),
|
||||
abstractAssetClassName
|
||||
), "_maps", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL
|
||||
)
|
||||
.initializer("new \$T<>()", java.util.HashMap::class.java)
|
||||
.build()
|
||||
)
|
||||
.addField(
|
||||
FieldSpec.builder(
|
||||
ParameterizedTypeName.get(
|
||||
ClassName.get(java.util.Map::class.java),
|
||||
ClassName.get(String::class.java),
|
||||
ClassName.get(Integer::class.java)
|
||||
), "_layers", Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL
|
||||
)
|
||||
.initializer("new \$T<>()", java.util.HashMap::class.java)
|
||||
.build()
|
||||
)
|
||||
.addStaticBlock(CodeBlock.builder()
|
||||
.apply {
|
||||
assets.forEach {
|
||||
addStatement("_maps.put(\"${it.name}\", ${getAssetName(it)})")
|
||||
}
|
||||
}
|
||||
.apply {
|
||||
mapLayers.forEach { asset, layers ->
|
||||
layers.forEach { layer ->
|
||||
addStatement(
|
||||
"_layers.put(\"${asset.name}::${layer.name}\", ${getAssetName(asset)}.layers.${
|
||||
getAssetName(
|
||||
layer.name
|
||||
)
|
||||
})"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.build()
|
||||
)
|
||||
.addMethod(
|
||||
MethodSpec
|
||||
.methodBuilder("get")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC)
|
||||
.returns(abstractAssetClassName)
|
||||
.addParameter(TypeName.get(String::class.java), "name")
|
||||
.addStatement("return _maps.get(name)")
|
||||
.build()
|
||||
)
|
||||
.addMethod(
|
||||
MethodSpec
|
||||
.methodBuilder("getLayer")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC)
|
||||
.returns(ClassName.get(Integer::class.java))
|
||||
.addParameter(TypeName.get(String::class.java), "mapName")
|
||||
.addParameter(TypeName.get(String::class.java), "layerName")
|
||||
.addStatement("return _layers.get(mapName + \"::\" + layerName)")
|
||||
.build()
|
||||
)
|
||||
.addType(
|
||||
TypeSpec.classBuilder(abstractAssetClassName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.ABSTRACT)
|
||||
.addField(String::class.java, "uid", Modifier.PUBLIC, Modifier.FINAL)
|
||||
.addField(
|
||||
FieldSpec.builder(
|
||||
ParameterizedTypeName.get(
|
||||
ClassName.get(java.util.Map::class.java),
|
||||
ClassName.get(String::class.java),
|
||||
ClassName.get(Integer::class.java)
|
||||
), "_layers", Modifier.PROTECTED, Modifier.FINAL
|
||||
)
|
||||
.initializer("new \$T<>()", java.util.HashMap::class.java)
|
||||
.build()
|
||||
)
|
||||
.addMethod(
|
||||
MethodSpec.constructorBuilder()
|
||||
.addParameter(ClassName.get(String::class.java), "uid")
|
||||
.addStatement("this.uid = uid")
|
||||
.build()
|
||||
)
|
||||
.addMethod(
|
||||
MethodSpec.methodBuilder("get")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(ClassName.get(String::class.java), "name")
|
||||
.returns(ClassName.get(Integer::class.java))
|
||||
.addStatement("return this._layers.get(name)")
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.apply {
|
||||
mapLayers.forEach { (asset, layers) ->
|
||||
val assetClassName = ClassName.get("", "GameMapAsset_${getCapitalizedAssetName(asset)}")
|
||||
val layersClassName = ClassName.get("", "GameMapAsset_Layers_${getCapitalizedAssetName(asset)}")
|
||||
|
||||
addField(
|
||||
FieldSpec
|
||||
.builder(assetClassName, getAssetName(asset), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.initializer("new \$T()", assetClassName)
|
||||
.build()
|
||||
)
|
||||
|
||||
addType(
|
||||
TypeSpec.classBuilder(assetClassName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.superclass(abstractAssetClassName)
|
||||
.addField(
|
||||
FieldSpec.builder(layersClassName, "layers", Modifier.PUBLIC, Modifier.FINAL)
|
||||
.initializer("new \$T()", layersClassName)
|
||||
.build()
|
||||
)
|
||||
.addMethod(
|
||||
MethodSpec.constructorBuilder()
|
||||
.addStatement("super(\"${asset.uid}\")")
|
||||
.apply {
|
||||
layers.forEach { layer ->
|
||||
addStatement("this._layers.put(\"${layer.name}\", layers.${getAssetName(layer.name)})")
|
||||
}
|
||||
}
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
addType(
|
||||
TypeSpec.classBuilder(layersClassName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.apply {
|
||||
layers.forEachIndexed { index, layer ->
|
||||
addField(
|
||||
FieldSpec.builder(
|
||||
TypeName.INT,
|
||||
getAssetName(layer.name),
|
||||
Modifier.PUBLIC,
|
||||
Modifier.FINAL
|
||||
)
|
||||
.initializer(index.toString())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getAssetName(asset: Asset) = getAssetName(asset.name)
|
||||
|
||||
private fun getAssetName(name: String) = name
|
||||
.split("\\s+".toRegex())
|
||||
.joinToString("_") { it.lowercase() }
|
||||
|
||||
private fun getCapitalizedAssetName(asset: Asset) = getCapitalizedAssetName(asset.name)
|
||||
|
||||
private fun getCapitalizedAssetName(name: String) = name
|
||||
.split("\\s+".toRegex())
|
||||
.joinToString("") { part -> part.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } }
|
||||
}
|
||||
@@ -13,6 +13,7 @@ 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.collections.ObservableList
|
||||
import javafx.scene.control.ListCell
|
||||
import javafx.scene.control.ListView
|
||||
import javafx.scene.control.cell.TextFieldListCell
|
||||
@@ -35,7 +36,7 @@ class MapLayersView : View() {
|
||||
isEditable = true
|
||||
|
||||
setCellFactory {
|
||||
LayerListViewItem { layer, name ->
|
||||
LayerListViewItem(mapVM.layers) { layer, name ->
|
||||
RenameLayerCommand(layer, name).let {
|
||||
it.execute()
|
||||
undoRedoService.push(it, scope)
|
||||
@@ -150,6 +151,7 @@ class MapLayersView : View() {
|
||||
|
||||
private class LayerListViewItemConverter(
|
||||
private val cell: ListCell<Layer>,
|
||||
private val layers: ObservableList<Layer>,
|
||||
private val onUpdate: (layer: Layer, name: String) -> Unit
|
||||
) : StringConverter<Layer>() {
|
||||
override fun toString(layer: Layer?) = layer?.name ?: ""
|
||||
@@ -160,15 +162,17 @@ class MapLayersView : View() {
|
||||
// so that the Command object has access to the actual as well as the new value of layer name.
|
||||
// That's why we are running the submission logic in the converter.
|
||||
override fun fromString(string: String?): Layer = cell.item.apply {
|
||||
string?.takeIf { it != name }?.let {
|
||||
onUpdate(this, it)
|
||||
}
|
||||
string
|
||||
?.takeIf { str -> str != name }
|
||||
?.takeIf { str -> layers.none { it.name == str }}
|
||||
?.let { onUpdate(this, it) }
|
||||
}
|
||||
}
|
||||
|
||||
private class LayerListViewItem(onUpdate: (layer: Layer, name: String) -> Unit) : TextFieldListCell<Layer>() {
|
||||
private class LayerListViewItem(layers: ObservableList<Layer>, onUpdate: (layer: Layer, name: String) -> Unit) :
|
||||
TextFieldListCell<Layer>() {
|
||||
init {
|
||||
converter = LayerListViewItemConverter(this, onUpdate)
|
||||
converter = LayerListViewItemConverter(this, layers, onUpdate)
|
||||
}
|
||||
|
||||
override fun updateItem(item: Layer?, empty: Boolean) {
|
||||
|
||||
@@ -5,11 +5,11 @@ import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.audio.asset.SoundAsset
|
||||
import com.bartlomiejpluta.base.editor.audio.asset.SoundAssetData
|
||||
import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAsset
|
||||
import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAssetData
|
||||
import com.bartlomiejpluta.base.editor.code.model.Code
|
||||
import com.bartlomiejpluta.base.editor.code.model.CodeType
|
||||
import com.bartlomiejpluta.base.editor.code.service.JavaClassService
|
||||
import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAsset
|
||||
import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAssetData
|
||||
import com.bartlomiejpluta.base.editor.file.model.FileNode
|
||||
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAsset
|
||||
import com.bartlomiejpluta.base.editor.gui.font.asset.FontAssetData
|
||||
@@ -108,6 +108,14 @@ class DefaultProjectContext : ProjectContext {
|
||||
|
||||
javaClassService.createClassFile(map.handler, it.codeFSNode, "map_handler.ftl") { model ->
|
||||
model["mapUid"] = uid
|
||||
model["mapName"] = name
|
||||
model["mapCode"] = name.split("\\s+".toRegex()).joinToString("") { part ->
|
||||
part.replaceFirstChar { c ->
|
||||
if (c.isLowerCase()) c.titlecase(Locale.getDefault())
|
||||
else c.toString()
|
||||
}
|
||||
}
|
||||
model["map_code"] = name.split("\\s+".toRegex()).joinToString("_") { part -> part.lowercase() }
|
||||
}
|
||||
|
||||
File(it.mapsDirectory, asset.source).outputStream().use { fos -> mapSerializer.serialize(map, fos) }
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.bartlomiejpluta.base.api.map.handler.MapHandler;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
|
||||
public class ${className} implements MapHandler {
|
||||
public static final String UID = "${mapUid}";
|
||||
|
||||
@Override
|
||||
public void onCreate(Context context, GameMap map) {
|
||||
|
||||
Reference in New Issue
Block a user