diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureAnimation.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureAnimation.kt
new file mode 100644
index 000000000..04ff0c97a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureAnimation.kt
@@ -0,0 +1,50 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program.If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.textures
+
+import de.bixilon.minosoft.gui.rendering.textures.properties.AnimationFrame
+
+class TextureAnimation(
+ val texture: Texture,
+) {
+ var currentFrameIndex = 0
+ var currentTime = 0L
+
+ val animationProperties = texture.properties.animation!!
+
+ fun getCurrentFrame(): AnimationFrame {
+ return animationProperties.frames[currentFrameIndex]
+ }
+
+ fun getAndSetNextFrame(): AnimationFrame {
+ currentFrameIndex = getNextIndex()
+ currentTime = 0L
+
+ return animationProperties.frames[currentFrameIndex]
+ }
+
+ fun getNextFrame(): AnimationFrame {
+ return animationProperties.frames[getNextIndex()]
+ }
+
+ private fun getNextIndex(): Int {
+ var nextFrameIndex = currentFrameIndex + 1
+
+ if (nextFrameIndex == animationProperties.frames.size) {
+ nextFrameIndex = 0
+ }
+
+ return nextFrameIndex
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt
index 0b7c81da9..eee88765b 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt
@@ -17,7 +17,6 @@ import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.assets.MinecraftAssetsManager
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.shader.Shader
-import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.logging.Log
import de.matthiasmann.twl.utils.PNGDecoder
import glm_.vec2.Vec2
@@ -74,7 +73,7 @@ class TextureArray(val allTextures: MutableList) {
it.add(texture)
texture.properties.animation?.let { properties ->
properties.animationId = animator.animatedTextures.size
- animator.animatedTextures.add(texture)
+ animator.animatedTextures.add(TextureAnimation(texture))
val bytesPerTexture = size.x * size.y * PNGDecoder.Format.RGBA.numComponents
val fullBuffer = texture.buffer!!
@@ -147,24 +146,22 @@ class TextureArray(val allTextures: MutableList) {
const val TEXTURE_MAX_RESOLUTION = 1024
val DEBUG_TEXTURE = Texture.getResourceTextureIdentifier(textureName = "block/debug")
+
+ private const val INTS_PER_ANIMATED_TEXTURE = 4
}
inner class Animator {
- val animatedTextures: MutableList = mutableListOf()
+ val animatedTextures: MutableList = mutableListOf()
private var animatedBufferDataId = -1
-
- private var currentTick = 0
- private var lastTickIncrementTime = 0L
-
-
- lateinit var animatedData: IntArray
+ var lastRun = 0L
+ private lateinit var animatedData: IntArray
var initialized = false
private set
fun initBuffer() {
- animatedData = IntArray(32 * 4) // 4 data ints per entry
+ animatedData = IntArray(32 * INTS_PER_ANIMATED_TEXTURE) // 4 data ints per entry
animatedBufferDataId = glGenBuffers()
@@ -184,21 +181,36 @@ class TextureArray(val allTextures: MutableList) {
if (!Minosoft.getConfig().config.game.animations.textures) {
return
}
+
val currentTime = System.currentTimeMillis()
- if (currentTime - lastTickIncrementTime >= ProtocolDefinition.TICK_TIME) {
- currentTick++
- lastTickIncrementTime = currentTime
- }
+ val deltaLastDraw = currentTime - lastRun
+ lastRun = currentTime
+
+ for (textureAnimation in animatedTextures) {
+ var currentFrame = textureAnimation.getCurrentFrame()
+ textureAnimation.currentTime += deltaLastDraw
+
+ if (textureAnimation.currentTime >= currentFrame.animationTime) {
+ currentFrame = textureAnimation.getAndSetNextFrame()
+ textureAnimation.currentTime = 0L
+ }
+
+ val nextFrame = textureAnimation.getNextFrame()
+
+ val interpolation = if (textureAnimation.animationProperties.interpolate) {
+ (textureAnimation.currentTime * 100) / currentFrame.animationTime
+ } else {
+ 0L
+ }
- for (texture in animatedTextures) {
- val animationProperties = texture.properties.animation!!
+ val baseAnimatedData = (textureAnimation.texture.arrayId shl 24) or textureAnimation.texture.arrayLayer
- val arrayOffset = animationProperties.animationId * 4
+ val arrayOffset = textureAnimation.animationProperties.animationId * INTS_PER_ANIMATED_TEXTURE
- animatedData[arrayOffset] = (texture.arrayId shl 24) or (texture.arrayLayer + (currentTick % animationProperties.frameCount))
- animatedData[arrayOffset + 1] = (texture.arrayId shl 24) or (texture.arrayLayer + 1) + (currentTick % animationProperties.frameCount)
- animatedData[arrayOffset + 2] = 0
+ animatedData[arrayOffset] = baseAnimatedData or currentFrame.index
+ animatedData[arrayOffset + 1] = baseAnimatedData or nextFrame.index
+ animatedData[arrayOffset + 2] = interpolation.toInt()
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationFrame.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationFrame.kt
new file mode 100644
index 000000000..60b8b2b0c
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationFrame.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program.If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.textures.properties
+
+import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
+
+data class AnimationFrame(
+ val index: Int,
+ val time: Int,
+) {
+ val animationTime = time * ProtocolDefinition.TICK_TIME
+}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationProperties.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationProperties.kt
index 8469feca8..9964957fd 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationProperties.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/AnimationProperties.kt
@@ -20,12 +20,17 @@ data class AnimationProperties(
val interpolate: Boolean = false,
var width: Int = -1,
var height: Int = -1,
- @Json(name = "frametime") val frameTime: Int = 1,
- val frames: Any = Any(),// ToDo,
+ @Json(name = "frametime") private val frameTime: Int = 1,
+ @Json(name = "frames") private val _frames: List = listOf(),
) {
+ @Transient
+ lateinit var frames: Array
+ private set
+
var animationId = -1
var frameCount = -1
+ private set
fun postInit(texture: Texture) {
if (width == -1) {
@@ -36,5 +41,26 @@ data class AnimationProperties(
}
frameCount = texture.size.y / height
+
+ val frames: MutableList = mutableListOf()
+
+ if (_frames.isEmpty()) {
+ for (i in 0 until frameCount) {
+ frames.add(AnimationFrame(i, frameTime))
+ }
+ } else {
+ for (frame in _frames) {
+ if (frame is Number) {
+ frames.add(AnimationFrame(frame.toInt(), frameTime))
+ continue
+ }
+ check(frame is Map<*, *>) { "Invalid frame: $frame" }
+
+ frames.add(AnimationFrame((frame["index"] as Number).toInt(), (frame["time"] as Number?)?.toInt() ?: frameTime))
+ }
+ }
+
+ this.frames = frames.toTypedArray()
+
}
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/TextureProperties.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/TextureProperties.kt
index b919e3857..82723c449 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/TextureProperties.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/properties/TextureProperties.kt
@@ -16,4 +16,5 @@ package de.bixilon.minosoft.gui.rendering.textures.properties
data class TextureProperties(
val blur: Boolean = false,
val clamp: Boolean = false,
+ // ToDo: mipmaps
)