use super::{Entity, EntityCommon};
use crate::types::{BoundingBox3D, Color, Transform, Vector3};
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LightPhotometricData {
pub has_web_file: bool,
pub web_file: String,
pub physical_intensity_method: i16,
pub physical_intensity: f64,
pub illuminance_distance: f64,
pub lamp_color_type: i16,
pub lamp_color_temperature: f64,
pub lamp_color_preset: i16,
pub web_rotation: Vector3,
pub extended_light_shape: i16,
pub extended_light_length: f64,
pub extended_light_width: f64,
pub extended_light_radius: f64,
pub web_file_type: i16,
pub web_symmetry: i16,
pub has_target_grip: i16,
pub web_flux: f64,
pub web_angles: [f64; 5],
pub glyph_display_type: i16,
}
impl Default for LightPhotometricData {
fn default() -> Self {
Self {
has_web_file: false,
web_file: String::new(),
physical_intensity_method: 0,
physical_intensity: 0.0,
illuminance_distance: 0.0,
lamp_color_type: 0,
lamp_color_temperature: 0.0,
lamp_color_preset: 0,
web_rotation: Vector3::new(1.0, 1.0, 1.0),
extended_light_shape: 0,
extended_light_length: 0.0,
extended_light_width: 0.0,
extended_light_radius: 0.0,
web_file_type: 0,
web_symmetry: 0,
has_target_grip: 0,
web_flux: 0.0,
web_angles: [0.0; 5],
glyph_display_type: 0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Light {
pub common: EntityCommon,
pub name: String,
pub class_version: i32,
pub light_type: i32,
pub position: Vector3,
pub target: Vector3,
pub status: bool,
pub light_color: Color,
pub plot_glyph: bool,
pub intensity: f64,
pub attenuation_type: i32,
pub use_attenuation_limits: bool,
pub attenuation_start_limit: f64,
pub attenuation_end_limit: f64,
pub hotspot_angle: f64,
pub falloff_angle: f64,
pub cast_shadows: bool,
pub shadow_type: i32,
pub shadow_map_size: i16,
pub shadow_map_softness: u8,
pub photometric_mode: bool,
pub photometric_data: Option<LightPhotometricData>,
}
impl Light {
pub fn new() -> Self {
Light {
common: EntityCommon::new(),
name: String::new(),
class_version: 1,
light_type: 2,
position: Vector3::ZERO,
target: Vector3::ZERO,
status: true,
light_color: Color::WHITE,
plot_glyph: false,
intensity: 1.0,
attenuation_type: 0,
use_attenuation_limits: false,
attenuation_start_limit: 0.0,
attenuation_end_limit: 0.0,
hotspot_angle: 0.0,
falloff_angle: 0.0,
cast_shadows: false,
shadow_type: 0,
shadow_map_size: 0,
shadow_map_softness: 0,
photometric_mode: false,
photometric_data: None,
}
}
pub fn is_spot(&self) -> bool {
self.light_type == 3
}
pub fn is_distant(&self) -> bool {
self.light_type == 1
}
}
impl Default for Light {
fn default() -> Self {
Self::new()
}
}
impl Entity for Light {
fn common(&self) -> &super::EntityCommon {
&self.common
}
fn common_mut(&mut self) -> &mut super::EntityCommon {
&mut self.common
}
fn bounding_box(&self) -> BoundingBox3D {
BoundingBox3D::from_point(self.position)
}
fn translate(&mut self, offset: Vector3) {
self.position = Vector3::new(
self.position.x + offset.x,
self.position.y + offset.y,
self.position.z + offset.z,
);
self.target = Vector3::new(
self.target.x + offset.x,
self.target.y + offset.y,
self.target.z + offset.z,
);
}
fn entity_type(&self) -> &'static str {
"LIGHT"
}
fn apply_transform(&mut self, transform: &Transform) {
self.common.raw_record = None;
self.position = transform.apply(self.position);
self.target = transform.apply(self.target);
if let Some(data) = &mut self.photometric_data {
data.web_rotation = transform.apply_rotation(data.web_rotation);
}
}
}