use crate::ecs::EditorWorld;
use nightshade::prelude::*;
pub fn spawn_with_shadows(editor_world: &mut EditorWorld, world: &mut World) {
let sun = spawn_sun(world);
if let Some(light) = world.core.get_light_mut(sun) {
light.cast_shadows = true;
light.intensity = 3.5;
light.shadow_bias = 0.008;
}
editor_world.resources.sun.sun_entity = Some(sun);
editor_world
.resources
.editor_scene
.register_scaffolding(sun);
update(editor_world, world);
}
pub fn despawn_default(editor_world: &mut EditorWorld, world: &mut World) {
let Some(sun) = editor_world.resources.sun.sun_entity.take() else {
return;
};
editor_world
.resources
.editor_scene
.unregister_scaffolding(sun);
despawn_recursive_immediate(world, sun);
}
pub fn scene_has_lights(editor_world: &EditorWorld, world: &World) -> bool {
use nightshade::ecs::world::LIGHT;
let mut has = false;
world.core.query().with(LIGHT).iter(|entity, _, _| {
if !editor_world.resources.editor_scene.is_scaffolding(entity) {
has = true;
}
});
has
}
pub fn find_scene_directional_light(editor_world: &EditorWorld, world: &World) -> Option<Entity> {
use nightshade::ecs::light::components::LightType;
use nightshade::ecs::world::LIGHT;
let mut result = None;
world.core.query().with(LIGHT).iter(|entity, _, _| {
if result.is_some() {
return;
}
if editor_world.resources.editor_scene.is_scaffolding(entity) {
return;
}
if let Some(light) = world.core.get_light(entity)
&& matches!(light.light_type, LightType::Directional)
{
result = Some(entity);
}
});
result
}
pub fn adopt_scene_sun(editor_world: &mut EditorWorld, world: &mut World) {
if let Some(sun) = find_scene_directional_light(editor_world, world) {
editor_world.resources.sun.sun_entity = Some(sun);
update(editor_world, world);
}
}
pub fn update(editor_world: &mut EditorWorld, world: &mut World) {
if !editor_world.resources.sun.auto_cycle {
return;
}
let Some(sun) = editor_world.resources.sun.sun_entity else {
return;
};
let hour = editor_world.resources.sun.day_night_hour;
let sun_dir = direction_for_hour(hour);
let is_night = !(6.0..=18.0).contains(&hour);
let sun_intensity = if is_night {
0.0
} else {
let elevation = sun_dir.y.max(0.0);
3.5 * elevation.sqrt()
};
let warm = Vec3::new(1.0, 0.7, 0.4);
let white = Vec3::new(1.0, 0.95, 0.8);
let sun_color = if is_night {
Vec3::new(0.0, 0.0, 0.0)
} else if hour < 7.5 {
let t = ((hour - 6.0) / 1.5).clamp(0.0, 1.0);
nalgebra_glm::lerp(&warm, &white, t)
} else if hour > 16.5 {
let t = ((18.0 - hour) / 1.5).clamp(0.0, 1.0);
nalgebra_glm::lerp(&warm, &white, t)
} else {
white
};
if let Some(light) = world.core.get_light_mut(sun) {
light.intensity = sun_intensity;
light.color = sun_color;
}
let sun_position = sun_dir * 100.0;
if let Some(transform) = world.core.get_local_transform_mut(sun) {
transform.translation = sun_position;
let forward = -sun_dir;
let up = Vec3::y();
let right = nalgebra_glm::normalize(&nalgebra_glm::cross(&forward, &up));
if right.norm() > 0.001 {
let corrected_up = nalgebra_glm::normalize(&nalgebra_glm::cross(&right, &forward));
transform.rotation = nalgebra_glm::mat3_to_quat(&nalgebra_glm::Mat3::from_columns(&[
right,
corrected_up,
-forward,
]));
}
}
mark_local_transform_dirty(world, sun);
}
pub fn direction_for_hour(hour: f32) -> Vec3 {
let pi = std::f32::consts::PI;
if !(6.0..=18.0).contains(&hour) {
Vec3::new(0.0, -1.0, 0.0)
} else {
let sun_angle = (hour - 6.0) / 12.0 * pi;
nalgebra_glm::normalize(&Vec3::new(-sun_angle.cos(), sun_angle.sin(), -0.3))
}
}