灵符lingfu

ling-lang

↓ 0 downloads

Ling - The Omniglot Systems Language

Keywords systems, polyglot, ai, crypto, game
lingfu install ling-lang
LicenseApache-2.0 OR MIT
AuthorsLing Lin, Sanny Lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (995)

crates/ling-animation/src/lib.rs
//! # ling-animation — "Anima"
//!
//! Ling's unified animation system. The thesis: **one rig, any target, any
//! temperament.** Every animated thing — a 2-D vtexture, a 3-D mesh, a particle
//! field, or a bag of scalar parameters — is a [`rig::Rig`] of abstract joints,
//! driven by composable drivers, and deformed onto its target by a binding.
//!
//! What sets it apart is the **temperament axis** ([`temperament::Temperament`]):
//! a per-chain scalar from **organic (灵)** to **mechanical (机)** that selects
//! and cross-fades the solver — muscle/jiggle/breath/IK on one end, exact
//! gear/cam/linkage coupling on the other. A robot can have organic hydraulic
//! sag; a creature can have a mechanical jaw.
//!
//! ## Layers
//! - [`ease`] — easing curves + a `Lerp` trait (standalone, wasm-safe).
//! - [`track`] — keyframe tracks + a playable [`track::Timeline`].
//! - [`rig`] — joints, hierarchy, world-pose + skinning matrices.
//! - [`temperament`] — the 灵 ↔ 机 axis.
//! - [`scalar`] — per-frame organic/mechanical driver math (powers the builtins).
//! - [`mechanism`] — exact linkages (gear trains, four-bar).
//! - [`creature`] — procedural biped/quadruped gaits + breathing.

pub mod creature;
pub mod ease;
pub mod face;
pub mod mechanism;
pub mod rig;
pub mod scalar;
pub mod temperament;
pub mod track;

pub use ease::{tween_ease, EaseFunction, Lerp};
pub use face::{Expression, FacePoint, FaceRig, Region};
pub use rig::{Joint, JointId, Rig, Transform};
pub use temperament::Temperament;
pub use track::{Keyframe, Timeline, Track};

/// A small owner of animation state, indexed by handle. Hosts (like the Ling
/// runtime) can park rigs and timelines here and drive them by integer handle.
#[derive(Debug, Default)]
pub struct Animator {
    rigs: Vec<Rig>,
    timelines: Vec<Timeline>,
}

impl Animator {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn add_rig(&mut self, rig: Rig) -> usize {
        self.rigs.push(rig);
        self.rigs.len() - 1
    }

    pub fn rig(&self, h: usize) -> Option<&Rig> {
        self.rigs.get(h)
    }

    pub fn rig_mut(&mut self, h: usize) -> Option<&mut Rig> {
        self.rigs.get_mut(h)
    }

    /// Create a looping timeline of `duration` seconds; returns its handle.
    pub fn add_timeline(&mut self, duration: f32) -> usize {
        self.timelines.push(Timeline::new(duration));
        self.timelines.len() - 1
    }

    pub fn timeline(&self, h: usize) -> Option<&Timeline> {
        self.timelines.get(h)
    }

    /// Advance one timeline by `dt`; returns its new normalized progress `[0,1]`.
    pub fn tick(&mut self, h: usize, dt: f32) -> f32 {
        match self.timelines.get_mut(h) {
            Some(tl) => {
                tl.tick(dt);
                tl.normalized()
            },
            None => 0.0,
        }
    }

    /// Advance every timeline by `dt`.
    pub fn tick_all(&mut self, dt: f32) {
        for tl in &mut self.timelines {
            tl.tick(dt);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn animator_ticks_timeline() {
        let mut a = Animator::new();
        let h = a.add_timeline(2.0);
        assert!((a.tick(h, 1.0) - 0.5).abs() < 1e-5);
    }
}

← Back to index