use std::collections::BTreeMap;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::ids::{AppearanceId, BodyId, EdgeId, FaceId, VertexId};
use crate::scalar::{Angle, FiniteReal, Length};
use crate::topology::Color;
use cadmpeg_core::text::NonBlankString;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct Appearance {
pub id: AppearanceId,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_name"
)]
pub name: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_asset_guid"
)]
pub asset_guid: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_library_id"
)]
pub library_id: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_visual_guid"
)]
pub visual_guid: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_physical_token"
)]
pub physical_token: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_schema"
)]
pub schema: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_category"
)]
pub category: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_base_color"
)]
pub base_color: Option<Color>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
#[serde(deserialize_with = "cadmpeg_core::distinct_keys::btree_map")]
#[cfg_attr(feature = "schema", schemars(with = "BTreeMap<NonBlankString, f64>"))]
pub properties: BTreeMap<NonBlankString, FiniteReal>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub textures: Vec<TextureRef>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct TextureRef {
pub asset_guid: String,
pub slot: String,
pub schema: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub paths: Vec<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_urn"
)]
pub urn: Option<String>,
pub mapping: TextureMap2d,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_bump"
)]
pub bump: Option<BumpMap>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct TextureMap2d {
pub map_channel: u32,
pub uvw_source: u32,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub u_offset: FiniteReal,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub v_offset: FiniteReal,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub u_scale: FiniteReal,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub v_scale: FiniteReal,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub rotation: Angle,
pub repeat_u: bool,
pub repeat_v: bool,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub real_world_offset_x: Length,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub real_world_offset_y: Length,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub real_world_scale_x: Length,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub real_world_scale_y: Length,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct BumpMap {
pub normal_map: bool,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub depth: Length,
#[cfg_attr(feature = "schema", schemars(with = "f64"))]
pub normal_scale: FiniteReal,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(tag = "kind", content = "id", rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
pub enum AppearanceTarget {
Body(BodyId),
Face(FaceId),
Edge(EdgeId),
Vertex(VertexId),
Surface(crate::ids::SurfaceId),
Curve(crate::ids::CurveId),
Point(crate::ids::PointId),
Tessellation(String),
Source {
source_id: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct AppearanceBinding {
pub id: crate::ids::AppearanceBindingId,
pub target: AppearanceTarget,
pub appearance: AppearanceId,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_source_entity_id"
)]
pub source_entity_id: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_object_type"
)]
pub object_type: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_visible"
)]
pub visible: Option<bool>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
#[serde(deserialize_with = "cadmpeg_core::distinct_keys::btree_map")]
pub channels: BTreeMap<NonBlankString, String>,
}
#[cfg(test)]
mod tests;
cadmpeg_core::named_optional_field!(deserialize_name, String, "name");
cadmpeg_core::named_optional_field!(deserialize_asset_guid, String, "asset_guid");
cadmpeg_core::named_optional_field!(deserialize_library_id, String, "library_id");
cadmpeg_core::named_optional_field!(deserialize_visual_guid, String, "visual_guid");
cadmpeg_core::named_optional_field!(deserialize_physical_token, String, "physical_token");
cadmpeg_core::named_optional_field!(deserialize_schema, String, "schema");
cadmpeg_core::named_optional_field!(deserialize_category, String, "category");
cadmpeg_core::named_optional_field!(deserialize_base_color, Color, "base_color");
cadmpeg_core::named_optional_field!(deserialize_urn, String, "urn");
cadmpeg_core::named_optional_field!(deserialize_bump, BumpMap, "bump");
cadmpeg_core::named_optional_field!(deserialize_source_entity_id, String, "source_entity_id");
cadmpeg_core::named_optional_field!(deserialize_object_type, String, "object_type");
cadmpeg_core::named_optional_field!(deserialize_visible, bool, "visible");
mod identity_rewrite;