BlendTree

Struct BlendTree 

Source
pub struct BlendTree { /* private fields */ }

Implementations§

Source§

impl BlendTree

Source

pub fn clear(&mut self)

Source

pub fn is_empty(&self) -> bool

Source

pub fn len(&self) -> usize

Source

pub fn with_capacity(len: usize) -> Self

Source

pub fn from_vec(tasks: Vec<BlendSample>) -> Self

Source

pub fn into_inner(self) -> Vec<BlendSample>

Source

pub fn get(&self) -> &[BlendSample]

Examples found in repository?
examples/third_person.rs (line 62)
8fn main() -> anyhow::Result<()> {
9    let (locomotion_definition, default_locomotion_skeleton, default_locomotion_resources) =
10        locomotion_graph_example()?;
11
12    let mut locomotion = create_instance(
13        locomotion_definition,
14        default_locomotion_skeleton,
15        default_locomotion_resources,
16    );
17
18    let (action_definition, default_action_skeleton, default_action_resources) =
19        action_graph_example()?;
20
21    let mut action = create_instance(
22        action_definition,
23        default_action_skeleton,
24        default_action_resources,
25    );
26
27    // Parameter lookups can be done ahead of time using the definition which each graph has a reference to.
28    let locomotion_speed = locomotion
29        .definition()
30        .get_number_parameter::<f32>("locomotion_speed")
31        .expect("Valid parameter");
32    let action_sit = action
33        .definition()
34        .get_event_parameter("sit")
35        .expect("Valid parameter");
36
37    // Parameters are specific to a definition
38    locomotion_speed.set(&mut locomotion, 2.0);
39
40    // Event has multiple states that micmics that of a state in a statemachine (entering, entered, exiting, exited)
41    action_sit.set(&mut action, FlowState::Entered);
42
43    let delta_time = 0.1;
44    let mut context = DefaultRunContext::new(delta_time);
45    let resources = RESOURCES.lock().expect("Single threaded");
46    for frame in 1..=5 {
47        // Multiple graphs can be concatenated where the output of the first is set
48        // as a reference to the next. It's ultimately up to the next graph if it decides
49        // to blend with the reference task at all.
50        context.run(&mut action);
51
52        // In this example the second graph looks for an emitted event from previous graphs
53        // to decided if it should blend or not.
54        context.run_and_append(&mut locomotion);
55
56        // The resulting blend tree is all the active animations that could be sampled
57        // even if they dont contribute to the final blend for things like animation events.
58        // The tree can be evaluated from the last sample to form a trimmed blend stack.
59
60        println!("Frame #{frame}:");
61        println!("- Blend Tree:");
62        for (index, task) in context.tree.get().iter().enumerate() {
63            let n = index + 1;
64            match task {
65                BlendSample::Animation {
66                    id,
67                    normalized_time,
68                } => {
69                    println!(
70                        "    #{n} Sample {} at t={normalized_time}",
71                        &resources.animations[id.0 as usize].name
72                    );
73                }
74                BlendSample::Blend(_, _, a, g) => {
75                    if *g == BoneGroupId::All {
76                        println!("    #{n} Blend a={a}");
77                    } else {
78                        println!("    #{n} Masked blend a={a}");
79                    }
80                }
81                BlendSample::Interpolate(_, _, a) => {
82                    println!("    #{n} Interpolate a={a}");
83                }
84            }
85        }
86
87        struct BlendStack<'a>(&'a GlobalResources);
88        impl<'a> BlendTreeVisitor for BlendStack<'a> {
89            fn visit(&mut self, tree: &BlendTree, sample: &BlendSample) {
90                match *sample {
91                    BlendSample::Animation {
92                        id,
93                        normalized_time,
94                    } => {
95                        println!(
96                            "    Sample {} at t={normalized_time}",
97                            &self.0.animations[id.0 as usize].name
98                        );
99                    }
100                    BlendSample::Interpolate(x, y, a) => {
101                        if a < 1.0 {
102                            tree.visit(self, x);
103                        }
104                        if a > 0.0 {
105                            tree.visit(self, y);
106                        }
107
108                        if a > 0.0 && a < 1.0 {
109                            println!("    Interpolate a={a}");
110                        }
111                    }
112                    BlendSample::Blend(x, y, a, g) => {
113                        if g == BoneGroupId::All {
114                            if a < 1.0 {
115                                tree.visit(self, x);
116                            }
117                            if a > 0.0 {
118                                tree.visit(self, y);
119                            }
120
121                            if a > 0.0 && a < 1.0 {
122                                println!("    Interpolate a={a}");
123                            }
124                        } else {
125                            tree.visit(self, x);
126                            tree.visit(self, y);
127                            println!("    Masked Blend a={a}");
128                        }
129                    }
130                }
131            }
132        }
133
134        println!("\n- Blend Stack:");
135        context.tree.visit_root(&mut BlendStack(&resources));
136        println!("");
137    }
138
139    Ok(())
140}
Source

