use bon::Builder;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::shared::{FileExportFormat, FileExportFormat2d, FileImportFormat};
pub mod dxf;
pub mod fbx;
pub mod gltf;
pub mod obj;
pub mod ply;
pub mod step;
pub mod stl;
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
#[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
pub enum OutputFormat2d {
Dxf(dxf::export::Options),
}
#[deprecated(since = "0.2.96", note = "use `OutputFormat3d` instead")]
pub type OutputFormat = OutputFormat3d;
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
#[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
pub enum OutputFormat3d {
Fbx(fbx::export::Options),
Gltf(gltf::export::Options),
Obj(obj::export::Options),
Ply(ply::export::Options),
Step(step::export::Options),
Stl(stl::export::Options),
}
#[deprecated(since = "0.2.96", note = "use `InputFormat3d` instead")]
pub type InputFormat = InputFormat3d;
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
#[cfg_attr(
feature = "python",
pyo3::pyclass,
pyo3_stub_gen::derive::gen_stub_pyclass_complex_enum
)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
#[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
pub enum InputFormat3d {
Acis(acis::import::Options),
Catia(catia::import::Options),
Creo(creo::import::Options),
Fbx(fbx::import::Options),
Gltf(gltf::import::Options),
Inventor(inventor::import::Options),
Nx(nx::import::Options),
Obj(obj::import::Options),
Parasolid(parasolid::import::Options),
Ply(ply::import::Options),
Sldprt(sldprt::import::Options),
Step(step::import::Options),
Stl(stl::import::Options),
}
impl InputFormat3d {
pub fn name(&self) -> &'static str {
match self {
InputFormat3d::Acis(_) => "acis",
InputFormat3d::Catia(_) => "catia",
InputFormat3d::Creo(_) => "creo",
InputFormat3d::Fbx(_) => "fbx",
InputFormat3d::Gltf(_) => "gltf",
InputFormat3d::Inventor(_) => "inventor",
InputFormat3d::Nx(_) => "nx",
InputFormat3d::Parasolid(_) => "parasolid",
InputFormat3d::Obj(_) => "obj",
InputFormat3d::Ply(_) => "ply",
InputFormat3d::Sldprt(_) => "sldprt",
InputFormat3d::Step(_) => "step",
InputFormat3d::Stl(_) => "stl",
}
}
}
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "snake_case", tag = "type")]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
#[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
pub enum Selection {
#[default]
DefaultScene,
SceneByIndex {
index: usize,
},
SceneByName {
name: String,
},
MeshByIndex {
index: usize,
},
MeshByName {
name: String,
},
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Builder)]
#[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
pub struct VirtualFile {
pub path: std::path::PathBuf,
pub data: Vec<u8>,
}
impl VirtualFile {
pub fn has_extension(&self, required_extension: &str) -> bool {
self.path
.extension()
.and_then(std::ffi::OsStr::to_str)
.map(|extension| extension.eq_ignore_ascii_case(required_extension))
.unwrap_or(false)
}
fn read_fs_impl(path: std::path::PathBuf) -> std::io::Result<Self> {
let data = std::fs::read(&path)?;
Ok(Self { path, data })
}
pub fn read_fs<P>(path: P) -> std::io::Result<Self>
where
P: Into<std::path::PathBuf>,
{
Self::read_fs_impl(path.into())
}
}
impl From<OutputFormat3d> for FileExportFormat {
fn from(output_format: OutputFormat3d) -> Self {
match output_format {
OutputFormat3d::Fbx(_) => Self::Fbx,
OutputFormat3d::Gltf(_) => Self::Gltf,
OutputFormat3d::Obj(_) => Self::Obj,
OutputFormat3d::Ply(_) => Self::Ply,
OutputFormat3d::Step(_) => Self::Step,
OutputFormat3d::Stl(_) => Self::Stl,
}
}
}
impl From<OutputFormat2d> for FileExportFormat2d {
fn from(output_format: OutputFormat2d) -> Self {
match output_format {
OutputFormat2d::Dxf(_) => Self::Dxf,
}
}
}
impl From<FileExportFormat2d> for OutputFormat2d {
fn from(export_format: FileExportFormat2d) -> Self {
match export_format {
FileExportFormat2d::Dxf => OutputFormat2d::Dxf(Default::default()),
}
}
}
impl From<FileExportFormat> for OutputFormat3d {
fn from(export_format: FileExportFormat) -> Self {
match export_format {
FileExportFormat::Fbx => OutputFormat3d::Fbx(Default::default()),
FileExportFormat::Glb => OutputFormat3d::Gltf(gltf::export::Options {
storage: gltf::export::Storage::Binary,
..Default::default()
}),
FileExportFormat::Gltf => OutputFormat3d::Gltf(gltf::export::Options {
storage: gltf::export::Storage::Embedded,
presentation: gltf::export::Presentation::Pretty,
}),
FileExportFormat::Obj => OutputFormat3d::Obj(Default::default()),
FileExportFormat::Ply => OutputFormat3d::Ply(Default::default()),
FileExportFormat::Step => OutputFormat3d::Step(Default::default()),
FileExportFormat::Stl => OutputFormat3d::Stl(stl::export::Options {
storage: stl::export::Storage::Ascii,
..Default::default()
}),
}
}
}
impl From<InputFormat3d> for FileImportFormat {
fn from(input_format: InputFormat3d) -> Self {
match input_format {
InputFormat3d::Acis(_) => Self::Acis,
InputFormat3d::Catia(_) => Self::Catia,
InputFormat3d::Creo(_) => Self::Creo,
InputFormat3d::Fbx(_) => Self::Fbx,
InputFormat3d::Gltf(_) => Self::Gltf,
InputFormat3d::Inventor(_) => Self::Inventor,
InputFormat3d::Nx(_) => Self::Nx,
InputFormat3d::Obj(_) => Self::Obj,
InputFormat3d::Parasolid(_) => Self::Parasolid,
InputFormat3d::Ply(_) => Self::Ply,
InputFormat3d::Sldprt(_) => Self::Sldprt,
InputFormat3d::Step(_) => Self::Step,
InputFormat3d::Stl(_) => Self::Stl,
}
}
}
impl From<FileImportFormat> for InputFormat3d {
fn from(import_format: FileImportFormat) -> Self {
match import_format {
FileImportFormat::Acis => InputFormat3d::Acis(Default::default()),
FileImportFormat::Catia => InputFormat3d::Catia(Default::default()),
FileImportFormat::Creo => InputFormat3d::Creo(Default::default()),
FileImportFormat::Fbx => InputFormat3d::Fbx(Default::default()),
FileImportFormat::Gltf => InputFormat3d::Gltf(Default::default()),
FileImportFormat::Inventor => InputFormat3d::Inventor(Default::default()),
FileImportFormat::Nx => InputFormat3d::Nx(Default::default()),
FileImportFormat::Obj => InputFormat3d::Obj(Default::default()),
FileImportFormat::Parasolid => InputFormat3d::Parasolid(Default::default()),
FileImportFormat::Ply => InputFormat3d::Ply(Default::default()),
FileImportFormat::Sldprt => InputFormat3d::Sldprt(Default::default()),
FileImportFormat::Step => InputFormat3d::Step(Default::default()),
FileImportFormat::Stl => InputFormat3d::Stl(Default::default()),
}
}
}
pub struct OutputFormat3dOptions {
src_unit: crate::units::UnitLength,
}
impl OutputFormat3dOptions {
pub fn new(src_unit: crate::units::UnitLength) -> Self {
Self { src_unit }
}
}
impl OutputFormat3d {
pub fn new(format: &FileExportFormat, options: OutputFormat3dOptions) -> Self {
let OutputFormat3dOptions { src_unit } = options;
let coords = crate::coord::System {
forward: crate::coord::AxisDirectionPair {
axis: crate::coord::Axis::Y,
direction: crate::coord::Direction::Negative,
},
up: crate::coord::AxisDirectionPair {
axis: crate::coord::Axis::Z,
direction: crate::coord::Direction::Positive,
},
};
match format {
FileExportFormat::Fbx => Self::Fbx(fbx::export::Options {
storage: fbx::export::Storage::Binary,
created: None,
}),
FileExportFormat::Glb => Self::Gltf(gltf::export::Options {
storage: gltf::export::Storage::Binary,
presentation: gltf::export::Presentation::Compact,
}),
FileExportFormat::Gltf => Self::Gltf(gltf::export::Options {
storage: gltf::export::Storage::Embedded,
presentation: gltf::export::Presentation::Pretty,
}),
FileExportFormat::Obj => Self::Obj(obj::export::Options {
coords,
units: src_unit,
}),
FileExportFormat::Ply => Self::Ply(ply::export::Options {
storage: ply::export::Storage::Ascii,
coords,
selection: Selection::DefaultScene,
units: src_unit,
}),
FileExportFormat::Step => Self::Step(step::export::Options {
coords,
created: None,
units: src_unit,
presentation: step::export::Presentation::Pretty,
}),
FileExportFormat::Stl => Self::Stl(stl::export::Options {
storage: stl::export::Storage::Ascii,
coords,
units: src_unit,
selection: Selection::DefaultScene,
}),
}
}
}
macro_rules! proprietary_brep_formats {
{
$(
(
$mod_name:ident,
$spec_name:literal,
$format_description:literal,
$coordinate_system:expr
)
)*
} => {
$(
#[doc = $format_description]
pub mod $mod_name {
pub mod import {
use bon::Builder;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::coord;
#[doc = std::concat!("Options for importing ", $format_description, ".")]
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Builder)]
#[serde(default, rename = $spec_name)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass,
pyo3::pyclass(name = $spec_name)
)]
pub struct Options {
#[builder(default = *$coordinate_system)]
pub coords: coord::System,
#[builder(default)]
pub split_closed_faces: bool,
}
#[cfg(feature = "python")]
#[pyo3_stub_gen::derive::gen_stub_pymethods]
#[pyo3::pymethods]
impl Options {
#[new]
pub fn new() -> Self {
Default::default()
}
}
impl Default for Options {
fn default() -> Self {
Self {
coords: *$coordinate_system,
split_closed_faces: false,
}
}
}
}
}
)*
};
}
proprietary_brep_formats! {
(acis, "AcisImportOptions", "ACIS part format", coord::KITTYCAD)
(catia, "CatiaImportOptions", "CATIA part format", coord::KITTYCAD)
(creo, "CreoImportOptions", "PTC Creo part format", coord::OPENGL)
(inventor, "InventorImportOptions", "Autodesk Inventor part format", coord::KITTYCAD)
(nx, "NxImportOptions", "Siemens NX part format", coord::KITTYCAD)
(parasolid, "ParasolidImportOptions", "Parasolid part format", coord::KITTYCAD)
(sldprt, "SldprtImportOptions", "SolidWorks part format", coord::OPENGL)
}