1use enum_iterator::Sequence;
2use parse_display_derive::{Display, FromStr};
3use schemars::{schema::SchemaObject, JsonSchema};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7#[cfg(feature = "cxx")]
8use crate::impl_extern_type;
9use crate::{length_unit::LengthUnit, output::ExtrusionFaceInfo, units::UnitAngle};
10
11pub use point::{Point2d, Point3d, Point4d, Quaternion};
12
13mod point;
14
15#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
17#[serde(rename_all = "snake_case")]
18#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
19#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
20pub enum CutType {
21 #[default]
23 Fillet,
24 Chamfer,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
30#[serde(rename_all = "snake_case")]
31#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
32#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
33pub struct Rotation {
34 pub axis: Point3d<f64>,
37 pub angle: Angle,
40 pub origin: OriginType,
42}
43
44impl Default for Rotation {
45 fn default() -> Self {
47 Self {
48 axis: z_axis(),
49 angle: Angle::default(),
50 origin: OriginType::Local,
51 }
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
57#[serde(rename_all = "snake_case")]
58#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
59#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
60pub struct Transform {
61 #[serde(default)]
64 pub translate: Point3d<LengthUnit>,
65 #[serde(default = "same_scale")]
68 pub scale: Point3d<f64>,
69 #[serde(default)]
72 pub rotation: Rotation,
73 #[serde(default = "bool_true")]
75 pub replicate: bool,
76}
77
78impl Default for Transform {
79 fn default() -> Self {
80 Self {
81 scale: same_scale(),
82 replicate: true,
83 translate: Default::default(),
84 rotation: Rotation::default(),
85 }
86 }
87}
88
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
91#[serde(rename_all = "snake_case")]
92#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
93#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
94pub struct AnnotationOptions {
95 pub text: Option<AnnotationTextOptions>,
97 pub line_ends: Option<AnnotationLineEndOptions>,
99 pub line_width: Option<f32>,
101 pub color: Option<Color>,
103 pub position: Option<Point3d<f32>>,
105}
106
107#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
109#[serde(rename_all = "snake_case")]
110#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
111#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
112pub struct AnnotationLineEndOptions {
113 pub start: AnnotationLineEnd,
115 pub end: AnnotationLineEnd,
117}
118
119#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
121#[serde(rename_all = "snake_case")]
122#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
123#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
124pub struct AnnotationTextOptions {
125 pub x: AnnotationTextAlignmentX,
127 pub y: AnnotationTextAlignmentY,
129 pub text: String,
131 pub point_size: u32,
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
139#[serde(rename_all = "snake_case", tag = "type")]
140#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
141#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
142pub enum DistanceType {
143 Euclidean {},
145 OnAxis {
147 axis: GlobalAxis,
149 },
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
154#[serde(rename_all = "snake_case", tag = "type")]
155#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
156#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
157pub enum OriginType {
158 #[default]
160 Local,
161 Global,
163 Custom {
165 origin: Point3d<f64>,
167 },
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
172#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
173#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
174pub struct Color {
175 pub r: f32,
177 pub g: f32,
179 pub b: f32,
181 pub a: f32,
183}
184
185#[allow(missing_docs)]
187#[derive(
188 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
189)]
190#[serde(rename_all = "lowercase")]
191#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
192#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
193pub enum AnnotationTextAlignmentX {
194 Left,
195 Center,
196 Right,
197}
198
199#[allow(missing_docs)]
201#[derive(
202 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
203)]
204#[serde(rename_all = "lowercase")]
205#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
206#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
207pub enum AnnotationTextAlignmentY {
208 Bottom,
209 Center,
210 Top,
211}
212
213#[allow(missing_docs)]
215#[derive(
216 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
217)]
218#[serde(rename_all = "lowercase")]
219#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
220#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
221pub enum AnnotationLineEnd {
222 None,
223 Arrow,
224}
225
226#[derive(
228 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
229)]
230#[serde(rename_all = "lowercase")]
231#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
232#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
233pub enum AnnotationType {
234 T2D,
236 T3D,
238}
239
240#[derive(
242 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
243)]
244#[serde(rename_all = "lowercase")]
245#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
246#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
247pub enum CameraDragInteractionType {
248 Pan,
250 Rotate,
252 RotateTrackball,
254 Zoom,
256}
257
258#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)]
261#[serde(rename_all = "snake_case", tag = "type")]
262#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
263#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
264pub enum PathSegment {
265 Line {
268 end: Point3d<LengthUnit>,
270 relative: bool,
272 },
273 Arc {
276 center: Point2d<LengthUnit>,
278 radius: LengthUnit,
280 start: Angle,
282 end: Angle,
284 relative: bool,
286 },
287 Bezier {
291 control1: Point3d<LengthUnit>,
293 control2: Point3d<LengthUnit>,
295 end: Point3d<LengthUnit>,
297 relative: bool,
299 },
300 TangentialArc {
302 radius: LengthUnit,
305 offset: Angle,
307 },
308 TangentialArcTo {
311 to: Point3d<LengthUnit>,
315 angle_snap_increment: Option<Angle>,
317 },
318 ArcTo {
320 interior: Point3d<LengthUnit>,
322 end: Point3d<LengthUnit>,
324 relative: bool,
326 },
327 CircularInvolute {
330 start_radius: LengthUnit,
333 end_radius: LengthUnit,
336 angle: Angle,
339 reverse: bool,
342 },
343 Ellipse {
345 center: Point2d<LengthUnit>,
347 major_axis: Point2d<LengthUnit>,
349 minor_radius: LengthUnit,
351 start_angle: Angle,
353 end_angle: Angle,
355 },
356 ConicTo {
359 interior: Point2d<LengthUnit>,
361 end: Point2d<LengthUnit>,
363 start_tangent: Point2d<LengthUnit>,
365 end_tangent: Point2d<LengthUnit>,
367 relative: bool,
369 },
370}
371
372#[derive(Clone, Copy, PartialEq, Debug, JsonSchema, Deserialize, Serialize)]
374#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
375#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
376pub struct Angle {
377 pub unit: UnitAngle,
379 pub value: f64,
381}
382
383impl Angle {
384 pub fn to_degrees(self) -> f64 {
386 match self.unit {
387 UnitAngle::Degrees => self.value,
388 UnitAngle::Radians => self.value.to_degrees(),
389 }
390 }
391 pub fn to_radians(self) -> f64 {
393 match self.unit {
394 UnitAngle::Degrees => self.value.to_radians(),
395 UnitAngle::Radians => self.value,
396 }
397 }
398 pub const fn from_degrees(value: f64) -> Self {
400 Self {
401 unit: UnitAngle::Degrees,
402 value,
403 }
404 }
405 pub const fn from_radians(value: f64) -> Self {
407 Self {
408 unit: UnitAngle::Radians,
409 value,
410 }
411 }
412 pub const fn turn() -> Self {
414 Self::from_degrees(360.0)
415 }
416 pub const fn half_circle() -> Self {
418 Self::from_degrees(180.0)
419 }
420 pub const fn quarter_circle() -> Self {
422 Self::from_degrees(90.0)
423 }
424 pub const fn zero() -> Self {
426 Self::from_degrees(0.0)
427 }
428}
429
430impl Default for Angle {
432 fn default() -> Self {
434 Self::zero()
435 }
436}
437
438impl PartialOrd for Angle {
439 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
440 match (self.unit, other.unit) {
441 (UnitAngle::Degrees, UnitAngle::Degrees) => self.value.partial_cmp(&other.value),
443 (UnitAngle::Radians, UnitAngle::Radians) => self.value.partial_cmp(&other.value),
444 _ => self.to_degrees().partial_cmp(&other.to_degrees()),
445 }
446 }
447}
448
449impl std::ops::Add for Angle {
450 type Output = Self;
451
452 fn add(self, rhs: Self) -> Self::Output {
453 Self {
454 unit: UnitAngle::Degrees,
455 value: self.to_degrees() + rhs.to_degrees(),
456 }
457 }
458}
459
460impl std::ops::AddAssign for Angle {
461 fn add_assign(&mut self, rhs: Self) {
462 match self.unit {
463 UnitAngle::Degrees => {
464 self.value += rhs.to_degrees();
465 }
466 UnitAngle::Radians => {
467 self.value += rhs.to_radians();
468 }
469 }
470 }
471}
472
473#[derive(
475 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
476)]
477#[serde(rename_all = "lowercase")]
478#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
479#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
480pub enum SceneSelectionType {
481 Replace,
483 Add,
485 Remove,
487}
488
489#[allow(missing_docs)]
491#[derive(
492 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
493)]
494#[serde(rename_all = "snake_case")]
495#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
496#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
497pub enum SceneToolType {
498 CameraRevolve,
499 Select,
500 Move,
501 SketchLine,
502 SketchTangentialArc,
503 SketchCurve,
504 SketchCurveMod,
505}
506
507#[allow(missing_docs)]
509#[derive(
510 Display,
511 FromStr,
512 Copy,
513 Eq,
514 PartialEq,
515 Debug,
516 JsonSchema,
517 Deserialize,
518 Serialize,
519 Sequence,
520 Clone,
521 Ord,
522 PartialOrd,
523 Default,
524)]
525#[serde(rename_all = "snake_case")]
526#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
527#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
528pub enum PathComponentConstraintBound {
529 #[default]
530 Unconstrained,
531 PartiallyConstrained,
532 FullyConstrained,
533}
534
535#[allow(missing_docs)]
537#[derive(
538 Display,
539 FromStr,
540 Copy,
541 Eq,
542 PartialEq,
543 Debug,
544 JsonSchema,
545 Deserialize,
546 Serialize,
547 Sequence,
548 Clone,
549 Ord,
550 PartialOrd,
551 Default,
552)]
553#[serde(rename_all = "snake_case")]
554#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
555#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
556pub enum PathComponentConstraintType {
557 #[default]
558 Unconstrained,
559 Vertical,
560 Horizontal,
561 EqualLength,
562 Parallel,
563 AngleBetween,
564}
565
566#[allow(missing_docs)]
568#[derive(
569 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
570)]
571#[serde(rename_all = "snake_case")]
572#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
573#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
574pub enum PathCommand {
575 MoveTo,
576 LineTo,
577 BezCurveTo,
578 NurbsCurveTo,
579 AddArc,
580}
581
582#[allow(missing_docs)]
584#[derive(
585 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
586)]
587#[serde(rename_all = "lowercase")]
588#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
589#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
590#[repr(u8)]
591pub enum EntityType {
592 Entity,
593 Object,
594 Path,
595 Curve,
596 Solid2D,
597 Solid3D,
598 Edge,
599 Face,
600 Plane,
601 Vertex,
602}
603
604#[allow(missing_docs)]
606#[derive(
607 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
608)]
609#[serde(rename_all = "snake_case")]
610#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
611#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
612pub enum CurveType {
613 Line,
614 Arc,
615 Nurbs,
616}
617
618#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
620#[cfg_attr(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass)]
621pub struct ExportFile {
622 pub name: String,
624 pub contents: crate::base64::Base64Data,
626}
627
628#[cfg(feature = "python")]
629#[pyo3_stub_gen::derive::gen_stub_pymethods]
630#[pyo3::pymethods]
631impl ExportFile {
632 #[getter]
633 fn contents(&self) -> Vec<u8> {
634 self.contents.0.clone()
635 }
636
637 #[getter]
638 fn name(&self) -> String {
639 self.name.clone()
640 }
641}
642
643#[derive(
645 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd, Sequence,
646)]
647#[serde(rename_all = "lowercase")]
648#[display(style = "lowercase")]
649#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
650#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
651#[cfg_attr(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass_enum)]
652pub enum FileExportFormat {
653 Fbx,
655 Glb,
662 Gltf,
673 Obj,
677 Ply,
679 Step,
681 Stl,
683}
684
685#[derive(
687 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd, Sequence,
688)]
689#[serde(rename_all = "lowercase")]
690#[display(style = "lowercase")]
691#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
692#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
693pub enum FileExportFormat2d {
694 Dxf,
696}
697
698#[derive(
700 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd, Sequence,
701)]
702#[serde(rename_all = "lowercase")]
703#[display(style = "lowercase")]
704#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
705#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
706pub enum FileImportFormat {
707 Fbx,
709 Gltf,
711 Obj,
715 Ply,
717 Sldprt,
719 Step,
721 Stl,
723}
724
725#[derive(Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd)]
727#[serde(rename_all = "snake_case")]
728#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
729#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
730pub enum EngineErrorCode {
731 BadRequest = 1,
735 InternalEngine,
737}
738
739impl From<EngineErrorCode> for http::StatusCode {
740 fn from(e: EngineErrorCode) -> Self {
741 match e {
742 EngineErrorCode::BadRequest => Self::BAD_REQUEST,
743 EngineErrorCode::InternalEngine => Self::INTERNAL_SERVER_ERROR,
744 }
745 }
746}
747
748#[derive(Default, Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
751#[serde(rename_all = "snake_case")]
752#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
753#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
754pub enum ExtrudeMethod {
755 New,
758 #[default]
761 Merge,
762}
763
764#[derive(Debug, PartialEq, Serialize, Deserialize, JsonSchema, Clone)]
766#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
767#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
768pub struct ExtrudedFaceInfo {
769 pub bottom: Option<Uuid>,
774 pub top: Uuid,
776 pub sides: Vec<SideFace>,
778}
779
780#[derive(Debug, PartialEq, Serialize, Deserialize, JsonSchema, Clone)]
782#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
783#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
784pub struct SideFace {
785 pub path_id: Uuid,
787 pub face_id: Uuid,
789}
790
791#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
793#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
794#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
795pub struct CameraSettings {
796 pub pos: Point3d,
798
799 pub center: Point3d,
801
802 pub up: Point3d,
804
805 pub orientation: Quaternion,
807
808 pub fov_y: Option<f32>,
810
811 pub ortho_scale: Option<f32>,
813
814 pub ortho: bool,
816}
817
818#[allow(missing_docs)]
819#[repr(u8)]
820#[derive(Default, Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
821#[serde(rename_all = "snake_case")]
822#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
823#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
824pub enum WorldCoordinateSystem {
825 #[default]
826 RightHandedUpZ,
827 RightHandedUpY,
828}
829
830#[allow(missing_docs)]
831#[repr(C)]
832#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
833#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
834#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
835pub struct CameraViewState {
836 pub pivot_rotation: Quaternion,
837 pub pivot_position: Point3d,
838 pub eye_offset: f32,
839 pub fov_y: f32,
840 pub ortho_scale_factor: f32,
841 pub is_ortho: bool,
842 pub ortho_scale_enabled: bool,
843 pub world_coord_system: WorldCoordinateSystem,
844}
845
846impl Default for CameraViewState {
847 fn default() -> Self {
848 CameraViewState {
849 pivot_rotation: Default::default(),
850 pivot_position: Default::default(),
851 eye_offset: 10.0,
852 fov_y: 45.0,
853 ortho_scale_factor: 1.6,
854 is_ortho: false,
855 ortho_scale_enabled: true,
856 world_coord_system: Default::default(),
857 }
858 }
859}
860
861#[cfg(feature = "cxx")]
862impl_extern_type! {
863 [Trivial]
864 CameraViewState = "Endpoints::CameraViewState"
865}
866
867impl From<CameraSettings> for crate::output::DefaultCameraZoom {
868 fn from(settings: CameraSettings) -> Self {
869 Self { settings }
870 }
871}
872impl From<CameraSettings> for crate::output::CameraDragMove {
873 fn from(settings: CameraSettings) -> Self {
874 Self { settings }
875 }
876}
877impl From<CameraSettings> for crate::output::CameraDragEnd {
878 fn from(settings: CameraSettings) -> Self {
879 Self { settings }
880 }
881}
882impl From<CameraSettings> for crate::output::DefaultCameraGetSettings {
883 fn from(settings: CameraSettings) -> Self {
884 Self { settings }
885 }
886}
887impl From<CameraSettings> for crate::output::ZoomToFit {
888 fn from(settings: CameraSettings) -> Self {
889 Self { settings }
890 }
891}
892impl From<CameraSettings> for crate::output::OrientToFace {
893 fn from(settings: CameraSettings) -> Self {
894 Self { settings }
895 }
896}
897impl From<CameraSettings> for crate::output::ViewIsometric {
898 fn from(settings: CameraSettings) -> Self {
899 Self { settings }
900 }
901}
902
903#[derive(Copy, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, PartialOrd, Default)]
905#[serde(rename_all = "snake_case")]
906#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
907#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
908pub struct PerspectiveCameraParameters {
909 pub fov_y: Option<f32>,
911 pub z_near: Option<f32>,
913 pub z_far: Option<f32>,
915}
916
917#[derive(
919 Default,
920 Display,
921 FromStr,
922 Copy,
923 Eq,
924 PartialEq,
925 Debug,
926 JsonSchema,
927 Deserialize,
928 Serialize,
929 Sequence,
930 Clone,
931 Ord,
932 PartialOrd,
933)]
934#[serde(rename_all = "snake_case")]
935#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
936#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
937pub enum CameraMovement {
938 #[default]
940 Vantage,
941 None,
943}
944
945#[derive(
947 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
948)]
949#[serde(rename_all = "lowercase")]
950#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
951#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
952pub enum GlobalAxis {
953 X,
955 Y,
957 Z,
959}
960
961#[derive(
963 Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
964)]
965#[serde(rename_all = "snake_case")]
966#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
967#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
968#[repr(u8)]
969pub enum ExtrusionFaceCapType {
970 None,
972 Top,
974 Bottom,
976 Both,
978}
979
980#[allow(missing_docs)]
982#[derive(
983 Display,
984 FromStr,
985 Copy,
986 Eq,
987 PartialEq,
988 Debug,
989 JsonSchema,
990 Deserialize,
991 Serialize,
992 Sequence,
993 Clone,
994 Ord,
995 PartialOrd,
996 Default,
997)]
998#[serde(rename_all = "lowercase")]
999#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1000#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1001pub enum PostEffectType {
1002 Phosphor,
1003 Ssao,
1004 #[default]
1005 NoEffect,
1006}
1007
1008#[cfg(feature = "cxx")]
1011impl_extern_type! {
1012 [Trivial]
1013 FileImportFormat = "Enums::_FileImportFormat"
1015 FileExportFormat = "Enums::_FileExportFormat"
1016 CameraDragInteractionType = "Enums::_CameraDragInteractionType"
1018 SceneSelectionType = "Enums::_SceneSelectionType"
1020 SceneToolType = "Enums::_SceneToolType"
1021 EntityType = "Enums::_EntityType"
1022 AnnotationType = "Enums::_AnnotationType"
1023 AnnotationTextAlignmentX = "Enums::_AnnotationTextAlignmentX"
1024 AnnotationTextAlignmentY = "Enums::_AnnotationTextAlignmentY"
1025 AnnotationLineEnd = "Enums::_AnnotationLineEnd"
1026
1027 CurveType = "Enums::_CurveType"
1028 PathCommand = "Enums::_PathCommand"
1029 PathComponentConstraintBound = "Enums::_PathComponentConstraintBound"
1030 PathComponentConstraintType = "Enums::_PathComponentConstraintType"
1031 ExtrusionFaceCapType = "Enums::_ExtrusionFaceCapType"
1032
1033 EngineErrorCode = "Enums::_ErrorCode"
1035 GlobalAxis = "Enums::_GlobalAxis"
1036 OriginType = "Enums::_OriginType"
1037
1038 PostEffectType = "Enums::_PostEffectType"
1040}
1041
1042fn bool_true() -> bool {
1043 true
1044}
1045fn same_scale() -> Point3d<f64> {
1046 Point3d::uniform(1.0)
1047}
1048
1049fn z_axis() -> Point3d<f64> {
1050 Point3d { x: 0.0, y: 0.0, z: 1.0 }
1051}
1052
1053impl ExtrudedFaceInfo {
1054 pub fn list_faces(self) -> Vec<ExtrusionFaceInfo> {
1057 let mut face_infos: Vec<_> = self
1058 .sides
1059 .into_iter()
1060 .map(|side| ExtrusionFaceInfo {
1061 curve_id: Some(side.path_id),
1062 face_id: Some(side.face_id),
1063 cap: ExtrusionFaceCapType::None,
1064 })
1065 .collect();
1066 face_infos.push(ExtrusionFaceInfo {
1067 curve_id: None,
1068 face_id: Some(self.top),
1069 cap: ExtrusionFaceCapType::Top,
1070 });
1071 if let Some(bottom) = self.bottom {
1072 face_infos.push(ExtrusionFaceInfo {
1073 curve_id: None,
1074 face_id: Some(bottom),
1075 cap: ExtrusionFaceCapType::Bottom,
1076 });
1077 }
1078 face_infos
1079 }
1080}
1081
1082#[cfg(test)]
1083mod tests {
1084 use schemars::schema_for;
1085
1086 use super::*;
1087
1088 #[test]
1089 fn check_transformby_deprecated() {
1090 let s = schema_for!(TransformBy<Point3d>);
1091 let pretty = serde_json::to_string_pretty(&s).unwrap();
1092 println!("{pretty}");
1093 let tests: Vec<(OriginType, TransformBy<Point3d>)> = vec![
1094 (
1096 OriginType::Local,
1097 TransformBy {
1098 property: Point3d::default(),
1099 set: true,
1100 #[allow(deprecated)] is_local: true,
1102 origin: None,
1103 },
1104 ),
1105 (
1108 OriginType::Local,
1109 TransformBy {
1110 property: Point3d::default(),
1111 set: true,
1112 #[allow(deprecated)] is_local: false,
1114 origin: Some(OriginType::Local),
1115 },
1116 ),
1117 (
1120 OriginType::Custom {
1121 origin: Point3d::uniform(2.0),
1122 },
1123 TransformBy {
1124 property: Point3d::default(),
1125 set: true,
1126 #[allow(deprecated)] is_local: false,
1128 origin: Some(OriginType::Custom{origin: Point3d::uniform(2.0)}),
1129 },
1130 ),
1131 ];
1132 for (expected, input) in tests {
1133 let actual = input.get_origin();
1134 assert_eq!(actual, expected);
1135 }
1136 }
1137
1138 #[test]
1139 fn test_angle_comparison() {
1140 let a = Angle::from_degrees(90.0);
1141 assert!(a < Angle::from_degrees(91.0));
1142 assert!(a > Angle::from_degrees(89.0));
1143 assert!(a <= Angle::from_degrees(90.0));
1144 assert!(a >= Angle::from_degrees(90.0));
1145 let b = Angle::from_radians(std::f64::consts::FRAC_PI_4);
1146 assert!(b < Angle::from_radians(std::f64::consts::FRAC_PI_2));
1147 assert!(b > Angle::from_radians(std::f64::consts::FRAC_PI_8));
1148 assert!(b <= Angle::from_radians(std::f64::consts::FRAC_PI_4));
1149 assert!(b >= Angle::from_radians(std::f64::consts::FRAC_PI_4));
1150 assert!(a > b);
1152 assert!(a >= b);
1153 assert!(b < a);
1154 assert!(b <= a);
1155 let c = Angle::from_radians(std::f64::consts::FRAC_PI_2 * 3.0);
1156 assert!(a < c);
1157 assert!(a <= c);
1158 assert!(c > a);
1159 assert!(c >= a);
1160 }
1161}
1162
1163#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, JsonSchema)]
1165#[schemars(rename = "TransformByFor{T}")]
1166#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1167#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1168pub struct TransformBy<T> {
1169 pub property: T,
1171 pub set: bool,
1176 #[deprecated(note = "Use the `origin` field instead.")]
1179 pub is_local: bool,
1180 #[serde(default)]
1184 pub origin: Option<OriginType>,
1185}
1186
1187impl<T> TransformBy<T> {
1188 pub fn get_origin(&self) -> OriginType {
1192 if let Some(origin) = self.origin {
1193 return origin;
1194 }
1195 #[expect(
1196 deprecated,
1197 reason = "Must fall back to the deprecated field if the API client isn't using the new field yet."
1198 )]
1199 if self.is_local {
1200 OriginType::Local
1201 } else {
1202 OriginType::Global
1203 }
1204 }
1205}
1206
1207#[derive(Clone, Debug, PartialEq, Deserialize, JsonSchema, Serialize, Default)]
1210#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1211#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1212pub struct ComponentTransform {
1213 pub translate: Option<TransformBy<Point3d<LengthUnit>>>,
1215 pub rotate_rpy: Option<TransformBy<Point3d<f64>>>,
1218 pub rotate_angle_axis: Option<TransformBy<Point4d<f64>>>,
1222 pub scale: Option<TransformBy<Point3d<f64>>>,
1224}
1225
1226#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
1229#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1230#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1231pub enum Opposite<T> {
1232 #[default]
1234 None,
1235 Symmetric,
1237 Other(T),
1239}
1240
1241impl<T: JsonSchema> JsonSchema for Opposite<T> {
1242 fn schema_name() -> String {
1243 format!("OppositeFor{}", T::schema_name())
1244 }
1245
1246 fn schema_id() -> std::borrow::Cow<'static, str> {
1247 std::borrow::Cow::Owned(format!("{}::Opposite<{}>", module_path!(), T::schema_id()))
1248 }
1249
1250 fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1251 SchemaObject {
1252 instance_type: Some(schemars::schema::InstanceType::String.into()),
1253 ..Default::default()
1254 }
1255 .into()
1256 }
1257}
1258
1259#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
1262#[serde(rename_all = "snake_case")]
1263#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1264#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1265pub enum CutStrategy {
1266 Basic,
1269 Csg,
1272 #[default]
1274 Automatic,
1275}
1276
1277#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
1279#[serde(rename_all = "snake_case")]
1280#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
1281#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
1282pub enum RelativeTo {
1283 #[default]
1285 SketchPlane,
1286 TrajectoryCurve,
1288}