pub struct MessageMutator<'w, 's, M>where
M: Message,{ /* private fields */ }Expand description
Reads and writes Messages of type T, keeping track of which messages have already been read.
This can be used if a system needs to both read and write messages of the same type.
Since it has exclusive access to the underlying messages, it also permits messages to be modified as they are read. This is ideal for chains of systems that all want to modify the same messages.
§Usage
MessageMutators are usually declared as a SystemParam.
#[derive(Message, Debug)]
pub struct MyMessage(pub u32); // Custom message type.
fn my_system(mut mutator: MessageMutator<MyMessage>) {
// This message will be read immediately by this system,
// and will then be visible to other systems.
mutator.write(MyMessage(0));
for message in mutator.read() {
message.0 += 1;
println!("received message: {:?}", message);
}
// This message will be read on the next run of this system,
// but will be visible immediately to other systems.
mutator.write(MyMessage(0));
}§Concurrency
Multiple systems with MessageMutator<T> of the same message type can not run concurrently.
They also can not be executed in parallel with MessageReader or MessageWriter.
§Clearing, Reading, and Peeking
Messages are stored in a double buffered queue that switches each frame. This switch also clears the previous
frame’s messages. Messages should be read each frame otherwise they may be lost. For manual control over this
behavior, see Messages.
Most of the time systems will want to use MessageMutator::read(). This function creates an iterator over
all messages that haven’t been read yet by this system, marking the message as read in the process.
Implementations§
Source§impl<'w, 's, M> MessageMutator<'w, 's, M>where
M: Message,
impl<'w, 's, M> MessageMutator<'w, 's, M>where
M: Message,
Sourcepub fn read(&mut self) -> MessageMutIterator<'_, M> ⓘ
pub fn read(&mut self) -> MessageMutIterator<'_, M> ⓘ
Iterates over the messages this MessageMutator has not seen yet. This updates the
MessageMutator’s message counter, which means subsequent message reads will not include messages
that happened before now.
Examples found in repository?
56fn apply_extra_damage(mut dmg_messages: MessageMutator<DealDamage>) {
57 let mut extra = Vec::new();
58 for message in dmg_messages.read() {
59 if message.amount >= 10 {
60 extra.push(DealDamage {
61 amount: message.amount / 10,
62 });
63 }
64 }
65 // Note that this system will read messages it wrote itself!
66 // These are written after the `read()`, so they will be read the next time it runs.
67 for message in extra {
68 dmg_messages.write(message);
69 }
70}
71
72// This system mutates the 'DealDamage' messages to apply some armor value
73// It also sends an 'ArmorBlockedDamage' message if the value of 'DealDamage' is zero
74//
75// Messages are mutated using an 'MessageMutator<T>' by calling 'read'. This returns an iterator
76// over all the &mut T that this system has not read yet. Note, you can have multiple
77// 'MessageReader', 'MessageWriter', and 'MessageMutator' in a given system, as long as the types (T) are different.
78fn apply_armor_to_damage(
79 mut dmg_messages: MessageMutator<DealDamage>,
80 mut armor_messages: MessageWriter<ArmorBlockedDamage>,
81) {
82 for message in dmg_messages.read() {
83 message.amount -= 1;
84 if message.amount <= 0 {
85 // Zero-sized messages can also be sent with 'send'
86 armor_messages.write(ArmorBlockedDamage);
87 }
88 }
89}Sourcepub fn read_with_id(&mut self) -> MessageMutIteratorWithId<'_, M> ⓘ
pub fn read_with_id(&mut self) -> MessageMutIteratorWithId<'_, M> ⓘ
Sourcepub fn par_read(&mut self) -> MessageMutParIter<'_, M>
Available on crate feature multi_threaded only.
pub fn par_read(&mut self) -> MessageMutParIter<'_, M>
multi_threaded only.Returns a parallel iterator over the messages this MessageMutator has not seen yet.
See also for_each.
§Example
#[derive(Message)]
struct MyMessage {
value: usize,
}
#[derive(Resource, Default)]
struct Counter(AtomicUsize);
// setup
let mut world = World::new();
world.init_resource::<Messages<MyMessage>>();
world.insert_resource(Counter::default());
let mut schedule = Schedule::default();
schedule.add_systems(|mut messages: MessageMutator<MyMessage>, counter: Res<Counter>| {
messages.par_read().for_each(|MyMessage { value }| {
counter.0.fetch_add(*value, Ordering::Relaxed);
});
});
for value in 0..100 {
world.write_message(MyMessage { value });
}
schedule.run(&mut world);
let Counter(counter) = world.remove_resource::<Counter>().unwrap();
// all messages were processed
assert_eq!(counter.into_inner(), 4950);Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Determines the number of messages available to be read from this MessageMutator without consuming any.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if there are no messages available to read.
§Example
The following example shows a useful pattern where some behavior is triggered if new messages are available.
MessageMutator::clear() is used so the same messages don’t re-trigger the behavior the next time the system runs.
#[derive(Message)]
struct Collision;
fn play_collision_sound(mut messages: MessageMutator<Collision>) {
if !messages.is_empty() {
messages.clear();
// Play a sound
}
}Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Consumes all available messages.
This means these messages will not appear in calls to MessageMutator::read() or
MessageMutator::read_with_id() and MessageMutator::is_empty() will return true.
For usage, see MessageMutator::is_empty().
Sourcepub fn write(&mut self, message: M) -> MessageId<M>
pub fn write(&mut self, message: M) -> MessageId<M>
Writes an message, which can later be read by MessageReaders.
This method returns the ID of the written message.
See Messages for details.
Examples found in repository?
56fn apply_extra_damage(mut dmg_messages: MessageMutator<DealDamage>) {
57 let mut extra = Vec::new();
58 for message in dmg_messages.read() {
59 if message.amount >= 10 {
60 extra.push(DealDamage {
61 amount: message.amount / 10,
62 });
63 }
64 }
65 // Note that this system will read messages it wrote itself!
66 // These are written after the `read()`, so they will be read the next time it runs.
67 for message in extra {
68 dmg_messages.write(message);
69 }
70}Sourcepub fn write_batch(
&mut self,
messages: impl IntoIterator<Item = M>,
) -> WriteBatchIds<M> ⓘ
pub fn write_batch( &mut self, messages: impl IntoIterator<Item = M>, ) -> WriteBatchIds<M> ⓘ
Writes a list of messages all at once, which can later be read by MessageReaders.
This is more efficient than writing each message individually.
This method returns the IDs of the written messages.
See Messages for details.
Trait Implementations§
Source§impl<'w, 's, M> Debug for MessageMutator<'w, 's, M>
impl<'w, 's, M> Debug for MessageMutator<'w, 's, M>
impl<'w, 's, M> ReadOnlySystemParam for MessageMutator<'w, 's, M>where
M: Message,
Local<'s, MessageCursor<M>>: ReadOnlySystemParam,
ResMut<'w, Messages<M>>: ReadOnlySystemParam,
Source§impl<M> SystemParam for MessageMutator<'_, '_, M>where
M: Message,
impl<M> SystemParam for MessageMutator<'_, '_, M>where
M: Message,
Source§type Item<'w, 's> = MessageMutator<'w, 's, M>
type Item<'w, 's> = MessageMutator<'w, 's, M>
Self, instantiated with new lifetimes. Read moreSource§fn init_state(
world: &mut World,
) -> <MessageMutator<'_, '_, M> as SystemParam>::State
fn init_state( world: &mut World, ) -> <MessageMutator<'_, '_, M> as SystemParam>::State
State.Source§fn init_access(
state: &<MessageMutator<'_, '_, M> as SystemParam>::State,
system_meta: &mut SystemMeta,
system_access: &mut SystemAccess,
world: &mut World,
)
fn init_access( state: &<MessageMutator<'_, '_, M> as SystemParam>::State, system_meta: &mut SystemMeta, system_access: &mut SystemAccess, world: &mut World, )
Source§fn apply(
state: &mut <MessageMutator<'_, '_, M> as SystemParam>::State,
system_meta: &SystemMeta,
world: &mut World,
)
fn apply( state: &mut <MessageMutator<'_, '_, M> as SystemParam>::State, system_meta: &SystemMeta, world: &mut World, )
SystemParam’s state.
This is used to apply Commands during ApplyDeferred.Source§fn queue(
state: &mut <MessageMutator<'_, '_, M> as SystemParam>::State,
system_meta: &SystemMeta,
world: DeferredWorld<'_>,
)
fn queue( state: &mut <MessageMutator<'_, '_, M> as SystemParam>::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )
ApplyDeferred.Source§unsafe fn get_param<'w, 's>(
state: &'s mut <MessageMutator<'_, '_, M> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick,
) -> Result<<MessageMutator<'_, '_, M> as SystemParam>::Item<'w, 's>, SystemParamValidationError>
unsafe fn get_param<'w, 's>( state: &'s mut <MessageMutator<'_, '_, M> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Result<<MessageMutator<'_, '_, M> as SystemParam>::Item<'w, 's>, SystemParamValidationError>
SystemParamFunction. Read moreAuto Trait Implementations§
impl<'w, 's, M> !UnwindSafe for MessageMutator<'w, 's, M>
impl<'w, 's, M> Freeze for MessageMutator<'w, 's, M>
impl<'w, 's, M> RefUnwindSafe for MessageMutator<'w, 's, M>
impl<'w, 's, M> Send for MessageMutator<'w, 's, M>
impl<'w, 's, M> Sync for MessageMutator<'w, 's, M>
impl<'w, 's, M> Unpin for MessageMutator<'w, 's, M>
impl<'w, 's, M> UnsafeUnpin for MessageMutator<'w, 's, M>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ConditionalSend for Twhere
T: Send,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T> HitDataExtra for T
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
impl<T> Settings for T
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.