pub fn get_reference_task(&mut self) -> Option<BlendSampleId>

Source

pub fn set_reference_task(&mut self, task: Option<BlendSampleId>)

Source

pub fn sample_animation_clip( &mut self, animation: AnimationId, time: Alpha, ) -> BlendSampleId

Source

pub fn interpolate( &mut self, a: BlendSampleId, b: BlendSampleId, w: Alpha, ) -> BlendSampleId

Source

pub fn blend_masked( &mut self, a: BlendSampleId, b: BlendSampleId, w: Alpha, ) -> BlendSampleId

Source

pub fn append( &mut self, graph: &Graph, layers: &LayerBuilder, ) -> Result<Option<BlendSampleId>>

Source

pub fn set( &mut self, graph: &Graph, layers: &LayerBuilder, ) -> Result<Option<BlendSampleId>>

Source

pub fn apply_mask( &mut self, sample: BlendSampleId, group: BoneGroupId, ) -> BlendSampleId

Source

pub fn visit<T: BlendTreeVisitor>(&self, visitor: &mut T, sample: BlendSampleId)

Examples found in repository?
examples/third_person.rs (line 102)
89            fn visit(&mut self, tree: &BlendTree, sample: &BlendSample) {
90                match *sample {
91                    BlendSample::Animation {
92                        id,
93                        normalized_time,
94                    } => {
95                        println!(
96                            "    Sample {} at t={normalized_time}",
97                            &self.0.animations[id.0 as usize].name
98                        );
99                    }
100                    BlendSample::Interpolate(x, y, a) => {
101                        if a < 1.0 {
102                            tree.visit(self, x);
103                        }
104                        if a > 0.0 {
105                            tree.visit(self, y);
106                        }
107
108                        if a > 0.0 && a < 1.0 {
109                            println!("    Interpolate a={a}");
110                        }
111                    }
112                    BlendSample::Blend(x, y, a, g) => {
113                        if g == BoneGroupId::All {
114                            if a < 1.0 {
115                                tree.visit(self, x);
116                            }
117                            if a > 0.0 {
118                                tree.visit(self, y);
119                            }
120
121                            if a > 0.0 && a < 1.0 {
122                                println!("    Interpolate a={a}");
123                            }
124                        } else {
125                            tree.visit(self, x);
126                            tree.visit(self, y);
127                            println!("    Masked Blend a={a}");
128                        }
129                    }
130                }
131            }
Source

pub fn visit_root<T: BlendTreeVisitor>(&self, visitor: &mut T)

