use std::fmt;
use std::str::FromStr;
use super::error::{Error, Result};
use super::primitive::Color;
#[derive(Debug, Clone, Default)]
pub struct Texture2D {
pub id: u32,
pub path: String,
pub content_type: ContentType,
pub tile_style_u: TileStyle,
pub tile_style_v: TileStyle,
pub filter: Filter,
}
impl Texture2D {
pub fn new(id: u32, path: impl Into<String>, content_type: ContentType) -> Self {
Self {
id,
path: path.into(),
content_type,
tile_style_u: TileStyle::Wrap,
tile_style_v: TileStyle::Wrap,
filter: Filter::Auto,
}
}
pub fn set_tile_style_u(&mut self, tile_style: TileStyle) -> &mut Self {
self.tile_style_u = tile_style;
self
}
pub fn set_tile_style_v(&mut self, tile_style: TileStyle) -> &mut Self {
self.tile_style_v = tile_style;
self
}
pub fn set_content_type(&mut self, content_type: ContentType) -> &mut Self {
self.content_type = content_type;
self
}
pub fn set_filter(&mut self, filter: Filter) -> &mut Self {
self.filter = filter;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ContentType {
#[default]
ImageJpeg,
ImagePng,
}
impl fmt::Display for ContentType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ContentType::ImageJpeg => write!(f, "image/jpeg"),
ContentType::ImagePng => write!(f, "image/png"),
}
}
}
impl FromStr for ContentType {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"image/jpeg" => Ok(ContentType::ImageJpeg),
"image/png" => Ok(ContentType::ImagePng),
_ => Err(Error::InvalidAttribute {
name: "contenttype".to_string(),
message: format!("unknown content type: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TileStyle {
#[default]
Wrap,
Mirror,
Clamp,
None,
}
impl fmt::Display for TileStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TileStyle::Wrap => write!(f, "wrap"),
TileStyle::Mirror => write!(f, "mirror"),
TileStyle::Clamp => write!(f, "clamp"),
TileStyle::None => write!(f, "none"),
}
}
}
impl FromStr for TileStyle {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"wrap" => Ok(TileStyle::Wrap),
"mirror" => Ok(TileStyle::Mirror),
"clamp" => Ok(TileStyle::Clamp),
"none" => Ok(TileStyle::None),
_ => Err(Error::InvalidAttribute {
name: "tilestyleu/tilestylev".to_string(),
message: format!("unknown tile style: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Filter {
#[default]
Auto,
Linear,
Nearest,
}
impl fmt::Display for Filter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Filter::Auto => write!(f, "auto"),
Filter::Linear => write!(f, "linear"),
Filter::Nearest => write!(f, "nearest"),
}
}
}
impl FromStr for Filter {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"auto" => Ok(Filter::Auto),
"linear" => Ok(Filter::Linear),
"nearest" => Ok(Filter::Nearest),
_ => Err(Error::InvalidAttribute {
name: "filter".to_string(),
message: format!("unknown filter: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ColorGroup {
pub id: u32,
pub display_properties_id: Option<u32>,
pub colors: Vec<ColorType>,
}
impl ColorGroup {
pub fn new(id: u32) -> Self {
Self {
id,
display_properties_id: None,
colors: Vec::new(),
}
}
pub fn add_color(&mut self, color: Color) -> usize {
let index = self.colors.len();
self.colors.push(ColorType { color });
index
}
pub fn set_display_properties(&mut self, display_properties_id: u32) -> &mut Self {
self.display_properties_id = Some(display_properties_id);
self
}
}
#[derive(Debug, Clone, Default)]
pub struct ColorType {
pub color: Color,
}
impl ColorType {
pub fn new(color: Color) -> Self {
Self { color }
}
}
#[derive(Debug, Clone, Default)]
pub struct Texture2DGroup {
pub id: u32,
pub tex_id: u32,
pub display_properties_id: Option<u32>,
pub tex_2_coords: Vec<Tex2Coord>,
}
impl Texture2DGroup {
pub fn new(id: u32, texture_id: u32) -> Self {
Self {
id,
tex_id: texture_id,
display_properties_id: None,
tex_2_coords: Vec::new(),
}
}
pub fn add_tex2_coord(&mut self, u: f64, v: f64) -> usize {
let index = self.tex_2_coords.len();
self.tex_2_coords.push(Tex2Coord { u, v });
index
}
pub fn set_display_properties(&mut self, display_properties_id: u32) -> &mut Self {
self.display_properties_id = Some(display_properties_id);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Tex2Coord {
pub u: f64,
pub v: f64,
}
impl Tex2Coord {
pub fn new(u: f64, v: f64) -> Self {
Self { u, v }
}
}
#[derive(Debug, Clone, Default)]
pub struct CompositeMaterials {
pub id: u32,
pub mat_id: u32,
pub mat_indices: Vec<u32>,
pub display_properties_id: Option<u32>,
pub composites: Vec<Composite>,
}
impl CompositeMaterials {
pub fn new(id: u32, material_id: u32) -> Self {
Self {
id,
mat_id: material_id,
mat_indices: Vec::new(),
display_properties_id: None,
composites: Vec::new(),
}
}
pub fn add_composite(mut self, values: Vec<f64>) -> usize {
let index = self.composites.len();
self.composites.push(Composite { values });
index
}
pub fn set_material_indices(&mut self, indices: Vec<u32>) -> &mut Self {
self.mat_indices = indices;
self
}
pub fn set_display_properties(&mut self, display_properties_id: u32) -> &mut Self {
self.display_properties_id = Some(display_properties_id);
self
}
}
#[derive(Debug, Clone, Default)]
pub struct Composite {
pub values: Vec<f64>,
}
impl Composite {
pub fn new(values: Vec<f64>) -> Self {
Self { values }
}
}
#[derive(Debug, Clone, Default)]
pub struct MultiProperties {
pub id: u32,
pub p_ids: Vec<u32>,
pub blend_methods: Vec<BlendMethod>,
pub multis: Vec<Multi>,
}
impl MultiProperties {
pub fn new(id: u32, property_ids: Vec<u32>) -> Self {
Self {
id,
p_ids: property_ids,
blend_methods: Vec::new(),
multis: Vec::new(),
}
}
pub fn add_multi(mut self, property_indices: Vec<u32>) -> usize {
let index = self.multis.len();
self.multis.push(Multi { p_indices: property_indices });
index
}
pub fn set_blend_methods(&mut self, blend_methods: Vec<BlendMethod>) -> &mut Self {
self.blend_methods = blend_methods;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BlendMethod {
#[default]
Mix,
Multiply,
}
impl fmt::Display for BlendMethod {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BlendMethod::Mix => write!(f, "mix"),
BlendMethod::Multiply => write!(f, "multiply"),
}
}
}
impl FromStr for BlendMethod {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"mix" => Ok(BlendMethod::Mix),
"multiply" => Ok(BlendMethod::Multiply),
_ => Err(Error::InvalidAttribute {
name: "blendmethods".to_string(),
message: format!("unknown blend method: {}", s),
}),
}
}
}
pub struct BlendMethods(Vec<BlendMethod>);
impl FromStr for BlendMethods {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let mut methods = vec![];
for s in s.split_whitespace() {
methods.push(BlendMethod::from_str(s)?);
}
Ok(BlendMethods(methods))
}
}
impl fmt::Display for BlendMethods {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let methods: Vec<String> = self.0.iter()
.map(|m| m.to_string()).collect();
write!(f, "{}", methods.join(" "))
}
}
impl From<BlendMethods> for Vec<BlendMethod> {
fn from(blend_methods: BlendMethods) -> Self {
blend_methods.0
}
}
#[derive(Debug, Clone, Default)]
pub struct Multi {
pub p_indices: Vec<u32>,
}
impl Multi {
pub fn new(property_indices: Vec<u32>) -> Self {
Self { p_indices: property_indices }
}
}
#[derive(Debug, Clone, Default)]
pub struct PBSpecularDisplayProperties {
pub id: u32,
pub pb_speculars: Vec<PBSpecular>,
}
impl PBSpecularDisplayProperties {
pub fn new(id: u32) -> Self {
Self {
id,
pb_speculars: Vec::new(),
}
}
pub fn add_pbspecular(mut self, pbspecular: PBSpecular) -> usize {
let index = self.pb_speculars.len();
self.pb_speculars.push(pbspecular);
index
}
}
#[derive(Debug, Clone, Default)]
pub struct PBSpecular {
pub name: String,
pub specular_color: Color,
pub glossiness: f64,
}
impl PBSpecular {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
specular_color: Color::rgb(0x38, 0x38, 0x38),
glossiness: 0.0,
}
}
pub fn set_specular_color(&mut self, color: Color) -> &mut Self {
self.specular_color = color;
self
}
pub fn set_glossiness(&mut self, glossiness: f64) -> &mut Self {
self.glossiness = glossiness;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct PBMetallicDisplayProperties {
pub id: u32,
pub pb_metallics: Vec<PBMetallic>,
}
impl PBMetallicDisplayProperties {
pub fn new(id: u32) -> Self {
Self {
id,
pb_metallics: Vec::new(),
}
}
pub fn add_pbmetallic(mut self, pbmetallic: PBMetallic) -> usize {
let index = self.pb_metallics.len();
self.pb_metallics.push(pbmetallic);
index
}
}
#[derive(Debug, Clone, Default)]
pub struct PBMetallic {
pub name: String,
pub metallicness: f64,
pub roughness: f64,
}
impl PBMetallic {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
metallicness: 0.0,
roughness: 1.0,
}
}
pub fn set_metallicness(&mut self, metallicness: f64) -> &mut Self {
self.metallicness = metallicness;
self
}
pub fn set_roughness(&mut self, roughness: f64) -> &mut Self {
self.roughness = roughness;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct PBSpecularTextureDisplayProperties {
pub id: u32,
pub name: String,
pub specular_texture_id: u32,
pub glossiness_texture_id: u32,
pub diffuse_factor: Color,
pub specular_factor: Color,
pub glossiness_factor: f64,
}
impl PBSpecularTextureDisplayProperties {
pub fn new(id: u32, name: impl Into<String>, specular_texture_id: u32, glossiness_texture_id: u32) -> Self {
Self {
id,
name: name.into(),
specular_texture_id,
glossiness_texture_id,
diffuse_factor: Color::WHITE,
specular_factor: Color::WHITE,
glossiness_factor: 1.0,
}
}
pub fn set_diffuse_factor(&mut self, color: Color) -> &mut Self {
self.diffuse_factor = color;
self
}
pub fn set_specular_factor(&mut self, color: Color) -> &mut Self {
self.specular_factor = color;
self
}
pub fn set_glossiness_factor(&mut self, factor: f64) -> &mut Self {
self.glossiness_factor = factor;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct PBMetallicTextureDisplayProperties {
pub id: u32,
pub name: String,
pub metallic_texture_id: u32,
pub roughness_texture_id: u32,
pub base_color_factor: Color, pub metallic_factor: f64,
pub roughness_factor: f64,
}
impl PBMetallicTextureDisplayProperties {
pub fn new(id: u32, name: impl Into<String>, metallic_texture_id: u32, roughness_texture_id: u32) -> Self {
Self {
id,
name: name.into(),
metallic_texture_id,
roughness_texture_id,
base_color_factor: Color::WHITE,
metallic_factor: 1.0,
roughness_factor: 1.0,
}
}
pub fn set_metallic_factor(&mut self, factor: f64) -> &mut Self {
self.metallic_factor = factor;
self
}
pub fn set_roughness_factor(&mut self, factor: f64) -> &mut Self {
self.roughness_factor = factor;
self
}
pub fn set_base_color_factor(&mut self, color: Color) -> &mut Self {
self.base_color_factor = color;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct TranslucentDisplayProperties {
pub id: u32,
pub translucents: Vec<Translucent>,
}
impl TranslucentDisplayProperties {
pub fn new(id: u32) -> Self {
Self {
id,
translucents: Vec::new(),
}
}
pub fn add_translucent(mut self, translucent: Translucent) -> usize {
let index = self.translucents.len();
self.translucents.push(translucent);
index
}
}
#[derive(Debug, Clone, Default)]
pub struct Translucent {
pub name: String,
pub attenuation: [f64; 3],
pub refractive_index: [f64; 3],
pub roughness: f64,
}
impl Translucent {
pub fn new(name: impl Into<String>, attenuation: [f64; 3]) -> Self {
Self {
name: name.into(),
attenuation,
refractive_index: [1.0, 1.0, 1.0],
roughness: 0.0,
}
}
pub fn set_refractive_index(&mut self, refractive_index: [f64; 3]) -> &mut Self {
self.refractive_index = refractive_index;
self
}
pub fn set_roughness(&mut self, roughness: f64) -> &mut Self {
self.roughness = roughness;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct MaterialResources {
pub texture_2ds: Vec<Texture2D>,
pub color_groups: Vec<ColorGroup>,
pub texture_2d_groups: Vec<Texture2DGroup>,
pub composite_materials: Vec<CompositeMaterials>,
pub multi_properties: Vec<MultiProperties>,
pub pb_specular_display_properties: Vec<PBSpecularDisplayProperties>,
pub pb_metallic_display_properties: Vec<PBMetallicDisplayProperties>,
pub pb_specular_texture_display_properties: Vec<PBSpecularTextureDisplayProperties>,
pub pb_metallic_texture_display_properties: Vec<PBMetallicTextureDisplayProperties>,
pub translucent_display_properties: Vec<TranslucentDisplayProperties>,
}
impl MaterialResources {
pub fn new() -> Self {
Self::default()
}
pub fn add_texture_2d(&mut self, texture: Texture2D) {
self.texture_2ds.push(texture);
}
pub fn add_color_group(&mut self, color_group: ColorGroup) {
self.color_groups.push(color_group);
}
pub fn add_texture_2d_group(&mut self, texture_group: Texture2DGroup) {
self.texture_2d_groups.push(texture_group);
}
pub fn add_composite_materials(&mut self, composite: CompositeMaterials) {
self.composite_materials.push(composite);
}
pub fn add_multi_properties(&mut self, multi_props: MultiProperties) {
self.multi_properties.push(multi_props);
}
pub fn add_pb_specular_display_properties(&mut self, props: PBSpecularDisplayProperties) {
self.pb_specular_display_properties.push(props);
}
pub fn add_pb_metallic_display_properties(&mut self, props: PBMetallicDisplayProperties) {
self.pb_metallic_display_properties.push(props);
}
pub fn add_pb_specular_texture_display_properties(&mut self, props: PBSpecularTextureDisplayProperties) {
self.pb_specular_texture_display_properties.push(props);
}
pub fn add_pb_metallic_texture_display_properties(&mut self, props: PBMetallicTextureDisplayProperties) {
self.pb_metallic_texture_display_properties.push(props);
}
pub fn add_translucent_display_properties(&mut self, props: TranslucentDisplayProperties) {
self.translucent_display_properties.push(props);
}
}