1use parse_display::{Display, FromStr};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
11#[serde(rename_all = "snake_case")]
12#[display(style = "snake_case")]
13#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
15#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
16#[cfg_attr(
17 feature = "python",
18 pyo3::pyclass(from_py_object),
19 pyo3_stub_gen::derive::gen_stub_pyclass_enum
20)]
21pub enum Axis {
22 Y = 1,
24 Z = 2,
26}
27
28#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
30#[serde(rename_all = "snake_case")]
31#[display(style = "snake_case")]
32#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
33#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
34#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
35#[cfg_attr(
36 feature = "python",
37 pyo3::pyclass(from_py_object),
38 pyo3_stub_gen::derive::gen_stub_pyclass_enum
39)]
40pub enum Direction {
41 Positive = 1,
43 Negative = -1,
45}
46
47impl std::ops::Mul for Direction {
48 type Output = Self;
49 fn mul(self, rhs: Self) -> Self::Output {
50 match self as i32 * rhs as i32 {
51 1 => Direction::Positive,
52 -1 => Direction::Negative,
53 _ => unreachable!(),
54 }
55 }
56}
57
58#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
60#[display("({axis}, {direction})")]
61#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
62#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
63#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
64#[cfg_attr(
65 feature = "python",
66 pyo3::pyclass(from_py_object),
67 pyo3_stub_gen::derive::gen_stub_pyclass
68)]
69pub struct AxisDirectionPair {
70 pub axis: Axis,
72
73 pub direction: Direction,
75}
76
77#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
85#[display("forward: {forward}, up: {up}")]
86#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
87#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
88#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
89#[cfg_attr(
90 feature = "python",
91 pyo3::pyclass(from_py_object),
92 pyo3_stub_gen::derive::gen_stub_pyclass
93)]
94pub struct System {
95 pub forward: AxisDirectionPair,
97 pub up: AxisDirectionPair,
99}
100
101pub const KITTYCAD: &System = &System {
107 forward: AxisDirectionPair {
109 axis: Axis::Y,
110 direction: Direction::Negative,
111 },
112 up: AxisDirectionPair {
114 axis: Axis::Z,
115 direction: Direction::Positive,
116 },
117};
118
119pub const OPENGL: &System = &System {
125 forward: AxisDirectionPair {
127 axis: Axis::Z,
128 direction: Direction::Positive,
129 },
130 up: AxisDirectionPair {
132 axis: Axis::Y,
133 direction: Direction::Positive,
134 },
135};
136
137pub const VULKAN: &System = &System {
143 forward: AxisDirectionPair {
145 axis: Axis::Z,
146 direction: Direction::Positive,
147 },
148 up: AxisDirectionPair {
150 axis: Axis::Y,
151 direction: Direction::Negative,
152 },
153};
154
155#[inline]
195pub fn transform(a: [f32; 3], from: &System, to: &System) -> [f32; 3] {
196 let mut b = a;
197 b[to.forward.axis as usize] =
198 (from.forward.direction * to.forward.direction) as i32 as f32 * a[from.forward.axis as usize];
199 b[to.up.axis as usize] = (from.up.direction * to.up.direction) as i32 as f32 * a[from.up.axis as usize];
200 b
201}