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 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.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.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer import com.mojang.blaze3d.vertex.VertexConsumer
@ -19,7 +8,7 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.core.linearInterpolation import ru.dbotthepony.mc.otm.core.linearInterpolation
import java.lang.reflect.Type import java.lang.ref.WeakReference
sealed class AbstractSkinElement { sealed class AbstractSkinElement {
/** /**
@ -39,6 +28,14 @@ sealed class AbstractSkinElement {
abstract val u1: Float abstract val u1: Float
abstract val v1: 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 { fun partialU(offset: Float): Float {
return u0 + (offset / width) * (u1 - u0) return u0 + (offset / width) * (u1 - u0)
} }
@ -316,4 +313,40 @@ sealed class AbstractSkinElement {
fun toNetwork(buff: FriendlyByteBuf) { fun toNetwork(buff: FriendlyByteBuf) {
type.toActualNetwork(this, buff) 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 spriteWidth: Float = Mth.smallestEncompassingPowerOfTwo(width.toInt()).toFloat(),
val spriteHeight: Float = Mth.smallestEncompassingPowerOfTwo(height.toInt()).toFloat(), val spriteHeight: Float = Mth.smallestEncompassingPowerOfTwo(height.toInt()).toFloat(),
override val winding: UVWindingOrder = UVWindingOrder.NORMAL, override val winding: UVWindingOrder = UVWindingOrder.NORMAL,
) : AbstractSkinElement() { ) : AbstractSkinElement.Mutable() {
init { init {
synchronized(keys) { synchronized(keys) {
if (keys.add(location)) { if (keys.add(location)) {
@ -33,9 +33,9 @@ class AtlasSkinElement(
} }
// optimistic: we should not create a lot of instances of this class // optimistic: we should not create a lot of instances of this class
synchronized(listeners) { synchronized(atlasListeners) {
listeners.add(WeakReference(this)) atlasListeners.add(WeakReference(this))
val iterator = listeners.listIterator() val iterator = atlasListeners.listIterator()
for (ref in iterator) { for (ref in iterator) {
val value = ref.get() val value = ref.get()
@ -78,6 +78,8 @@ class AtlasSkinElement(
u1 = get.u1 - (get.u1 - get.u0) * (1f - width / spriteWidth) u1 = get.u1 - (get.u1 - get.u0) * (1f - width / spriteWidth)
v1 = get.v1 - (get.v1 - get.v0) * (1f - height / spriteHeight) v1 = get.v1 - (get.v1 - get.v0) * (1f - height / spriteHeight)
notifyListeners()
return get return get
} }
@ -120,12 +122,12 @@ class AtlasSkinElement(
companion object { companion object {
private val keys = HashSet<ResourceLocation>() private val keys = HashSet<ResourceLocation>()
private val listeners = ArrayList<WeakReference<AtlasSkinElement>>() private val atlasListeners = ArrayList<WeakReference<AtlasSkinElement>>()
val keysStream: Stream<ResourceLocation> get() = keys.stream() val keysStream: Stream<ResourceLocation> get() = keys.stream()
fun notifyListeners() { fun notifyListeners() {
synchronized(listeners) { synchronized(atlasListeners) {
val iterator = listeners.listIterator() val iterator = atlasListeners.listIterator()
for (ref in iterator) { for (ref in iterator) {
val value = ref.get() val value = ref.get()

View File

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

View File

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