Skip to main content

space_prefab/component/
shape.rs

1use bevy::prelude::*;
2
3use space_shared::ext::bevy_inspector_egui;
4use space_shared::ext::bevy_inspector_egui::prelude::*;
5
6/// Component to setup mesh of prefab
7#[derive(Component, Reflect, Clone)]
8#[reflect(Default, Component)]
9pub enum MeshPrimitivePrefab {
10    Cube(f32),
11    Box(BoxPrefab),
12    Sphere(SpherePrefab),
13    Quad(QuadPrefab),
14    Capsule(CapsulePrefab),
15    Circle(CirclePrefab),
16    Cylinder(CylinderPrefab),
17    Icosphere(IcospherePrefab),
18    Plane(PlanePrefab),
19    RegularPolygon(RegularPolygonPrefab),
20    Torus(TorusPrefab),
21}
22
23impl Default for MeshPrimitivePrefab {
24    fn default() -> Self {
25        Self::Box(BoxPrefab {
26            w: 1.0,
27            h: 1.0,
28            d: 1.0,
29        })
30    }
31}
32
33impl MeshPrimitivePrefab {
34    /// Convert [`MeshPrimitivePrefab`] to bevy [`Mesh`]
35    pub fn to_mesh(&self) -> Mesh {
36        match self {
37            Self::Cube(s) => Mesh::from(shape::Cube::new(*s)),
38            Self::Box(b) => b.to_mesh(),
39            Self::Sphere(s) => s.to_mesh(),
40            Self::Quad(q) => q.to_mesh(),
41            Self::Capsule(c) => c.to_mesh(),
42            Self::Circle(c) => c.to_mesh(),
43            Self::Cylinder(c) => c.to_mesh(),
44            Self::Icosphere(c) => c.to_mesh(),
45            Self::Plane(c) => c.to_mesh(),
46            Self::RegularPolygon(c) => c.to_mesh(),
47            Self::Torus(c) => c.to_mesh(),
48        }
49    }
50}
51
52/// Values to setup box mesh
53#[derive(Reflect, Clone)]
54#[reflect(Default)]
55pub struct BoxPrefab {
56    pub w: f32,
57    pub h: f32,
58    pub d: f32,
59}
60
61impl Default for BoxPrefab {
62    fn default() -> Self {
63        Self {
64            w: 1.0,
65            h: 1.0,
66            d: 1.0,
67        }
68    }
69}
70
71impl BoxPrefab {
72    pub fn to_mesh(&self) -> Mesh {
73        Mesh::from(shape::Box::new(self.w, self.h, self.d))
74    }
75}
76
77/// Values to setup sphere mesh
78#[derive(Reflect, Clone)]
79#[reflect(Default)]
80pub struct SpherePrefab {
81    pub r: f32,
82}
83
84impl Default for SpherePrefab {
85    fn default() -> Self {
86        Self { r: 1.0 }
87    }
88}
89
90impl SpherePrefab {
91    pub fn to_mesh(&self) -> Mesh {
92        let data = shape::UVSphere {
93            radius: self.r,
94            ..Default::default()
95        };
96        Mesh::from(data)
97    }
98}
99
100/// Values to setup quad mesh
101#[derive(Reflect, Clone)]
102#[reflect(Default)]
103pub struct QuadPrefab {
104    /// Full width and height of the rectangle.
105    pub size: Vec2,
106    /// Horizontally-flip the texture coordinates of the resulting mesh.
107    pub flip: bool,
108}
109
110impl Default for QuadPrefab {
111    fn default() -> Self {
112        Self {
113            size: Vec2::ONE,
114            flip: false,
115        }
116    }
117}
118
119impl QuadPrefab {
120    pub fn to_mesh(&self) -> Mesh {
121        let data = shape::Quad {
122            size: self.size,
123            flip: self.flip,
124        };
125        Mesh::from(data)
126    }
127}
128
129/// Values to setup capsule mesh
130#[derive(Reflect, Clone)]
131#[reflect(Default)]
132pub struct CapsulePrefab {
133    pub r: f32,
134    pub rings: usize,
135}
136
137impl Default for CapsulePrefab {
138    fn default() -> Self {
139        let def = shape::Capsule::default();
140        Self {
141            r: def.radius,
142            rings: def.rings,
143        }
144    }
145}
146
147impl CapsulePrefab {
148    pub fn to_mesh(&self) -> Mesh {
149        let data = shape::Capsule {
150            radius: self.r,
151            rings: self.rings,
152            ..Default::default()
153        };
154        Mesh::from(data)
155    }
156}
157
158/// Values to setup circle mesh
159#[derive(Reflect, Clone, InspectorOptions)]
160#[reflect(Default, InspectorOptions)]
161pub struct CirclePrefab {
162    pub r: f32,
163    #[inspector(min = 3)]
164    pub vertices: usize,
165}
166
167impl Default for CirclePrefab {
168    fn default() -> Self {
169        let def = shape::Circle::default();
170        Self {
171            r: def.radius,
172            vertices: def.vertices,
173        }
174    }
175}
176
177impl CirclePrefab {
178    pub fn to_mesh(&self) -> Mesh {
179        let data = shape::Circle {
180            radius: self.r,
181            vertices: self.vertices,
182        };
183        Mesh::from(data)
184    }
185}
186
187/// Values to setup cylinder mesh
188#[derive(Reflect, Clone)]
189#[reflect(Default)]
190pub struct CylinderPrefab {
191    pub r: f32,
192    pub resolution: u32,
193    pub segments: u32,
194}
195
196impl Default for CylinderPrefab {
197    fn default() -> Self {
198        let def = shape::Cylinder::default();
199        Self {
200            r: def.radius,
201            resolution: def.resolution,
202            segments: def.segments,
203        }
204    }
205}
206
207impl CylinderPrefab {
208    pub fn to_mesh(&self) -> Mesh {
209        let data = shape::Cylinder {
210            radius: self.r,
211            resolution: self.resolution,
212            segments: self.segments,
213            ..Default::default()
214        };
215        Mesh::from(data)
216    }
217}
218
219/// Values to setup icosphere mesh
220#[derive(Reflect, Clone)]
221#[reflect(Default)]
222pub struct IcospherePrefab {
223    pub r: f32,
224    pub subdivisions: usize,
225}
226
227impl Default for IcospherePrefab {
228    fn default() -> Self {
229        let def = shape::Icosphere::default();
230        Self {
231            r: def.radius,
232            subdivisions: def.subdivisions,
233        }
234    }
235}
236
237impl IcospherePrefab {
238    pub fn to_mesh(&self) -> Mesh {
239        let data = shape::Icosphere {
240            radius: self.r,
241            subdivisions: self.subdivisions,
242        };
243        Mesh::try_from(data).map_or_else(
244            |_| Mesh::try_from(shape::Icosphere::default()).unwrap(),
245            |mesh| mesh,
246        )
247    }
248}
249
250/// Values to setup plane mesh
251#[derive(Reflect, Clone)]
252#[reflect(Default)]
253pub struct PlanePrefab {
254    pub size: f32,
255    pub subdivisions: u32,
256}
257
258impl Default for PlanePrefab {
259    fn default() -> Self {
260        let def = shape::Plane::default();
261        Self {
262            size: def.size,
263            subdivisions: def.subdivisions,
264        }
265    }
266}
267
268impl PlanePrefab {
269    pub fn to_mesh(&self) -> Mesh {
270        let data = shape::Plane {
271            size: self.size,
272            subdivisions: self.subdivisions,
273        };
274        Mesh::from(data)
275    }
276}
277
278/// Values to setup regular polygon mesh
279#[derive(Reflect, Clone, InspectorOptions)]
280#[reflect(Default, InspectorOptions)]
281pub struct RegularPolygonPrefab {
282    pub radius: f32,
283    #[inspector(min = 3)]
284    pub sides: usize,
285}
286
287impl Default for RegularPolygonPrefab {
288    fn default() -> Self {
289        let def = shape::RegularPolygon::default();
290        Self {
291            radius: def.radius,
292            sides: def.sides,
293        }
294    }
295}
296
297impl RegularPolygonPrefab {
298    pub fn to_mesh(&self) -> Mesh {
299        let data = shape::RegularPolygon {
300            radius: self.radius,
301            sides: self.sides,
302        };
303        Mesh::from(data)
304    }
305}
306
307/// Values to setup torus mesh
308#[derive(Reflect, Clone)]
309#[reflect(Default)]
310pub struct TorusPrefab {
311    pub radius: f32,
312    pub ring_radius: f32,
313    pub subdivisions_sides: usize,
314    pub subdivisions_segments: usize,
315}
316
317impl Default for TorusPrefab {
318    fn default() -> Self {
319        let def = shape::Torus::default();
320        Self {
321            radius: def.radius,
322            ring_radius: def.ring_radius,
323            subdivisions_sides: def.subdivisions_sides,
324            subdivisions_segments: def.subdivisions_segments,
325        }
326    }
327}
328
329impl TorusPrefab {
330    pub fn to_mesh(&self) -> Mesh {
331        let data = shape::Torus {
332            radius: self.radius,
333            ring_radius: self.ring_radius,
334            subdivisions_sides: self.subdivisions_sides,
335            subdivisions_segments: self.subdivisions_segments,
336        };
337        Mesh::from(data)
338    }
339}