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;
pub mod sldprt;
#[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 {
Fbx(fbx::import::Options),
Gltf(gltf::import::Options),
Obj(obj::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::Fbx(_) => "fbx",
InputFormat3d::Gltf(_) => "gltf",
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::Fbx(_) => Self::Fbx,
InputFormat3d::Gltf(_) => Self::Gltf,
InputFormat3d::Obj(_) => Self::Obj,
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::Fbx => InputFormat3d::Fbx(Default::default()),
FileImportFormat::Gltf => InputFormat3d::Gltf(Default::default()),
FileImportFormat::Obj => InputFormat3d::Obj(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,
}),
}
}
}