use rin_math::{Deg, Rad, Vec2, Vec3, Vec4, Mat4, Mat3};
use super::texture::{TextureSampler, CubemapSampler};
use color::{Rgb, Rgba, color_space::{Srgb, LinearRgb}};
use rin_util::{Result, Error};
use std::ops::{Deref, DerefMut};
use std::cmp;
use std::hash::{Hash, Hasher};
use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess};
use std::marker::PhantomData;
use std::fmt;
#[derive(Debug, Default)]
pub struct Parameter<T>{
value: T,
prev_value: Option<T>,
}
impl<T: Clone> Clone for Parameter<T>{
fn clone(&self) -> Parameter<T>{
Parameter {
value: self.value.clone(),
prev_value: None
}
}
}
impl<T: Clone> Parameter<T>{
pub fn new(t: T) -> Parameter<T>{
Parameter{
value: t.clone(),
prev_value: None,
}
}
pub fn reset_changed(&mut self){
self.prev_value = Some(self.value.clone())
}
}
impl<T: PartialEq> Parameter<T>{
pub fn has_changed(&self) -> bool{
Some(&self.value) != self.prev_value.as_ref()
}
}
impl<T> Parameter<Option<T>>{
pub fn option_changed(&self) -> bool{
Some(self.value.is_some()) != self.prev_value.as_ref().map(|prev| prev.is_some())
}
}
impl<T> Parameter<T>{
pub fn get(&self) -> &T{
&self.value
}
pub fn get_mut(&mut self) -> &mut T{
&mut self.value
}
pub fn set(&mut self, t: T){
self.value = t
}
pub fn as_ref(&self) -> Parameter<&T>{
Parameter{
value: &self.value,
prev_value: self.prev_value.as_ref(),
}
}
pub fn map<U,F>(self, f: F) -> Parameter<U>
where F: Fn(T) -> U
{
Parameter{
value: f(self.value),
prev_value: self.prev_value.map(f)
}
}
}
impl<T: 'static> Parameter<T> {
pub fn as_any<'a>(&'a self, name: &'a str) -> ParameterAny<'a> {
ParameterAny {
name,
parameter: self as & dyn std::any::Any,
}
}
pub fn as_mut_any<'a>(&'a mut self, name: &'a str) -> ParameterMutAny<'a> {
ParameterMutAny {
name,
parameter: self as &mut dyn std::any::Any,
}
}
}
impl<T: IntoUniformValueRef> Parameter<T> {
pub fn as_uniform_ref<'a>(&'a self, name: &'static str) -> UniformRef<'a>{
UniformRef{
name,
value: self.value.into_uniform_value_ref(),
}
}
}
impl<T: std140_data::WriteStd140> std140_data::WriteStd140 for Parameter<T> {
fn write_std140(&self, data: &mut std140_data::Data) {
self.value.write_std140(data)
}
}
impl<'a, T: std140_data::WriteStd140> std140_data::WriteStd140 for &'a Parameter<T> {
fn write_std140(&self, data: &mut std140_data::Data) {
self.value.write_std140(data)
}
}
impl<T> Deref for Parameter<T>{
type Target = T;
fn deref(&self) -> &T{
&self.value
}
}
impl<T> DerefMut for Parameter<T>{
fn deref_mut(&mut self) -> &mut T{
&mut self.value
}
}
impl<T: PartialEq + Clone> From<T> for Parameter<T>{
fn from(t: T) -> Parameter<T>{
Parameter::new(t)
}
}
pub struct ParameterAny<'a>{
name: &'a str,
parameter: &'a dyn std::any::Any,
}
impl<'a> ParameterAny<'a>{
pub fn get<T: 'static>(&self) -> Option<&T>{
let parameter: Option<&Parameter<T>> = self.parameter.downcast_ref();
parameter.map(|p| p.get())
}
pub fn name(&self) -> &str {
self.name
}
}
pub struct ParameterMutAny<'a>{
name: &'a str,
parameter: &'a mut dyn std::any::Any,
}
impl<'a> ParameterMutAny<'a>{
pub fn get<T: 'static>(&self) -> Option<&T>{
let parameter: Option<&Parameter<T>> = self.parameter.downcast_ref();
parameter.map(|p| p.get())
}
pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T>{
let parameter: Option<&mut Parameter<T>> = self.parameter.downcast_mut();
parameter.map(|p| p.get_mut())
}
pub fn set<T: 'static>(&mut self, t: T) -> Result<()>{
if let Some(value) = self.get_mut() {
*value = t;
Ok(())
}else{
Err(Error::new("Wrong type"))
}
}
pub fn name(&self) -> &str {
self.name
}
}
pub struct UniformRef<'a> {
name: &'static str,
value: UniformValueRef<'a>,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum UniformValueRef<'a>{
Float(&'a f32),
I32(&'a i32),
U32(&'a u32),
Bool(&'a bool),
Vec2(&'a Vec2),
Vec3(&'a Vec3),
Vec4(&'a Vec4),
IVec2(&'a Vec2<i32>),
IVec3(&'a Vec3<i32>),
IVec4(&'a Vec4<i32>),
UVec2(&'a Vec2<u32>),
UVec3(&'a Vec3<u32>),
UVec4(&'a Vec4<u32>),
Rgb(&'a Rgb<f32, Srgb>),
Rgba(&'a Rgba<f32, Srgb>),
RgbLinear(&'a Rgb<f32, LinearRgb>),
RgbaLinear(&'a Rgba<f32, LinearRgb>),
Texture(&'a TextureSampler),
Cubemap(&'a CubemapSampler),
Rad(&'a Rad<f32>),
Deg(&'a Deg<f32>),
Mat4(&'a Mat4),
Mat3(&'a Mat3),
ArrayFloat(&'a Vec<f32>),
ArrayVec2(&'a Vec<Vec2>),
ArrayVec3(&'a Vec<Vec3>),
ArrayVec4(&'a Vec<Vec4>),
ArrayInt(&'a Vec<i32>),
ArrayIVec2(&'a Vec<Vec2<i32>>),
ArrayIVec3(&'a Vec<Vec3<i32>>),
ArrayIVec4(&'a Vec<Vec4<i32>>),
ArrayUInt(&'a Vec<u32>),
ArrayUVec2(&'a Vec<Vec2<u32>>),
ArrayUVec3(&'a Vec<Vec3<u32>>),
ArrayUVec4(&'a Vec<Vec4<u32>>),
OptionFloat(&'a Option<f32>),
OptionI32(&'a Option<i32>),
OptionU32(&'a Option<u32>),
OptionBool(&'a Option<bool>),
OptionVec2(&'a Option<Vec2>),
OptionVec3(&'a Option<Vec3>),
OptionVec4(&'a Option<Vec4>),
OptionIVec2(&'a Option<Vec2<i32>>),
OptionIVec3(&'a Option<Vec3<i32>>),
OptionIVec4(&'a Option<Vec4<i32>>),
OptionUVec2(&'a Option<Vec2<u32>>),
OptionUVec3(&'a Option<Vec3<u32>>),
OptionUVec4(&'a Option<Vec4<u32>>),
OptionRgb(&'a Option<Rgb<f32, Srgb>>),
OptionRgba(&'a Option<Rgba<f32, Srgb>>),
OptionRgbLinear(&'a Option<Rgb<f32, LinearRgb>>),
OptionRgbaLinear(&'a Option<Rgba<f32, LinearRgb>>),
OptionTexture(&'a Option<TextureSampler>),
OptionCubemap(&'a Option<CubemapSampler>),
OptionRad(&'a Option<Rad<f32>>),
OptionDeg(&'a Option<Deg<f32>>),
OptionMat4(&'a Option<Mat4>),
OptionMat3(&'a Option<Mat3>),
OptionArrayFloat(&'a Option<Vec<f32>>),
OptionArrayVec2(&'a Option<Vec<Vec2>>),
OptionArrayVec3(&'a Option<Vec<Vec3>>),
OptionArrayVec4(&'a Option<Vec<Vec4>>),
OptionArrayInt(&'a Option<Vec<i32>>),
OptionArrayIVec2(&'a Option<Vec<Vec2<i32>>>),
OptionArrayIVec3(&'a Option<Vec<Vec3<i32>>>),
OptionArrayIVec4(&'a Option<Vec<Vec4<i32>>>),
OptionArrayUInt(&'a Option<Vec<u32>>),
OptionArrayUVec2(&'a Option<Vec<Vec2<u32>>>),
OptionArrayUVec3(&'a Option<Vec<Vec3<u32>>>),
OptionArrayUVec4(&'a Option<Vec<Vec4<u32>>>),
}
impl<'a> UniformValueRef<'a>{
pub fn is_some(self) -> bool{
match self {
UniformValueRef::Float(_)
| UniformValueRef::I32(_)
| UniformValueRef::U32(_)
| UniformValueRef::Bool(_)
| UniformValueRef::Vec2(_)
| UniformValueRef::Vec3(_)
| UniformValueRef::Vec4(_)
| UniformValueRef::IVec2(_)
| UniformValueRef::IVec3(_)
| UniformValueRef::IVec4(_)
| UniformValueRef::UVec2(_)
| UniformValueRef::UVec3(_)
| UniformValueRef::UVec4(_)
| UniformValueRef::Rgb(_)
| UniformValueRef::Rgba(_)
| UniformValueRef::RgbLinear(_)
| UniformValueRef::RgbaLinear(_)
| UniformValueRef::Texture(_)
| UniformValueRef::Cubemap(_)
| UniformValueRef::Rad(_)
| UniformValueRef::Deg(_)
| UniformValueRef::Mat4(_)
| UniformValueRef::Mat3(_)
| UniformValueRef::ArrayFloat(_)
| UniformValueRef::ArrayVec2(_)
| UniformValueRef::ArrayVec3(_)
| UniformValueRef::ArrayVec4(_)
| UniformValueRef::ArrayInt(_)
| UniformValueRef::ArrayIVec2(_)
| UniformValueRef::ArrayIVec3(_)
| UniformValueRef::ArrayIVec4(_)
| UniformValueRef::ArrayUInt(_)
| UniformValueRef::ArrayUVec2(_)
| UniformValueRef::ArrayUVec3(_)
| UniformValueRef::ArrayUVec4(_) => true,
UniformValueRef::OptionFloat(opt) => opt.is_some(),
UniformValueRef::OptionI32(opt) => opt.is_some(),
UniformValueRef::OptionU32(opt) => opt.is_some(),
UniformValueRef::OptionBool(opt) => opt.is_some(),
UniformValueRef::OptionVec2(opt) => opt.is_some(),
UniformValueRef::OptionVec3(opt) => opt.is_some(),
UniformValueRef::OptionVec4(opt) => opt.is_some(),
UniformValueRef::OptionIVec2(opt) => opt.is_some(),
UniformValueRef::OptionIVec3(opt) => opt.is_some(),
UniformValueRef::OptionIVec4(opt) => opt.is_some(),
UniformValueRef::OptionUVec2(opt) => opt.is_some(),
UniformValueRef::OptionUVec3(opt) => opt.is_some(),
UniformValueRef::OptionUVec4(opt) => opt.is_some(),
UniformValueRef::OptionRgb(opt) => opt.is_some(),
UniformValueRef::OptionRgba(opt) => opt.is_some(),
UniformValueRef::OptionRgbLinear(opt) => opt.is_some(),
UniformValueRef::OptionRgbaLinear(opt) => opt.is_some(),
UniformValueRef::OptionTexture(opt) => opt.is_some(),
UniformValueRef::OptionCubemap(opt) => opt.is_some(),
UniformValueRef::OptionRad(opt) => opt.is_some(),
UniformValueRef::OptionDeg(opt) => opt.is_some(),
UniformValueRef::OptionMat4(opt) => opt.is_some(),
UniformValueRef::OptionMat3(opt) => opt.is_some(),
UniformValueRef::OptionArrayFloat(opt) => opt.is_some(),
UniformValueRef::OptionArrayVec2(opt) => opt.is_some(),
UniformValueRef::OptionArrayVec3(opt) => opt.is_some(),
UniformValueRef::OptionArrayVec4(opt) => opt.is_some(),
UniformValueRef::OptionArrayInt(opt) => opt.is_some(),
UniformValueRef::OptionArrayIVec2(opt) => opt.is_some(),
UniformValueRef::OptionArrayIVec3(opt) => opt.is_some(),
UniformValueRef::OptionArrayIVec4(opt) => opt.is_some(),
UniformValueRef::OptionArrayUInt(opt) => opt.is_some(),
UniformValueRef::OptionArrayUVec2(opt) => opt.is_some(),
UniformValueRef::OptionArrayUVec3(opt) => opt.is_some(),
UniformValueRef::OptionArrayUVec4(opt) => opt.is_some(),
}
}
pub fn float(&self) -> Option<f32>{
match self {
UniformValueRef::Float(f) => Some(**f),
UniformValueRef::OptionFloat(f) => **f,
_ => None,
}
}
pub fn int(&self) -> Option<i32>{
match self {
UniformValueRef::I32(f) => Some(**f),
UniformValueRef::OptionI32(f) => **f,
_ => None,
}
}
pub fn uint(&self) -> Option<u32>{
match self {
UniformValueRef::U32(f) => Some(**f),
UniformValueRef::OptionU32(f) => **f,
_ => None,
}
}
pub fn boolean(&self) -> Option<bool>{
match self {
UniformValueRef::Bool(f) => Some(**f),
UniformValueRef::OptionBool(f) => **f,
_ => None,
}
}
pub fn vec2(&self) -> Option<Vec2>{
match self {
UniformValueRef::Vec2(f) => Some(**f),
UniformValueRef::OptionVec2(f) => **f,
_ => None,
}
}
pub fn vec3(&self) -> Option<Vec3>{
match self {
UniformValueRef::Vec3(f) => Some(**f),
UniformValueRef::OptionVec3(f) => **f,
_ => None,
}
}
pub fn vec4(&self) -> Option<Vec4>{
match self {
UniformValueRef::Vec4(f) => Some(**f),
UniformValueRef::OptionVec4(f) => **f,
_ => None,
}
}
pub fn rgb(&self) -> Option<Rgb<f32>>{
match self {
UniformValueRef::Rgb(f) => Some(**f),
UniformValueRef::OptionRgb(f) => **f,
_ => None,
}
}
pub fn rgba(&self) -> Option<Rgba<f32>>{
match self {
UniformValueRef::Rgba(f) => Some(**f),
UniformValueRef::OptionRgba(f) => **f,
_ => None,
}
}
pub fn texture(&self) -> Option<TextureSampler>{
match self {
UniformValueRef::Texture(f) => Some(**f),
UniformValueRef::OptionTexture(f) => **f,
_ => None,
}
}
pub fn cubemap(&self) -> Option<CubemapSampler>{
match self {
UniformValueRef::Cubemap(f) => Some(**f),
UniformValueRef::OptionCubemap(f) => **f,
_ => None,
}
}
pub fn mat4(&self) -> Option<Mat4>{
match self {
UniformValueRef::Mat4(f) => Some(**f),
UniformValueRef::OptionMat4(f) => **f,
_ => None,
}
}
pub fn mat3(&self) -> Option<Mat3>{
match self {
UniformValueRef::Mat3(f) => Some(**f),
UniformValueRef::OptionMat3(f) => **f,
_ => None,
}
}
}
pub trait IntoUniformValueRef{
fn into_uniform_value_ref(&self) -> UniformValueRef;
}
macro_rules! into_uniform_value_ref {
($t: ty, $p: ident, $option: ident) => {
impl IntoUniformValueRef for $t{
fn into_uniform_value_ref(&self) -> UniformValueRef{
UniformValueRef::$p(self)
}
}
impl IntoUniformValueRef for Option<$t>{
fn into_uniform_value_ref(&self) -> UniformValueRef{
UniformValueRef::$option(self)
}
}
};
}
into_uniform_value_ref!(f32, Float, OptionFloat);
into_uniform_value_ref!(i32, I32, OptionI32);
into_uniform_value_ref!(u32, U32, OptionU32);
into_uniform_value_ref!(bool, Bool, OptionBool);
into_uniform_value_ref!(Vec2, Vec2, OptionVec2);
into_uniform_value_ref!(Vec3, Vec3, OptionVec3);
into_uniform_value_ref!(Vec4, Vec4, OptionVec4);
into_uniform_value_ref!(Vec2<i32>, IVec2, OptionIVec2);
into_uniform_value_ref!(Vec3<i32>, IVec3, OptionIVec3);
into_uniform_value_ref!(Vec4<i32>, IVec4, OptionIVec4);
into_uniform_value_ref!(Vec2<u32>, UVec2, OptionUVec2);
into_uniform_value_ref!(Vec3<u32>, UVec3, OptionUVec3);
into_uniform_value_ref!(Vec4<u32>, UVec4, OptionUVec4);
into_uniform_value_ref!(Rgb<f32, Srgb>, Rgb, OptionRgb);
into_uniform_value_ref!(Rgba<f32, Srgb>, Rgba, OptionRgba);
into_uniform_value_ref!(Rgb<f32, LinearRgb>, RgbLinear, OptionRgbLinear);
into_uniform_value_ref!(Rgba<f32, LinearRgb>, RgbaLinear, OptionRgbaLinear);
into_uniform_value_ref!(TextureSampler, Texture, OptionTexture);
into_uniform_value_ref!(CubemapSampler, Cubemap, OptionCubemap);
into_uniform_value_ref!(Rad<f32>, Rad, OptionRad);
into_uniform_value_ref!(Deg<f32>, Deg, OptionDeg);
into_uniform_value_ref!(Mat4, Mat4, OptionMat4);
into_uniform_value_ref!(Mat3, Mat3, OptionMat3);
into_uniform_value_ref!(Vec<f32>, ArrayFloat, OptionArrayFloat);
into_uniform_value_ref!(Vec<Vec2>, ArrayVec2, OptionArrayVec2);
into_uniform_value_ref!(Vec<Vec3>, ArrayVec3, OptionArrayVec3);
into_uniform_value_ref!(Vec<Vec4>, ArrayVec4, OptionArrayVec4);
into_uniform_value_ref!(Vec<i32>, ArrayInt, OptionArrayInt);
into_uniform_value_ref!(Vec<Vec2<i32>>, ArrayIVec2, OptionArrayIVec2);
into_uniform_value_ref!(Vec<Vec3<i32>>, ArrayIVec3, OptionArrayIVec3);
into_uniform_value_ref!(Vec<Vec4<i32>>, ArrayIVec4, OptionArrayIVec4);
into_uniform_value_ref!(Vec<u32>, ArrayUInt, OptionArrayUInt);
into_uniform_value_ref!(Vec<Vec2<u32>>, ArrayUVec2, OptionArrayUVec2);
into_uniform_value_ref!(Vec<Vec3<u32>>, ArrayUVec3, OptionArrayUVec3);
into_uniform_value_ref!(Vec<Vec4<u32>>, ArrayUVec4, OptionArrayUVec4);
impl<'a> UniformRef<'a>{
pub fn name(&self) -> &'static str{
self.name
}
pub fn value(&self) -> UniformValueRef<'a> {
self.value
}
pub fn is_some(&self) -> bool{
self.value.is_some()
}
pub fn float(&self) -> Option<f32>{
self.value.float()
}
pub fn int(&self) -> Option<i32>{
self.value.int()
}
pub fn uint(&self) -> Option<u32>{
self.value.uint()
}
pub fn boolean(&self) -> Option<bool>{
self.value.boolean()
}
pub fn vec2(&self) -> Option<Vec2>{
self.value.vec2()
}
pub fn vec3(&self) -> Option<Vec3>{
self.value.vec3()
}
pub fn vec4(&self) -> Option<Vec4>{
self.value.vec4()
}
pub fn rgb(&self) -> Option<Rgb<f32>>{
self.value.rgb()
}
pub fn rgba(&self) -> Option<Rgba<f32>>{
self.value.rgba()
}
pub fn texture(&self) -> Option<TextureSampler>{
self.value.texture()
}
pub fn cubemap(&self) -> Option<CubemapSampler>{
self.value.cubemap()
}
pub fn mat4(&self) -> Option<Mat4>{
self.value.mat4()
}
pub fn mat3(&self) -> Option<Mat3>{
self.value.mat3()
}
}
impl<T> PartialEq for Parameter<T> where T: PartialEq{
fn eq(&self, other: &Parameter<T>) -> bool {
self.value.eq(&other.value)
}
}
impl<T> Eq for Parameter<T> where T: Eq {}
impl<T> PartialOrd for Parameter<T> where T: PartialOrd{
fn partial_cmp(&self, other: &Parameter<T>) -> Option<cmp::Ordering>{
self.value.partial_cmp(&other.value)
}
}
impl<T> Ord for Parameter<T> where T: Ord {
fn cmp(&self, other: &Parameter<T>) -> cmp::Ordering{
self.value.cmp(&other.value)
}
}
impl<T> Hash for Parameter<T> where T: Hash {
fn hash<H: Hasher>(&self, state: &mut H){
self.value.hash(state)
}
}
impl<T> Serialize for Parameter<T> where T: Serialize{
fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>{
let mut param = serializer.serialize_struct("Parameter", 2)?;
param.serialize_field("value", &self.value)?;
param.serialize_field("prev_value", &self.prev_value)?;
param.end()
}
}
const FIELDS: &'static [&'static str] = &["value", "prev_value"];
impl<'de, T> Deserialize<'de> for Parameter<T> where T: Deserialize<'de>{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Parameter<T>, D::Error>{
deserializer.deserialize_struct(
"Parameter",
FIELDS,
ParamVisitor::<T>{
marker: PhantomData
})
}
}
struct ParamVisitor<T>{
marker: PhantomData<T>
}
enum Field { Value, PrevValue }
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> std::result::Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`value` or `prev_value`")
}
fn visit_str<E>(self, value: &str) -> std::result::Result<Field, E>
where
E: de::Error,
{
match value {
"value" => Ok(Field::Value),
"prev_value" => Ok(Field::PrevValue),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
impl<'de, T> Visitor<'de> for ParamVisitor<T>
where T: Deserialize<'de>
{
type Value = Parameter<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Parameter<T>")
}
fn visit_seq<V>(self, mut struc: V) -> std::result::Result<Parameter<T>, V::Error>
where V: SeqAccess<'de>
{
let value = struc.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let prev_value = struc.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(Parameter{ value, prev_value })
}
fn visit_map<V>(self, mut map: V) -> std::result::Result<Parameter<T>, V::Error>
where
V: MapAccess<'de>,
{
let mut value = None;
let mut prev_value = None;
while let Some(key) = map.next_key()? {
match key {
Field::Value => {
if value.is_some(){
return Err(de::Error::duplicate_field("value"));
}
value = Some(map.next_value()?);
}
Field::PrevValue => {
if prev_value.is_some(){
return Err(de::Error::duplicate_field("prev_value"));
}
prev_value = Some(map.next_value()?);
}
}
}
let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
let prev_value = prev_value.ok_or_else(|| de::Error::missing_field("prev_value"))?;
Ok(Parameter{value, prev_value})
}
}