diff --git a/src/asset.rs b/src/asset.rs index 3839ed99..387dee90 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -71,20 +71,40 @@ pub struct RenderLayout { #[uuid = "249aefa4-9b8e-48d3-b167-3adf6c081c34"] pub struct EffectAsset { /// Display name of the effect. + /// + /// This has no internal use, and is mostly for the user to identify an + /// effect or for display is some tool UI. pub name: String, /// Maximum number of concurrent particles. + /// + /// The capacity is the maximum number of particles that can be alive at the + /// same time. It determines the size of various GPU resources, most notably + /// the particle buffer itself. To prevent wasting GPU resources, users + /// should keep this quantity as close as possible to the maximum number of + /// particles they expect to render. pub capacity: u32, /// Spawner. pub spawner: Spawner, /// Layout describing the particle initialize code. + /// + /// The initialize layout determines how new particles are initialized when + /// spawned. Compatible layouts increase the chance of batching together + /// effects. #[serde(skip)] // TODO #[reflect(ignore)] // TODO? pub init_layout: InitLayout, /// Layout describing the particle update code. + /// + /// The update layout determines how all alive particles are updated each + /// frame. Compatible layouts increase the chance of batching together + /// effects. #[serde(skip)] // TODO #[reflect(ignore)] // TODO? pub update_layout: UpdateLayout, /// Layout describing the particle rendering code. + /// + /// The render layout determines how alive particles are rendered. + /// Compatible layouts increase the chance of batching together effects. #[serde(skip)] // TODO #[reflect(ignore)] // TODO? pub render_layout: RenderLayout, @@ -97,8 +117,6 @@ pub struct EffectAsset { /// /// Ignored for 3D rendering. pub z_layer_2d: f32, - //#[serde(skip)] // TODO - //modifiers: Vec>, } impl EffectAsset { diff --git a/src/bundle.rs b/src/bundle.rs index 373128e3..7c9750f5 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -2,19 +2,35 @@ use crate::{EffectAsset, ParticleEffect, Spawner}; use bevy::prelude::*; /// A component bundle for a particle effect. +/// +/// This bundle contains all necessary components for a [`ParticleEffect`] to +/// function correctly, and is the preferred method for spawning a new +/// [`ParticleEffect`]. #[derive(Bundle, Clone)] pub struct ParticleEffectBundle { - /// The particle effect itself. + /// The particle effect instance itself. pub effect: ParticleEffect, /// Transform of the entity, representing the frame of reference for the /// particle emission. + /// + /// New particles are emitted relative to this transform, ignoring the + /// scale. pub transform: Transform, /// Computed global transform. + /// + /// Users should not interact with this component manually, but it is + /// required by Bevy's built-in transform system. pub global_transform: GlobalTransform, /// User indication of whether an entity is visible. + /// + /// Invisible entities do not process any particles, making it efficient to + /// temporarily disable an effect instance. pub visibility: Visibility, /// Algorithmically-computed indication of whether an entity is visible and /// should be extracted for rendering. + /// + /// Users should not interact with this component manually, but it is + /// required by Bevy's built-in visibility system. pub computed_visibility: ComputedVisibility, } diff --git a/src/lib.rs b/src/lib.rs index 6231e954..4670fc6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,7 +147,12 @@ compile_error!( "You need to enable at least one of the '2d' or '3d' features for anything to happen." ); -/// Get the smallest multiple of align greater than or equal to value, where `align` must be a power of two. +/// Get the smallest multiple of align greater than or equal to value, where +/// `align` must be a power of two. +/// +/// # Panics +/// +/// Panics if `align` is not a power of two. // TODO - filler for usize.next_multiple_of() // https://github.com/rust-lang/rust/issues/88581 pub(crate) fn next_multiple_of(value: usize, align: usize) -> usize { @@ -160,9 +165,9 @@ pub(crate) fn next_multiple_of(value: usize, align: usize) -> usize { /// format matching the WGSL grammar. /// /// This is required because WGSL doesn't support a floating point constant -/// without a decimal separator (e.g. `0.` instead of `0`), which would be what -/// a regular float to string formatting produces, but is interpreted as an -/// integral type by WGSL. +/// without a decimal separator (_e.g._ `0.` instead of `0`), which would be +/// what a regular string formatting function like [`format!()`] would produce, +/// but which is interpreted as an integral type by WGSL instead. /// /// # Example /// @@ -171,6 +176,8 @@ pub(crate) fn next_multiple_of(value: usize, align: usize) -> usize { /// let x = 2.0_f32; /// assert_eq!("let x = 2.;", format!("let x = {};", x.to_wgsl_string())); /// ``` +/// +/// [`format!()`]: std::format pub trait ToWgslString { /// Convert a floating point scalar or vector to a string representing a /// WGSL constant. @@ -243,6 +250,10 @@ impl ToWgslString for Value { /// effect. The visual effect itself is described by a handle to an /// [`EffectAsset`]. This instance is associated to an [`Entity`], inheriting /// its [`Transform`] as the origin frame for its particle spawning. +/// +/// When spawning a new [`ParticleEffect`], consider using the +/// [`ParticleEffectBundle`] to ensure all the necessary components are present +/// on the entity for the effect to render correctly. #[derive(Debug, Default, Clone, Component, Reflect)] #[reflect(Component)] pub struct ParticleEffect { @@ -314,15 +325,22 @@ impl ParticleEffect { self } - /// Sets the spawner of this particle effect. + /// Set the spawner of this particle effect instance. + /// + /// By default particle effect instances inherit the spawner of the + /// [`EffectAsset`] they're derived from. This allows overriding the spawner + /// configuration per instance. pub fn set_spawner(&mut self, spawner: Spawner) { self.spawner = Some(spawner); } /// Configure the spawner of a new particle effect. /// - /// The call returns a reference to the added spawner, allowing to chain - /// adding modifiers to the effect. + /// In general this is called internally while the spawner is ticked, to + /// assign the source asset's spawner to this instance. + /// + /// Returns a reference to the added spawner owned by the current instance, + /// allowing to chain adding modifiers to the effect. pub fn spawner(&mut self, spawner: &Spawner) -> &mut Spawner { if self.spawner.is_none() { self.spawner = Some(*spawner); @@ -332,8 +350,10 @@ impl ParticleEffect { /// Get the spawner of this particle effect. /// - /// Returns None if `with_spawner` was not called - /// and the effect has not rendered yet. + /// Returns `None` if [`configure_spawner()`] was not called and the effect + /// has not been internally allocated yet. + /// + /// [`configure_spawner()`]: crate::ParticleEffect::configure_spawner pub fn maybe_spawner(&mut self) -> Option<&mut Spawner> { self.spawner.as_mut() } @@ -506,8 +526,7 @@ fn tick_spawners( // Loop over all existing effects to update them for (computed_visibility, mut effect) in query.p0().iter_mut() { - // Check if visible. Hidden effects are entirely skipped for performance - // reasons. + // Hidden effects are entirely skipped for performance reasons if !computed_visibility.is_visible() { continue; } diff --git a/src/spawn.rs b/src/spawn.rs index f8be26d8..cea87e48 100644 --- a/src/spawn.rs +++ b/src/spawn.rs @@ -22,7 +22,12 @@ pub struct Random(pub Pcg32); pub enum Value { /// Single constant value. Single(T), - /// Random value distributed uniformly between two bounds. + /// Random value distributed uniformly between two inclusive bounds. + /// + /// The minimum bound must be less than or equal to the maximum one, + /// otherwise some methods like [`sample()`] will panic. + /// + /// [`sample()`]: crate::Value::sample Uniform((T, T)), } @@ -34,6 +39,9 @@ impl Default for Value { impl Value { /// Sample the value. + /// - For [`Value::Single`], always return the same single value. + /// - For [`Value::Uniform`], use the given pseudo-random number generator + /// to generate a random sample. pub fn sample(&self, rng: &mut Pcg32) -> T { match self { Value::Single(x) => *x, @@ -43,8 +51,8 @@ impl Value { } impl Value { - /// Returns the range of values this can be - /// in the form `[minimum, maximum]` + /// Returns the range of allowable values in the form `[minimum, maximum]`. + /// For [`Value::Single`], both values are the same. pub fn range(&self) -> [T; 2] { match self { Value::Single(x) => [*x; 2], @@ -65,7 +73,12 @@ impl From for Value { } } -/// Spawner defining how new particles are created. +/// Spawner defining how new particles are emitted. +/// +/// The spawner defines how new particles are emitted and when. Each time the +/// spawner ticks, once per frame, it calculates a number of particles to emit +/// for this tick. This spawn count is passed to the GPU for the init compute +/// pass to actually allocate the new particles and initialize them. #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Reflect)] pub struct Spawner { /// Number of particles to spawn over [`spawn_time`].