use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, input::keyboard::Key, prelude::{ 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::{ 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() { let config: toids::Config = argh::from_env(); App::new() .add_plugins(DefaultPlugins) .add_plugins(( FrameTimeDiagnosticsPlugin::default(), 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 { color: Color::WHITE, brightness: 150.0, affects_lightmapped_meshes: true, ..Default::default() }) .insert_resource(Naybs { index: RTree::new(), positions: None, }) .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() .run_if(should_run), ) .add_systems( Update, (handle_inputs, close_on_esc, update_naybs.after(update_pos)), ) //.add_systems(Update, update_gizmos) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, mut positions: ResMut, config: Res, models: Res, ) { let rand = &mut rand::rng(); commands.spawn(( Transform::from_xyz(0., 5.0, 25.).looking_at(Vec3::new(0.0, 5.0, 0.0), Vec3::Y), Camera3d::default(), )); // plane commands.spawn(( Mesh3d(meshes.add(Mesh::from(Plane3d::new(Vec3::Y, Vec2::splat(500.0))))), MeshMaterial3d(materials.add(Color::srgb(0.3, 0.9, 0.3))), Visibility::Visible, Transform::default(), )); for _ in 0..config.toids { turkey_time(&mut commands, rand, &models, &mut positions); } // instructions commands.spawn(( Visibility::Visible, Node { position_type: PositionType::Absolute, top: px(12.0), left: px(12.0), ..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 'SPACE' to pause, 'ESC' to quit."), TextFont { font_size: FontSize::Px(20.0), ..default() }, )], )); } fn close_on_esc( mut commands: Commands, windows: Query>, input: Res>, handle: ResMut, ) { let background_gone = handle.as_ref().is_finished(); if background_gone { warn!("background is gone, shutting down"); } 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 }