[orx-fcurves] Add override values to CompoundFCurve

This commit is contained in:
Edwin Jakobs
2024-06-17 07:22:41 +02:00
parent ab062d10ec
commit e58322768d
2 changed files with 154 additions and 33 deletions

View File

@@ -3,41 +3,75 @@ package org.openrndr.extra.fcurve
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.math.* import org.openrndr.math.*
abstract class CompoundFCurve<T>(val compounds: List<FCurve?>) { abstract class CompoundFCurve<T>(val compounds: List<FCurve?>, val compoundNames: List<String>) {
val duration: Double val duration: Double
get() { get() {
return compounds.maxOf { it?.duration ?: 0.0 } return compounds.maxOf { it?.duration ?: 0.0 }
} }
abstract fun value(t: Double, overrides: Map<String, Double>? = null): T
abstract fun sampler(normalized: Boolean = false): (Double) -> T abstract fun sampler(normalized: Boolean = false): (Double) -> T
} }
class BooleanFCurve(value: FCurve?, val default: Boolean = true) : class BooleanFCurve(value: Pair<String, FCurve?>, val default: Boolean = true) :
CompoundFCurve<Boolean>(listOf(value)) { CompoundFCurve<Boolean>(listOf(value.second), listOf(value.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Boolean {
val d = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t)
return if (d != null) {
d >= 1.0
} else {
default
}
}
override fun sampler(normalized: Boolean): (Double) -> Boolean { override fun sampler(normalized: Boolean): (Double) -> Boolean {
val sampler = compounds[0]?.sampler(normalized) ?: { if (default) 1.0 else 0.0 } val sampler = compounds[0]?.sampler(normalized) ?: { if (default) 1.0 else 0.0 }
return { t -> sampler(t) >= 1.0 } return { t -> sampler(t) >= 1.0 }
} }
} }
class DoubleFCurve(value: FCurve?, val default: Double = 0.0) : class DoubleFCurve(value: Pair<String, FCurve?>, val default: Double = 0.0) :
CompoundFCurve<Double>(listOf(value)) { CompoundFCurve<Double>(listOf(value.second), listOf(value.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Double {
return overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default
}
override fun sampler(normalized: Boolean): (Double) -> Double { override fun sampler(normalized: Boolean): (Double) -> Double {
val sampler = compounds[0]?.sampler(normalized) ?: { default } val sampler = compounds[0]?.sampler(normalized) ?: { default }
return { t -> sampler(t) } return { t -> sampler(t) }
} }
} }
class IntFCurve(value: FCurve?, val default: Int = 0) : class IntFCurve(value: Pair<String, FCurve?>, val default: Int = 0) :
CompoundFCurve<Int>(listOf(value)) { CompoundFCurve<Int>(listOf(value.second), listOf(value.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Int {
val d = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t)
return if (d != null) {
d.toInt()
} else {
default
}
}
override fun sampler(normalized: Boolean): (Double) -> Int { override fun sampler(normalized: Boolean): (Double) -> Int {
val sampler = compounds[0]?.sampler(normalized) ?: { default.toDouble() } val sampler = compounds[0]?.sampler(normalized) ?: { default.toDouble() }
return { t -> sampler(t).toInt() } return { t -> sampler(t).toInt() }
} }
} }
class Vector2FCurve(x: FCurve?, y: FCurve?, val default: Vector2 = Vector2.ZERO) : class Vector2FCurve(
CompoundFCurve<Vector2>(listOf(x, y)) { x: Pair<String, FCurve?>, y: Pair<String, FCurve?>,
val default: Vector2 = Vector2.ZERO
) :
CompoundFCurve<Vector2>(listOf(x.second, y.second), listOf(x.first, y.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Vector2 {
val x = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.x
val y = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.y
return Vector2(x, y)
}
override fun sampler(normalized: Boolean): (Double) -> Vector2 { override fun sampler(normalized: Boolean): (Double) -> Vector2 {
val xSampler = compounds[0]?.sampler(normalized) ?: { default.x } val xSampler = compounds[0]?.sampler(normalized) ?: { default.x }
val ySampler = compounds[1]?.sampler(normalized) ?: { default.y } val ySampler = compounds[1]?.sampler(normalized) ?: { default.y }
@@ -45,8 +79,20 @@ class Vector2FCurve(x: FCurve?, y: FCurve?, val default: Vector2 = Vector2.ZERO)
} }
} }
class Vector3FCurve(x: FCurve?, y: FCurve?, z: FCurve?, val default: Vector3 = Vector3.ZERO) : class Vector3FCurve(
CompoundFCurve<Vector3>(listOf(x, y, z)) { x: Pair<String, FCurve?>,
y: Pair<String, FCurve?>,
z: Pair<String, FCurve?>,
val default: Vector3 = Vector3.ZERO
) :
CompoundFCurve<Vector3>(listOf(x.second, y.second, z.second), listOf(x.first, y.first, z.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Vector3 {
val x = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.x
val y = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.y
val z = overrides?.get(compoundNames[2]) ?: compounds[2]?.value(t) ?: default.z
return Vector3(x, y, z)
}
override fun sampler(normalized: Boolean): (Double) -> Vector3 { override fun sampler(normalized: Boolean): (Double) -> Vector3 {
val xSampler = compounds[0]?.sampler(normalized) ?: { default.x } val xSampler = compounds[0]?.sampler(normalized) ?: { default.x }
val ySampler = compounds[1]?.sampler(normalized) ?: { default.y } val ySampler = compounds[1]?.sampler(normalized) ?: { default.y }
@@ -55,8 +101,26 @@ class Vector3FCurve(x: FCurve?, y: FCurve?, z: FCurve?, val default: Vector3 = V
} }
} }
class Vector4FCurve(x: FCurve?, y: FCurve?, z: FCurve?, w: FCurve?, val default: Vector4 = Vector4.ZERO) : class Vector4FCurve(
CompoundFCurve<Vector4>(listOf(x, y, z, w)) { x: Pair<String, FCurve?>,
y: Pair<String, FCurve?>,
z: Pair<String, FCurve?>,
w: Pair<String, FCurve?>,
val default: Vector4 = Vector4.ZERO
) :
CompoundFCurve<Vector4>(
listOf(x.second, y.second, z.second, w.second),
listOf(x.first, y.first, z.first, w.first)
) {
override fun value(t: Double, overrides: Map<String, Double>?): Vector4 {
val x = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.x
val y = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.y
val z = overrides?.get(compoundNames[2]) ?: compounds[2]?.value(t) ?: default.z
val w = overrides?.get(compoundNames[3]) ?: compounds[3]?.value(t) ?: default.w
return Vector4(x, y, z, w)
}
override fun sampler(normalized: Boolean): (Double) -> Vector4 { override fun sampler(normalized: Boolean): (Double) -> Vector4 {
val xSampler = compounds[0]?.sampler(normalized) ?: { default.x } val xSampler = compounds[0]?.sampler(normalized) ?: { default.x }
val ySampler = compounds[1]?.sampler(normalized) ?: { default.y } val ySampler = compounds[1]?.sampler(normalized) ?: { default.y }
@@ -66,8 +130,21 @@ class Vector4FCurve(x: FCurve?, y: FCurve?, z: FCurve?, w: FCurve?, val default:
} }
} }
class RgbFCurve(r: FCurve?, g: FCurve?, b: FCurve?, val default: ColorRGBa = ColorRGBa.WHITE) : class RgbFCurve(
CompoundFCurve<ColorRGBa>(listOf(r, g, b)) { r: Pair<String, FCurve?>,
g: Pair<String, FCurve?>,
b: Pair<String, FCurve?>,
val default: ColorRGBa = ColorRGBa.WHITE
) :
CompoundFCurve<ColorRGBa>(listOf(r.second, g.second, b.second), listOf(r.first, g.first, b.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): ColorRGBa {
val r = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.r
val g = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.g
val b = overrides?.get(compoundNames[2]) ?: compounds[2]?.value(t) ?: default.g
return ColorRGBa(r, g, b)
}
override fun sampler(normalized: Boolean): (Double) -> ColorRGBa { override fun sampler(normalized: Boolean): (Double) -> ColorRGBa {
val rSampler = compounds[0]?.sampler(normalized) ?: { default.r } val rSampler = compounds[0]?.sampler(normalized) ?: { default.r }
val gSampler = compounds[1]?.sampler(normalized) ?: { default.g } val gSampler = compounds[1]?.sampler(normalized) ?: { default.g }
@@ -76,8 +153,26 @@ class RgbFCurve(r: FCurve?, g: FCurve?, b: FCurve?, val default: ColorRGBa = Col
} }
} }
class RgbaFCurve(r: FCurve?, g: FCurve?, b: FCurve?, a: FCurve?, val default: ColorRGBa = ColorRGBa.WHITE) : class RgbaFCurve(
CompoundFCurve<ColorRGBa>(listOf(r, g, b, a)) { r: Pair<String, FCurve?>,
g: Pair<String, FCurve?>,
b: Pair<String, FCurve?>,
a: Pair<String, FCurve?>,
val default: ColorRGBa = ColorRGBa.WHITE
) :
CompoundFCurve<ColorRGBa>(
listOf(r.second, g.second, b.second, a.second),
listOf(r.first, g.first, b.first, a.first)
) {
override fun value(t: Double, overrides: Map<String, Double>?): ColorRGBa {
val r = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.r
val g = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.g
val b = overrides?.get(compoundNames[2]) ?: compounds[2]?.value(t) ?: default.g
val a = overrides?.get(compoundNames[3]) ?: compounds[3]?.value(t) ?: default.alpha
return ColorRGBa(r, g, b, a)
}
override fun sampler(normalized: Boolean): (Double) -> ColorRGBa { override fun sampler(normalized: Boolean): (Double) -> ColorRGBa {
val rSampler = compounds[0]?.sampler(normalized) ?: { default.r } val rSampler = compounds[0]?.sampler(normalized) ?: { default.r }
val gSampler = compounds[1]?.sampler(normalized) ?: { default.g } val gSampler = compounds[1]?.sampler(normalized) ?: { default.g }
@@ -87,8 +182,19 @@ class RgbaFCurve(r: FCurve?, g: FCurve?, b: FCurve?, a: FCurve?, val default: Co
} }
} }
class PolarFCurve(angleInDegrees: FCurve?, radius: FCurve?, val default: Polar = Polar(0.0, 1.0)) : class PolarFCurve(
CompoundFCurve<Polar>(listOf(angleInDegrees, radius)) { angleInDegrees: Pair<String, FCurve?>,
radius: Pair<String, FCurve?>,
val default: Polar = Polar(0.0, 1.0)
) :
CompoundFCurve<Polar>(listOf(angleInDegrees.second, radius.second), listOf(angleInDegrees.first, radius.first)) {
override fun value(t: Double, overrides: Map<String, Double>?): Polar {
val theta = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.theta
val radius = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.radius
return Polar(theta, radius)
}
override fun sampler(normalized: Boolean): (Double) -> Polar { override fun sampler(normalized: Boolean): (Double) -> Polar {
val angleSampler = compounds[0]?.sampler(normalized) ?: { default.theta } val angleSampler = compounds[0]?.sampler(normalized) ?: { default.theta }
val radiusSampler = compounds[1]?.sampler(normalized) ?: { default.radius } val radiusSampler = compounds[1]?.sampler(normalized) ?: { default.radius }
@@ -97,12 +203,22 @@ class PolarFCurve(angleInDegrees: FCurve?, radius: FCurve?, val default: Polar =
} }
class SphericalFCurve( class SphericalFCurve(
thetaInDegrees: FCurve?, thetaInDegrees: Pair<String, FCurve?>,
phiInDegrees: FCurve?, phiInDegrees: Pair<String, FCurve?>,
radius: FCurve?, radius: Pair<String, FCurve?>,
val default: Spherical = Spherical(0.0, 1.0, 1.0) val default: Spherical = Spherical(0.0, 1.0, 1.0)
) : ) :
CompoundFCurve<Spherical>(listOf(thetaInDegrees, phiInDegrees, radius)) { CompoundFCurve<Spherical>(
listOf(thetaInDegrees.second, phiInDegrees.second, radius.second),
listOf(thetaInDegrees.first, phiInDegrees.first, radius.first)
) {
override fun value(t: Double, overrides: Map<String, Double>?): Spherical {
val theta = overrides?.get(compoundNames[0]) ?: compounds[0]?.value(t) ?: default.theta
val phi = overrides?.get(compoundNames[1]) ?: compounds[1]?.value(t) ?: default.phi
val radius = overrides?.get(compoundNames[2]) ?: compounds[2]?.value(t) ?: default.radius
return Spherical(theta, phi, radius)
}
override fun sampler(normalized: Boolean): (Double) -> Spherical { override fun sampler(normalized: Boolean): (Double) -> Spherical {
val thetaSampler = compounds[0]?.sampler(normalized) ?: { default.theta } val thetaSampler = compounds[0]?.sampler(normalized) ?: { default.theta }
val phiSampler = compounds[0]?.sampler(normalized) ?: { default.theta } val phiSampler = compounds[0]?.sampler(normalized) ?: { default.theta }

View File

@@ -3,32 +3,37 @@ package org.openrndr.extra.fcurve
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.math.* import org.openrndr.math.*
fun MultiFCurve.boolean(value: String, default: Boolean = true) = BooleanFCurve(this[value], default) fun MultiFCurve.boolean(value: String, default: Boolean = true) = BooleanFCurve(value to this[value], default)
fun MultiFCurve.double(value: String, default: Double = 0.0) = DoubleFCurve(this[value], default) fun MultiFCurve.double(value: String, default: Double = 0.0) = DoubleFCurve(value to this[value], default)
fun MultiFCurve.int(value: String, default: Int = 0) = IntFCurve(this[value], default) fun MultiFCurve.int(value: String, default: Int = 0) = IntFCurve(value to this[value], default)
fun MultiFCurve.vector2(x: String, y: String, default: Vector2 = Vector2.ZERO) = fun MultiFCurve.vector2(x: String, y: String, default: Vector2 = Vector2.ZERO) =
Vector2FCurve(this[x], this[y], default) Vector2FCurve(x to this[x], y to this[y], default)
fun MultiFCurve.vector3(x: String, y: String, z: String, default: Vector3 = Vector3.ZERO) = fun MultiFCurve.vector3(x: String, y: String, z: String, default: Vector3 = Vector3.ZERO) =
Vector3FCurve(this[x], this[y], this[z], default) Vector3FCurve(x to this[x], y to this[y], z to this[z], default)
fun MultiFCurve.vector4(x: String, y: String, z: String, w: String, default: Vector4 = Vector4.ZERO) = fun MultiFCurve.vector4(x: String, y: String, z: String, w: String, default: Vector4 = Vector4.ZERO) =
Vector4FCurve(this[x], this[y], this[z], this[w], default) Vector4FCurve(x to this[x], y to this[y], z to this[z], w to this[w], default)
fun MultiFCurve.rgb(r: String, g: String, b: String, default: ColorRGBa = ColorRGBa.WHITE) = fun MultiFCurve.rgb(r: String, g: String, b: String, default: ColorRGBa = ColorRGBa.WHITE) =
RgbFCurve(this[r], this[g], this[b], default) RgbFCurve(r to this[r], g to this[g], b to this[b], default)
fun MultiFCurve.rgba(r: String, g: String, b: String, a: String, default: ColorRGBa = ColorRGBa.WHITE) = fun MultiFCurve.rgba(r: String, g: String, b: String, a: String, default: ColorRGBa = ColorRGBa.WHITE) =
RgbaFCurve(this[r], this[g], this[b], this[a], default) RgbaFCurve(r to this[r], g to this[g], b to this[b], a to this[a], default)
fun MultiFCurve.polar(angleInDegrees: String, radius: String, default: Polar = Polar(0.0, 1.0)) = fun MultiFCurve.polar(angleInDegrees: String, radius: String, default: Polar = Polar(0.0, 1.0)) =
PolarFCurve(this[angleInDegrees], this[radius], default) PolarFCurve(angleInDegrees to this[angleInDegrees], radius to this[radius], default)
fun MultiFCurve.spherical( fun MultiFCurve.spherical(
thetaInDegrees: String, thetaInDegrees: String,
phiInDegrees: String, phiInDegrees: String,
radius: String, radius: String,
default: Spherical = Spherical(0.0, 0.0, 1.0) default: Spherical = Spherical(0.0, 0.0, 1.0)
) = SphericalFCurve(this[thetaInDegrees], this[phiInDegrees], this[radius], default) ) = SphericalFCurve(
thetaInDegrees to this[thetaInDegrees],
phiInDegrees to this[phiInDegrees],
radius to this[radius],
default
)