use std::mem::{self, Discriminant};
use rin_math::{Vec2, vec2, Vec4, vec4};
use rin_util::{Result, Error};
use rinecs::{Component, OneToNComponent};
use serde_derive::{Serialize, Deserialize};
#[derive(Component, Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum Type{
PCSS,
Poisson{
soft_scatter: f32
},
Gaussian3,
Gaussian5,
Gaussian7,
Hard,
}
impl Type{
pub fn to_str(&self) -> &'static str{
match self{
Type::PCSS => "SHADOW_MAP_PCSS",
Type::Poisson{..} => "SHADOW_MAP_POISON_DISK",
Type::Gaussian3 | Type::Gaussian5 | Type::Gaussian7 => "SHADOW_MAP_GAUSSIAN",
Type::Hard => "SHADOW_MAP_HARD",
}
}
pub fn discriminant_to_str(ty: Discriminant<Type>) -> &'static str{
if ty == mem::discriminant(&Type::PCSS) { "SHADOW_MAP_PCSS" }
else if ty == mem::discriminant(&Type::Poisson{soft_scatter: 0.}) { "SHADOW_MAP_POISON_DISK" }
else if ty == mem::discriminant(&Type::Gaussian3)
|| ty == mem::discriminant(&Type::Gaussian5)
|| ty == mem::discriminant(&Type::Gaussian7) { "SHADOW_MAP_GAUSSIAN" }
else if ty == mem::discriminant(&Type::Hard) { "SHADOW_MAP_HARD" }
else { unreachable!() }
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum Resolution{
_16,
_24,
_32,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Parameters{
pub map_size: u16,
pub resolution: Resolution,
pub left: f32,
pub right: f32,
pub bottom: f32,
pub top: f32,
pub near_clip: f32,
pub far_clip: f32,
pub bias: f32,
pub depth_clamp: bool,
}
impl Parameters{
pub fn frustum_size(&self) -> Vec2{
vec2(self.right - self.left, self.top - self.bottom)
}
}
#[derive(OneToNComponent, Debug, Copy, Clone, Serialize, Deserialize)]
#[autochanges]
pub struct Map{
parameters: Parameters,
next_parameters: Option<Parameters>,
update_frequency: usize,
last_updated: usize,
changed: bool,
}
impl Map{
pub fn new(parameters: Parameters) -> Map {
Map{
parameters,
next_parameters: None,
update_frequency: 1,
last_updated: 0,
changed: true,
}
}
pub fn new_with_update_frequency(parameters: Parameters, update_frequency: usize) -> Map {
Map{
parameters,
next_parameters: None,
update_frequency,
last_updated: 0,
changed: true,
}
}
pub fn parameters(&self) -> &Parameters{
&self.parameters
}
pub fn set_parameters(&mut self, params: Parameters){
if self.update_frequency == 1{
self.changed = true;
self.parameters = params;
}else{
self.next_parameters = Some(params)
}
}
pub fn update_frequency(&self) -> usize{
self.update_frequency
}
pub fn set_update_frequency(&mut self, update_frequency: usize){
self.changed = true;
self.update_frequency = update_frequency;
}
pub fn update(&mut self){
if self.update_frequency == 0{
return;
}
if self.last_updated == 0 {
self.last_updated = self.update_frequency;
if let Some(next_parameters) = self.next_parameters.take(){
self.parameters = next_parameters;
self.changed = true;
}
}
self.last_updated -= 1;
}
pub fn needs_update(&self) -> bool{
self.update_frequency != 0 && self.last_updated == self.update_frequency - 1
}
}
impl rinecs::Changes for Map{
fn has_changed(&self) -> bool{
self.changed
}
fn reset_changed(&mut self){
self.changed = false;
}
}
impl std::ops::Deref for Map{
type Target = Parameters;
fn deref(&self) -> &Parameters{
self.parameters()
}
}
impl std::ops::DerefMut for Map{
fn deref_mut(&mut self) -> &mut Parameters{
if self.update_frequency == 1 {
&mut self.parameters
}else{
if self.next_parameters.is_none(){
self.next_parameters = Some(self.parameters.clone())
}
self.next_parameters.as_mut().unwrap()
}
}
}
#[derive(OneToNComponent, Debug, Copy, Clone, Serialize, Deserialize)]
#[autochanges]
pub struct StaticMap{
parameters: Parameters,
changed: bool,
}
impl StaticMap{
pub fn new(parameters: Parameters) -> StaticMap {
StaticMap{
parameters,
changed: true,
}
}
pub fn parameters(&self) -> &Parameters{
&self.parameters
}
pub fn set_parameters(&mut self, params: Parameters){
self.changed = true;
self.parameters = params;
}
}
impl rinecs::Changes for StaticMap{
fn has_changed(&self) -> bool{
self.changed
}
fn reset_changed(&mut self){
self.changed = false;
}
}
impl std::ops::Deref for StaticMap{
type Target = Parameters;
fn deref(&self) -> &Parameters{
&self.parameters
}
}
impl std::ops::DerefMut for StaticMap{
fn deref_mut(&mut self) -> &mut Parameters{
&mut self.parameters
}
}
#[derive(Component, Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Cascades{
starts: Vec4,
ends: Vec4,
debug: bool,
}
impl Cascades{
pub fn new(cascades: Vec<(f32,f32)>) -> Result<Cascades>{
if cascades.len() <= 4 {
let far = cascades.last().map(|(_,e)| *e).unwrap_or(0.);
Ok(Cascades{
starts: vec4(
cascades.get(0).map(|(s,_)| *s).unwrap_or(far),
cascades.get(1).map(|(s,_)| *s).unwrap_or(far),
cascades.get(2).map(|(s,_)| *s).unwrap_or(far),
cascades.get(3).map(|(s,_)| *s).unwrap_or(far),
),
ends: vec4(
cascades.get(0).map(|(_,e)| *e).unwrap_or(far),
cascades.get(1).map(|(_,e)| *e).unwrap_or(far),
cascades.get(2).map(|(_,e)| *e).unwrap_or(far),
cascades.get(3).map(|(_,e)| *e).unwrap_or(far),
),
debug: false,
})
}else{
Err(Error::new("Only a maximum of 4 shadow cascades allowed"))
}
}
pub fn starts(&self) -> Vec4{
self.starts
}
pub fn ends(&self) -> Vec4{
self.ends
}
pub fn enable_debug(&mut self){
self.debug = true;
}
pub fn disable_debug(&mut self){
self.debug = true;
}
pub fn debug_enabled(&self) -> bool{
self.debug
}
}
#[derive(Component, Debug, Copy, Clone, Serialize, Deserialize)]
pub struct StaticCascades{
starts: Vec4,
ends: Vec4,
debug: bool,
}
impl StaticCascades{
pub fn new(cascades: Vec<(f32,f32)>) -> Result<StaticCascades>{
if cascades.len() <= 4 {
let far = cascades.last().map(|(_,e)| *e).unwrap_or(0.);
Ok(StaticCascades{
starts: vec4(
cascades.get(0).map(|(s,_)| *s).unwrap_or(far),
cascades.get(1).map(|(s,_)| *s).unwrap_or(far),
cascades.get(2).map(|(s,_)| *s).unwrap_or(far),
cascades.get(3).map(|(s,_)| *s).unwrap_or(far),
),
ends: vec4(
cascades.get(0).map(|(_,e)| *e).unwrap_or(far),
cascades.get(1).map(|(_,e)| *e).unwrap_or(far),
cascades.get(2).map(|(_,e)| *e).unwrap_or(far),
cascades.get(3).map(|(_,e)| *e).unwrap_or(far),
),
debug: false,
})
}else{
Err(Error::new("Only a maximum of 4 shadow cascades allowed"))
}
}
pub fn starts(&self) -> Vec4{
self.starts
}
pub fn ends(&self) -> Vec4{
self.ends
}
pub fn enable_debug(&mut self){
self.debug = true;
}
pub fn disable_debug(&mut self){
self.debug = true;
}
pub fn debug_enabled(&self) -> bool{
self.debug
}
}