[orx-keyframer] Add DoubleArrayChannel

This commit is contained in:
Edwin Jakobs
2020-09-15 14:58:56 +02:00
parent 8e8aef200f
commit 54e9579a6c

View File

@@ -18,7 +18,6 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible import kotlin.reflect.jvm.isAccessible
enum class KeyframerFormat { enum class KeyframerFormat {
SIMPLE, SIMPLE,
FULL FULL
@@ -64,46 +63,58 @@ open class Keyframer {
inner class DoubleChannel(key: String, defaultValue: Double = 0.0) : inner class DoubleChannel(key: String, defaultValue: Double = 0.0) :
CompoundChannel(arrayOf(key), arrayOf(defaultValue)) { CompoundChannel(arrayOf(key), arrayOf(defaultValue)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Double = getValue(0) operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Double = getValue(0)
} }
inner class Vector2Channel(keys: Array<String>, defaultValue: Vector2 = Vector2.ZERO) : inner class Vector2Channel(keys: Array<String>, defaultValue: Vector2 = Vector2.ZERO) :
CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y)) { CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector2 = Vector2(getValue(0), getValue(1)) operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector2 = Vector2(getValue(0), getValue(1))
} }
inner class Vector3Channel(keys: Array<String>, defaultValue: Vector3 = Vector3.ZERO) : inner class Vector3Channel(keys: Array<String>, defaultValue: Vector3 = Vector3.ZERO) :
CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y, defaultValue.z)) { CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y, defaultValue.z)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector3 = operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector3 =
Vector3(getValue(0), getValue(1), getValue(2)) Vector3(getValue(0), getValue(1), getValue(2))
} }
inner class Vector4Channel(keys: Array<String>, defaultValue: Vector4 = Vector4.ZERO) : inner class Vector4Channel(keys: Array<String>, defaultValue: Vector4 = Vector4.ZERO) :
CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y, defaultValue.z, defaultValue.w)) { CompoundChannel(keys, arrayOf(defaultValue.x, defaultValue.y, defaultValue.z, defaultValue.w)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector4 = operator fun getValue(keyframer: Keyframer, property: KProperty<*>): Vector4 =
Vector4(getValue(0), getValue(1), getValue(2), getValue(3)) Vector4(getValue(0), getValue(1), getValue(2), getValue(3))
} }
inner class RGBaChannel(keys: Array<String>, defaultValue: ColorRGBa = ColorRGBa.WHITE) : inner class RGBaChannel(keys: Array<String>, defaultValue: ColorRGBa = ColorRGBa.WHITE) :
CompoundChannel(keys, arrayOf(defaultValue.r, defaultValue.g, defaultValue.b, defaultValue.a)) { CompoundChannel(keys, arrayOf(defaultValue.r, defaultValue.g, defaultValue.b, defaultValue.a)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): ColorRGBa = operator fun getValue(keyframer: Keyframer, property: KProperty<*>): ColorRGBa =
ColorRGBa(getValue(0), getValue(1), getValue(2), getValue(3)) ColorRGBa(getValue(0), getValue(1), getValue(2), getValue(3))
} }
inner class RGBChannel(keys: Array<String>, defaultValue: ColorRGBa = ColorRGBa.WHITE) : inner class RGBChannel(keys: Array<String>, defaultValue: ColorRGBa = ColorRGBa.WHITE) :
CompoundChannel(keys, arrayOf(defaultValue.r, defaultValue.g, defaultValue.b)) { CompoundChannel(keys, arrayOf(defaultValue.r, defaultValue.g, defaultValue.b)) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): ColorRGBa = operator fun getValue(keyframer: Keyframer, property: KProperty<*>): ColorRGBa =
ColorRGBa(getValue(0), getValue(1), getValue(2)) ColorRGBa(getValue(0), getValue(1), getValue(2))
} }
inner class DoubleArrayChannel(keys: Array<String>, defaultValue: DoubleArray = DoubleArray(keys.size)) :
CompoundChannel(keys, defaultValue.toTypedArray()) {
operator fun getValue(keyframer: Keyframer, property: KProperty<*>): DoubleArray {
val result = DoubleArray(keys.size)
for (i in keys.indices) {
result[i] = getValue(i)
}
return result
}
}
val channels = mutableMapOf<String, KeyframerChannel>() val channels = mutableMapOf<String, KeyframerChannel>()
fun loadFromJson( fun loadFromJson(
file: File, file: File,
format: KeyframerFormat = KeyframerFormat.SIMPLE, format: KeyframerFormat = KeyframerFormat.SIMPLE,
parameters: Map<String, Double> = emptyMap(), parameters: Map<String, Double> = emptyMap(),
functions: FunctionExtensions = FunctionExtensions.EMPTY functions: FunctionExtensions = FunctionExtensions.EMPTY
) { ) {
require(file.exists()) { require(file.exists()) {
"failed to load keyframer from json: '${file.absolutePath}' does not exist." "failed to load keyframer from json: '${file.absolutePath}' does not exist."
@@ -125,16 +136,16 @@ open class Keyframer {
loadFromJsonString(url.readText(), format, parameters, functions) loadFromJsonString(url.readText(), format, parameters, functions)
} catch (e: ExpressionException) { } catch (e: ExpressionException) {
throw ExpressionException("Error loading $format from '${url}': ${e.message ?: ""}") throw ExpressionException("Error loading $format from '${url}': ${e.message ?: ""}")
} catch(e: IllegalStateException) { } catch (e: IllegalStateException) {
throw ExpressionException("Error loading $format from '${url}': ${e.message ?: ""}") throw ExpressionException("Error loading $format from '${url}': ${e.message ?: ""}")
} }
} }
fun loadFromJsonString( fun loadFromJsonString(
json: String, json: String,
format: KeyframerFormat = KeyframerFormat.SIMPLE, format: KeyframerFormat = KeyframerFormat.SIMPLE,
parameters: Map<String, Double> = emptyMap(), parameters: Map<String, Double> = emptyMap(),
functions: FunctionExtensions = FunctionExtensions.EMPTY functions: FunctionExtensions = FunctionExtensions.EMPTY
) { ) {
when (format) { when (format) {
KeyframerFormat.SIMPLE -> { KeyframerFormat.SIMPLE -> {
@@ -164,9 +175,9 @@ open class Keyframer {
private val prototypes = mutableMapOf<String, Map<String, Any>>() private val prototypes = mutableMapOf<String, Map<String, Any>>()
fun loadFromObjects( fun loadFromObjects(
dict: Map<String, Any>, dict: Map<String, Any>,
externalParameters: Map<String, Double> = emptyMap(), externalParameters: Map<String, Double> = emptyMap(),
functions: FunctionExtensions = FunctionExtensions.EMPTY functions: FunctionExtensions = FunctionExtensions.EMPTY
) { ) {
this.parameters.clear() this.parameters.clear()
this.parameters.putAll(externalParameters) this.parameters.putAll(externalParameters)
@@ -179,7 +190,7 @@ open class Keyframer {
when (val candidate = entry.value) { when (val candidate = entry.value) {
is Double -> candidate is Double -> candidate
is String -> evaluateExpression(candidate, parameters, functions) is String -> evaluateExpression(candidate, parameters, functions)
?: error("could not evaluate expression: '$candidate'") ?: error("could not evaluate expression: '$candidate'")
is Int -> candidate.toDouble() is Int -> candidate.toDouble()
is Float -> candidate.toDouble() is Float -> candidate.toDouble()
else -> error("unknown type for parameter '${entry.key}'") else -> error("unknown type for parameter '${entry.key}'")
@@ -214,9 +225,9 @@ open class Keyframer {
} }
fun loadFromKeyObjects( fun loadFromKeyObjects(
keys: List<Map<String, Any>>, keys: List<Map<String, Any>>,
externalParameters: Map<String, Double>, externalParameters: Map<String, Double>,
functions: FunctionExtensions functions: FunctionExtensions
) { ) {
if (externalParameters !== parameters) { if (externalParameters !== parameters) {
parameters.clear() parameters.clear()
@@ -226,12 +237,12 @@ open class Keyframer {
var lastTime = 0.0 var lastTime = 0.0
val channelDelegates = this::class.memberProperties val channelDelegates = this::class.memberProperties
.mapNotNull { .mapNotNull {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
it as? KProperty1<Keyframer, Any> it as? KProperty1<Keyframer, Any>
} }
.filter { it.isAccessible = true; it.getDelegate(this) is CompoundChannel } .filter { it.isAccessible = true; it.getDelegate(this) is CompoundChannel }
.associate { Pair(it.name, it.getDelegate(this) as CompoundChannel) } .associate { Pair(it.name, it.getDelegate(this) as CompoundChannel) }
val channelKeys = channelDelegates.values.flatMap { channel -> val channelKeys = channelDelegates.values.flatMap { channel ->
channel.keys.map { it } channel.keys.map { it }
@@ -260,7 +271,7 @@ open class Keyframer {
when (val candidate = computed["time"]) { when (val candidate = computed["time"]) {
null -> lastTime null -> lastTime
is String -> evaluateExpression(candidate, expressionContext, functions) is String -> evaluateExpression(candidate, expressionContext, functions)
?: error { "unknown value format for time : $candidate" } ?: error { "unknown value format for time : $candidate" }
is Double -> candidate is Double -> candidate
is Int -> candidate.toDouble() is Int -> candidate.toDouble()
is Float -> candidate.toDouble() is Float -> candidate.toDouble()
@@ -274,7 +285,7 @@ open class Keyframer {
when (val candidate = computed["duration"]) { when (val candidate = computed["duration"]) {
null -> 0.0 null -> 0.0
is String -> evaluateExpression(candidate, expressionContext, functions) is String -> evaluateExpression(candidate, expressionContext, functions)
?: error { "unknown value format for time : $candidate" } ?: error { "unknown value format for time : $candidate" }
is Int -> candidate.toDouble() is Int -> candidate.toDouble()
is Float -> candidate.toDouble() is Float -> candidate.toDouble()
is Double -> candidate is Double -> candidate
@@ -343,7 +354,7 @@ open class Keyframer {
when (val candidate = channelCandidate.value) { when (val candidate = channelCandidate.value) {
is Double -> candidate is Double -> candidate
is String -> evaluateExpression(candidate, expressionContext, functions) is String -> evaluateExpression(candidate, expressionContext, functions)
?: error("unknown value format for key '${channelCandidate.key}' : $candidate") ?: error("unknown value format for key '${channelCandidate.key}' : $candidate")
is Int -> candidate.toDouble() is Int -> candidate.toDouble()
else -> error("unknown value type for key '${channelCandidate.key}' : $candidate") else -> error("unknown value type for key '${channelCandidate.key}' : $candidate")
} }
@@ -365,7 +376,7 @@ open class Keyframer {
is Int -> candidate is Int -> candidate
is Double -> candidate.toInt() is Double -> candidate.toInt()
is String -> evaluateExpression(candidate, expressionContext, functions)?.roundToInt() is String -> evaluateExpression(candidate, expressionContext, functions)?.roundToInt()
?: error("cannot evaluate expression for count: '$candidate'") ?: error("cannot evaluate expression for count: '$candidate'")
else -> error("unknown value type for count: '$candidate") else -> error("unknown value type for count: '$candidate")
} }
} catch (e: ExpressionException) { } catch (e: ExpressionException) {