use bevy::{
color::palettes::css,
diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin},
prelude::*,
};
use bevy_mod_raycast::prelude::*;
fn main() {
App::new()
.add_plugins((
DefaultPlugins.set(bevy_mod_raycast::low_latency_window_plugin()),
CursorRayPlugin,
FrameTimeDiagnosticsPlugin,
))
.add_systems(Startup, (setup_scene, setup_ui))
.add_systems(Update, (raycast, update_fps, manage_simplified_mesh))
.run();
}
fn raycast(cursor_ray: Res<CursorRay>, mut raycast: Raycast, mut gizmos: Gizmos) {
if let Some(ray) = **cursor_ray {
raycast.debug_cast_ray(ray, &default(), &mut gizmos);
}
}
fn setup_scene(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(Camera3dBundle::default());
commands.spawn((
PbrBundle {
mesh: meshes.add(Sphere::default().mesh().uv(1000, 1000)),
material: materials.add(Color::srgb(1.0, 1.0, 1.0)),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0)),
..default()
},
SimplifiedMesh {
mesh: meshes.add(Sphere::default()),
},
));
commands.spawn(PointLightBundle {
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
..default()
});
}
fn setup_ui(mut commands: Commands) {
commands
.spawn(NodeBundle {
style: Style {
align_self: AlignSelf::FlexStart,
flex_direction: FlexDirection::Column,
..default()
},
background_color: Color::NONE.into(),
..default()
})
.with_children(|ui| {
ui.spawn(TextBundle {
text: Text {
sections: vec![
TextSection {
value: "Press spacebar to toggle - FPS: ".to_string(),
style: TextStyle {
font_size: 30.0,
color: Color::WHITE,
..default()
},
},
TextSection {
value: "".to_string(),
style: TextStyle {
font_size: 30.0,
color: Color::WHITE,
..default()
},
},
],
..default()
},
..default()
})
.insert(FpsText);
ui.spawn(TextBundle {
text: Text {
sections: vec![
TextSection {
value: "Simplified Mesh: ".to_string(),
style: TextStyle {
font_size: 30.0,
color: Color::WHITE,
..default()
},
},
TextSection {
value: "ON".to_string(),
style: TextStyle {
font_size: 30.0,
color: css::GREEN.into(),
..default()
},
},
],
..default()
},
..default()
})
.insert(SimplifiedStatus);
});
}
#[derive(Component)]
struct SimplifiedStatus;
#[derive(Component)]
struct FpsText;
fn manage_simplified_mesh(
mut commands: Commands,
query: Query<(Entity, Option<&SimplifiedMesh>), With<Handle<Mesh>>>,
mut status_query: Query<&mut Text, With<SimplifiedStatus>>,
keyboard: Res<ButtonInput<KeyCode>>,
mut meshes: ResMut<Assets<Mesh>>,
) {
if keyboard.just_pressed(KeyCode::Space) {
if let Ok((entity, simplified_mesh)) = query.get_single() {
if let Ok(mut text) = status_query.get_single_mut() {
if simplified_mesh.is_none() {
commands.entity(entity).insert(SimplifiedMesh {
mesh: meshes.add(Sphere::default()),
});
text.sections[1].value = "ON".to_string();
text.sections[1].style.color = css::GREEN.into();
} else {
commands.entity(entity).remove::<SimplifiedMesh>();
text.sections[1].value = "OFF".to_string();
text.sections[1].style.color = css::RED.into();
}
}
}
}
}
fn update_fps(diagnostics: Res<DiagnosticsStore>, mut query: Query<&mut Text, With<FpsText>>) {
for mut text in &mut query {
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
if let Some(average) = fps.average() {
text.sections[1].value = format!("{:.2}", average);
}
}
}
}