From b4ad5000013409cfc892691925c555a6a25d61c8 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Sat, 3 Oct 2026 15:16:41 -0700 Subject: [PATCH] tidy --- src/lib.rs | 9 ++++--- src/main.rs | 60 +++++++++++++++++++++++++++------------------ src/systems.rs | 66 ++++++++++++++++++++++++++++---------------------- 3 files changed, 80 insertions(+), 55 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6c847cb..3d9c757 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ use rstar::{primitives::GeomWithData, RTree}; mod systems; pub use systems::{ - init_naybs, rotate_camera, setup_channels, spawn_background, turkey_time, update_buddies, + handle_inputs, init_naybs, setup_channels, spawn_background, turkey_time, update_buddies, update_gizmos, update_naybs, update_pos, update_vel, }; @@ -59,8 +59,8 @@ struct IndexMessage { struct RawMessage(Vec); -#[derive(Default, Resource, Deref, DerefMut)] -pub struct BackgroundHandle(Option>); +#[derive(Resource, Deref, DerefMut)] +pub struct BackgroundHandle(bevy::tasks::Task<()>); #[derive(Component)] pub struct Toid { @@ -70,3 +70,6 @@ pub struct Toid { #[derive(Debug, Default, Clone, Copy, Deref, DerefMut, Resource)] pub struct LookAt(Vec3); + +#[derive(Resource, Debug, Deref, DerefMut, Clone, Default)] +pub struct Paused(bool); diff --git a/src/main.rs b/src/main.rs index b9fc857..3f44642 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,16 +2,18 @@ use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, input::keyboard::Key, prelude::{ - children, default, px, App, AssetServer, Assets, ButtonInput, Camera3d, ClearColor, Color, - Commands, DefaultPlugins, Entity, FontSize, GlobalAmbientLight, IntoScheduleConfigs, Mesh, - Mesh3d, MeshMaterial3d, Node, Plane3d, PositionType, Query, Res, ResMut, StandardMaterial, - Startup, Text, TextFont, Transform, Update, Vec2, Vec3, Visibility, Window, + children, default, px, warn, App, AssetServer, Assets, ButtonInput, Camera3d, ClearColor, + Color, Commands, DefaultPlugins, Entity, FontSize, GlobalAmbientLight, IntoScheduleConfigs, + Mesh, Mesh3d, MeshMaterial3d, Node, Plane3d, PositionType, Query, Res, ResMut, + StandardMaterial, Startup, Text, TextFont, Transform, Update, Vec2, Vec3, Visibility, + Window, With, }, }; use rstar::RTree; use toids::{ - init_naybs, rotate_camera, setup_channels, spawn_background, turkey_time, update_buddies, - update_naybs, update_pos, update_vel, BackgroundHandle, Config, LookAt, Naybs, Positions, + handle_inputs, init_naybs, setup_channels, spawn_background, turkey_time, update_buddies, + update_naybs, update_pos, update_vel, BackgroundHandle, Config, LookAt, Naybs, Paused, + Positions, }; fn main() { @@ -23,6 +25,7 @@ fn main() { LogDiagnosticsPlugin::default(), )) .insert_resource(config) + .insert_resource(Paused::default()) .insert_resource(Positions::default()) .insert_resource(ClearColor(Color::srgb(0.64, 0.745, 0.937))) // a nice light blue .insert_resource(GlobalAmbientLight { @@ -35,16 +38,20 @@ fn main() { index: RTree::new(), positions: None, }) - .insert_resource(BackgroundHandle::default()) .insert_resource(LookAt::default()) .add_systems( Startup, (setup_channels, setup, init_naybs, spawn_background).chain(), ) - .add_systems(Update, (update_pos, update_buddies, update_vel).chain()) .add_systems( Update, - (rotate_camera, close_on_esc, update_naybs.after(update_pos)), + (update_pos, update_buddies, update_vel) + .chain() + .run_if(should_run), + ) + .add_systems( + Update, + (handle_inputs, close_on_esc, update_naybs.after(update_pos)), ) //.add_systems(Update, update_gizmos) .run(); @@ -72,10 +79,8 @@ fn setup( Transform::default(), )); - // let toid_model = models.load("models/boid.glb#Scene0"); - for _ in 0..config.toids { - turkey_time(&mut commands, rand, &models, &mut positions.0); + turkey_time(&mut commands, rand, &models, &mut positions); } // instructions @@ -88,7 +93,7 @@ fn setup( ..default() }, children![( - Text::new("Up and down for camera forward and back; hold shift to change height.\nLeft or right to move left or right.\nPress 'ESC' to quit."), + Text::new("Up and down for camera forward and back; hold shift to change height.\nLeft or right to move left or right.\nPress 'SPACE' to pause, 'ESC' to quit."), TextFont { font_size: FontSize::Px(20.0), ..default() @@ -99,18 +104,27 @@ fn setup( fn close_on_esc( mut commands: Commands, - focused_windows: Query<(Entity, &Window)>, + windows: Query>, input: Res>, - mut handle: ResMut, + handle: ResMut, ) { - for (window, focus) in focused_windows.iter() { - if !focus.focused { - continue; - } + let background_gone = handle.as_ref().is_finished(); + if background_gone { + warn!("background is gone, shutting down"); + } - if input.just_pressed(Key::Escape) { - drop((*handle).take()); - commands.entity(window).despawn(); - } + let exited = background_gone || input.just_pressed(Key::Escape); + if !exited { + return; + } + + drop(handle); + + for window in windows.iter() { + commands.entity(window).despawn(); } } + +fn should_run(paused: Res) -> bool { + !**paused +} diff --git a/src/systems.rs b/src/systems.rs index cfce885..2542638 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -5,14 +5,14 @@ use bevy::{input::keyboard::Key, prelude::*, tasks::AsyncComputeTaskPool}; use rand::RngExt; use super::{ - BackgroundHandle, Buddies, GeomWithData, IndexChannel, IndexMessage, LookAt, Naybs, Positions, - RTree, RawMessage, RawPosChannel, Toid, Velocity, + BackgroundHandle, Buddies, GeomWithData, IndexChannel, IndexMessage, LookAt, Naybs, Paused, + Positions, RTree, RawMessage, RawPosChannel, Toid, Velocity, }; // toid stuff const SPEED: f32 = 12.0; const SPEED_DIFF_RANGE: f32 = 0.1; -const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; +const MAX_DELTA_V: f32 = std::f32::consts::PI * 1.2; // how far from origin before really wanting to come back const RADIUS: f32 = 30.0; @@ -44,7 +44,6 @@ pub fn update_naybs( if let Ok(idx_msg) = idx_chan.rx.try_recv() { naybs.index = idx_msg.index; let _ = naybs.positions.insert(idx_msg.raw); - return; } if let Some(mut raw) = naybs.positions.take() { @@ -68,9 +67,9 @@ pub fn init_naybs(positions: Res, mut naybs: ResMut) { } pub fn spawn_background( + mut commands: Commands, mut raw_chan: ResMut, idx_chan: Res, - mut handle: ResMut, ) { let pool = AsyncComputeTaskPool::get(); @@ -80,6 +79,7 @@ pub fn spawn_background( let task = pool.spawn(async move { let tx = idx_tx; let rx = raw_rx; + loop { match rx.recv().await { Ok(RawMessage(e_posns)) => { @@ -102,7 +102,7 @@ pub fn spawn_background( } }); - let _ = handle.0.insert(task); + commands.insert_resource(BackgroundHandle(task)); } pub fn turkey_time( @@ -160,7 +160,7 @@ pub fn update_vel( let original_dir = dir; // find buddies and orient; point more towards further-away buddies - for buddy in buddies.0.iter() { + for buddy in buddies.iter() { let bp = positions.get(buddy).unwrap(); let bdir = *bp - pos; let dist = bdir.length(); @@ -174,7 +174,7 @@ pub fn update_vel( let min_dist = speed; for neighbor in index .index - .locate_within_distance(pos.to_array(), min_dist * 10.0) + .locate_within_distance(pos.to_array(), speed.powi(2)) .filter(|n| n.data != entity) { let bp = Vec3::from_array(*neighbor.geom()); @@ -230,7 +230,7 @@ pub fn update_pos( let look_at = xform.translation + vel.0; xform.translation += vel.0 * dt; xform.look_at(look_at, Vec3::Y); - *positions.entry(entity).or_insert(Vec3::ZERO) = xform.translation; + positions.insert(entity, xform.translation); new_look += xform.translation; } **lookat = new_look / positions.len() as f32; @@ -242,28 +242,30 @@ pub fn update_buddies( positions: Res, ) { let d2 = (BUDDY_RADIUS * 1.5).powi(2); - for (xform, entity, toid, mut buddies) in toids.iter_mut() { - let pos = xform.translation; - for buddy in buddies.clone().iter() { - let bp = positions[buddy]; - let bd2 = (bp - pos).length_squared(); - if bd2 > d2 { - buddies.remove(buddy); + toids + .par_iter_mut() + .for_each(|(xform, entity, toid, mut buddies)| { + let pos = xform.translation; + for buddy in buddies.clone().iter() { + let bp = positions.get(buddy).unwrap(); + let bd2 = (bp - pos).length_squared(); + if bd2 > d2 { + buddies.remove(buddy); + } } - } - if buddies.len() < toid.buddies { - let diff = toid.buddies - buddies.len(); - for neighbor in index - .index - .nearest_neighbor_iter(pos.to_array()) - .filter(|n| n.data != entity) - .take(diff) - { - buddies.insert(neighbor.data); + if buddies.len() < toid.buddies { + let diff = toid.buddies - buddies.len(); + for neighbor in index + .index + .nearest_neighbor_iter(pos.to_array()) + .filter(|n| n.data != entity) + .take(diff) + { + buddies.insert(neighbor.data); + } } - } - } + }); } pub fn update_gizmos(toids: Query<&Transform, With>, mut gizmos: Gizmos) { @@ -278,11 +280,17 @@ pub fn update_gizmos(toids: Query<&Transform, With>, mut gizmos: Gizmos) { } } -pub fn rotate_camera( +pub fn handle_inputs( mut query: Query<&mut Transform, With>, + mut paused: ResMut, keys: Res>, lookat: Res, ) { + if keys.just_pressed(Key::Space) { + let pause = **paused; + **paused = !pause; + } + let mut xform = query.single_mut().unwrap(); let forward = xform.forward().as_vec3() * 0.7;