Fix PreviousParent lag by merging parent update systems (#713)
* Sync previous parent in parent_update_system * Previous parent does not need to be an option now * Remove previous parent after parent deletion
This commit is contained in:
parent
bf2a917b81
commit
7734b1ea6d
@ -26,7 +26,7 @@ impl MapEntities for Parent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct PreviousParent(pub Option<Entity>);
|
pub struct PreviousParent(pub Entity);
|
||||||
|
|
||||||
impl Deref for Parent {
|
impl Deref for Parent {
|
||||||
type Target = Entity;
|
type Target = Entity;
|
||||||
|
@ -15,10 +15,7 @@ impl Command for InsertChildren {
|
|||||||
fn write(self: Box<Self>, world: &mut World, _resources: &mut Resources) {
|
fn write(self: Box<Self>, world: &mut World, _resources: &mut Resources) {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
world
|
world
|
||||||
.insert(
|
.insert(*child, (Parent(self.parent), PreviousParent(self.parent)))
|
||||||
*child,
|
|
||||||
(Parent(self.parent), PreviousParent(Some(self.parent))),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -53,10 +50,7 @@ impl Command for PushChildren {
|
|||||||
fn write(self: Box<Self>, world: &mut World, _resources: &mut Resources) {
|
fn write(self: Box<Self>, world: &mut World, _resources: &mut Resources) {
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
world
|
world
|
||||||
.insert(
|
.insert(*child, (Parent(self.parent), PreviousParent(self.parent)))
|
||||||
*child,
|
|
||||||
(Parent(self.parent), PreviousParent(Some(self.parent))),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -255,11 +249,11 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child1).unwrap(),
|
*world.get::<PreviousParent>(child1).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child2).unwrap(),
|
*world.get::<PreviousParent>(child2).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,11 +285,11 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child1).unwrap(),
|
*world.get::<PreviousParent>(child1).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child2).unwrap(),
|
*world.get::<PreviousParent>(child2).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
|
|
||||||
commands.insert_children(parent, 1, &entities[3..]);
|
commands.insert_children(parent, 1, &entities[3..]);
|
||||||
@ -310,11 +304,11 @@ mod tests {
|
|||||||
assert_eq!(*world.get::<Parent>(child4).unwrap(), Parent(parent));
|
assert_eq!(*world.get::<Parent>(child4).unwrap(), Parent(parent));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child3).unwrap(),
|
*world.get::<PreviousParent>(child3).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*world.get::<PreviousParent>(child4).unwrap(),
|
*world.get::<PreviousParent>(child4).unwrap(),
|
||||||
PreviousParent(Some(parent))
|
PreviousParent(parent)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,23 @@ use bevy_ecs::{Commands, Entity, IntoQuerySystem, Query, System, Without};
|
|||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
pub fn missing_previous_parent_system(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut query: Query<Without<PreviousParent, (Entity, &Parent)>>,
|
|
||||||
) {
|
|
||||||
// Add missing `PreviousParent` components
|
|
||||||
for (entity, _parent) in &mut query.iter() {
|
|
||||||
log::trace!("Adding missing PreviousParent to {:?}", entity);
|
|
||||||
commands.insert_one(entity, PreviousParent(None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parent_update_system(
|
pub fn parent_update_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut removed_parent_query: Query<Without<Parent, (Entity, &PreviousParent)>>,
|
mut removed_parent_query: Query<Without<Parent, (Entity, &PreviousParent)>>,
|
||||||
// TODO: ideally this only runs when the Parent component has changed
|
// TODO: ideally this only runs when the Parent component has changed
|
||||||
mut changed_parent_query: Query<(Entity, &Parent, &mut PreviousParent)>,
|
mut changed_parent_query: Query<(Entity, &Parent, Option<&mut PreviousParent>)>,
|
||||||
children_query: Query<&mut Children>,
|
children_query: Query<&mut Children>,
|
||||||
) {
|
) {
|
||||||
// Entities with a missing `Parent` (ie. ones that have a `PreviousParent`), remove
|
// Entities with a missing `Parent` (ie. ones that have a `PreviousParent`), remove
|
||||||
// them from the `Children` of the `PreviousParent`.
|
// them from the `Children` of the `PreviousParent`.
|
||||||
for (entity, previous_parent) in &mut removed_parent_query.iter() {
|
for (entity, previous_parent) in &mut removed_parent_query.iter() {
|
||||||
log::trace!("Parent was removed from {:?}", entity);
|
log::trace!("Parent was removed from {:?}", entity);
|
||||||
if let Some(previous_parent_entity) = previous_parent.0 {
|
if let Ok(mut previous_parent_children) =
|
||||||
if let Ok(mut previous_parent_children) =
|
children_query.get_mut::<Children>(previous_parent.0)
|
||||||
children_query.get_mut::<Children>(previous_parent_entity)
|
{
|
||||||
{
|
log::trace!(" > Removing {:?} from it's prev parent's children", entity);
|
||||||
log::trace!(" > Removing {:?} from it's prev parent's children", entity);
|
previous_parent_children.0.retain(|e| *e != entity);
|
||||||
previous_parent_children.0.retain(|e| *e != entity);
|
commands.remove_one::<PreviousParent>(entity);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,28 +27,29 @@ pub fn parent_update_system(
|
|||||||
let mut children_additions = HashMap::<Entity, SmallVec<[Entity; 8]>>::default();
|
let mut children_additions = HashMap::<Entity, SmallVec<[Entity; 8]>>::default();
|
||||||
|
|
||||||
// Entities with a changed Parent (that also have a PreviousParent, even if None)
|
// Entities with a changed Parent (that also have a PreviousParent, even if None)
|
||||||
for (entity, parent, mut previous_parent) in &mut changed_parent_query.iter() {
|
for (entity, parent, possible_previous_parent) in &mut changed_parent_query.iter() {
|
||||||
log::trace!("Parent changed for {:?}", entity);
|
log::trace!("Parent changed for {:?}", entity);
|
||||||
|
if let Some(mut previous_parent) = possible_previous_parent {
|
||||||
// If the `PreviousParent` is not None.
|
|
||||||
if let Some(previous_parent_entity) = previous_parent.0 {
|
|
||||||
// New and previous point to the same Entity, carry on, nothing to see here.
|
// New and previous point to the same Entity, carry on, nothing to see here.
|
||||||
if previous_parent_entity == parent.0 {
|
if previous_parent.0 == parent.0 {
|
||||||
log::trace!(" > But the previous parent is the same, ignoring...");
|
log::trace!(" > But the previous parent is the same, ignoring...");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from `PreviousParent.Children`.
|
// Remove from `PreviousParent.Children`.
|
||||||
if let Ok(mut previous_parent_children) =
|
if let Ok(mut previous_parent_children) =
|
||||||
children_query.get_mut::<Children>(previous_parent_entity)
|
children_query.get_mut::<Children>(previous_parent.0)
|
||||||
{
|
{
|
||||||
log::trace!(" > Removing {:?} from prev parent's children", entity);
|
log::trace!(" > Removing {:?} from prev parent's children", entity);
|
||||||
(*previous_parent_children).0.retain(|e| *e != entity);
|
(*previous_parent_children).0.retain(|e| *e != entity);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Set `PreviousParent = Parent`.
|
// Set `PreviousParent = Parent`.
|
||||||
*previous_parent = PreviousParent(Some(parent.0));
|
*previous_parent = PreviousParent(parent.0);
|
||||||
|
} else {
|
||||||
|
log::trace!("Adding missing PreviousParent to {:?}", entity);
|
||||||
|
commands.insert_one(entity, PreviousParent(parent.0));
|
||||||
|
};
|
||||||
|
|
||||||
// Add to the parent's `Children` (either the real component, or
|
// Add to the parent's `Children` (either the real component, or
|
||||||
// `children_additions`).
|
// `children_additions`).
|
||||||
@ -99,10 +88,7 @@ pub fn parent_update_system(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hierarchy_maintenance_systems() -> Vec<Box<dyn System>> {
|
pub fn hierarchy_maintenance_systems() -> Vec<Box<dyn System>> {
|
||||||
vec![
|
vec![parent_update_system.system()]
|
||||||
missing_previous_parent_system.system(),
|
|
||||||
parent_update_system.system(),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -16,7 +16,7 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> {
|
|||||||
.expect("There should always be a parent at this point.");
|
.expect("There should always be a parent at this point.");
|
||||||
self.world_builder
|
self.world_builder
|
||||||
.spawn(components)
|
.spawn(components)
|
||||||
.with_bundle((Parent(parent_entity), PreviousParent(Some(parent_entity))));
|
.with_bundle((Parent(parent_entity), PreviousParent(parent_entity)));
|
||||||
let entity = self.world_builder.current_entity.unwrap();
|
let entity = self.world_builder.current_entity.unwrap();
|
||||||
{
|
{
|
||||||
let world = &mut self.world_builder.world;
|
let world = &mut self.world_builder.world;
|
||||||
|
Loading…
Reference in New Issue
Block a user