use crate::*;
#[derive(Clone, Debug)]
pub struct Material {
pub id: Option<String>,
pub name: Option<String>,
pub asset: Option<Box<Asset>>,
pub instance_effect: Instance<Effect>,
pub extra: Vec<Extra>,
}
impl Material {
pub fn new(id: impl Into<String>, name: impl Into<String>, instance_effect: Url) -> Self {
Self {
id: Some(id.into()),
name: Some(name.into()),
asset: None,
instance_effect: Instance::new(instance_effect),
extra: vec![],
}
}
}
impl XNode for Material {
const NAME: &'static str = "material";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
Ok(Material {
id: element.attr("id").map(Into::into),
name: element.attr("name").map(Into::into),
asset: Asset::parse_opt_box(&mut it)?,
instance_effect: Instance::parse_one(&mut it)?,
extra: Extra::parse_many(it)?,
})
}
}
impl XNodeWrite for Material {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("id", &self.id);
e.opt_attr("name", &self.name);
let e = e.start(w)?;
self.asset.write_to(w)?;
self.instance_effect.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct InstanceMaterial {
pub sid: Option<String>,
pub name: Option<String>,
pub symbol: String,
pub target: UrlRef<Material>,
pub bind: Vec<BindM>,
pub bind_vertex_input: Vec<BindVertexInput>,
pub extra: Vec<Extra>,
}
impl InstanceMaterial {
pub fn new(
symbol: impl Into<String>,
target: Url,
bind_vertex_input: Vec<BindVertexInput>,
) -> Self {
Self {
sid: None,
name: None,
symbol: symbol.into(),
target: Ref::new(target),
bind: vec![],
bind_vertex_input,
extra: vec![],
}
}
}
impl XNode for InstanceMaterial {
const NAME: &'static str = "instance_material";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let symbol = element.attr("symbol").ok_or("expecting symbol attr")?;
let mut it = element.children().peekable();
Ok(InstanceMaterial {
sid: element.attr("sid").map(Into::into),
name: element.attr("name").map(Into::into),
symbol: symbol.into(),
target: parse_attr(element.attr("target"))?.ok_or("missing target attribute")?,
bind: BindM::parse_list(&mut it)?,
bind_vertex_input: BindVertexInput::parse_list(&mut it)?,
extra: Extra::parse_many(it)?,
})
}
}
impl XNodeWrite for InstanceMaterial {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("sid", &self.sid);
e.opt_attr("name", &self.name);
e.attr("symbol", &self.symbol);
e.print_attr("target", &self.target);
let e = e.start(w)?;
self.bind.write_to(w)?;
self.bind_vertex_input.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct BindMaterial {
pub param: Vec<Param>,
pub instance_material: Vec<InstanceMaterial>,
pub technique: Vec<Technique>,
pub extra: Vec<Extra>,
}
impl BindMaterial {
pub fn new(instance_material: Vec<InstanceMaterial>) -> Self {
assert!(!instance_material.is_empty());
Self {
param: vec![],
instance_material,
technique: vec![],
extra: vec![],
}
}
}
impl XNode for BindMaterial {
const NAME: &'static str = "bind_material";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
Ok(BindMaterial {
param: Param::parse_list(&mut it)?,
instance_material: parse_one(Technique::COMMON, &mut it, |e| {
let mut it = e.children().peekable();
finish(InstanceMaterial::parse_list_n::<1>(&mut it)?, it)
})?,
technique: Technique::parse_list(&mut it)?,
extra: Extra::parse_many(it)?,
})
}
}
impl XNodeWrite for BindMaterial {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let e = Self::elem().start(w)?;
self.param.write_to(w)?;
let common = ElemBuilder::new(Technique::COMMON).start(w)?;
self.instance_material.write_to(w)?;
common.end(w)?;
self.technique.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct BindM {
pub semantic: Option<String>,
pub target: Address,
}
impl BindM {
pub fn new(semantic: impl Into<String>, target: impl Into<String>) -> Self {
Self {
semantic: Some(semantic.into()),
target: Address(target.into()),
}
}
}
impl XNode for BindM {
const NAME: &'static str = "bind";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let target = element.attr("target").ok_or("missing target attribute")?;
Ok(BindM {
semantic: element.attr("semantic").map(Into::into),
target: Address(target.into()),
})
}
}
impl XNodeWrite for BindM {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("semantic", &self.semantic);
e.print_attr("target", &self.target);
e.end(w)
}
}