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(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass_enum)]
17pub enum Axis {
18 Y = 1,
20 Z = 2,
22}
23
24#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
26#[serde(rename_all = "snake_case")]
27#[display(style = "snake_case")]
28#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
29#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
30#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
31#[cfg_attr(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass_enum)]
32pub enum Direction {
33 Positive = 1,
35 Negative = -1,
37}
38
39impl std::ops::Mul for Direction {
40 type Output = Self;
41 fn mul(self, rhs: Self) -> Self::Output {
42 match self as i32 * rhs as i32 {
43 1 => Direction::Positive,
44 -1 => Direction::Negative,
45 _ => unreachable!(),
46 }
47 }
48}
49
50#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
52#[display("({axis}, {direction})")]
53#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
54#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
55#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
56#[cfg_attr(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass)]
57pub struct AxisDirectionPair {
58 pub axis: Axis,
60
61 pub direction: Direction,
63}
64
65#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, Display, FromStr)]
73#[display("forward: {forward}, up: {up}")]
74#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
75#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
76#[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
77#[cfg_attr(feature = "python", pyo3::pyclass, pyo3_stub_gen::derive::gen_stub_pyclass)]
78pub struct System {
79 pub forward: AxisDirectionPair,
81 pub up: AxisDirectionPair,
83}
84
85pub const KITTYCAD: &System = &System {
91 forward: AxisDirectionPair {
93 axis: Axis::Y,
94 direction: Direction::Negative,
95 },
96 up: AxisDirectionPair {
98 axis: Axis::Z,
99 direction: Direction::Positive,
100 },
101};
102
103pub const OPENGL: &System = &System {
109 forward: AxisDirectionPair {
111 axis: Axis::Z,
112 direction: Direction::Positive,
113 },
114 up: AxisDirectionPair {
116 axis: Axis::Y,
117 direction: Direction::Positive,
118 },
119};
120
121pub const VULKAN: &System = &System {
127 forward: AxisDirectionPair {
129 axis: Axis::Z,
130 direction: Direction::Positive,
131 },
132 up: AxisDirectionPair {
134 axis: Axis::Y,
135 direction: Direction::Negative,
136 },
137};
138
139#[inline]
179pub fn transform(a: [f32; 3], from: &System, to: &System) -> [f32; 3] {
180 let mut b = a;
181 b[to.forward.axis as usize] =
182 (from.forward.direction * to.forward.direction) as i32 as f32 * a[from.forward.axis as usize];
183 b[to.up.axis as usize] = (from.up.direction * to.up.direction) as i32 as f32 * a[from.up.axis as usize];
184 b
185}