Improved documentation for Events (#1669)

Explains subtle behavior more explicitly, documents `add_event`, mentions `EventWriter`.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Alice Cecile 2021-03-17 23:42:19 +00:00
parent 5fedb6029a
commit ab0165d20d
5 changed files with 39 additions and 12 deletions

View file

@ -207,6 +207,10 @@ impl AppBuilder {
.add_stage(CoreStage::Last, SystemStage::parallel()) .add_stage(CoreStage::Last, SystemStage::parallel())
} }
/// Setup the application to manage events of type `T`.
///
/// This is done by adding a `Resource` of type `Events::<T>`,
/// and inserting a `Events::<T>::update_system` system into `CoreStage::First`.
pub fn add_event<T>(&mut self) -> &mut Self pub fn add_event<T>(&mut self) -> &mut Self
where where
T: Component, T: Component,

View file

@ -56,11 +56,23 @@ enum State {
} }
/// An event collection that represents the events that occurred within the last two /// An event collection that represents the events that occurred within the last two
/// [Events::update] calls. Events can be cheaply read using an [EventReader]. This collection is /// [`Events::update`] calls.
/// meant to be paired with a system that calls [Events::update] exactly once per update/frame. /// Events can be written to using an [`EventWriter`]
/// [Events::update_system] is a system that does this. [EventReader]s are expected to read events /// and are typically cheaply read using an [`EventReader`].
/// from this collection at least once per update/frame. If events are not handled within one ///
/// frame/update, they will be dropped. /// Each event can be consumed by multiple systems, in parallel,
/// with consumption tracked by the [`EventReader`] on a per-system basis.
///
/// This collection is meant to be paired with a system that calls
/// [`Events::update`] exactly once per update/frame.
///
/// [`Events::update_system`] is a system that does this, typically intialized automatically using
/// [`AppBuilder::add_event`]. [EventReader]s are expected to read events from this collection at
/// least once per loop/frame.
/// Events will persist across a single frame boundary and so ordering of event producers and
/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).
/// If events are not handled by the end of the frame after they are updated, they will be
/// dropped silently.
/// ///
/// # Example /// # Example
/// ``` /// ```
@ -100,7 +112,9 @@ enum State {
/// The buffers in [Events] will grow indefinitely if [Events::update] is never called. /// The buffers in [Events] will grow indefinitely if [Events::update] is never called.
/// ///
/// An alternative call pattern would be to call [Events::update] manually across frames to control /// An alternative call pattern would be to call [Events::update] manually across frames to control
/// when events are cleared. However this complicates consumption /// when events are cleared.
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
/// but can be done by adding your event as a resource instead of using [`AppBuilder::add_event`].
#[derive(Debug)] #[derive(Debug)]
pub struct Events<T> { pub struct Events<T> {
events_a: Vec<EventInstance<T>>, events_a: Vec<EventInstance<T>>,

View file

@ -173,18 +173,21 @@ impl SystemStage {
pub fn parallel_systems(&self) -> &[impl SystemContainer] { pub fn parallel_systems(&self) -> &[impl SystemContainer] {
&self.parallel &self.parallel
} }
/// Topologically sorted exclusive systems that want to be run at the start of the stage. /// Topologically sorted exclusive systems that want to be run at the start of the stage.
/// ///
/// Note that systems won't be fully-formed until the stage has been run at least once. /// Note that systems won't be fully-formed until the stage has been run at least once.
pub fn exclusive_at_start_systems(&self) -> &[impl SystemContainer] { pub fn exclusive_at_start_systems(&self) -> &[impl SystemContainer] {
&self.exclusive_at_start &self.exclusive_at_start
} }
/// Topologically sorted exclusive systems that want to be run at the end of the stage. /// Topologically sorted exclusive systems that want to be run at the end of the stage.
/// ///
/// Note that systems won't be fully-formed until the stage has been run at least once. /// Note that systems won't be fully-formed until the stage has been run at least once.
pub fn exclusive_at_end_systems(&self) -> &[impl SystemContainer] { pub fn exclusive_at_end_systems(&self) -> &[impl SystemContainer] {
&self.exclusive_at_end &self.exclusive_at_end
} }
/// Topologically sorted exclusive systems that want to be run after parallel systems but /// Topologically sorted exclusive systems that want to be run after parallel systems but
/// before the application of their command buffers. /// before the application of their command buffers.
/// ///

View file

@ -188,7 +188,8 @@ impl<T: Component + Clone + Eq> State<T> {
/// Creates a driver set for the State. /// Creates a driver set for the State.
/// ///
/// Important note: this set must be inserted **before** all other state-dependant sets to work properly! /// Important note: this set must be inserted **before** all other state-dependant sets to work
/// properly!
pub fn make_driver() -> SystemSet { pub fn make_driver() -> SystemSet {
SystemSet::default().with_run_criteria(state_cleaner::<T>.system()) SystemSet::default().with_run_criteria(state_cleaner::<T>.system())
} }
@ -203,7 +204,8 @@ impl<T: Component + Clone + Eq> State<T> {
} }
/// Schedule a state change that replaces the full stack with the given state. /// Schedule a state change that replaces the full stack with the given state.
/// This will fail if there is a scheduled operation, or if the given `state` matches the current state /// This will fail if there is a scheduled operation, or if the given `state` matches the
/// current state
pub fn set_next(&mut self, state: T) -> Result<(), StateError> { pub fn set_next(&mut self, state: T) -> Result<(), StateError> {
if self.stack.last().unwrap() == &state { if self.stack.last().unwrap() == &state {
return Err(StateError::AlreadyInState); return Err(StateError::AlreadyInState);
@ -217,7 +219,8 @@ impl<T: Component + Clone + Eq> State<T> {
Ok(()) Ok(())
} }
/// Same as [Self::set_next], but if there is already a next state, it will be overwritten instead of failing /// Same as [Self::set_next], but if there is already a next state, it will be overwritten
/// instead of failing
pub fn overwrite_next(&mut self, state: T) -> Result<(), StateError> { pub fn overwrite_next(&mut self, state: T) -> Result<(), StateError> {
if self.stack.last().unwrap() == &state { if self.stack.last().unwrap() == &state {
return Err(StateError::AlreadyInState); return Err(StateError::AlreadyInState);
@ -241,7 +244,8 @@ impl<T: Component + Clone + Eq> State<T> {
Ok(()) Ok(())
} }
/// Same as [Self::set_push], but if there is already a next state, it will be overwritten instead of failing /// Same as [Self::set_push], but if there is already a next state, it will be overwritten
/// instead of failing
pub fn overwrite_push(&mut self, state: T) -> Result<(), StateError> { pub fn overwrite_push(&mut self, state: T) -> Result<(), StateError> {
if self.stack.last().unwrap() == &state { if self.stack.last().unwrap() == &state {
return Err(StateError::AlreadyInState); return Err(StateError::AlreadyInState);
@ -265,7 +269,8 @@ impl<T: Component + Clone + Eq> State<T> {
Ok(()) Ok(())
} }
/// Same as [Self::set_pop], but if there is already a next state, it will be overwritten instead of failing /// Same as [Self::set_pop], but if there is already a next state, it will be overwritten
/// instead of failing
pub fn overwrite_pop(&mut self) -> Result<(), StateError> { pub fn overwrite_pop(&mut self) -> Result<(), StateError> {
if self.stack.len() == 1 { if self.stack.len() == 1 {
return Err(StateError::StackEmpty); return Err(StateError::StackEmpty);

View file

@ -58,7 +58,8 @@ pub enum StorageTextureAccess {
/// ``` /// ```
WriteOnly, WriteOnly,
/// The texture can be both read and written in the shader. /// The texture can be both read and written in the shader.
/// `wgpu::Features::STORAGE_TEXTURE_ACCESS_READ_WRITE` must be enabled to use this access mode. /// `wgpu::Features::STORAGE_TEXTURE_ACCESS_READ_WRITE` must be enabled to use this access
/// mode.
/// ///
/// Example GLSL syntax: /// Example GLSL syntax:
/// ```cpp,ignore /// ```cpp,ignore