mod common;
use bevy::prelude::*;
use bevy_elements::*;
use common::{ExampleHarness, FlyCamera, camera, test_scene};
fn main() {
let fixed: Option<f64> = std::env::var("ELEMENTS_HOUR")
.ok()
.and_then(|h| h.parse().ok());
let date = std::env::var("ELEMENTS_DATE")
.ok()
.and_then(|d| {
let mut part = d.split('-');
let year: i32 = part.next()?.trim().parse().ok()?;
let month: u8 = part.next()?.trim().parse().ok()?;
let day: u8 = part.next()?.trim().parse().ok()?;
Some(CivilDate::new(year, month, day))
})
.unwrap_or(CivilDate::new(2026, 6, 21));
let start: f64 = std::env::var("ELEMENTS_START")
.ok()
.and_then(|h| h.parse().ok())
.unwrap_or(4.0);
let clock = WorldClock::new(date).at_hour(fixed.unwrap_or(start));
let clock = match fixed {
Some(_) => WorldClock {
paused: true,
..clock
},
None => clock.with_time_scale(720.0),
};
let preset = std::env::var("ELEMENTS_PRESET")
.ok()
.and_then(|name| {
WeatherPreset::ALL
.into_iter()
.find(|p| format!("{p:?}").eq_ignore_ascii_case(&name))
})
.unwrap_or(WeatherPreset::Clear);
let mut director = WeatherDirector::default();
director.force(preset, std::time::Duration::ZERO);
App::new()
.add_plugins((DefaultPlugins, ElementsPlugins, ExampleHarness))
.insert_resource(clock)
.insert_resource(director)
.insert_resource(GeoLocation {
latitude_deg: 45.0,
..default()
})
.add_systems(Startup, setup)
.add_systems(PostUpdate, aim_at_sky)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(camera(
Vec3::new(0.0, 8.0, 0.0),
Vec3::new(-200.0, 30.0, 60.0),
));
test_scene(&mut commands, &mut meshes, &mut materials);
}
fn aim_at_sky(
sun: Res<SunState>,
clock: Res<WorldClock>,
mouse: Res<ButtonInput<MouseButton>>,
mut cameras: Query<(&mut Transform, &mut FlyCamera)>,
mut framed: Local<bool>,
) {
if std::env::var("DAYNIGHT_DEBUG").as_deref() == Ok("1") {
eprintln!(
"AIMENTRY paused={} mouse={} sun {:.2} moon {:.2}",
clock.paused,
mouse.pressed(MouseButton::Right),
sun.altitude_deg,
sun.moon_altitude_deg
);
}
if mouse.pressed(MouseButton::Right) {
*framed = false;
return;
}
if clock.paused && *framed {
return;
}
let dir = if sun.altitude_deg > 0.5 {
Some(sun.direction)
} else if sun.moon_altitude_deg > 0.5 {
Some(sun.moon_direction)
} else {
None
};
if std::env::var("DAYNIGHT_DEBUG").as_deref() == Ok("1") {
eprintln!(
"AIM sun {:.2} moon {:.2} dir {:?} branch {}",
sun.altitude_deg,
sun.moon_altitude_deg,
sun.moon_direction,
dir.is_some()
);
}
let Some(dir) = dir else {
*framed = clock.paused;
return;
};
let yaw = (-dir.x).atan2(-dir.z);
let pitch = dir.y.clamp(-1.0, 1.0).asin();
for (mut transform, mut fly) in &mut cameras {
fly.face(yaw, pitch);
transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, 0.0);
}
*framed = clock.paused;
}