use crate::{
core::{
inspect::{Inspect, PropertyInfo},
pool::Handle,
visitor::{Visit, VisitResult, Visitor},
},
resource::texture::Texture,
scene::{
graph::Graph,
light::{BaseLight, BaseLightBuilder, Light},
node::Node,
},
};
use std::ops::{Deref, DerefMut};
#[derive(Debug, Inspect)]
pub struct SpotLight {
base_light: BaseLight,
#[inspect(min_value = 0.0, max_value = 3.14159, step = 0.1)]
hotspot_cone_angle: f32,
#[inspect(min_value = 0.0, step = 0.1)]
falloff_angle_delta: f32,
#[inspect(min_value = 0.0, step = 0.001)]
shadow_bias: f32,
#[inspect(min_value = 0.0, step = 0.1)]
distance: f32,
cookie_texture: Option<Texture>,
}
impl Deref for SpotLight {
type Target = BaseLight;
fn deref(&self) -> &Self::Target {
&self.base_light
}
}
impl DerefMut for SpotLight {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.base_light
}
}
impl Default for SpotLight {
fn default() -> Self {
Self {
base_light: Default::default(),
hotspot_cone_angle: 90.0f32.to_radians(),
falloff_angle_delta: 5.0f32.to_radians(),
shadow_bias: 0.00005,
distance: 10.0,
cookie_texture: None,
}
}
}
impl SpotLight {
#[inline]
pub fn hotspot_cone_angle(&self) -> f32 {
self.hotspot_cone_angle
}
#[inline]
pub fn set_hotspot_cone_angle(&mut self, cone_angle: f32) -> &mut Self {
self.hotspot_cone_angle = cone_angle.abs();
self
}
#[inline]
pub fn set_falloff_angle_delta(&mut self, delta: f32) -> &mut Self {
self.falloff_angle_delta = delta;
self
}
#[inline]
pub fn falloff_angle_delta(&self) -> f32 {
self.falloff_angle_delta
}
#[inline]
pub fn full_cone_angle(&self) -> f32 {
self.hotspot_cone_angle + self.falloff_angle_delta
}
pub fn set_shadow_bias(&mut self, bias: f32) {
self.shadow_bias = bias;
}
pub fn shadow_bias(&self) -> f32 {
self.shadow_bias
}
#[inline]
pub fn set_distance(&mut self, distance: f32) -> &mut Self {
self.distance = distance.abs();
self
}
#[inline]
pub fn distance(&self) -> f32 {
self.distance
}
#[inline]
pub fn set_cookie_texture(&mut self, texture: Option<Texture>) -> &mut Self {
self.cookie_texture = texture;
self
}
#[inline]
pub fn cookie_texture(&self) -> Option<Texture> {
self.cookie_texture.clone()
}
#[inline]
pub fn cookie_texture_ref(&self) -> Option<&Texture> {
self.cookie_texture.as_ref()
}
pub fn raw_copy(&self) -> Self {
Self {
base_light: self.base_light.raw_copy(),
hotspot_cone_angle: self.hotspot_cone_angle,
falloff_angle_delta: self.falloff_angle_delta,
shadow_bias: self.shadow_bias,
distance: self.distance,
cookie_texture: self.cookie_texture.clone(),
}
}
}
impl Visit for SpotLight {
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
visitor.enter_region(name)?;
self.base_light.visit("BaseLight", visitor)?;
self.hotspot_cone_angle.visit("HotspotConeAngle", visitor)?;
self.falloff_angle_delta
.visit("FalloffAngleDelta", visitor)?;
self.distance.visit("Distance", visitor)?;
self.shadow_bias.visit("ShadowBias", visitor)?;
self.cookie_texture.visit("CookieTexture", visitor)?;
visitor.leave_region()
}
}
pub struct SpotLightBuilder {
base_light_builder: BaseLightBuilder,
hotspot_cone_angle: f32,
falloff_angle_delta: f32,
shadow_bias: f32,
distance: f32,
cookie_texture: Option<Texture>,
}
impl SpotLightBuilder {
pub fn new(base_light_builder: BaseLightBuilder) -> Self {
Self {
base_light_builder,
hotspot_cone_angle: 90.0f32.to_radians(),
falloff_angle_delta: 5.0f32.to_radians(),
shadow_bias: 0.00005,
distance: 10.0,
cookie_texture: None,
}
}
pub fn with_hotspot_cone_angle(mut self, hotspot_cone_angle: f32) -> Self {
self.hotspot_cone_angle = hotspot_cone_angle;
self
}
pub fn with_falloff_angle_delta(mut self, falloff_angle_delta: f32) -> Self {
self.falloff_angle_delta = falloff_angle_delta;
self
}
pub fn with_distance(mut self, distance: f32) -> Self {
self.distance = distance;
self
}
pub fn with_shadow_bias(mut self, bias: f32) -> Self {
self.shadow_bias = bias;
self
}
pub fn with_cookie_texture(mut self, texture: Texture) -> Self {
self.cookie_texture = Some(texture);
self
}
pub fn build_spot_light(self) -> SpotLight {
SpotLight {
base_light: self.base_light_builder.build(),
hotspot_cone_angle: self.hotspot_cone_angle,
falloff_angle_delta: self.falloff_angle_delta,
shadow_bias: self.shadow_bias,
distance: self.distance,
cookie_texture: self.cookie_texture,
}
}
pub fn build_node(self) -> Node {
Node::Light(Light::Spot(self.build_spot_light()))
}
pub fn build(self, graph: &mut Graph) -> Handle<Node> {
graph.add_node(self.build_node())
}
}