use crate::resources::AmbientColor;
use amethyst_assets::{PrefabData, ProgressCounter};
use amethyst_core::{
ecs::prelude::{Component, DenseVecStorage, Entity, WriteStorage},
math::Vector3,
};
use amethyst_error::Error;
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, PrefabData)]
#[prefab(Component)]
pub enum Light {
Area,
Directional(DirectionalLight),
Point(PointLight),
Spot(SpotLight),
Sun(SunLight),
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct DirectionalLight {
#[serde(with = "crate::serde_shim::srgb")]
pub color: palette::Srgb,
pub intensity: f32,
pub direction: Vector3<f32>,
}
impl Default for DirectionalLight {
fn default() -> Self {
DirectionalLight {
color: Default::default(),
intensity: 1.0,
direction: [-1.0, -1.0, -1.0].into(),
}
}
}
impl From<DirectionalLight> for Light {
fn from(dir: DirectionalLight) -> Self {
Light::Directional(dir)
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct PointLight {
#[serde(with = "crate::serde_shim::srgb")]
pub color: palette::Srgb,
pub intensity: f32,
pub radius: f32,
pub smoothness: f32,
}
impl Default for PointLight {
fn default() -> Self {
PointLight {
color: Default::default(),
intensity: 10.0,
radius: 10.0,
smoothness: 4.0,
}
}
}
impl From<PointLight> for Light {
fn from(pt: PointLight) -> Self {
Light::Point(pt)
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct SpotLight {
pub angle: f32,
#[serde(with = "crate::serde_shim::srgb")]
pub color: palette::Srgb,
pub direction: Vector3<f32>,
pub intensity: f32,
pub range: f32,
pub smoothness: f32,
}
impl Default for SpotLight {
fn default() -> Self {
SpotLight {
angle: std::f32::consts::FRAC_PI_3,
color: Default::default(),
direction: [0.0, -1.0, 0.0].into(),
intensity: 10.0,
range: 10.0,
smoothness: 4.0,
}
}
}
impl From<SpotLight> for Light {
fn from(sp: SpotLight) -> Self {
Light::Spot(sp)
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct SunLight {
pub angle: f32,
#[serde(with = "crate::serde_shim::srgb")]
pub color: palette::Srgb,
pub direction: Vector3<f32>,
pub intensity: f32,
}
impl Default for SunLight {
fn default() -> Self {
SunLight {
angle: 0.0093_f32.to_radians(),
color: Default::default(),
direction: [-1.0, -1.0, -1.0].into(),
intensity: 64_000.0,
}
}
}
impl From<SunLight> for Light {
fn from(sun: SunLight) -> Self {
Light::Sun(sun)
}
}
impl Component for Light {
type Storage = DenseVecStorage<Self>;
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize, PrefabData)]
#[serde(default)]
pub struct LightPrefab {
light: Option<Light>,
ambient_color: Option<AmbientColor>,
}
use gltf::khr_lights_punctual;
use gltf::khr_lights_punctual::Kind;
impl From<khr_lights_punctual::Light<'_>> for LightPrefab {
fn from(light: khr_lights_punctual::Light<'_>) -> Self {
let color = {
let parts = light.color();
palette::Srgb::new(parts[0], parts[1], parts[2])
};
let intensity = light.intensity();
let range = light.range();
LightPrefab {
light: Some(match light.kind() {
Kind::Directional => {
let mut directional = DirectionalLight::default();
directional.color = color;
directional.intensity = intensity;
Light::Directional(directional)
}
Kind::Point => {
let mut point = PointLight::default();
point.color = color;
point.intensity = intensity;
if let Some(r) = range {
point.radius = r;
}
Light::Point(point)
}
Kind::Spot {
inner_cone_angle,
outer_cone_angle,
} => {
let mut spot = SpotLight::default();
spot.angle = outer_cone_angle;
spot.color = color;
spot.intensity = intensity;
Light::Spot(spot)
}
}),
ambient_color: None,
}
}
}