use bevy::{ prelude::*, transform::TransformSystem, window::{CursorGrabMode, PrimaryWindow}, }; use bevy_color::palettes; use big_space::{ camera::{CameraController, CameraInput}, commands::BigSpaceCommands, reference_frame::{local_origin::ReferenceFrames, ReferenceFrame}, world_query::GridTransformReadOnly, FloatingOrigin, }; fn main() { App::new() .add_plugins(( DefaultPlugins.build().disable::(), big_space::BigSpacePlugin::::default(), big_space::debug::FloatingOriginDebugPlugin::::default(), big_space::camera::CameraControllerPlugin::::default(), )) .insert_resource(ClearColor(Color::BLACK)) .add_systems(Startup, (setup, ui_setup)) .add_systems(PreUpdate, (cursor_grab_system, ui_text_system)) .add_systems( PostUpdate, highlight_nearest_sphere.after(TransformSystem::TransformPropagate), ) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { commands.spawn_big_space(ReferenceFrame::::default(), |root| { root.spawn_spatial(( Camera3dBundle { transform: Transform::from_xyz(0.0, 0.0, 8.0) .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), projection: Projection::Perspective(PerspectiveProjection { near: 1e-18, ..default() }), ..default() }, FloatingOrigin, // Important: marks the floating origin entity for rendering. CameraController::default() // Built-in camera controller .with_speed_bounds([10e-18, 10e35]) .with_smoothness(0.9, 0.8) .with_speed(1.0), )); let mesh_handle = meshes.add(Sphere::new(0.5).mesh().ico(32).unwrap()); let matl_handle = materials.add(StandardMaterial { base_color: Color::Srgba(palettes::basic::BLUE), perceptual_roughness: 0.8, reflectance: 1.0, ..default() }); let mut translation = Vec3::ZERO; for i in -16..=27 { let j = 10_f32.powf(i as f32); let k = 10_f32.powf((i - 1) as f32); translation.x += j / 2.0 + k; translation.y = j / 2.0; root.spawn_spatial(PbrBundle { mesh: mesh_handle.clone(), material: matl_handle.clone(), transform: Transform::from_scale(Vec3::splat(j)).with_translation(translation), ..default() }); } // light root.spawn_spatial(DirectionalLightBundle { directional_light: DirectionalLight { illuminance: 10_000.0, ..default() }, ..default() }); }); } #[derive(Component, Reflect)] pub struct BigSpaceDebugText; #[derive(Component, Reflect)] pub struct FunFactText; fn ui_setup(mut commands: Commands) { commands.spawn(( TextBundle::from_section( "", TextStyle { font_size: 18.0, color: Color::WHITE, ..default() }, ) .with_text_justify(JustifyText::Left) .with_style(Style { position_type: PositionType::Absolute, top: Val::Px(10.0), left: Val::Px(10.0), ..default() }), BigSpaceDebugText, )); commands.spawn(( TextBundle::from_section( "", TextStyle { font_size: 52.0, color: Color::WHITE, ..default() }, ) .with_style(Style { position_type: PositionType::Absolute, bottom: Val::Px(10.0), right: Val::Px(10.0), left: Val::Px(10.0), ..default() }) .with_text_justify(JustifyText::Center), FunFactText, )); } fn highlight_nearest_sphere( cameras: Query<&CameraController>, objects: Query<&GlobalTransform>, mut gizmos: Gizmos, ) { let Some((entity, _)) = cameras.single().nearest_object() else { return; }; let Ok(transform) = objects.get(entity) else { return; }; // Ignore rotation due to panicking in gizmos, as of bevy 0.13 let (scale, _, translation) = transform.to_scale_rotation_translation(); gizmos .sphere( translation, Quat::IDENTITY, // Bevy likes to explode on non-normalized quats in gizmos, scale.x * 0.505, Color::Srgba(palettes::basic::RED), ) .resolution(128); } #[allow(clippy::type_complexity)] fn ui_text_system( mut debug_text: Query< (&mut Text, &GlobalTransform), (With, Without), >, mut fun_text: Query<&mut Text, (With, Without)>, ref_frames: ReferenceFrames, time: Res