const SIMULATION_STARTS_PAUSED: bool = false;
const INSPECTOR_STARTS_HIDDEN: bool = false;
use std::ffi::CString;
use std::time::Duration;
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
use bevy::input::common_conditions::input_toggle_active;
use bevy::light::DirectionalLightShadowMap;
use bevy::platform::collections::HashSet;
use bevy::prelude::*;
use bevy_mod_physx::prelude::*;
pub mod debug_render;
use debug_render::DebugRenderPlugin;
pub mod orbit_camera;
use orbit_camera::{OrbitCamera, OrbitCameraPlugin};
#[derive(Default)]
pub struct DemoUtils;
impl Plugin for DemoUtils {
fn build(&self, app: &mut App) {
app.insert_resource(NameFormatter(|entity, name| {
let str = if let Some(name) = name {
format!("{name} ({entity:?})")
} else {
format!("({entity:?})")
};
std::borrow::Cow::Owned(CString::new(str).unwrap())
}));
app.add_plugins(DebugRenderPlugin);
app.insert_resource(ClearColor(Color::srgb(0., 0., 0.)));
app.insert_resource(AmbientLight {
brightness: 1.0 / 5.0f32,
..default()
});
app.insert_resource(DirectionalLightShadowMap { size: 4096 });
app.add_plugins(FrameTimeDiagnosticsPlugin::default());
app.add_plugins(LogDiagnosticsPlugin {
wait_duration: Duration::from_millis(1000),
filter: Some(HashSet::from([FrameTimeDiagnosticsPlugin::FPS])),
..default()
});
app.add_plugins(OrbitCameraPlugin);
app.add_plugins(bevy_inspector_egui::bevy_egui::EguiPlugin::default());
app.add_plugins(
bevy_inspector_egui::quick::WorldInspectorPlugin::default()
.run_if(input_toggle_active(!INSPECTOR_STARTS_HIDDEN, KeyCode::F12)),
);
app.add_systems(Update, adjust_light_settings);
app.add_systems(Update, adjust_camera_settings);
app.add_systems(Update, spacebar_pauses_simulation);
if SIMULATION_STARTS_PAUSED {
app.add_systems(Startup, |mut time: ResMut<Time<Virtual>>| time.pause());
}
app.add_systems(Update, close_on_esc);
}
}
#[derive(Component)]
struct DemoUtilsLightFixed;
fn adjust_light_settings(
mut commands: Commands,
mut query: Query<(Entity, &mut DirectionalLight), Without<DemoUtilsLightFixed>>,
) {
for (entity, mut light) in query.iter_mut() {
light.illuminance = 6500.;
light.shadows_enabled = true;
commands.entity(entity).insert(DemoUtilsLightFixed);
}
}
#[allow(clippy::type_complexity)]
fn adjust_camera_settings(
mut commands: Commands,
mut query: Query<(Entity, &Transform), (With<Camera3d>, Without<OrbitCamera>)>,
) {
for (entity, transform) in query.iter_mut() {
let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
commands.entity(entity)
.insert(OrbitCamera {
gimbal_x: -yaw,
gimbal_y: -pitch,
distance: transform.translation.length(),
..default()
});
}
}
fn spacebar_pauses_simulation(
keys: Res<ButtonInput<KeyCode>>,
mut time: ResMut<Time<Virtual>>,
) {
if keys.just_pressed(KeyCode::Space) {
if time.is_paused() {
time.unpause();
} else {
time.pause();
}
}
}
pub fn close_on_esc(
mut commands: Commands,
focused_windows: Query<(Entity, &Window)>,
input: Res<ButtonInput<KeyCode>>,
) {
for (window, focus) in focused_windows.iter() {
if !focus.focused { continue; }
if input.just_pressed(KeyCode::Escape) {
commands.entity(window).despawn();
}
}
}