nightshade-api 0.48.0

Procedural high level API for the nightshade game engine
Documentation
//! Lights beyond the default sun.

use crate::runner::{SUN_NAME, lookup_named};
use nightshade::prelude::*;

/// A point light at `position`. Color is linear RGB, intensity scales with
/// inverse square falloff so values around 3.0 to 10.0 read well.
pub fn point_light(world: &mut World, position: Vec3, color: [f32; 3], intensity: f32) -> Entity {
    let entity = spawn_light_entity(world, position, "api::light::point");
    world.core.set_light(
        entity,
        Light {
            light_type: LightType::Point,
            color: Vec3::new(color[0], color[1], color[2]),
            intensity,
            range: 30.0,
            cast_shadows: false,
            shadow_bias: 0.007,
            ..Default::default()
        },
    );
    entity
}

/// A shadow casting spot light at `position` aimed at `target`.
pub fn spot_light(
    world: &mut World,
    position: Vec3,
    target: Vec3,
    color: [f32; 3],
    intensity: f32,
) -> Entity {
    let entity = spawn_light_entity(world, position, "api::light::spot");
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.rotation = camera_look_rotation(position, target, 0.0);
    }
    world.core.set_light(
        entity,
        Light {
            light_type: LightType::Spot,
            color: Vec3::new(color[0], color[1], color[2]),
            intensity,
            range: 50.0,
            inner_cone_angle: 0.3,
            outer_cone_angle: 0.5,
            cast_shadows: true,
            shadow_bias: 0.0001,
            ..Default::default()
        },
    );
    entity
}

/// A directional light shining along `direction`, like a second sun. Color is
/// linear RGB. Shadows are off by default so the scene keeps one shadow casting
/// sun.
pub fn directional_light(
    world: &mut World,
    direction: Vec3,
    color: [f32; 3],
    intensity: f32,
) -> Entity {
    let entity = spawn_light_entity(world, Vec3::zeros(), "api::light::directional");
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.rotation = camera_look_rotation(Vec3::zeros(), direction, 0.0);
    }
    world.core.set_light(
        entity,
        Light {
            light_type: LightType::Directional,
            color: Vec3::new(color[0], color[1], color[2]),
            intensity,
            cast_shadows: false,
            ..Default::default()
        },
    );
    entity
}

/// A rectangular area light: a glowing panel `width` by `height` at `position`
/// facing `target`. Area lights give soft, physically plausible highlights a
/// point light cannot.
pub fn area_light(
    world: &mut World,
    position: Vec3,
    target: Vec3,
    width: f32,
    height: f32,
    color: [f32; 3],
    intensity: f32,
) -> Entity {
    let entity = spawn_light_entity(world, position, "api::light::area");
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.rotation = camera_look_rotation(position, target, 0.0);
    }
    world.core.set_light(
        entity,
        Light {
            light_type: LightType::Area,
            color: Vec3::new(color[0], color[1], color[2]),
            intensity,
            area_shape: AreaLightShape::Rectangle,
            area_width: width,
            area_height: height,
            ..Default::default()
        },
    );
    entity
}

/// Turns shadow casting on or off for a light entity.
pub fn set_light_shadows(world: &mut World, light: Entity, enabled: bool) {
    if let Some(component) = world.core.get_light_mut(light) {
        component.cast_shadows = enabled;
    }
}

/// Adjusts the default sun's color and intensity.
pub fn set_sun(world: &mut World, color: [f32; 3], intensity: f32) {
    if let Some(sun) = lookup_named(world, SUN_NAME)
        && let Some(light) = world.core.get_light_mut(sun)
    {
        light.color = Vec3::new(color[0], color[1], color[2]);
        light.intensity = intensity;
    }
}