use crate::*;
#[derive(Clone, Debug)]
pub struct NewParam {
pub sid: String,
pub annotate: Vec<Annotate>,
pub semantic: Option<String>,
pub modifier: Option<Modifier>,
pub ty: ParamType,
}
impl NewParam {
pub fn new(sid: impl Into<String>, ty: impl Into<ParamType>) -> Self {
Self {
sid: sid.into(),
annotate: vec![],
semantic: None,
modifier: None,
ty: ty.into(),
}
}
}
impl XNode for NewParam {
const NAME: &'static str = "newparam";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
let res = NewParam {
sid: element.attr("sid").ok_or("expecting sid attr")?.into(),
annotate: Annotate::parse_list(&mut it)?,
semantic: parse_opt("semantic", &mut it, parse_text)?,
modifier: parse_opt("modifier", &mut it, parse_elem)?,
ty: parse_one_many(&mut it, ParamType::parse)?,
};
finish(res, it)
}
}
impl XNodeWrite for NewParam {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.attr("sid", &self.sid);
let e = e.start(w)?;
self.annotate.write_to(w)?;
opt(&self.semantic, |e| ElemBuilder::print_str("semantic", e, w))?;
ElemBuilder::opt_print("modifier", &self.modifier, w)?;
self.ty.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct EffectSetParam {
pub ref_: String,
pub value: AnnotType,
}
impl EffectSetParam {
pub fn new(ref_: impl Into<String>, value: impl Into<AnnotType>) -> Self {
Self {
ref_: ref_.into(),
value: value.into(),
}
}
}
impl XNode for EffectSetParam {
const NAME: &'static str = "setparam";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
let res = EffectSetParam {
ref_: element.attr("ref").ok_or("expected ref attr")?.into(),
value: parse_one_many(&mut it, AnnotType::parse)?,
};
finish(res, it)
}
}
impl XNodeWrite for EffectSetParam {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.attr("ref", &self.ref_);
let e = e.start(w)?;
self.value.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct Annotate {
pub name: String,
pub value: AnnotType,
}
impl Annotate {
pub fn new(name: impl Into<String>, value: impl Into<AnnotType>) -> Self {
Self {
name: name.into(),
value: value.into(),
}
}
}
impl XNode for Annotate {
const NAME: &'static str = "annotate";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
let res = Annotate {
name: element.attr("name").ok_or("expecting name attr")?.into(),
value: parse_one_many(&mut it, AnnotType::parse)?,
};
finish(res, it)
}
}
impl XNodeWrite for Annotate {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.attr("name", &self.name);
let e = e.start(w)?;
self.value.write_to(w)?;
e.end(w)
}
}
mk_extensible_enum! {
pub enum Modifier {
Const = "CONST",
Uniform = "UNIFORM",
Varying = "VARYING",
Static = "STATIC",
Volatile = "VOLATILE",
Extern = "EXTERN",
Shared = "SHARED",
}
}
#[derive(Clone, Debug)]
pub enum AnnotType {
Bool(bool),
Bool2([bool; 2]),
Bool3([bool; 3]),
Bool4([bool; 4]),
Int(u32),
Int2([u32; 2]),
Int3(Box<[u32; 3]>),
Int4(Box<[u32; 4]>),
Float(f32),
Float2([f32; 2]),
Float3(Box<[f32; 3]>),
Float4(Box<[f32; 4]>),
Float2x2(Box<[f32; 2 * 2]>),
Float3x3(Box<[f32; 3 * 3]>),
Float4x4(Box<[f32; 4 * 4]>),
String(Box<str>),
}
impl From<&str> for AnnotType {
fn from(v: &str) -> Self {
Self::String(v.into())
}
}
impl From<Box<str>> for AnnotType {
fn from(v: Box<str>) -> Self {
Self::String(v)
}
}
impl From<bool> for AnnotType {
fn from(v: bool) -> Self {
Self::Bool(v)
}
}
impl From<f32> for AnnotType {
fn from(v: f32) -> Self {
Self::Float(v)
}
}
impl From<u32> for AnnotType {
fn from(v: u32) -> Self {
Self::Int(v)
}
}
impl AnnotType {
pub fn parse(e: &Element) -> Result<Option<Self>> {
Ok(Some(match e.name() {
"bool" => Self::Bool(parse_elem(e)?),
"bool2" => Self::Bool2(*parse_array_n(e)?),
"bool3" => Self::Bool3(*parse_array_n(e)?),
"bool4" => Self::Bool4(*parse_array_n(e)?),
"int" => Self::Int(parse_elem(e)?),
"int2" => Self::Int2(*parse_array_n(e)?),
"int3" => Self::Int3(parse_array_n(e)?),
"int4" => Self::Int4(parse_array_n(e)?),
"float" => Self::Float(parse_elem(e)?),
"float2" => Self::Float2(*parse_array_n(e)?),
"float3" => Self::Float3(parse_array_n(e)?),
"float4" => Self::Float4(parse_array_n(e)?),
"float2x2" => Self::Float2x2(parse_array_n(e)?),
"float3x3" => Self::Float3x3(parse_array_n(e)?),
"float4x4" => Self::Float4x4(parse_array_n(e)?),
"string" => Self::String(parse_text(e)?.into()),
_ => return Ok(None),
}))
}
}
impl XNodeWrite for AnnotType {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
match self {
AnnotType::Bool(e) => ElemBuilder::print("bool", e, w),
AnnotType::Bool2(e) => ElemBuilder::print_arr("bool2", e, w),
AnnotType::Bool3(e) => ElemBuilder::print_arr("bool3", e, w),
AnnotType::Bool4(e) => ElemBuilder::print_arr("bool4", e, w),
AnnotType::Int(e) => ElemBuilder::print("int", e, w),
AnnotType::Int2(e) => ElemBuilder::print_arr("int2", e, w),
AnnotType::Int3(e) => ElemBuilder::print_arr("int3", &**e, w),
AnnotType::Int4(e) => ElemBuilder::print_arr("int4", &**e, w),
AnnotType::Float(e) => ElemBuilder::print("float", e, w),
AnnotType::Float2(e) => ElemBuilder::print_arr("float2", e, w),
AnnotType::Float3(e) => ElemBuilder::print_arr("float3", &**e, w),
AnnotType::Float4(e) => ElemBuilder::print_arr("float4", &**e, w),
AnnotType::Float2x2(e) => ElemBuilder::print_arr("float2x2", &**e, w),
AnnotType::Float3x3(e) => ElemBuilder::print_arr("float3x3", &**e, w),
AnnotType::Float4x4(e) => ElemBuilder::print_arr("float4x4", &**e, w),
AnnotType::String(e) => ElemBuilder::print_str("string", e, w),
}
}
}
#[derive(Clone, Debug)]
pub enum ParamType {
Float(f32),
Float2([f32; 2]),
Float3(Box<[f32; 3]>),
Float4(Box<[f32; 4]>),
Surface(Box<Surface>),
Sampler2D(Box<Sampler2D>),
Other(Box<Element>),
}
impl From<f32> for ParamType {
fn from(v: f32) -> Self {
Self::Float(v)
}
}
impl ParamType {
pub fn parse(e: &Element) -> Result<Option<Self>> {
Ok(Some(match e.name() {
"float" => Self::Float(parse_elem(e)?),
"float2" => Self::Float2(*parse_array_n(e)?),
"float3" => Self::Float3(parse_array_n(e)?),
"float4" => Self::Float4(parse_array_n(e)?),
Surface::NAME => Self::Surface(Surface::parse_box(e)?),
Sampler2D::NAME => Self::Sampler2D(Sampler2D::parse_box(e)?),
_ => Self::Other(Box::new(e.clone())),
}))
}
pub fn as_surface(&self) -> Option<&Surface> {
match self {
ParamType::Surface(s) => Some(s),
_ => None,
}
}
pub fn as_sampler2d(&self) -> Option<&Sampler2D> {
match self {
ParamType::Sampler2D(s) => Some(s),
_ => None,
}
}
}
impl XNodeWrite for ParamType {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
match self {
ParamType::Float(e) => ElemBuilder::print("float", e, w),
ParamType::Float2(e) => ElemBuilder::print_arr("float2", e, w),
ParamType::Float3(e) => ElemBuilder::print_arr("float3", &**e, w),
ParamType::Float4(e) => ElemBuilder::print_arr("float4", &**e, w),
ParamType::Surface(e) => e.write_to(w),
ParamType::Sampler2D(e) => e.write_to(w),
ParamType::Other(e) => XNodeWrite::write_to(e, w),
}
}
}