Image Reference как и для изображений, так и для спрайтов
This commit is contained in:
parent
3ef02ad450
commit
791e57cb0f
@ -4,9 +4,6 @@ import com.google.common.collect.Interner
|
|||||||
import com.google.common.collect.Interners
|
import com.google.common.collect.Interners
|
||||||
import com.google.gson.*
|
import com.google.gson.*
|
||||||
import com.google.gson.internal.bind.JsonTreeReader
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
import com.google.gson.internal.bind.TypeAdapters
|
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
@ -18,7 +15,6 @@ import ru.dbotthepony.kstarbound.api.explore
|
|||||||
import ru.dbotthepony.kstarbound.defs.*
|
import ru.dbotthepony.kstarbound.defs.*
|
||||||
import ru.dbotthepony.kstarbound.defs.image.AtlasConfiguration
|
import ru.dbotthepony.kstarbound.defs.image.AtlasConfiguration
|
||||||
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
|
||||||
import ru.dbotthepony.kstarbound.defs.item.BackArmorItemPrototype
|
import ru.dbotthepony.kstarbound.defs.item.BackArmorItemPrototype
|
||||||
import ru.dbotthepony.kstarbound.defs.item.ChestArmorItemPrototype
|
import ru.dbotthepony.kstarbound.defs.item.ChestArmorItemPrototype
|
||||||
import ru.dbotthepony.kstarbound.defs.item.CurrencyItemPrototype
|
import ru.dbotthepony.kstarbound.defs.item.CurrencyItemPrototype
|
||||||
@ -100,8 +96,6 @@ class Starbound : ISBFileLocator {
|
|||||||
private val _items = ObjectRegistry("items", IItemDefinition::itemName)
|
private val _items = ObjectRegistry("items", IItemDefinition::itemName)
|
||||||
val items = _items.view
|
val items = _items.view
|
||||||
|
|
||||||
val spriteRegistry: SpriteReference.Adapter
|
|
||||||
|
|
||||||
val gson: Gson = with(GsonBuilder()) {
|
val gson: Gson = with(GsonBuilder()) {
|
||||||
serializeNulls()
|
serializeNulls()
|
||||||
setDateFormat(DateFormat.LONG)
|
setDateFormat(DateFormat.LONG)
|
||||||
@ -160,13 +154,11 @@ class Starbound : ISBFileLocator {
|
|||||||
|
|
||||||
registerTypeAdapter(EnumAdapter(DamageType::class, default = DamageType.NORMAL))
|
registerTypeAdapter(EnumAdapter(DamageType::class, default = DamageType.NORMAL))
|
||||||
|
|
||||||
spriteRegistry = SpriteReference.Adapter(pathStack, this@Starbound::atlasRegistry)
|
registerTypeAdapterFactory(InventoryIcon.Factory(pathStack))
|
||||||
registerTypeAdapter(spriteRegistry)
|
|
||||||
registerTypeAdapterFactory(InventoryIcon.Factory(pathStack, spriteRegistry))
|
|
||||||
|
|
||||||
registerTypeAdapterFactory(IArmorItemDefinition.Frames.Factory)
|
registerTypeAdapterFactory(IArmorItemDefinition.Frames.Factory)
|
||||||
registerTypeAdapterFactory(DirectAssetReferenceFactory(pathStack))
|
registerTypeAdapterFactory(DirectAssetReferenceFactory(pathStack))
|
||||||
registerTypeAdapterFactory(ImageReference.Adapter(this@Starbound::atlasRegistry))
|
registerTypeAdapterFactory(ImageReference.Factory({ atlasRegistry.get(it) }, pathStack))
|
||||||
|
|
||||||
registerTypeAdapterFactory(AssetReferenceFactory(pathStack, this@Starbound))
|
registerTypeAdapterFactory(AssetReferenceFactory(pathStack, this@Starbound))
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
|
|||||||
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
import ru.dbotthepony.kstarbound.client.gl.vertex.QuadTransformers
|
||||||
import ru.dbotthepony.kstarbound.defs.image.AtlasConfiguration
|
import ru.dbotthepony.kstarbound.defs.image.AtlasConfiguration
|
||||||
import ru.dbotthepony.kstarbound.defs.image.IUVCoordinates
|
import ru.dbotthepony.kstarbound.defs.image.IUVCoordinates
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Связка текстуры-атласа + координат спрайта на ней
|
* Связка текстуры-атласа + координат спрайта на ней
|
||||||
@ -45,15 +45,15 @@ class BoundSprite(
|
|||||||
/**
|
/**
|
||||||
* Создаёт связку текстуры-атласа + координгат спрайта на ней
|
* Создаёт связку текстуры-атласа + координгат спрайта на ней
|
||||||
*/
|
*/
|
||||||
fun SpriteReference.bind(texture: GLTexture2D): BoundSprite {
|
fun ImageReference.bind(texture: GLTexture2D): BoundSprite {
|
||||||
return BoundSprite(stateless, texture)
|
return BoundSprite(sprite!!, texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Создаёт связку текстуры-атласа, которая загружается через [GLStateTracker.loadNamedTextureSafe] + координгат спрайта на ней
|
* Создаёт связку текстуры-атласа, которая загружается через [GLStateTracker.loadNamedTextureSafe] + координгат спрайта на ней
|
||||||
*/
|
*/
|
||||||
fun SpriteReference.bind(state: GLStateTracker): BoundSprite {
|
fun ImageReference.bind(state: GLStateTracker): BoundSprite {
|
||||||
return BoundSprite(stateless, state.loadNamedTextureSafe(image))
|
return BoundSprite(sprite!!, state.loadNamedTextureSafe(imagePath.value!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,7 +185,7 @@ private class ModifierEqualityTester(val definition: MaterialModifier) : Equalit
|
|||||||
|
|
||||||
class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
|
class TileRenderer(val renderers: TileRenderers, val def: IRenderableTile) {
|
||||||
val state get() = renderers.state
|
val state get() = renderers.state
|
||||||
val texture = state.loadNamedTexture(def.renderParameters.texture.image.fullPath).also {
|
val texture = state.loadNamedTexture(def.renderParameters.texture.imagePath.value!!).also {
|
||||||
it.textureMagFilter = GL_NEAREST
|
it.textureMagFilter = GL_NEAREST
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
import ru.dbotthepony.kstarbound.defs.item.IItemDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.player.BlueprintLearnList
|
import ru.dbotthepony.kstarbound.defs.player.BlueprintLearnList
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
@ -33,8 +33,8 @@ data class Species(
|
|||||||
@JsonFactory
|
@JsonFactory
|
||||||
data class Gender(
|
data class Gender(
|
||||||
val name: String,
|
val name: String,
|
||||||
val image: SpriteReference,
|
val image: ImageReference,
|
||||||
val characterImage: SpriteReference,
|
val characterImage: ImageReference,
|
||||||
val hairGroup: String? = null,
|
val hairGroup: String? = null,
|
||||||
val hair: ImmutableSet<String>,
|
val hair: ImmutableSet<String>,
|
||||||
val shirt: ImmutableSet<RegistryReference<IItemDefinition>>,
|
val shirt: ImmutableSet<RegistryReference<IItemDefinition>>,
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.kstarbound.defs
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
@ -11,7 +11,7 @@ data class StatusEffectDefinition(
|
|||||||
val defaultDuration: Double,
|
val defaultDuration: Double,
|
||||||
val blockingStat: String? = null,
|
val blockingStat: String? = null,
|
||||||
val label: String? = null,
|
val label: String? = null,
|
||||||
val icon: SpriteReference? = null,
|
val icon: ImageReference? = null,
|
||||||
override val scripts: ImmutableList<DirectAssetReference> = ImmutableList.of(),
|
override val scripts: ImmutableList<DirectAssetReference> = ImmutableList.of(),
|
||||||
override val scriptDelta: Int = 1,
|
override val scriptDelta: Int = 1,
|
||||||
val animationConfig: AssetReference<AnimationDefinition>? = null,
|
val animationConfig: AssetReference<AnimationDefinition>? = null,
|
||||||
|
@ -3,10 +3,8 @@ package ru.dbotthepony.kstarbound.defs.animation
|
|||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
|
||||||
import ru.dbotthepony.kstarbound.defs.particle.ParticleEmitter
|
import ru.dbotthepony.kstarbound.defs.particle.ParticleEmitter
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.util.Either
|
|
||||||
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
import ru.dbotthepony.kvector.vector.ndouble.Vector2d
|
||||||
|
|
||||||
@JsonFactory
|
@JsonFactory
|
||||||
@ -74,7 +72,7 @@ data class AnimationDefinition(
|
|||||||
val centered: Boolean? = null,
|
val centered: Boolean? = null,
|
||||||
val transformationGroups: ImmutableList<String>? = null,
|
val transformationGroups: ImmutableList<String>? = null,
|
||||||
val offset: Vector2d? = null,
|
val offset: Vector2d? = null,
|
||||||
val image: SpriteReference? = null
|
val image: ImageReference? = null
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = Properties()
|
val EMPTY = Properties()
|
||||||
|
@ -70,8 +70,10 @@ class AtlasConfiguration private constructor(
|
|||||||
return get(name) ?: first
|
return get(name) ?: first
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val any by lazy { get("root") ?: get("0") ?: get("default") ?: first }
|
||||||
|
|
||||||
fun any(): Sprite {
|
fun any(): Sprite {
|
||||||
return get("root") ?: get("0") ?: get("default") ?: first
|
return any
|
||||||
}
|
}
|
||||||
|
|
||||||
class Sprite(
|
class Sprite(
|
||||||
|
@ -10,36 +10,102 @@ import com.google.gson.stream.JsonToken
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.defs.DirectAssetReference
|
import ru.dbotthepony.kstarbound.defs.DirectAssetReference
|
||||||
import ru.dbotthepony.kstarbound.util.PathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Хранит данные (пару) вида "/example/animated.png" у которого, вероятнее всего, есть "/example/animated.frames"
|
|
||||||
*
|
|
||||||
* @see [AtlasConfiguration.Companion.get]
|
* @see [AtlasConfiguration.Companion.get]
|
||||||
*/
|
*/
|
||||||
data class ImageReference(
|
class ImageReference private constructor(
|
||||||
val image: DirectAssetReference,
|
val raw: DirectAssetReference,
|
||||||
val config: AtlasConfiguration,
|
val imagePath: SBPattern,
|
||||||
|
val spritePath: SBPattern?,
|
||||||
|
val atlas: AtlasConfiguration?,
|
||||||
|
private val atlasLocator: (String) -> AtlasConfiguration?
|
||||||
) {
|
) {
|
||||||
class Adapter(private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapterFactory {
|
/**
|
||||||
|
* Спрайт, на которое ссылается данный референс, или `null` если:
|
||||||
|
* * [atlas] равен `null`
|
||||||
|
* * [spritePath] является шаблоном и определены не все значения
|
||||||
|
*/
|
||||||
|
val sprite by lazy {
|
||||||
|
if (atlas == null)
|
||||||
|
null
|
||||||
|
else if (spritePath == null)
|
||||||
|
atlas.any()
|
||||||
|
else
|
||||||
|
atlas.get(spritePath.value ?: return@lazy null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun with(values: (String) -> String?): ImageReference {
|
||||||
|
val imagePath = this.imagePath.with(values)
|
||||||
|
val spritePath = this.spritePath?.with(values)
|
||||||
|
|
||||||
|
if (imagePath != this.imagePath || spritePath != this.spritePath) {
|
||||||
|
if (imagePath != this.imagePath) {
|
||||||
|
val resolved = imagePath.value
|
||||||
|
|
||||||
|
if (resolved == null)
|
||||||
|
return ImageReference(raw, imagePath, spritePath, null, atlasLocator)
|
||||||
|
else
|
||||||
|
return ImageReference(raw, imagePath, spritePath, atlasLocator.invoke(resolved), atlasLocator)
|
||||||
|
} else {
|
||||||
|
return ImageReference(raw, imagePath, spritePath, atlas, atlasLocator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun with(values: Map<String, String>): ImageReference {
|
||||||
|
return with(values::get)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other is ImageReference && other.imagePath == imagePath && other.spritePath == spritePath && other.atlas == atlas
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return imagePath.hashCode() * 31 + spritePath.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "ImageReference[$imagePath:$spritePath]"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Factory(private val atlasLocator: (String) -> AtlasConfiguration, private val remapper: PathStack) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == ImageReference::class.java) {
|
if (type.rawType == ImageReference::class.java) {
|
||||||
return object : TypeAdapter<ImageReference>() {
|
return object : TypeAdapter<ImageReference>() {
|
||||||
private val assets = gson.getAdapter(DirectAssetReference::class.java)
|
private val strings = gson.getAdapter(String::class.java)
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: ImageReference?) {
|
override fun write(out: JsonWriter, value: ImageReference?) {
|
||||||
out.value(value?.image?.fullPath)
|
out.value(value?.raw?.fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(`in`: JsonReader): ImageReference? {
|
override fun read(`in`: JsonReader): ImageReference? {
|
||||||
if (`in`.peek() == JsonToken.NULL)
|
if (`in`.peek() == JsonToken.NULL)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
val image = assets.read(`in`)
|
val path = strings.read(`in`)
|
||||||
|
|
||||||
if (image.path.contains(':'))
|
if (path == "")
|
||||||
throw JsonSyntaxException("Expected atlas/image reference, but got sprite reference: $image")
|
return NEVER
|
||||||
|
|
||||||
return ImageReference(image, atlasRegistry.invoke().get(image.fullPath))
|
val split = path.split(':')
|
||||||
|
|
||||||
|
if (split.size > 2) {
|
||||||
|
throw JsonSyntaxException("Ambiguous image reference: $path")
|
||||||
|
}
|
||||||
|
|
||||||
|
val imagePath = if (split.size == 2) SBPattern.of(split[0]) else SBPattern.of(path)
|
||||||
|
val spritePath = if (split.size == 2) SBPattern.of(split[1]) else null
|
||||||
|
|
||||||
|
if (imagePath.isPlainString) {
|
||||||
|
val remapped = remapper.remap(split[0])
|
||||||
|
return ImageReference(DirectAssetReference(path, remapper.remap(path)), SBPattern.raw(remapped), spritePath, atlasLocator.invoke(remapped), atlasLocator)
|
||||||
|
} else {
|
||||||
|
return ImageReference(DirectAssetReference(path, path), imagePath, spritePath, null, atlasLocator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} as TypeAdapter<T>
|
} as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
@ -47,4 +113,8 @@ data class ImageReference(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val NEVER = ImageReference(DirectAssetReference("", ""), SBPattern.EMPTY, null, null) { null }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.image
|
|
||||||
|
|
||||||
import com.google.gson.TypeAdapter
|
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import ru.dbotthepony.kstarbound.util.PathStack
|
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Хранит данные (пару) вида "/example/image.png:sprite.name"
|
|
||||||
*/
|
|
||||||
data class SpriteReference(
|
|
||||||
val image: String,
|
|
||||||
val atlas: AtlasConfiguration,
|
|
||||||
val sprite: SBPattern
|
|
||||||
) {
|
|
||||||
val stateless by lazy { resolve { null } }
|
|
||||||
|
|
||||||
fun resolve(with: (String) -> String?): AtlasConfiguration.Sprite {
|
|
||||||
val resolved = sprite.resolve(with) ?: return atlas.any()
|
|
||||||
return atlas[resolved] ?: atlas.any()
|
|
||||||
}
|
|
||||||
|
|
||||||
class Adapter(private val remapper: PathStack, private val atlasRegistry: () -> AtlasConfiguration.Registry) : TypeAdapter<SpriteReference>() {
|
|
||||||
override fun write(out: JsonWriter, value: SpriteReference?) {
|
|
||||||
if (value == null)
|
|
||||||
out.nullValue()
|
|
||||||
else
|
|
||||||
out.value(value.image + ":" + value.sprite.raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(`in`: JsonReader): SpriteReference? {
|
|
||||||
val value = `in`.nextString() ?: return null
|
|
||||||
|
|
||||||
// TODO: если нам надо принудительно удалить спрайт с вышестоящей ступени, как это сделать?
|
|
||||||
// а ещё, зачем вы это сделали.
|
|
||||||
if (value == "")
|
|
||||||
return null
|
|
||||||
|
|
||||||
return parse(remapper.remap(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse(input: String): SpriteReference {
|
|
||||||
val grid = atlasRegistry.invoke().get(input.substringBefore(':'))
|
|
||||||
|
|
||||||
return when (input.count { it == ':' }) {
|
|
||||||
0 -> SpriteReference(input, grid, SBPattern.raw(grid.any().name))
|
|
||||||
1 -> SpriteReference(input.substringBefore(':'), grid, SBPattern.of(input.substringAfter(':')))
|
|
||||||
else -> throw IllegalArgumentException("Invalid sprite reference: $input")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.item
|
package ru.dbotthepony.kstarbound.defs.item
|
||||||
|
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonImplementation
|
||||||
|
|
||||||
@JsonImplementation(InventoryIcon::class)
|
@JsonImplementation(InventoryIcon::class)
|
||||||
interface IInventoryIcon {
|
interface IInventoryIcon {
|
||||||
val image: SpriteReference
|
val image: ImageReference
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
package ru.dbotthepony.kstarbound.defs.item
|
package ru.dbotthepony.kstarbound.defs.item
|
||||||
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
import com.google.gson.TypeAdapterFactory
|
import com.google.gson.TypeAdapterFactory
|
||||||
|
import com.google.gson.internal.bind.JsonTreeReader
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonToken
|
import com.google.gson.stream.JsonToken
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
import ru.dbotthepony.kstarbound.io.json.builder.FactoryAdapter
|
||||||
import ru.dbotthepony.kstarbound.util.PathStack
|
import ru.dbotthepony.kstarbound.util.PathStack
|
||||||
|
|
||||||
data class InventoryIcon(
|
data class InventoryIcon(
|
||||||
override val image: SpriteReference
|
override val image: ImageReference
|
||||||
) : IInventoryIcon {
|
) : IInventoryIcon {
|
||||||
class Factory(val remapper: PathStack, val spriteRegistry: SpriteReference.Adapter) : TypeAdapterFactory {
|
class Factory(val remapper: PathStack) : TypeAdapterFactory {
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == InventoryIcon::class.java) {
|
if (type.rawType == InventoryIcon::class.java) {
|
||||||
return object : TypeAdapter<InventoryIcon>() {
|
return object : TypeAdapter<InventoryIcon>() {
|
||||||
private val adapter = FactoryAdapter.Builder(InventoryIcon::class, InventoryIcon::image).build(gson)
|
private val adapter = FactoryAdapter.Builder(InventoryIcon::class, InventoryIcon::image).build(gson)
|
||||||
|
private val images = gson.getAdapter(ImageReference::class.java)
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: InventoryIcon?) {
|
override fun write(out: JsonWriter, value: InventoryIcon?) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
@ -32,7 +35,7 @@ data class InventoryIcon(
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
if (`in`.peek() == JsonToken.STRING) {
|
if (`in`.peek() == JsonToken.STRING) {
|
||||||
return InventoryIcon(spriteRegistry.parse(remapper.remap(`in`.nextString())))
|
return InventoryIcon(images.read(JsonTreeReader(JsonPrimitive(remapper.remap(`in`.nextString())))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return adapter.read(`in`)
|
return adapter.read(`in`)
|
||||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.defs.particle
|
|||||||
import ru.dbotthepony.kstarbound.defs.AssetReference
|
import ru.dbotthepony.kstarbound.defs.AssetReference
|
||||||
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
import ru.dbotthepony.kstarbound.defs.animation.AnimationDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.animation.DestructionAction
|
import ru.dbotthepony.kstarbound.defs.animation.DestructionAction
|
||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.ImageReference
|
||||||
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
import ru.dbotthepony.kstarbound.io.json.builder.JsonFactory
|
||||||
import ru.dbotthepony.kstarbound.util.SBPattern
|
import ru.dbotthepony.kstarbound.util.SBPattern
|
||||||
import ru.dbotthepony.kvector.vector.Color
|
import ru.dbotthepony.kvector.vector.Color
|
||||||
@ -14,7 +14,7 @@ import ru.dbotthepony.kvector.vector.ndouble.Vector4d
|
|||||||
data class ParticleConfig(
|
data class ParticleConfig(
|
||||||
val type: ParticleType,
|
val type: ParticleType,
|
||||||
val animation: AssetReference<AnimationDefinition>? = null,
|
val animation: AssetReference<AnimationDefinition>? = null,
|
||||||
val image: SpriteReference? = null,
|
val image: ImageReference? = null,
|
||||||
override val offset: Vector2d? = null,
|
override val offset: Vector2d? = null,
|
||||||
override val position: Vector2d? = null,
|
override val position: Vector2d? = null,
|
||||||
override val offsetRegion: Vector4d? = null,
|
override val offsetRegion: Vector4d? = null,
|
||||||
|
@ -16,4 +16,8 @@ data class RenderParameters(
|
|||||||
val occludesBelow: Boolean = false,
|
val occludesBelow: Boolean = false,
|
||||||
val lightTransparent: Boolean = false,
|
val lightTransparent: Boolean = false,
|
||||||
val zLevel: Int,
|
val zLevel: Int,
|
||||||
)
|
) {
|
||||||
|
init {
|
||||||
|
checkNotNull(texture.imagePath.value) { "Tile render parameters are stateless, but provided image is a pattern: ${texture.raw}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.util
|
|||||||
import com.google.common.collect.Interner
|
import com.google.common.collect.Interner
|
||||||
import kotlin.concurrent.getOrSet
|
import kotlin.concurrent.getOrSet
|
||||||
|
|
||||||
class PathStack(private val interner: Interner<String>? = null) {
|
class PathStack(private val interner: Interner<String> = Interner { it }) {
|
||||||
private val _stack = ThreadLocal<ArrayDeque<String>>()
|
private val _stack = ThreadLocal<ArrayDeque<String>>()
|
||||||
private val stack: ArrayDeque<String> get() = _stack.getOrSet { ArrayDeque() }
|
private val stack: ArrayDeque<String> get() = _stack.getOrSet { ArrayDeque() }
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ class PathStack(private val interner: Interner<String>? = null) {
|
|||||||
if (b[0] == '/')
|
if (b[0] == '/')
|
||||||
return b
|
return b
|
||||||
|
|
||||||
return interner?.intern("$a/$b") ?: "$a/$b"
|
return interner.intern("$a/$b")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remap(path: String): String {
|
fun remap(path: String): String {
|
||||||
|
@ -26,6 +26,7 @@ class SBPattern private constructor(
|
|||||||
val pieces: ImmutableList<Piece>,
|
val pieces: ImmutableList<Piece>,
|
||||||
val names: ImmutableSet<String>
|
val names: ImmutableSet<String>
|
||||||
) {
|
) {
|
||||||
|
val isPlainString get() = names.isEmpty()
|
||||||
val value by lazy { resolve { null } }
|
val value by lazy { resolve { null } }
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@ -72,15 +73,28 @@ class SBPattern private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun with(params: Map<String, String>): SBPattern {
|
fun with(params: Map<String, String>): SBPattern {
|
||||||
|
return with(params::get)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun with(params: (String) -> String?): SBPattern {
|
||||||
if (names.isEmpty())
|
if (names.isEmpty())
|
||||||
return this
|
return this
|
||||||
|
|
||||||
val map = Object2ObjectArrayMap<String, String>()
|
val map = Object2ObjectArrayMap<String, String>()
|
||||||
map.putAll(this.params)
|
map.putAll(this.params)
|
||||||
|
var any = false
|
||||||
|
|
||||||
for ((key, value) in params.entries)
|
for (name in names) {
|
||||||
if (names.contains(key))
|
val get = params.invoke(name)
|
||||||
map[key] = value
|
|
||||||
|
if (get != null && get != map[name]) {
|
||||||
|
map[name] = get
|
||||||
|
any = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!any)
|
||||||
|
return this
|
||||||
|
|
||||||
return SBPattern(raw, ImmutableMap.copyOf(map), pieces, names)
|
return SBPattern(raw, ImmutableMap.copyOf(map), pieces, names)
|
||||||
}
|
}
|
||||||
@ -97,10 +111,14 @@ class SBPattern private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object : TypeAdapterFactory {
|
companion object : TypeAdapterFactory {
|
||||||
|
private val interner = Interners.newWeakInterner<SBPattern>()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val EMPTY = raw("")
|
||||||
|
|
||||||
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
|
||||||
if (type.rawType == SBPattern::class.java) {
|
if (type.rawType == SBPattern::class.java) {
|
||||||
return object : TypeAdapter<SBPattern>() {
|
return object : TypeAdapter<SBPattern>() {
|
||||||
private val interner = Interners.newWeakInterner<SBPattern>()
|
|
||||||
private val strings = gson.getAdapter(String::class.java)
|
private val strings = gson.getAdapter(String::class.java)
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: SBPattern?) {
|
override fun write(out: JsonWriter, value: SBPattern?) {
|
||||||
@ -118,6 +136,9 @@ class SBPattern private constructor(
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun of(raw: String): SBPattern {
|
fun of(raw: String): SBPattern {
|
||||||
|
if (raw == "")
|
||||||
|
return EMPTY
|
||||||
|
|
||||||
val pieces = ImmutableList.Builder<Piece>()
|
val pieces = ImmutableList.Builder<Piece>()
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
||||||
@ -144,10 +165,15 @@ class SBPattern private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val built = pieces.build()
|
val built = pieces.build()
|
||||||
return SBPattern(raw, pieces = built, params = ImmutableMap.of(), names = built.stream().map { it.name }.filter { it != null }.collect(ImmutableSet.toImmutableSet()))
|
return interner.intern(SBPattern(raw, pieces = built, params = ImmutableMap.of(), names = built.stream().map { it.name }.filter { it != null }.collect(ImmutableSet.toImmutableSet())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun raw(raw: String): SBPattern = SBPattern(raw, ImmutableMap.of(), ImmutableList.of(), ImmutableSet.of())
|
fun raw(raw: String): SBPattern {
|
||||||
|
if (raw == "")
|
||||||
|
return EMPTY
|
||||||
|
|
||||||
|
return SBPattern(raw, ImmutableMap.of(), ImmutableList.of(), ImmutableSet.of())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user