pub struct UpdateContext<'a> {
pub input: &'a Input,
/* private fields */
}Expand description
Context passed to the update callback each frame.
Provides access to input state and allows updating custom uniforms.
§Input Access
The context provides full access to input state through the input field:
.with_update(|ctx| {
// Check if a key was just pressed this frame
if ctx.input.key_pressed(KeyCode::Space) {
ctx.set("burst", 1.0);
}
// Check if left mouse is held down
if ctx.input.mouse_held(MouseButton::Left) {
ctx.set("attractor", ctx.mouse_world_pos());
}
// Get mouse movement delta
let delta = ctx.input.mouse_delta();
})§CPU Readback
You can request GPU particle data to be read back to the CPU:
.with_update(|ctx| {
// Request readback every second
if ctx.time() as u32 != (ctx.time() - ctx.delta_time()) as u32 {
ctx.request_readback();
}
// Access previous frame's readback data (if available)
if let Some(bytes) = ctx.particles_raw() {
let particles: &[MyParticleGpu] = bytemuck::cast_slice(bytes);
println!("First particle position: {:?}", particles[0].position);
}
})Fields§
§input: &'a InputInput state for the current frame.
Implementations§
Source§impl<'a> UpdateContext<'a>
impl<'a> UpdateContext<'a>
Sourcepub fn delta_time(&self) -> f32
pub fn delta_time(&self) -> f32
Get the time since last frame in seconds.
Sourcepub fn mouse_ndc(&self) -> Vec2
pub fn mouse_ndc(&self) -> Vec2
Get the mouse position in normalized device coordinates (-1 to 1).
This is a convenience method. For full input access, use ctx.input.
Sourcepub fn mouse_world_pos(&self) -> Vec3
pub fn mouse_world_pos(&self) -> Vec3
Get the mouse position in world coordinates.
Maps the mouse position from screen space to world space using the simulation bounds. The z-coordinate is set to 0 (front-facing plane).
This accounts for window aspect ratio, so the mapping is correct regardless of window shape.
§Example
.with_update(|ctx| {
if ctx.input.mouse_held(MouseButton::Left) {
// Get mouse position in world coordinates
let pos = ctx.mouse_world_pos();
ctx.set("attractor", pos);
}
})Sourcepub fn aspect_ratio(&self) -> f32
pub fn aspect_ratio(&self) -> f32
Get the window aspect ratio (width / height).
Sourcepub fn mouse_pressed(&self) -> bool
pub fn mouse_pressed(&self) -> bool
Check if the left mouse button is currently held down.
This is a convenience method. For full input access, use ctx.input.
Sourcepub fn key_pressed(&self, key: KeyCode) -> bool
pub fn key_pressed(&self, key: KeyCode) -> bool
Check if a key was just pressed this frame.
This is a convenience method. For full input access, use ctx.input.
Sourcepub fn key_held(&self, key: KeyCode) -> bool
pub fn key_held(&self, key: KeyCode) -> bool
Check if a key is currently held down.
This is a convenience method. For full input access, use ctx.input.
Sourcepub fn set<V: Into<UniformValue>>(&mut self, name: &str, value: V)
pub fn set<V: Into<UniformValue>>(&mut self, name: &str, value: V)
Set a custom uniform value.
Sourcepub fn get(&self, name: &str) -> Option<&UniformValue>
pub fn get(&self, name: &str) -> Option<&UniformValue>
Get a custom uniform value.
Sourcepub fn set_grid_opacity(&mut self, opacity: f32)
pub fn set_grid_opacity(&mut self, opacity: f32)
Set the spatial grid visualization opacity.
Use 0.0 to hide the grid, 1.0 for full visibility. The change takes effect on the next frame.
Sourcepub fn request_readback(&mut self)
pub fn request_readback(&mut self)
Request particle data to be read back from GPU after this frame.
The data will be available via particles_raw() on the next frame.
This is an expensive operation that stalls the GPU pipeline.
Use sparingly (e.g., once per second, or on user request).
§Example
.with_update(|ctx| {
// Request readback when space is pressed
if ctx.key_pressed(KeyCode::Space) {
ctx.request_readback();
}
})Sourcepub fn particles_raw(&self) -> Option<&[u8]>
pub fn particles_raw(&self) -> Option<&[u8]>
Get the raw bytes of particle data from the previous readback request.
Returns None if no readback was requested on the previous frame.
The bytes can be cast to your particle’s GPU type using bytemuck::cast_slice.
Note: This returns a reference, so you cannot call ctx.set() while
holding the returned slice. Use with_particles() for the common pattern
of reading data and then updating uniforms.
§Example
.with_update(|ctx| {
if let Some(bytes) = ctx.particles_raw() {
let particles: &[MyParticleGpu] = bytemuck::cast_slice(bytes);
for p in particles.iter().take(10) {
println!("Position: {:?}", p.position);
}
}
})Sourcepub fn with_particles<T, F>(&self, f: F) -> Option<T>
pub fn with_particles<T, F>(&self, f: F) -> Option<T>
Process particle data and return a result, handling borrow scope automatically.
This is the recommended way to read particle data when you also need to
update uniforms based on the results. The closure receives the raw bytes
and returns any value you need; after the closure completes, you can
freely call ctx.set() with the results.
Returns None if no readback data is available.
§Example
.with_update(|ctx| {
// Compute stats from particles
if let Some((center, count)) = ctx.with_particles(|bytes| {
let particles: &[MyParticleGpu] = bytemuck::cast_slice(bytes);
let sum: Vec3 = particles.iter()
.map(|p| Vec3::from_array(p.position))
.sum();
let count = particles.len();
(sum / count as f32, count)
}) {
// Now we can update uniforms with the results
ctx.set("center_x", center.x);
ctx.set("center_y", center.y);
ctx.set("particle_count", count as f32);
}
})Auto Trait Implementations§
impl<'a> Freeze for UpdateContext<'a>
impl<'a> RefUnwindSafe for UpdateContext<'a>
impl<'a> Send for UpdateContext<'a>
impl<'a> Sync for UpdateContext<'a>
impl<'a> Unpin for UpdateContext<'a>
impl<'a> !UnwindSafe for UpdateContext<'a>
Blanket Implementations§
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
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.