Skip to content

Commit fd87eec

Browse files
committed
finish state and cache refactor for core library, still pending editor
1 parent ae6c22e commit fd87eec

11 files changed

Lines changed: 124 additions & 284 deletions

File tree

crates/bevy_animation_graph/src/core/animation_graph/core.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use crate::{
1212
},
1313
nodes::FSMNode,
1414
prelude::{
15-
DataSpec, DataValue, DeferredGizmos, OptDataSpec, PassContext, SpecContext, SystemResources,
15+
DataSpec, DataValue, DeferredGizmos, OptDataSpec, PassContext, SpecContext,
16+
SystemResources, graph_context::QueryOutputTime,
1617
},
1718
};
1819
use bevy::{
@@ -767,7 +768,7 @@ impl AnimationGraph {
767768
TargetPin::NodeTime(target_node, target_pin) => ctx
768769
.node_caches()
769770
.get_input_time_update(target_node.clone(), key, target_pin.clone()),
770-
TargetPin::OutputTime => match ctx.context().query_output_time.clone() {
771+
TargetPin::OutputTime => match ctx.context().query_output_time.get(key) {
771772
Some(update) => Ok(update),
772773
None => ctx.parent_time_update_fwd(),
773774
},
@@ -815,7 +816,7 @@ impl AnimationGraph {
815816
entity_map,
816817
deferred_gizmos,
817818
);
818-
ctx.context_mut().query_output_time = Some(time_update);
819+
ctx.context_mut().query_output_time = QueryOutputTime::Forced(time_update);
819820
let mut outputs = HashMap::new();
820821
for k in self.output_parameters.keys() {
821822
let out = self.get_data(TargetPin::OutputData(k.clone()), ctx.clone())?;
Lines changed: 28 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -1,212 +1,17 @@
11
use crate::{
2-
core::{
3-
animation_graph::{NodeId, SourcePin, TargetPin, TimeUpdate},
4-
duration_data::DurationData,
5-
prelude::AnimationGraph,
6-
state_machine::low_level::FSMState,
2+
core::{animation_graph::TimeUpdate, prelude::AnimationGraph},
3+
prelude::{
4+
node_caches::NodeCaches,
5+
node_states::{NodeStates, StateKey},
76
},
8-
prelude::{DataValue, node_caches::NodeCaches, node_states::NodeStates},
97
};
10-
use bevy::{
11-
asset::AssetId,
12-
platform::collections::{HashMap, HashSet},
13-
reflect::prelude::*,
14-
};
15-
16-
#[derive(Reflect, Debug, Default, Clone)]
17-
pub struct CacheReadFilter {
18-
pub allow_primary: bool,
19-
pub allow_temp: bool,
20-
}
21-
22-
#[derive(Clone, Copy, Debug, Reflect, PartialEq, Eq, Hash)]
23-
pub enum CacheWriteFilter {
24-
Primary,
25-
Temp,
26-
}
27-
28-
impl CacheReadFilter {
29-
pub const TEMP: Self = Self {
30-
allow_primary: false,
31-
allow_temp: true,
32-
};
33-
pub const PRIMARY: Self = Self {
34-
allow_primary: true,
35-
allow_temp: false,
36-
};
37-
pub const FULL: Self = Self {
38-
allow_primary: true,
39-
allow_temp: true,
40-
};
41-
42-
pub fn for_temp(is_temp: bool) -> Self {
43-
if is_temp { Self::TEMP } else { Self::PRIMARY }
44-
}
45-
}
46-
47-
impl CacheWriteFilter {
48-
pub fn for_temp(is_temp: bool) -> Self {
49-
if is_temp { Self::Temp } else { Self::Primary }
50-
}
51-
}
52-
53-
#[derive(Reflect, Debug, Default, Clone)]
54-
pub struct TimeCache {
55-
current: HashMap<SourcePin, f32>,
56-
previous: HashMap<SourcePin, f32>,
57-
}
58-
59-
impl TimeCache {
60-
pub fn next_frame(&mut self) {
61-
self.previous.clone_from(&self.current);
62-
}
63-
64-
pub fn get(&self, source_pin: &SourcePin) -> Option<f32> {
65-
self.current.get(source_pin).copied()
66-
}
67-
68-
pub fn get_prev(&self, source_pin: &SourcePin) -> Option<f32> {
69-
self.previous.get(source_pin).copied()
70-
}
71-
72-
pub fn save(&mut self, source_pin: SourcePin, time: f32) -> Option<f32> {
73-
self.current.insert(source_pin, time)
74-
}
75-
}
76-
77-
#[derive(Reflect, Debug, Default)]
78-
pub struct GraphState {
79-
pub data: HashMap<SourcePin, DataValue>,
80-
pub durations: HashMap<SourcePin, DurationData>,
81-
pub time_updates: HashMap<SourcePin, TimeUpdate>,
82-
pub time_updates_back: HashMap<TargetPin, TimeUpdate>,
83-
pub times: TimeCache,
84-
pub updated: HashSet<NodeId>,
85-
pub fsm_state: HashMap<NodeId, FSMState>,
86-
}
87-
88-
impl GraphState {
89-
pub fn next_frame(&mut self) {
90-
self.times.next_frame();
91-
92-
self.data.clear();
93-
self.durations.clear();
94-
self.time_updates.clear();
95-
self.time_updates_back.clear();
96-
self.updated.clear();
97-
}
98-
99-
pub fn get_data(&self, source_pin: &SourcePin) -> Option<&DataValue> {
100-
self.data.get(source_pin)
101-
}
102-
103-
pub fn set_data(&mut self, source_pin: SourcePin, value: DataValue) -> Option<DataValue> {
104-
self.data.insert(source_pin, value)
105-
}
106-
107-
pub fn get_duration(&self, source_pin: &SourcePin) -> Option<DurationData> {
108-
self.durations.get(source_pin).cloned()
109-
}
110-
111-
pub fn set_duration(
112-
&mut self,
113-
source_pin: SourcePin,
114-
value: DurationData,
115-
) -> Option<DurationData> {
116-
self.durations.insert(source_pin, value)
117-
}
118-
119-
pub fn get_time_update(&self, source_pin: &SourcePin) -> Option<&TimeUpdate> {
120-
self.time_updates.get(source_pin)
121-
}
122-
123-
pub fn set_time_update(
124-
&mut self,
125-
source_pin: SourcePin,
126-
value: TimeUpdate,
127-
) -> Option<TimeUpdate> {
128-
self.time_updates.insert(source_pin, value)
129-
}
130-
131-
pub fn get_time_update_back(&self, target_pin: &TargetPin) -> Option<&TimeUpdate> {
132-
self.time_updates_back.get(target_pin)
133-
}
134-
135-
pub fn set_time_update_back(
136-
&mut self,
137-
target_pin: TargetPin,
138-
value: TimeUpdate,
139-
) -> Option<TimeUpdate> {
140-
self.time_updates_back.insert(target_pin, value)
141-
}
142-
143-
pub fn get_time(&self, source_pin: &SourcePin) -> Option<f32> {
144-
self.times.get(source_pin)
145-
}
146-
147-
pub fn get_prev_time(&self, source_pin: &SourcePin) -> Option<f32> {
148-
self.times.get_prev(source_pin)
149-
}
150-
151-
pub fn set_time(&mut self, source_pin: SourcePin, value: f32) -> Option<f32> {
152-
self.times.save(source_pin, value)
153-
}
154-
155-
pub fn is_updated(&self, node_id: &NodeId) -> bool {
156-
self.updated.contains(node_id)
157-
}
158-
159-
pub fn set_updated(&mut self, node_id: NodeId) {
160-
self.updated.insert(node_id);
161-
}
162-
163-
pub fn get_fsm_state(&self, node_id: &NodeId) -> Option<&FSMState> {
164-
self.fsm_state.get(node_id)
165-
}
166-
167-
pub fn set_fsm_state(&mut self, node_id: NodeId, state: FSMState) -> Option<FSMState> {
168-
self.fsm_state.insert(node_id, state)
169-
}
170-
}
171-
172-
// TODO: Maybe we should consider the multiple caches to be a stack of overlays?
173-
// Might reduce the amount of cloning between frames.
174-
#[derive(Reflect, Debug, Default)]
175-
pub struct GraphStateStack {
176-
primary_cache: GraphState,
177-
temp_cache: GraphState,
178-
}
179-
180-
impl GraphStateStack {
181-
pub fn next_frame(&mut self) {
182-
self.primary_cache.next_frame();
183-
self.temp_cache = GraphState::default();
184-
}
185-
186-
pub fn get<T>(&self, f: impl Fn(&GraphState) -> Option<T>, opts: CacheReadFilter) -> Option<T> {
187-
opts.allow_temp
188-
.then(|| f(&self.temp_cache))
189-
.flatten()
190-
.or_else(|| opts.allow_primary.then(|| f(&self.primary_cache)).flatten())
191-
}
192-
193-
pub fn get_primary<T>(&self, f: impl Fn(&GraphState) -> Option<T>) -> Option<T> {
194-
self.get(f, CacheReadFilter::PRIMARY)
195-
}
196-
197-
pub fn set<T>(&mut self, f: impl FnOnce(&mut GraphState) -> T, opts: CacheWriteFilter) -> T {
198-
match opts {
199-
CacheWriteFilter::Primary => f(&mut self.primary_cache),
200-
CacheWriteFilter::Temp => f(&mut self.temp_cache),
201-
}
202-
}
203-
}
8+
use bevy::{asset::AssetId, platform::collections::HashMap, reflect::prelude::*};
2049

20510
#[derive(Debug, Reflect)]
20611
pub struct GraphContext {
20712
pub node_states: NodeStates,
20813
pub node_caches: NodeCaches,
209-
pub query_output_time: Option<TimeUpdate>,
14+
pub query_output_time: QueryOutputTime,
21015
graph_id: AssetId<AnimationGraph>,
21116
}
21217

@@ -216,7 +21,7 @@ impl GraphContext {
21621
graph_id,
21722
node_states: NodeStates::default(),
21823
node_caches: NodeCaches::default(),
219-
query_output_time: None,
24+
query_output_time: QueryOutputTime::None,
22025
}
22126
}
22227

@@ -229,3 +34,24 @@ impl GraphContext {
22934
self.graph_id
23035
}
23136
}
37+
38+
#[derive(Debug, Reflect)]
39+
pub enum QueryOutputTime {
40+
None,
41+
Forced(TimeUpdate),
42+
ByKey(HashMap<StateKey, TimeUpdate>),
43+
}
44+
45+
impl QueryOutputTime {
46+
pub fn from_key(key: StateKey, update: TimeUpdate) -> Self {
47+
Self::ByKey([(key, update)].into())
48+
}
49+
50+
pub fn get(&self, key: StateKey) -> Option<TimeUpdate> {
51+
match self {
52+
QueryOutputTime::None => None,
53+
QueryOutputTime::Forced(time_update) => Some(time_update.clone()),
54+
QueryOutputTime::ByKey(hash_map) => hash_map.get(&key).cloned(),
55+
}
56+
}
57+
}

crates/bevy_animation_graph/src/core/context/graph_context_arena.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use super::GraphContext;
2-
use crate::core::{
3-
animation_graph::NodeId, prelude::AnimationGraph, state_machine::low_level::LowLevelStateId,
1+
use crate::{
2+
core::{
3+
animation_graph::NodeId, prelude::AnimationGraph, state_machine::low_level::LowLevelStateId,
4+
},
5+
prelude::graph_context::GraphContext,
46
};
57
use bevy::{asset::AssetId, platform::collections::HashMap, reflect::Reflect};
68

crates/bevy_animation_graph/src/core/context/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod deferred_gizmos;
2-
mod graph_context;
2+
pub mod graph_context;
33
mod graph_context_arena;
44
pub mod node_caches;
55
pub mod node_state_box;
@@ -13,7 +13,6 @@ pub use deferred_gizmos::{
1313
CustomRelativeDrawCommand, CustomRelativeDrawCommandReference, DeferredGizmos,
1414
DeferredGizmosContext,
1515
};
16-
pub use graph_context::{CacheReadFilter, CacheWriteFilter, GraphContext};
1716
pub use graph_context_arena::{GraphContextArena, GraphContextId};
1817
pub use pass_context::{FsmContext, PassContext, StateRole, StateStack};
1918
pub use pose_fallback::{PoseFallbackContext, RootOffsetResult};

crates/bevy_animation_graph/src/core/context/node_states.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ impl NodeState {
5656
self.upcoming_time.clear();
5757
}
5858

59+
pub fn get_state<T: GraphStateType>(&self, key: StateKey) -> Result<&T, GraphError> {
60+
self.upcoming_state
61+
.get(&key)
62+
.or(self.last_state.as_ref())
63+
.ok_or(GraphError::MissingStateValue)
64+
.and_then(|v| {
65+
let v: &dyn Any = v.value.as_ref();
66+
v.downcast_ref::<T>().ok_or(GraphError::MismatchedStateType)
67+
})
68+
}
69+
5970
pub fn get_mut_or_insert_with<T: GraphStateType>(
6071
&mut self,
6172
key: StateKey,
@@ -102,7 +113,7 @@ impl NodeState {
102113

103114
#[derive(Debug, Reflect, Default)]
104115
pub struct NodeStates {
105-
pub states: HashMap<NodeId, NodeState>,
116+
states: HashMap<NodeId, NodeState>,
106117
}
107118

108119
impl NodeStates {
@@ -112,6 +123,13 @@ impl NodeStates {
112123
}
113124
}
114125

126+
pub fn get<T: GraphStateType>(&self, node_id: NodeId, key: StateKey) -> Result<&T, GraphError> {
127+
self.states
128+
.get(&node_id)
129+
.ok_or(GraphError::MissingStateValue)
130+
.and_then(|n| n.get_state(key))
131+
}
132+
115133
pub fn get_mut_or_insert_with<T: GraphStateType>(
116134
&mut self,
117135
node_id: NodeId,

0 commit comments

Comments
 (0)