use super::tracks;
use crate::check::{Check, CheckCtx};
use crate::finding::{Finding, Severity};
use crate::model::Property;
pub const NON_UNIFORM_TOLERANCE: f32 = 1e-4;
pub const UNIT_TOLERANCE: f32 = 1e-4;
pub struct ScaleKeys;
impl Check for ScaleKeys {
fn id(&self) -> &'static str {
"scale-keys"
}
fn run(&self, ctx: &CheckCtx, out: &mut Vec<Finding>) {
let doc = ctx.doc;
for (clip, bone, track) in tracks(doc) {
if track.property != Property::Scale {
continue;
}
let mut scaling = false;
let mut non_uniform_at: Option<usize> = None;
for k in 0..track.key_count() {
let Some(v) = track.key_vec3(k) else { continue };
if !v.is_finite() {
continue;
}
if (v - glam::Vec3::ONE).abs().max_element() > UNIT_TOLERANCE {
scaling = true;
}
if (v.max_element() - v.min_element()).abs() > NON_UNIFORM_TOLERANCE
&& non_uniform_at.is_none()
{
non_uniform_at = Some(k);
}
}
if scaling {
out.push(
Finding::new(
self.id(),
Severity::Warning,
"scale animation present — verify it is intentional; many rigs \
and retargeters mishandle animated scale",
)
.clip(clip)
.bone(bone),
);
}
if let Some(k) = non_uniform_at {
out.push(
Finding::new(
self.id(),
Severity::Warning,
format!("non-uniform scale key (first at key {k})"),
)
.clip(clip)
.bone(bone)
.time(track.times[k]),
);
}
}
}
}