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>
impl<C: Clip> Motion<C>
Sourcepub fn looping(clip: C) -> Self
pub fn looping(clip: C) -> Self
Plays clip over and over, wrapping from its last key to its first.
Examples found in repository?
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 }Sourcepub fn once(clip: C) -> Self
pub fn once(clip: C) -> Self
Plays clip once and holds its last key.
Examples found in repository?
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 }Sourcepub fn blend(from: C, to: C, weight: f32) -> Self
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?
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 }Sourcepub fn scrubbed(clip: C, fraction: f32) -> Self
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.
Sourcepub fn paced(self, rate: f32) -> Self
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?
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§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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