Don't calculate uvs of subelements on each access

This commit is contained in:
DBotThePony 2022-10-13 14:21:22 +07:00
parent 4de6be0289
commit bdd0fb28f0
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 89 additions and 41 deletions

View File

@ -1,17 +1,6 @@
package ru.dbotthepony.mc.otm.client.render
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.JsonSyntaxException
import com.google.gson.TypeAdapter
import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
@ -19,7 +8,7 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.core.linearInterpolation
import java.lang.reflect.Type
import java.lang.ref.WeakReference
sealed class AbstractSkinElement {
/**
@ -39,6 +28,14 @@ sealed class AbstractSkinElement {
abstract val u1: Float
abstract val v1: Float
internal open fun addListener(listener: AbstractSkinElement) {
// no-op by default
}
internal open fun parentChanges(parent: AbstractSkinElement) {
}
fun partialU(offset: Float): Float {
return u0 + (offset / width) * (u1 - u0)
}
@ -316,4 +313,40 @@ sealed class AbstractSkinElement {
fun toNetwork(buff: FriendlyByteBuf) {
type.toActualNetwork(this, buff)
}
abstract class Mutable : AbstractSkinElement() {
private val listeners = ArrayList<WeakReference<AbstractSkinElement>>(0)
override fun addListener(listener: AbstractSkinElement) {
synchronized(listeners) {
val iterator = listeners.listIterator()
for (ref in iterator) {
if (ref.get() == null) {
iterator.remove()
} else if (ref.get() === listener) {
return
}
}
listeners.add(WeakReference(listener))
}
}
protected fun notifyListeners() {
synchronized(listeners) {
val iterator = listeners.listIterator()
for (ref in iterator) {
val value = ref.get()
if (value == null) {
iterator.remove()
} else {
value.parentChanges(this)
}
}
}
}
}
}

View File

@ -22,7 +22,7 @@ class AtlasSkinElement(
val spriteWidth: Float = Mth.smallestEncompassingPowerOfTwo(width.toInt()).toFloat(),
val spriteHeight: Float = Mth.smallestEncompassingPowerOfTwo(height.toInt()).toFloat(),
override val winding: UVWindingOrder = UVWindingOrder.NORMAL,
) : AbstractSkinElement() {
) : AbstractSkinElement.Mutable() {
init {
synchronized(keys) {
if (keys.add(location)) {
@ -33,9 +33,9 @@ class AtlasSkinElement(
}
// optimistic: we should not create a lot of instances of this class
synchronized(listeners) {
listeners.add(WeakReference(this))
val iterator = listeners.listIterator()
synchronized(atlasListeners) {
atlasListeners.add(WeakReference(this))
val iterator = atlasListeners.listIterator()
for (ref in iterator) {
val value = ref.get()
@ -78,6 +78,8 @@ class AtlasSkinElement(
u1 = get.u1 - (get.u1 - get.u0) * (1f - width / spriteWidth)
v1 = get.v1 - (get.v1 - get.v0) * (1f - height / spriteHeight)
notifyListeners()
return get
}
@ -120,12 +122,12 @@ class AtlasSkinElement(
companion object {
private val keys = HashSet<ResourceLocation>()
private val listeners = ArrayList<WeakReference<AtlasSkinElement>>()
private val atlasListeners = ArrayList<WeakReference<AtlasSkinElement>>()
val keysStream: Stream<ResourceLocation> get() = keys.stream()
fun notifyListeners() {
synchronized(listeners) {
val iterator = listeners.listIterator()
synchronized(atlasListeners) {
val iterator = atlasListeners.listIterator()
for (ref in iterator) {
val value = ref.get()

View File

@ -106,8 +106,8 @@ enum class SkinElementType {
it["parent"] = value.parent.toJson()
it["xOffset"] = JsonPrimitive(value.xOffset)
it["yOffset"] = JsonPrimitive(value.yOffset)
it["subWidth"] = JsonPrimitive(value.subWidth)
it["subHeight"] = JsonPrimitive(value.subHeight)
it["subWidth"] = JsonPrimitive(value.width)
it["subHeight"] = JsonPrimitive(value.height)
}
}
@ -117,8 +117,8 @@ enum class SkinElementType {
value.parent.toNetwork(buff)
buff.writeFloat(value.xOffset)
buff.writeFloat(value.yOffset)
buff.writeFloat(value.subWidth)
buff.writeFloat(value.subHeight)
buff.writeFloat(value.width)
buff.writeFloat(value.height)
}
override fun fromNetwork(buff: FriendlyByteBuf): AbstractSkinElement {

View File

@ -6,24 +6,37 @@ class SubSkinElement(
val parent: AbstractSkinElement,
val xOffset: Float = 0f,
val yOffset: Float = 0f,
val subWidth: Float = parent.width,
val subHeight: Float = parent.height,
override val width: Float = parent.width,
override val height: Float = parent.height,
private val overrideWinding: UVWindingOrder? = null
) : AbstractSkinElement() {
override val width: Float
get() = subWidth
override val height: Float
get() = subHeight
) : AbstractSkinElement.Mutable() {
override var u0: Float = 0f
private set
override var v0: Float = 0f
private set
override var u1: Float = 0f
private set
override var v1: Float = 0f
private set
override val u0: Float
get() = parent.u0 + (xOffset / parent.width) * (parent.u1 - parent.u0)
override val v0: Float
get() = parent.v0 + (yOffset / parent.height) * (parent.v1 - parent.v0)
private fun calculateUVs() {
u0 = parent.u0 + (xOffset / parent.width) * (parent.u1 - parent.u0)
v0 = parent.v0 + (yOffset / parent.height) * (parent.v1 - parent.v0)
u1 = parent.u0 + ((xOffset + width) / parent.width) * (parent.u1 - parent.u0)
v1 = parent.v0 + ((yOffset + height) / parent.height) * (parent.v1 - parent.v0)
override val u1: Float
get() = parent.u0 + ((xOffset + subWidth) / parent.width) * (parent.u1 - parent.u0)
override val v1: Float
get() = parent.v0 + ((yOffset + subHeight) / parent.height) * (parent.v1 - parent.v0)
notifyListeners()
}
override fun parentChanges(parent: AbstractSkinElement) = calculateUVs()
init {
parent.addListener(this)
}
init {
calculateUVs()
}
override val texture: ResourceLocation
get() = parent.texture
@ -37,10 +50,10 @@ class SubSkinElement(
fun copy(
xOffset: Float = this.xOffset,
yOffset: Float = this.yOffset,
subWidth: Float = this.subWidth,
subHeight: Float = this.subHeight,
width: Float = this.width,
height: Float = this.height,
overrideWinding: UVWindingOrder? = this.overrideWinding
) = SubSkinElement(parent, xOffset, yOffset, subWidth, subHeight, overrideWinding)
) = SubSkinElement(parent, xOffset, yOffset, width, height, overrideWinding)
}
fun AbstractSkinElement.subElement(