Skip to content

Commit 54cba7a

Browse files
committed
Move EntityPath and NameLookup to core
1 parent b08081b commit 54cba7a

File tree

4 files changed

+110
-120
lines changed

4 files changed

+110
-120
lines changed

crates/bevy_animation/src/lib.rs

Lines changed: 11 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ use std::ops::Deref;
66

77
use bevy_app::{App, CoreStage, Plugin};
88
use bevy_asset::{AddAsset, Assets, Handle};
9-
use bevy_core::Name;
9+
use bevy_core::{EntityPath, Name, NameLookup};
1010
use bevy_ecs::{
1111
change_detection::DetectChanges,
1212
entity::Entity,
1313
prelude::Component,
14+
query::QueryEntityError,
1415
reflect::ReflectComponent,
1516
schedule::ParallelSystemDescriptorCoercion,
1617
system::{Query, Res, SystemParam},
17-
query::QueryEntityError,
1818
};
1919
use bevy_hierarchy::Children;
2020
use bevy_math::{Quat, Vec3};
@@ -26,94 +26,9 @@ use bevy_utils::{tracing::warn, HashMap};
2626
#[allow(missing_docs)]
2727
pub mod prelude {
2828
#[doc(hidden)]
29-
pub use crate::{
30-
AnimationClip, AnimationPlayer, AnimationPlugin, EntityPath, Keyframes, VariableCurve,
31-
};
32-
}
33-
34-
/// System param to enable entity lookup of an entity via EntityPath
35-
#[derive(SystemParam)]
36-
pub struct NameLookup<'w, 's> {
37-
named: Query<'w, 's, (Entity, &'static Name)>,
38-
children: Query<'w, 's, &'static Children>,
39-
}
40-
41-
/// Errors when looking up an entity by name
42-
pub enum LookupError {
43-
/// An entity could not be found, this either means the entity has been
44-
/// despawned, or the entity doesn't have the required components
45-
Query(QueryEntityError),
46-
/// The root node does not have the corrent name
47-
// TODO: add expected / found name
48-
RootNotFound,
49-
/// A child was not found
50-
// TODO: add expected name
51-
ChildNotFound,
52-
/// The name does not uniquely identify an entity
53-
// TODO: add name
54-
NameNotUnique,
55-
}
56-
57-
impl From<QueryEntityError> for LookupError {
58-
fn from(q: QueryEntityError) -> Self {
59-
Self::Query(q)
60-
}
61-
}
62-
63-
impl<'w, 's> NameLookup<'w, 's> {
64-
/// Find an entity by entity path, may return an error if the root name isn't unique
65-
pub fn lookup_any(&self, path: &EntityPath) -> Result<Entity, LookupError> {
66-
let mut path = path.parts.iter();
67-
let root_name = path.next().unwrap();
68-
let mut root = None;
69-
for (entity, name) in self.named.iter() {
70-
if root_name == name {
71-
if root.is_some() {
72-
return Err(LookupError::NameNotUnique);
73-
}
74-
root = Some(entity);
75-
}
76-
}
77-
let mut current_node = root.ok_or(LookupError::RootNotFound)?;
78-
for part in path {
79-
current_node = self.find_child(current_node, part)?;
80-
}
81-
Ok(current_node)
82-
}
83-
84-
/// Find an entity by the root & entity path
85-
pub fn lookup(&self, root: Entity, path: &EntityPath) -> Result<Entity, LookupError> {
86-
let mut path = path.parts.iter();
87-
let (_, root_name) = self.named.get(root)?;
88-
if root_name != path.next().unwrap() {
89-
return Err(LookupError::RootNotFound);
90-
}
91-
let mut current_node = root;
92-
for part in path {
93-
current_node = self.find_child(current_node, part)?;
94-
}
95-
Ok(current_node)
96-
}
97-
98-
/// Internal function to get the child of `current_node` that has the name `part`
99-
fn find_child(&self, current_node: Entity, part: &Name) -> Result<Entity, LookupError> {
100-
let children = self.children.get(current_node)?;
101-
let mut ret = Err(LookupError::ChildNotFound);
102-
for child in children {
103-
if let Ok((_, name)) = self.named.get(*child) {
104-
if name == part {
105-
if ret.is_ok() {
106-
return Err(LookupError::NameNotUnique);
107-
}
108-
ret = Ok(*child);
109-
}
110-
}
111-
}
112-
ret
113-
}
29+
pub use crate::{AnimationClip, AnimationPlayer, AnimationPlugin, Keyframes, VariableCurve};
11430
}
11531

116-
11732
/// List of keyframes for one of the attribute of a [`Transform`].
11833
#[derive(Clone, Debug)]
11934
pub enum Keyframes {
@@ -136,13 +51,6 @@ pub struct VariableCurve {
13651
pub keyframes: Keyframes,
13752
}
13853

139-
/// Path to an entity, with [`Name`]s. Each entity in a path must have a name.
140-
#[derive(Clone, Debug, Hash, PartialEq, Eq, Default)]
141-
pub struct EntityPath {
142-
/// Parts of the path
143-
pub parts: Vec<Name>,
144-
}
145-
14654
/// A list of [`VariableCurve`], and the [`EntityPath`] to which they apply.
14755
#[derive(Clone, TypeUuid, Debug, Default)]
14856
#[uuid = "d81b7179-0448-4eb0-89fe-c067222725bf"]
@@ -263,9 +171,8 @@ pub fn animation_player(
263171
time: Res<Time>,
264172
animations: Res<Assets<AnimationClip>>,
265173
mut animation_players: Query<(Entity, &mut AnimationPlayer)>,
266-
names: Query<&Name>,
267174
mut transforms: Query<&mut Transform>,
268-
children: Query<&Children>,
175+
lookup: NameLookup,
269176
) {
270177
for (entity, mut player) in &mut animation_players {
271178
if let Some(animation_clip) = animations.get(&player.animation_clip) {
@@ -284,29 +191,15 @@ pub fn animation_player(
284191
if elapsed < 0.0 {
285192
elapsed += animation_clip.duration;
286193
}
287-
'entity: for (path, curves) in &animation_clip.curves {
194+
for (path, curves) in &animation_clip.curves {
288195
// PERF: finding the target entity can be optimised
289-
let mut current_entity = entity;
290-
// Ignore the first name, it is the root node which we already have
291-
for part in path.parts.iter().skip(1) {
292-
let mut found = false;
293-
if let Ok(children) = children.get(current_entity) {
294-
for child in children.deref() {
295-
if let Ok(name) = names.get(*child) {
296-
if name == part {
297-
// Found a children with the right name, continue to the next part
298-
current_entity = *child;
299-
found = true;
300-
break;
301-
}
302-
}
303-
}
196+
let current_entity = match lookup.lookup(entity, path) {
197+
Ok(e) => e,
198+
Err(e) => {
199+
warn!("Entity for path {path:?} was not found");
200+
continue;
304201
}
305-
if !found {
306-
warn!("Entity not found for path {:?} on part {:?}", path, part);
307-
continue 'entity;
308-
}
309-
}
202+
};
310203
if let Ok(mut transform) = transforms.get_mut(current_entity) {
311204
for curve in curves {
312205
// Some curves have only one keyframe used to set a transform

crates/bevy_core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ bevy_math = { path = "../bevy_math", version = "0.9.0-dev" }
1717
bevy_reflect = { path = "../bevy_reflect", version = "0.9.0-dev", features = ["bevy"] }
1818
bevy_tasks = { path = "../bevy_tasks", version = "0.9.0-dev" }
1919
bevy_utils = { path = "../bevy_utils", version = "0.9.0-dev" }
20+
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.9.0-dev" }
2021

2122
# other
2223
bytemuck = "1.5"

crates/bevy_core/src/name.rs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
use bevy_ecs::{component::Component, reflect::ReflectComponent};
1+
use bevy_ecs::{
2+
component::Component,
3+
entity::Entity,
4+
query::QueryEntityError,
5+
reflect::ReflectComponent,
6+
system::{Query, SystemParam},
7+
};
8+
use bevy_hierarchy::Children;
29
use bevy_reflect::std_traits::ReflectDefault;
310
use bevy_reflect::Reflect;
411
use bevy_utils::AHasher;
@@ -150,3 +157,92 @@ impl Deref for Name {
150157
self.name.as_ref()
151158
}
152159
}
160+
161+
/// Path to an entity, with [`Name`]s. Each entity in a path must have a name.
162+
#[derive(Clone, Debug, Hash, PartialEq, Eq, Default)]
163+
pub struct EntityPath {
164+
/// Parts of the path
165+
pub parts: Vec<Name>,
166+
}
167+
168+
/// System param to enable entity lookup of an entity via EntityPath
169+
#[derive(SystemParam)]
170+
pub struct NameLookup<'w, 's> {
171+
named: Query<'w, 's, (Entity, &'static Name)>,
172+
children: Query<'w, 's, &'static Children>,
173+
}
174+
175+
/// Errors when looking up an entity by name
176+
pub enum LookupError {
177+
/// An entity could not be found, this either means the entity has been
178+
/// despawned, or the entity doesn't have the required components
179+
Query(QueryEntityError),
180+
/// The root node does not have the corrent name
181+
// TODO: add expected / found name
182+
RootNotFound,
183+
/// A child was not found
184+
// TODO: add expected name
185+
ChildNotFound,
186+
/// The name does not uniquely identify an entity
187+
// TODO: add name
188+
NameNotUnique,
189+
}
190+
191+
impl From<QueryEntityError> for LookupError {
192+
fn from(q: QueryEntityError) -> Self {
193+
Self::Query(q)
194+
}
195+
}
196+
197+
impl<'w, 's> NameLookup<'w, 's> {
198+
/// Find an entity by entity path, may return an error if the root name isn't unique
199+
pub fn lookup_any(&self, path: &EntityPath) -> Result<Entity, LookupError> {
200+
let mut path = path.parts.iter();
201+
let root_name = path.next().unwrap();
202+
let mut root = None;
203+
for (entity, name) in self.named.iter() {
204+
if root_name == name {
205+
if root.is_some() {
206+
return Err(LookupError::NameNotUnique);
207+
}
208+
root = Some(entity);
209+
}
210+
}
211+
let mut current_node = root.ok_or(LookupError::RootNotFound)?;
212+
for part in path {
213+
current_node = self.find_child(current_node, part)?;
214+
}
215+
Ok(current_node)
216+
}
217+
218+
/// Find an entity by the root & entity path
219+
pub fn lookup(&self, root: Entity, path: &EntityPath) -> Result<Entity, LookupError> {
220+
let mut path = path.parts.iter();
221+
let (_, root_name) = self.named.get(root)?;
222+
if root_name != path.next().unwrap() {
223+
return Err(LookupError::RootNotFound);
224+
}
225+
let mut current_node = root;
226+
for part in path {
227+
current_node = self.find_child(current_node, part)?;
228+
}
229+
Ok(current_node)
230+
}
231+
232+
/// Internal function to get the child of `current_node` that has the name `part`
233+
fn find_child(&self, current_node: Entity, part: &Name) -> Result<Entity, LookupError> {
234+
let children = self.children.get(current_node)?;
235+
let mut ret = Err(LookupError::ChildNotFound);
236+
for child in children {
237+
if let Ok((_, name)) = self.named.get(*child) {
238+
if name == part {
239+
if ret.is_ok() {
240+
return Err(LookupError::NameNotUnique);
241+
}
242+
ret = Ok(*child);
243+
}
244+
}
245+
}
246+
ret
247+
}
248+
}

crates/bevy_gltf/src/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ async fn load_gltf<'a, 'b>(
204204
if let Some((root_index, path)) = paths.get(&node.index()) {
205205
animation_roots.insert(root_index);
206206
animation_clip.add_curve_to_path(
207-
bevy_animation::EntityPath {
207+
bevy_core::EntityPath {
208208
parts: path.clone(),
209209
},
210210
bevy_animation::VariableCurve {

0 commit comments

Comments
 (0)