kittycad_modeling_cmds/format/
mod.rs1use parse_display_derive::{Display, FromStr};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use crate::shared::{FileExportFormat, FileExportFormat2d, FileImportFormat};
6
7pub mod dxf;
9pub mod fbx;
11pub mod gltf;
16pub mod obj;
18pub mod ply;
20pub mod step;
22pub mod stl;
24
25pub mod sldprt;
27
28#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
30#[serde(tag = "type", rename_all = "snake_case")]
31#[display(style = "snake_case")]
32#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
33#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
34pub enum OutputFormat2d {
35 #[display("{}: {0}")]
37 Dxf(dxf::export::Options),
38}
39
40#[deprecated(since = "0.2.96", note = "use `OutputFormat3d` instead")]
42pub type OutputFormat = OutputFormat3d;
43
44#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
46#[serde(tag = "type", rename_all = "snake_case")]
47#[display(style = "snake_case")]
48#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
49#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
50pub enum OutputFormat3d {
51 #[display("{}: {0}")]
53 Fbx(fbx::export::Options),
54 #[display("{}: {0}")]
59 Gltf(gltf::export::Options),
60 #[display("{}: {0}")]
62 Obj(obj::export::Options),
63 #[display("{}: {0}")]
65 Ply(ply::export::Options),
66 #[display("{}: {0}")]
68 Step(step::export::Options),
69 #[display("{}: {0}")]
71 Stl(stl::export::Options),
72}
73
74#[deprecated(since = "0.2.96", note = "use `InputFormat3d` instead")]
76pub type InputFormat = InputFormat3d;
77
78#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
80#[serde(tag = "type", rename_all = "snake_case")]
81#[display(style = "snake_case")]
82#[cfg_attr(
83 feature = "python",
84 pyo3::pyclass,
85 pyo3_stub_gen::derive::gen_stub_pyclass_complex_enum
86)]
87#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
88#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
89pub enum InputFormat3d {
90 #[display("{}: {0}")]
92 Fbx(fbx::import::Options),
93 #[display("{}: {0}")]
97 Gltf(gltf::import::Options),
98 #[display("{}: {0}")]
100 Obj(obj::import::Options),
101 #[display("{}: {0}")]
103 Ply(ply::import::Options),
104 #[display("{}: {0}")]
106 Sldprt(sldprt::import::Options),
107 #[display("{}: {0}")]
109 Step(step::import::Options),
110 #[display("{}: {0}")]
112 Stl(stl::import::Options),
113}
114
115#[derive(Clone, Debug, Default, Display, Eq, FromStr, Hash, PartialEq, JsonSchema, Deserialize, Serialize)]
117#[display(style = "snake_case")]
118#[serde(rename_all = "snake_case", tag = "type")]
119#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
120#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
121pub enum Selection {
122 #[default]
124 DefaultScene,
125
126 #[display("{}: {index}")]
128 SceneByIndex {
129 index: usize,
131 },
132
133 #[display("{}: {name}")]
135 SceneByName {
136 name: String,
138 },
139
140 #[display("{}: {index}")]
142 MeshByIndex {
143 index: usize,
145 },
146
147 #[display("{}: {name}")]
149 MeshByName {
150 name: String,
152 },
153}
154
155#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
157pub struct VirtualFile {
158 pub path: std::path::PathBuf,
160 pub data: Vec<u8>,
162}
163
164impl VirtualFile {
165 pub fn has_extension(&self, required_extension: &str) -> bool {
167 self.path
168 .extension()
169 .and_then(std::ffi::OsStr::to_str)
170 .map(|extension| extension.eq_ignore_ascii_case(required_extension))
171 .unwrap_or(false)
172 }
173
174 fn read_fs_impl(path: std::path::PathBuf) -> std::io::Result<Self> {
175 let data = std::fs::read(&path)?;
176 Ok(Self { path, data })
177 }
178
179 pub fn read_fs<P>(path: P) -> std::io::Result<Self>
181 where
182 P: Into<std::path::PathBuf>,
183 {
184 Self::read_fs_impl(path.into())
185 }
186}
187
188impl From<OutputFormat3d> for FileExportFormat {
189 fn from(output_format: OutputFormat3d) -> Self {
190 match output_format {
191 OutputFormat3d::Fbx(_) => Self::Fbx,
192 OutputFormat3d::Gltf(_) => Self::Gltf,
193 OutputFormat3d::Obj(_) => Self::Obj,
194 OutputFormat3d::Ply(_) => Self::Ply,
195 OutputFormat3d::Step(_) => Self::Step,
196 OutputFormat3d::Stl(_) => Self::Stl,
197 }
198 }
199}
200
201impl From<OutputFormat2d> for FileExportFormat2d {
202 fn from(output_format: OutputFormat2d) -> Self {
203 match output_format {
204 OutputFormat2d::Dxf(_) => Self::Dxf,
205 }
206 }
207}
208
209impl From<FileExportFormat2d> for OutputFormat2d {
210 fn from(export_format: FileExportFormat2d) -> Self {
211 match export_format {
212 FileExportFormat2d::Dxf => OutputFormat2d::Dxf(Default::default()),
213 }
214 }
215}
216
217impl From<FileExportFormat> for OutputFormat3d {
218 fn from(export_format: FileExportFormat) -> Self {
219 match export_format {
220 FileExportFormat::Fbx => OutputFormat3d::Fbx(Default::default()),
221 FileExportFormat::Glb => OutputFormat3d::Gltf(gltf::export::Options {
222 storage: gltf::export::Storage::Binary,
223 ..Default::default()
224 }),
225 FileExportFormat::Gltf => OutputFormat3d::Gltf(gltf::export::Options {
226 storage: gltf::export::Storage::Embedded,
227 presentation: gltf::export::Presentation::Pretty,
228 }),
229 FileExportFormat::Obj => OutputFormat3d::Obj(Default::default()),
230 FileExportFormat::Ply => OutputFormat3d::Ply(Default::default()),
231 FileExportFormat::Step => OutputFormat3d::Step(Default::default()),
232 FileExportFormat::Stl => OutputFormat3d::Stl(stl::export::Options {
233 storage: stl::export::Storage::Ascii,
234 ..Default::default()
235 }),
236 }
237 }
238}
239
240impl From<InputFormat3d> for FileImportFormat {
241 fn from(input_format: InputFormat3d) -> Self {
242 match input_format {
243 InputFormat3d::Fbx(_) => Self::Fbx,
244 InputFormat3d::Gltf(_) => Self::Gltf,
245 InputFormat3d::Obj(_) => Self::Obj,
246 InputFormat3d::Ply(_) => Self::Ply,
247 InputFormat3d::Sldprt(_) => Self::Sldprt,
248 InputFormat3d::Step(_) => Self::Step,
249 InputFormat3d::Stl(_) => Self::Stl,
250 }
251 }
252}
253
254impl From<FileImportFormat> for InputFormat3d {
255 fn from(import_format: FileImportFormat) -> Self {
256 match import_format {
257 FileImportFormat::Fbx => InputFormat3d::Fbx(Default::default()),
258 FileImportFormat::Gltf => InputFormat3d::Gltf(Default::default()),
259 FileImportFormat::Obj => InputFormat3d::Obj(Default::default()),
260 FileImportFormat::Ply => InputFormat3d::Ply(Default::default()),
261 FileImportFormat::Sldprt => InputFormat3d::Sldprt(Default::default()),
262 FileImportFormat::Step => InputFormat3d::Step(Default::default()),
263 FileImportFormat::Stl => InputFormat3d::Stl(Default::default()),
264 }
265 }
266}