Skip to content

Commit

Permalink
mutate observer
Browse files Browse the repository at this point in the history
  • Loading branch information
xiejiaen committed Nov 4, 2024
1 parent e38618c commit ea62087
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 48 deletions.
3 changes: 1 addition & 2 deletions crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Types that detect when their internal data mutate.
use crate::world::entity_change::{EntityChange, EntityChanges};
use crate::{
component::{Tick, TickCells},
ptr::PtrMut,
Expand All @@ -16,7 +17,6 @@ use {
bevy_ptr::ThinSlicePtr,
core::{cell::UnsafeCell, panic::Location},
};
use crate::world::entity_change::{EntityChange, EntityChanges};

/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
///
Expand Down Expand Up @@ -1103,7 +1103,6 @@ where
}
}


change_detection_impl!(Mut<'w, T>, T,);
change_detection_mut_with_onchange_impl!(Mut<'w, T>, T,);
impl_methods_with_onchange!(Mut<'w, T>, T,);
Expand Down
16 changes: 5 additions & 11 deletions crates/bevy_ecs/src/query/fetch.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::world::entity_change::{EntityChange, EntityChanges};
use crate::{
archetype::{Archetype, Archetypes},
bundle::Bundle,
Expand All @@ -14,9 +15,8 @@ use crate::{
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::all_tuples;
use core::{cell::UnsafeCell, marker::PhantomData};
use std::cell::RefCell;
use smallvec::SmallVec;
use crate::world::entity_change::{EntityChange, EntityChanges};
use std::cell::RefCell;

/// Types that can be fetched from a [`World`] using a [`Query`].
///
Expand Down Expand Up @@ -1431,7 +1431,7 @@ unsafe impl<'__w, T: Component> ReadOnlyQueryData for Ref<'__w, T> {}
/// The [`WorldQuery::Fetch`] type for `&mut T`.
pub struct WriteFetch<'w, T: Component> {
component_id: ComponentId,
changes: &'w RefCell<EntityChanges>,
changes: &'w RefCell<EntityChanges>,
components: StorageSwitch<
T,
// T::STORAGE_TYPE = StorageType::Table
Expand Down Expand Up @@ -1571,10 +1571,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
let caller = unsafe { _callers.get(table_row.as_usize()) };

Mut {
on_change: Some((
EntityChange::new(entity, fetch.component_id),
fetch.changes,
)),
on_change: Some((EntityChange::new(entity, fetch.component_id), fetch.changes)),
value: component.deref_mut(),
ticks: TicksMut {
added: added.deref_mut(),
Expand All @@ -1592,10 +1589,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
unsafe { sparse_set.get_with_ticks(entity).debug_checked_unwrap() };

Mut {
on_change: Some((
EntityChange::new(entity, fetch.component_id),
fetch.changes,
)),
on_change: Some((EntityChange::new(entity, fetch.component_id), fetch.changes)),
value: component.assert_unique().deref_mut(),
ticks: TicksMut::from_tick_cells(ticks, fetch.last_run, fetch.this_run),
#[cfg(feature = "track_change_detection")]
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/query/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
}
};
const IS_MUTATE: bool = false;

#[inline]
unsafe fn set_archetype(
_fetch: &mut (),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::Populated;
pub use crate::change_detection::{NonSendMut, Res, ResMut};
use crate::{
archetype::{Archetype, Archetypes},
Expand Down Expand Up @@ -28,7 +29,6 @@ use core::{
marker::PhantomData,
ops::{Deref, DerefMut},
};
use super::Populated;

/// A parameter that can be used in a [`System`](super::System).
///
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/world/component_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ pub struct OnRemove;
#[derive(Event, Debug)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", reflect(Debug))]
pub struct OnMutate;
pub struct OnMutate;
9 changes: 4 additions & 5 deletions crates/bevy_ecs/src/world/entity_change.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::cell::RefCell;
use bevy_utils::Parallel;
use crate::component::ComponentId;
use crate::entity::Entity;
use bevy_utils::Parallel;
use std::cell::RefCell;

/// A shorthand for [`Vec<EntityChange>`].
pub type EntityChanges = Vec<EntityChange>;
Expand All @@ -14,7 +14,6 @@ pub struct ParallelEntityChanges {
}

impl ParallelEntityChanges {

/// Returns a default `Changes`
pub fn new() -> Self {
Expand All @@ -35,7 +34,7 @@ impl ParallelEntityChanges {
/// A Record hint which entity's component has changed
#[derive(Copy, Clone, Debug)]
pub struct EntityChange {
entity: Entity,
entity: Entity,
component: ComponentId,
}

Expand All @@ -53,4 +52,4 @@ impl EntityChange {
pub fn component(&self) -> ComponentId {
self.component
}
}
}
22 changes: 14 additions & 8 deletions crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
pub(crate) mod command_queue;

pub(crate) mod entity_change;
mod component_constants;
mod deferred_world;
pub(crate) mod entity_change;
mod entity_fetch;
mod entity_ref;
pub mod error;
Expand Down Expand Up @@ -63,9 +63,9 @@ use core::{
#[cfg(feature = "track_change_detection")]
use bevy_ptr::UnsafeCellDeref;

use crate::world::entity_change::ParallelEntityChanges;
use core::panic::Location;
use unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell};
use crate::world::entity_change::ParallelEntityChanges;

/// A [`World`] mutation.
///
Expand Down Expand Up @@ -3024,12 +3024,18 @@ impl World {
pub(crate) fn flush_entity_changes(&mut self) {
let mut parallel_entity_changes = std::mem::take(&mut self.entity_changes);
let mut deferred_world = DeferredWorld::from(&mut *self);
parallel_entity_changes.iter_mut().for_each(|entity_changes| {
entity_changes.drain(..).for_each(|entity_change| unsafe {
// SAFETY: [`OnMutate`] Event is ZST
deferred_world.trigger_observers(ON_MUTATE, entity_change.entity(), std::iter::once(entity_change.component()))
})
});
parallel_entity_changes
.iter_mut()
.for_each(|entity_changes| {
entity_changes.drain(..).for_each(|entity_change| unsafe {
// SAFETY: [`OnMutate`] Event is ZST
deferred_world.trigger_observers(
ON_MUTATE,
entity_change.entity(),
std::iter::once(entity_change.component()),
)
})
});
_ = std::mem::replace(&mut self.entity_changes, parallel_entity_changes);
}

Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_ecs/src/world/unsafe_world_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![warn(unsafe_op_in_unsafe_fn)]

use super::{Mut, Ref, World, WorldId};
use crate::world::entity_change::{EntityChange, EntityChanges};
use crate::{
archetype::{Archetype, Archetypes},
bundle::Bundles,
Expand All @@ -22,7 +23,6 @@ use bevy_ptr::Ptr;
use bevy_ptr::UnsafeCellDeref;
use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
use std::cell::RefCell;
use crate::world::entity_change::{EntityChange, EntityChanges};

/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
Expand Down Expand Up @@ -332,7 +332,9 @@ impl<'w> UnsafeWorldCell<'w> {
/// time as any other accesses to that same component.
pub unsafe fn entity_changes(self) -> &'w RefCell<EntityChanges> {
// SAFETY: The caller promises to only access world data allowed by this instance.
&unsafe { self.unsafe_world() }.entity_changes.get_local_ref_cell()
&unsafe { self.unsafe_world() }
.entity_changes
.get_local_ref_cell()
}

/// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
Expand Down
1 change: 0 additions & 1 deletion crates/bevy_render/src/pipelined_rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ impl RenderAppChannels {
self.app_to_render_sender.send_blocking(render_app).unwrap();
self.render_app_in_render_thread = true;
}

}

impl Drop for RenderAppChannels {
Expand Down
26 changes: 10 additions & 16 deletions examples/ecs/responding_to_changes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

//! Bevy has two primary ways to respond to changes in your ECS data:
//!
//! 1. **Change detection:** whenever a component or resource is mutated, it will be flagged as changed.
Expand Down Expand Up @@ -192,11 +191,8 @@ fn update_counter_observer(
trigger: Trigger<OnMutate, Interaction>,
mut button_query: Query<(&mut CounterValue, &Interaction, &ChangeStrategy)>,
) {
let Ok((
mut counter,
interaction,
change_strategy
)) = button_query.get_mut(trigger.entity()) else {
let Ok((mut counter, interaction, change_strategy)) = button_query.get_mut(trigger.entity())
else {
// Other entities may have the Interaction component, but we're only interested in these particular buttons.
return;
};
Expand All @@ -216,16 +212,14 @@ fn setup_ui(mut commands: Commands) {
commands.spawn(Camera2d::default());

let root_node = commands
.spawn((
Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
))
.spawn((Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},))
.id();

let changed_filter_button =
Expand Down

0 comments on commit ea62087

Please sign in to comment.