Skip to main content

Motion

Struct Motion 

Source
pub struct Motion<C: Clip> { /* private fields */ }
Expand description

What a state plays: one clip, two of them blended, or one a value of the game’s own scrubs.

Every clip runs on its own timeline, so a pace of 1.0 plays it as long as its source states.

Implementations§

Source§

impl<C: Clip> Motion<C>

Source

pub fn looping(clip: C) -> Self

Plays clip over and over, wrapping from its last key to its first.

Examples found in repository?
examples/animation.rs (line 353)
351    fn motion(&self, input: &ElfInput) -> Motion<ElfClip> {
352        match self {
353            Self::Idle => Motion::looping(ElfClip::Idle),
354            Self::Locomotion => {
355                Motion::blend(ElfClip::Walk, ElfClip::Jog, input.speed).paced(input.speed)
356            }
357            Self::Attack => Motion::once(ElfClip::Attack),
358            Self::Hit => Motion::once(ElfClip::Hit),
359            Self::Death => Motion::once(ElfClip::Death),
360            Self::SitDown => Motion::once(ElfClip::SitDown),
361            Self::Sit => Motion::looping(ElfClip::Sit),
362            Self::StandUp => Motion::once(ElfClip::StandUp),
363            Self::Jump => Motion::once(ElfClip::Jump),
364            Self::Dance => Motion::looping(ElfClip::Dance),
365        }
366    }
367
368    fn next(&self, input: &ElfInput, at: Progress) -> Option<Transition<Self>> {
369        match (self, input) {
370            (Self::Death, _) => None,
371            (_, ElfInput { dying: true, .. }) => Some(Self::Death.fade(DEATH_FADE)),
372            (_, ElfInput { hit: true, .. }) if *self != Self::Hit => {
373                Some(Self::Hit.fade(HIT_ENTER_FADE))
374            }
375            (Self::Hit, _) if at.ended() => Some(ElfState::grounded(input).fade(HIT_EXIT_FADE)),
376            (Self::Attack, ElfInput { attack: true, .. }) if at.past(ATTACK_RELEASE) => Some(
377                Self::Attack
378                    .restarted()
379                    .entering_at(ATTACK_CHAIN_ENTRY)
380                    .fade(ATTACK_CHAIN_FADE),
381            ),
382            (Self::Attack, _) if at.past(ATTACK_RELEASE) => {
383                Some(ElfState::grounded(input).fade(ATTACK_EXIT_FADE))
384            }
385            (Self::SitDown | Self::Sit | Self::StandUp, i) if i.speed > WALK_THRESHOLD => {
386                Some(Self::Locomotion.fade(STAND_EXIT_FADE))
387            }
388            (Self::SitDown | Self::Sit | Self::StandUp, ElfInput { attack: true, .. }) => {
389                Some(Self::Attack.fade(ATTACK_ENTER_FADE))
390            }
391            (Self::SitDown | Self::Sit | Self::StandUp, ElfInput { jump: true, .. }) => {
392                Some(Self::Jump.fade(JUMP_ENTER_FADE))
393            }
394            (Self::SitDown, _) if at.ended() => Some(Self::Sit.at_once()),
395            (Self::Sit, ElfInput { interact: true, .. }) => Some(Self::StandUp.fade(STAND_UP_FADE)),
396            (Self::StandUp, _) if at.ended() => Some(Self::Idle.fade(STAND_EXIT_FADE)),
397            (Self::Jump, ElfInput { landed: true, .. }) => {
398                Some(ElfState::grounded(input).fade(JUMP_EXIT_FADE))
399            }
400            (Self::Jump, _) if at.ended() => Some(ElfState::grounded(input).fade(JUMP_EXIT_FADE)),
401            (
402                Self::Idle | Self::Locomotion,
403                ElfInput {
404                    interact: true,
405                    near_seat: true,
406                    ..
407                },
408            ) => Some(Self::SitDown.fade(SIT_DOWN_FADE)),
409            (Self::Idle | Self::Locomotion, ElfInput { attack: true, .. }) => {
410                Some(Self::Attack.fade(ATTACK_ENTER_FADE))
411            }
412            (Self::Idle | Self::Locomotion, ElfInput { jump: true, .. }) => {
413                Some(Self::Jump.fade(JUMP_ENTER_FADE))
414            }
415            (Self::Idle, ElfInput { dance: true, .. }) => Some(Self::Dance.fade(DANCE_FADE)),
416            (Self::Dance, i) if i.speed > WALK_THRESHOLD => {
417                Some(Self::Locomotion.fade(IDLE_LOCOMOTION_FADE))
418            }
419            (Self::Idle, i) if i.speed > WALK_THRESHOLD => {
420                Some(Self::Locomotion.fade(IDLE_LOCOMOTION_FADE))
421            }
422            (Self::Locomotion, i) if i.speed <= WALK_THRESHOLD => {
423                Some(Self::Idle.fade(IDLE_LOCOMOTION_FADE))
424            }
425            _ => None,
426        }
427    }
428}
429
430/// A machine of one state, posed by nothing but the value it scrubs.
431#[derive(Clone, Copy, Eq, PartialEq, Debug)]
432enum ScrubbedState {
433    SitDown,
434}
435
436/// What the game fills each tick to move `ScrubbedState` on.
437#[derive(Default)]
438struct ScrubbedInput {
439    /// How far into sitting down the second elf reads, a fraction in
440    /// `0.0..=1.0`.
441    settled: f32,
442}
443
444impl AnimationStates for ScrubbedState {
445    type Clip = ElfClip;
446    type Input = ScrubbedInput;
447
448    fn entry() -> Self {
449        Self::SitDown
450    }
451
452    fn motion(&self, input: &ScrubbedInput) -> Motion<ElfClip> {
453        Motion::scrubbed(ElfClip::SitDown, input.settled)
454    }
455
456    fn next(&self, _input: &ScrubbedInput, _at: Progress) -> Option<Transition<Self>> {
457        None
458    }
459}
460
461#[derive(Catalog, Clone, PartialEq, Eq, Hash)]
462struct Butterfly;
463
464/// The one clip `FlyingState` plays, named as the source names it.
465#[derive(Clip, Clone, Debug, PartialEq, Eq, Hash)]
466enum ButterflyClip {
467    #[clip("fly")]
468    Fly,
469}
470
471impl Mesh<NoParts, ButterflyClip> for Butterfly {
472    fn build(&self, assets: &Assets) -> MeshData<NoParts, ButterflyClip> {
473        assets.model(BUTTERFLY_ROOT)
474    }
475}
476
477/// A machine of one state, looping the butterfly's only clip.
478#[derive(Clone, Copy, Eq, PartialEq, Debug)]
479enum FlyingState {
480    Flying,
481}
482
483impl AnimationStates for FlyingState {
484    type Clip = ButterflyClip;
485    type Input = ();
486
487    fn entry() -> Self {
488        Self::Flying
489    }
490
491    fn motion(&self, _input: &()) -> Motion<ButterflyClip> {
492        Motion::looping(ButterflyClip::Fly)
493    }
Source

pub fn once(clip: C) -> Self

Plays clip once and holds its last key.

Examples found in repository?
examples/animation.rs (line 357)
351    fn motion(&self, input: &ElfInput) -> Motion<ElfClip> {
352        match self {
353            Self::Idle => Motion::looping(ElfClip::Idle),
354            Self::Locomotion => {
355                Motion::blend(ElfClip::Walk, ElfClip::Jog, input.speed).paced(input.speed)
356            }
357            Self::Attack => Motion::once(ElfClip::Attack),
358            Self::Hit => Motion::once(ElfClip::Hit),
359            Self::Death => Motion::once(ElfClip::Death),
360            Self::SitDown => Motion::once(ElfClip::SitDown),
361            Self::Sit => Motion::looping(ElfClip::Sit),
362            Self::StandUp => Motion::once(ElfClip::StandUp),
363            Self::Jump => Motion::once(ElfClip::Jump),
364            Self::Dance => Motion::looping(ElfClip::Dance),
365        }
366    }
Source

pub fn blend(from: C, to: C, weight: f32) -> Self

Plays from and to together, weight of the way to to, as a fraction held inside 0.0..=1.0 and read as 0.0 where it is not a number.

Each is read at the same fraction of its own timeline and both count cycles together, so a walk and a run of different lengths keep their steps together.

Examples found in repository?
examples/animation.rs (line 355)
351    fn motion(&self, input: &ElfInput) -> Motion<ElfClip> {
352        match self {
353            Self::Idle => Motion::looping(ElfClip::Idle),
354            Self::Locomotion => {
355                Motion::blend(ElfClip::Walk, ElfClip::Jog, input.speed).paced(input.speed)
356            }
357            Self::Attack => Motion::once(ElfClip::Attack),
358            Self::Hit => Motion::once(ElfClip::Hit),
359            Self::Death => Motion::once(ElfClip::Death),
360            Self::SitDown => Motion::once(ElfClip::SitDown),
361            Self::Sit => Motion::looping(ElfClip::Sit),
362            Self::StandUp => Motion::once(ElfClip::StandUp),
363            Self::Jump => Motion::once(ElfClip::Jump),
364            Self::Dance => Motion::looping(ElfClip::Dance),
365        }
366    }
Source

pub fn scrubbed(clip: C, fraction: f32) -> Self

Holds clip at fraction of the way along it, a fraction held inside 0.0..=1.0 and read as 0.0 where it is not a number.

Required if you want a value of the game’s own to pose a mesh: no clock moves it, so a door opens as far as the game states and no further.

Examples found in repository?
examples/animation.rs (line 453)
452    fn motion(&self, input: &ScrubbedInput) -> Motion<ElfClip> {
453        Motion::scrubbed(ElfClip::SitDown, input.settled)
454    }
Source

pub fn paced(self, rate: f32) -> Self

Runs at rate of the pace its source states, a fraction that is 1.0 until set.

A rate of nothing or less holds the motion where it is, and one that is not a number reads as 1.0. The last call is the one used.

Examples found in repository?
examples/animation.rs (line 355)
351    fn motion(&self, input: &ElfInput) -> Motion<ElfClip> {
352        match self {
353            Self::Idle => Motion::looping(ElfClip::Idle),
354            Self::Locomotion => {
355                Motion::blend(ElfClip::Walk, ElfClip::Jog, input.speed).paced(input.speed)
356            }
357            Self::Attack => Motion::once(ElfClip::Attack),
358            Self::Hit => Motion::once(ElfClip::Hit),
359            Self::Death => Motion::once(ElfClip::Death),
360            Self::SitDown => Motion::once(ElfClip::SitDown),
361            Self::Sit => Motion::looping(ElfClip::Sit),
362            Self::StandUp => Motion::once(ElfClip::StandUp),
363            Self::Jump => Motion::once(ElfClip::Jump),
364            Self::Dance => Motion::looping(ElfClip::Dance),
365        }
366    }

Trait Implementations§

Source§

impl<C: Clone + Clip> Clone for Motion<C>

Source§

fn clone(&self) -> Motion<C>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<C: Debug + Clip> Debug for Motion<C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<C: PartialEq + Clip> PartialEq for Motion<C>

Source§

fn eq(&self, other: &Motion<C>) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<C: PartialEq + Clip> StructuralPartialEq for Motion<C>

Auto Trait Implementations§

§

impl<C> Freeze for Motion<C>
where Plays<C>: Freeze,

§

impl<C> RefUnwindSafe for Motion<C>
where Plays<C>: RefUnwindSafe,

§

impl<C> Send for Motion<C>
where Plays<C>: Send,

§

impl<C> Sync for Motion<C>
where Plays<C>: Sync,

§

impl<C> Unpin for Motion<C>
where Plays<C>: Unpin,

§

impl<C> UnsafeUnpin for Motion<C>
where Plays<C>: UnsafeUnpin,

§

impl<C> UnwindSafe for Motion<C>
where Plays<C>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> SerializableAny for T
where T: 'static + Any + Clone + for<'a> Send + Sync,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more