Examples found in repository?
examples/third_person.rs (line 135)
8fn main() -> anyhow::Result<()> {
9    let (locomotion_definition, default_locomotion_skeleton, default_locomotion_resources) =
10        locomotion_graph_example()?;
11
12    let mut locomotion = create_instance(
13        locomotion_definition,
14        default_locomotion_skeleton,
15        default_locomotion_resources,
16    );
17
18    let (action_definition, default_action_skeleton, default_action_resources) =
19        action_graph_example()?;
20
21    let mut action = create_instance(
22        action_definition,
23        default_action_skeleton,
24        default_action_resources,
25    );
26
27    // Parameter lookups can be done ahead of time using the definition which each graph has a reference to.
28    let locomotion_speed = locomotion
29        .definition()
30        .get_number_parameter::<f32>("locomotion_speed")
31        .expect("Valid parameter");
32    let action_sit = action
33        .definition()
34        .get_event_parameter("sit")
35        .expect("Valid parameter");
36
37    // Parameters are specific to a definition
38    locomotion_speed.set(&mut locomotion, 2.0);
39
40    // Event has multiple states that micmics that of a state in a statemachine (entering, entered, exiting, exited)
41    action_sit.set(&mut action, FlowState::Entered);
42
43    let delta_time = 0.1;
44    let mut context = DefaultRunContext::new(delta_time);
45    let resources = RESOURCES.lock().expect("Single threaded");
46    for frame in 1..=5 {
47        // Multiple graphs can be concatenated where the output of the first is set
48        // as a reference to the next. It's ultimately up to the next graph if it decides
49        // to blend with the reference task at all.
50        context.run(&mut action);
51
52        // In this example the second graph looks for an emitted event from previous graphs
53        // to decided if it should blend or not.
54        context.run_and_append(&mut locomotion);
55
56        // The resulting blend tree is all the active animations that could be sampled
57        // even if they dont contribute to the final blend for things like animation events.
58        // The tree can be evaluated from the last sample to form a trimmed blend stack.
59
60        println!("Frame #{frame}:");
61        println!("- Blend Tree:");
62        for (index, task) in context.tree.get().iter().enumerate() {
63            let n = index + 1;
64            match task {
65                BlendSample::Animation {
66                    id,
67                    normalized_time,
68                } => {
69                    println!(
70                        "    #{n} Sample {} at t={normalized_time}",
71                        &resources.animations[id.0 as usize].name
72                    );
73                }
74                BlendSample::Blend(_, _, a, g) => {
75                    if *g == BoneGroupId::All {
76                        println!("    #{n} Blend a={a}");
77                    } else {
78                        println!("    #{n} Masked blend a={a}");
79                    }
80                }
81                BlendSample::Interpolate(_, _, a) => {
82                    println!("    #{n} Interpolate a={a}");
83                }
84            }
85        }
86
87        struct BlendStack<'a>(&'a GlobalResources);
88        impl<'a> BlendTreeVisitor for BlendStack<'a> {
89            fn visit(&mut self, tree: &BlendTree, sample: &BlendSample) {
90                match *sample {
91                    BlendSample::Animation {
92                        id,
93                        normalized_time,
94                    } => {
95                        println!(
96                            "    Sample {} at t={normalized_time}",
97                            &self.0.animations[id.0 as usize].name
98                        );
99                    }
100                    BlendSample::Interpolate(x, y, a) => {
101                        if a < 1.0 {
102                            tree.visit(self, x);
103                        }
104                        if a > 0.0 {
105                            tree.visit(self, y);
106                        }
107
108                        if a > 0.0 && a < 1.0 {
109                            println!("    Interpolate a={a}");
110                        }
111                    }
112                    BlendSample::Blend(x, y, a, g) => {
113                        if g == BoneGroupId::All {
114                            if a < 1.0 {
115                                tree.visit(self, x);
116                            }
117                            if a > 0.0 {
118                                tree.visit(self, y);
119                            }
120
121                            if a > 0.0 && a < 1.0 {
122                                println!("    Interpolate a={a}");
123                            }
124                        } else {
125                            tree.visit(self, x);
126                            tree.visit(self, y);
127                            println!("    Masked Blend a={a}");
128                        }
129                    }
130                }
131            }
132        }
133
134        println!("\n- Blend Stack:");
135        context.tree.visit_root(&mut BlendStack(&resources));
136        println!("");
137    }
138
139    Ok(())
140}

Trait Implementations§

Source§

impl Clone for BlendTree

Source§

fn clone(&self) -> BlendTree

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Default for BlendTree

Source§

fn default() -> BlendTree

Returns the “default value” for a type. Read more

Auto Trait Implementations§

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<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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V