honeycomb_render/capture/
system.rs

1use bevy::color::Color;
2use bevy::prelude::*;
3use bevy_mod_outline::{OutlineBundle, OutlineVolume};
4use bevy_mod_picking::PickableBundle;
5
6use crate::capture::{CaptureList, FocusedCapture};
7use crate::resources::{
8    DartHeadHandle, DartHeadMul, DartMatHandle, DartRenderColor, DartShrink, DartWidth,
9    EdgeMatHandle, EdgeRenderColor, EdgeWidth, FaceMatHandle, FaceNormals, FaceRenderColor,
10    FaceShrink, MapVertices, VertexHandle, VertexMatHandle, VertexRenderColor, VertexWidth,
11};
12
13/// System used to generate dart entities in the ECS.
14#[allow(clippy::too_many_arguments)]
15pub fn populate_darts(
16    mut commands: Commands,
17    mut meshes: ResMut<Assets<Mesh>>,
18    mut materials: ResMut<Assets<StandardMaterial>>,
19    focused_capture: Res<FocusedCapture>,
20    captures: Res<CaptureList>,
21    dart_render_color: Res<DartRenderColor>,
22    dart_head_mul: Res<DartHeadMul>,
23    dart_width: Res<DartWidth>,
24    dart_shrink: Res<DartShrink>,
25) {
26    let head_shape = Cone {
27        radius: dart_head_mul.0 * dart_width.0 / 2.,
28        height: dart_head_mul.0 * dart_width.0 / 2.,
29    };
30    let dart_head_handle = meshes.add(head_shape);
31    let dart_mat = materials.add(Color::Srgba(Srgba::from_u8_array(
32        dart_render_color.1.to_array(),
33    )));
34    for capture in &captures.0 {
35        let vertices = &capture.vertex_vals;
36        let normals = &capture.normals;
37        let visibility =
38            if focused_capture.0 .0 == capture.metadata.capture_id && dart_render_color.0 {
39                Visibility::Visible
40            } else {
41                Visibility::Hidden
42            };
43        for (head, body) in &capture.darts {
44            let face_id = head.face_id.0;
45            let (n1, n2) = (
46                &normals[&face_id][body.dart_body.normals.0],
47                &normals[&face_id][body.dart_body.normals.1],
48            );
49            let (ov1, ov2) = (
50                &vertices[body.dart_body.vertices.0],
51                &vertices[body.dart_body.vertices.1],
52            );
53            let (v1, v2) = (*ov1 + (*n1 * dart_shrink.0), *ov2 + (*n2 * dart_shrink.0));
54            let (dir, len) = ((v2 - v1).normalize(), (v2 - v1).length());
55
56            let mut transform = Transform::from_translation((v1 + v2) / 2.);
57            transform.rotation = if dir == Vec3::Y {
58                Quat::IDENTITY
59            } else {
60                Quat::from_rotation_arc(Vec3::Y, dir)
61            };
62            // dart body
63            commands
64                .spawn((
65                    body.clone(),
66                    PbrBundle {
67                        mesh: meshes.add(Cylinder::new(
68                            dart_width.0 / 2.,
69                            // FIXME: clunky
70                            len * (1. - dart_shrink.0.abs()),
71                        )),
72                        material: dart_mat.clone(),
73                        transform,
74                        visibility,
75                        ..Default::default()
76                    },
77                    PickableBundle::default(),
78                ))
79                .insert(OutlineBundle {
80                    outline: OutlineVolume {
81                        visible: false,
82                        colour: Color::WHITE,
83                        width: 1.0,
84                    },
85                    ..default()
86                });
87            // dart head
88            // FIXME: clunky
89            let mut transform_head = Transform::from_translation(
90                (v1 + v2 + dir * len * (1. - dart_shrink.0.abs())) / 2.,
91            );
92            transform_head.rotation = Quat::from_rotation_arc(Vec3::Y, dir);
93            commands
94                .spawn((
95                    head.clone(),
96                    PbrBundle {
97                        mesh: dart_head_handle.clone(),
98                        material: dart_mat.clone(),
99                        transform: transform_head,
100                        visibility,
101                        ..Default::default()
102                    },
103                    PickableBundle::default(),
104                ))
105                .insert(OutlineBundle {
106                    outline: OutlineVolume {
107                        visible: false,
108                        colour: Color::WHITE,
109                        width: 1.0,
110                    },
111                    ..default()
112                });
113        }
114        commands.insert_resource(MapVertices(vertices.clone()));
115        commands.insert_resource(FaceNormals(normals.clone()));
116    }
117    commands.insert_resource(DartHeadHandle(dart_head_handle));
118    commands.insert_resource(DartMatHandle(dart_mat));
119}
120
121/// System used to generate beta entities in the ECS.
122#[allow(unused)]
123pub fn populate_beta() {
124    todo!()
125}
126
127/// System used to generate vertex entities in the ECS.
128pub fn populate_vertices(
129    mut commands: Commands,
130    mut meshes: ResMut<Assets<Mesh>>,
131    mut materials: ResMut<Assets<StandardMaterial>>,
132    focused_capture: Res<FocusedCapture>,
133    captures: Res<CaptureList>,
134    vertex_render_color: Res<VertexRenderColor>,
135    vertex_width: Res<VertexWidth>,
136) {
137    let vertex_handle = meshes.add(Sphere::new(vertex_width.0 / 2.));
138    let vertex_mat = materials.add(StandardMaterial {
139        unlit: true,
140        base_color: Color::Srgba(Srgba::from_u8_array(vertex_render_color.1.to_array())),
141        ..default()
142    });
143    for capture in &captures.0 {
144        let vertices = &capture.vertex_vals;
145        let visibility =
146            if focused_capture.0 .0 == capture.metadata.capture_id && vertex_render_color.0 {
147                Visibility::Visible
148            } else {
149                Visibility::Hidden
150            };
151        // insert vertices
152        for vertex in &capture.vertices {
153            commands
154                .spawn((
155                    vertex.clone(),
156                    PbrBundle {
157                        mesh: vertex_handle.clone(),
158                        material: vertex_mat.clone(),
159                        transform: Transform::from_translation(vertices[vertex.vertex.0]),
160                        visibility,
161                        ..Default::default()
162                    },
163                    PickableBundle::default(),
164                ))
165                .insert(OutlineBundle {
166                    outline: OutlineVolume {
167                        visible: false,
168                        colour: Color::WHITE,
169                        width: 1.0,
170                    },
171                    ..default()
172                });
173        }
174    }
175    commands.insert_resource(VertexHandle(vertex_handle));
176    commands.insert_resource(VertexMatHandle(vertex_mat));
177}
178
179/// System used to generate edge entities in the ECS.
180pub fn populate_edges(
181    mut commands: Commands,
182    mut meshes: ResMut<Assets<Mesh>>,
183    mut materials: ResMut<Assets<StandardMaterial>>,
184    focused_capture: Res<FocusedCapture>,
185    captures: Res<CaptureList>,
186    edge_render_color: Res<EdgeRenderColor>,
187    edge_width: Res<EdgeWidth>,
188) {
189    let edge_mat = materials.add(StandardMaterial {
190        unlit: true,
191        base_color: Color::Srgba(Srgba::from_u8_array(edge_render_color.1.to_array())),
192        ..default()
193    });
194    for capture in &captures.0 {
195        let vertices = &capture.vertex_vals;
196        let visibility =
197            if focused_capture.0 .0 == capture.metadata.capture_id && edge_render_color.0 {
198                Visibility::Visible
199            } else {
200                Visibility::Hidden
201            };
202        for edge in &capture.edges {
203            let v1 = &vertices[edge.edge.0]; // == translation
204            let v2 = &vertices[edge.edge.1];
205            let (dir, len) = ((*v2 - *v1).normalize(), (*v2 - *v1).length());
206            let mut transform = Transform::from_translation((*v1 + *v2) / 2.);
207            transform.rotation = if dir == Vec3::Y {
208                Quat::IDENTITY
209            } else {
210                Quat::from_rotation_arc(Vec3::Y, dir)
211            };
212            commands
213                .spawn((
214                    edge.clone(),
215                    PbrBundle {
216                        mesh: meshes.add(Cylinder::new(edge_width.0 / 2., len)),
217                        material: edge_mat.clone(),
218                        transform,
219                        visibility,
220                        ..Default::default()
221                    },
222                    PickableBundle::default(),
223                ))
224                .insert(OutlineBundle {
225                    outline: OutlineVolume {
226                        visible: false,
227                        colour: Color::WHITE,
228                        width: 1.0,
229                    },
230                    ..default()
231                });
232        }
233    }
234    commands.insert_resource(EdgeMatHandle(edge_mat));
235}
236
237/// System used to generate face entities in the ECS.
238///
239/// NOT YET IMPLEMENTED
240#[allow(unused)]
241pub fn populate_faces(
242    mut commands: Commands,
243    mut materials: ResMut<Assets<StandardMaterial>>,
244    focused_capture: Res<FocusedCapture>,
245    captures: Res<CaptureList>,
246    face_render_color: Res<FaceRenderColor>,
247    face_shrink: Res<FaceShrink>,
248) {
249    let face_mat = materials.add(Color::Srgba(Srgba::from_u8_array(
250        face_render_color.1.to_array(),
251    )));
252    for capture in &captures.0 {
253        let vertices = &capture.vertex_vals;
254        let normals = &capture.normals;
255        let visibility =
256            if focused_capture.0 .0 == capture.metadata.capture_id && face_render_color.0 {
257                Visibility::Visible
258            } else {
259                Visibility::Hidden
260            };
261        for face in &capture.faces {
262            let loc_n = &normals[&face.id.0];
263            let ovs = face
264                .face
265                .0
266                .iter()
267                .map(|id| vertices[*id])
268                .collect::<Vec<_>>();
269            let nvs: Vec<_> = loc_n
270                .iter()
271                .zip(ovs.iter())
272                .map(|(vertex, normal)| (*vertex + *normal * face_shrink.0).truncate())
273                .collect();
274        }
275    }
276    commands.insert_resource(FaceMatHandle(face_mat));
277}