import simd
import PhysarumEngine
/// HSV (each 0…1) → engine RGB.
func hsv2rgb(_ h: Double, _ s: Double, _ v: Double) -> RGB {
let i = Int(h * 6) % 6
let f = h * 6 - Double(Int(h * 6))
let p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s)
let c: (Double, Double, Double)
switch i {
case 0: c = (v, t, p)
case 1: c = (q, v, p)
case 2: c = (p, v, t)
case 3: c = (p, q, v)
case 4: c = (t, p, v)
default: c = (v, p, q)
}
return RGB(Float(c.0), Float(c.1), Float(c.2))
}
/// Component-wise linear interpolation of two RGB colors.
func mixRGB(_ a: RGB, _ b: RGB, _ t: Double) -> RGB {
a + (b - a) * Float(t)
}
/// Interpolate two presets at t∈[0,1]. Scalars (incl. matrix, agentCount) lerp via
/// the registry; colors lerp component-wise; discrete enums switch at the 0.5
/// threshold. Endpoints are exact (t≤0 → a, t≥1 → b).
func morphParams(_ a: PresetParams, _ b: PresetParams, t: Double) -> PresetParams {
if t <= 0 { return a }
if t >= 1 { return b }
var out = a
for d in ParamRegistry.all {
let va = d.get(a), vb = d.get(b)
d.set(&out, va + (vb - va) * t) // set() rounds ints
}
for i in 0..<3 {
out.species[i].color = mixRGB(a.species[i].color, b.species[i].color, t)
}
out.backgroundColor = mixRGB(a.backgroundColor, b.backgroundColor, t)
out.spawnPattern = t < 0.5 ? a.spawnPattern : b.spawnPattern
out.blendMode = t < 0.5 ? a.blendMode : b.blendMode
return out
}