1use crate::engine_state::EngineState;
9use crate::scene::{RenderScene, SolidDisplay};
10use std::collections::HashSet;
11
12pub(crate) fn named_visibility(
14 names: impl IntoIterator<Item = String>,
15 hidden: &HashSet<String>,
16) -> Vec<(String, bool)> {
17 names.into_iter().map(|name| {
18 let visible = !hidden.contains(&name);
19 (name, visible)
20 }).collect()
21}
22
23pub(crate) fn named_visibility_json(entries: Vec<(String, bool)>) -> String {
24 let list: Vec<serde_json::Value> = entries.into_iter()
25 .map(|(name, visible)| serde_json::json!({ "name": name, "visible": visible }))
26 .collect();
27 serde_json::Value::Array(list).to_string()
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum EntityKind {
33 Face,
34 Edge,
35 Vertex,
36}
37
38impl EntityKind {
39 pub fn parse(kind: &str) -> Option<Self> {
42 match kind.to_ascii_lowercase().as_str() {
43 "face" => Some(Self::Face),
44 "edge" => Some(Self::Edge),
45 "vertex" => Some(Self::Vertex),
46 _ => None,
47 }
48 }
49
50 pub fn as_str(self) -> &'static str {
52 match self {
53 Self::Face => "face",
54 Self::Edge => "edge",
55 Self::Vertex => "vertex",
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum GroupState {
64 All,
65 Partial,
66 None,
67}
68
69impl GroupState {
70 pub fn as_str(self) -> &'static str {
73 match self {
74 Self::All => "all",
75 Self::Partial => "partial",
76 Self::None => "none",
77 }
78 }
79}
80
81#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
84pub struct EntityVisibility {
85 hidden_faces: HashSet<usize>,
86 hidden_edges: HashSet<usize>,
87 hidden_vertices: HashSet<usize>,
88}
89
90impl EntityVisibility {
91 fn set_of(&self, kind: EntityKind) -> &HashSet<usize> {
92 match kind {
93 EntityKind::Face => &self.hidden_faces,
94 EntityKind::Edge => &self.hidden_edges,
95 EntityKind::Vertex => &self.hidden_vertices,
96 }
97 }
98
99 fn set_mut(&mut self, kind: EntityKind) -> &mut HashSet<usize> {
100 match kind {
101 EntityKind::Face => &mut self.hidden_faces,
102 EntityKind::Edge => &mut self.hidden_edges,
103 EntityKind::Vertex => &mut self.hidden_vertices,
104 }
105 }
106
107 pub fn is_visible(&self, kind: EntityKind, index: usize) -> bool {
109 !self.set_of(kind).contains(&index)
110 }
111
112 pub fn any_hidden(&self, kind: EntityKind) -> bool {
115 !self.set_of(kind).is_empty()
116 }
117
118 pub fn set_visible(&mut self, kind: EntityKind, index: usize, visible: bool) {
120 if visible {
121 self.set_mut(kind).remove(&index);
122 } else {
123 self.set_mut(kind).insert(index);
124 }
125 }
126
127 pub fn set_group_visible(&mut self, kind: EntityKind, count: usize, visible: bool) {
130 let set = self.set_mut(kind);
131 set.clear();
132 if !visible {
133 set.extend(0..count);
134 }
135 }
136
137 pub fn group_state(&self, kind: EntityKind, count: usize) -> GroupState {
142 if count == 0 {
143 return GroupState::All;
144 }
145 let hidden = self.set_of(kind).len();
146 if hidden == 0 {
147 GroupState::All
148 } else if hidden >= count {
149 GroupState::None
150 } else {
151 GroupState::Partial
152 }
153 }
154
155 pub fn is_face_visible(&self, index: usize) -> bool {
157 self.is_visible(EntityKind::Face, index)
158 }
159 pub fn is_edge_visible(&self, index: usize) -> bool {
160 self.is_visible(EntityKind::Edge, index)
161 }
162 pub fn is_vertex_visible(&self, index: usize) -> bool {
163 self.is_visible(EntityKind::Vertex, index)
164 }
165 pub fn any_face_hidden(&self) -> bool {
166 self.any_hidden(EntityKind::Face)
167 }
168 pub fn any_edge_hidden(&self) -> bool {
169 self.any_hidden(EntityKind::Edge)
170 }
171 pub fn any_vertex_hidden(&self) -> bool {
172 self.any_hidden(EntityKind::Vertex)
173 }
174
175 pub fn all_hidden(&self, kind: EntityKind, count: usize) -> bool {
183 count > 0 && self.set_of(kind).len() >= count
184 }
185 pub fn all_vertices_hidden(&self, count: usize) -> bool {
186 self.all_hidden(EntityKind::Vertex, count)
187 }
188}
189
190fn entity_count(solid: &SolidDisplay, kind: EntityKind) -> usize {
192 match kind {
193 EntityKind::Face => solid.faces.len(),
194 EntityKind::Edge => solid.edges.len(),
195 EntityKind::Vertex => solid.vertices.len(),
196 }
197}
198
199impl RenderScene {
202 pub fn set_entity_visible(
204 &mut self,
205 solid: &str,
206 kind: EntityKind,
207 index: usize,
208 visible: bool,
209 ) -> bool {
210 match self.solid_mut(solid) {
211 Some(s) => {
212 s.visibility.set_visible(kind, index, visible);
213 true
214 }
215 None => false,
216 }
217 }
218
219 pub fn set_group_visible(&mut self, solid: &str, kind: EntityKind, visible: bool) -> bool {
222 let Some(count) = self.solid(solid).map(|s| entity_count(s, kind)) else {
223 return false;
224 };
225 if let Some(s) = self.solid_mut(solid) {
227 s.visibility.set_group_visible(kind, count, visible);
228 }
229 true
230 }
231
232 pub fn entity_visible(&self, solid: &str, kind: EntityKind, index: usize) -> Option<bool> {
234 self.solid(solid).map(|s| s.visibility.is_visible(kind, index))
235 }
236
237 pub fn group_visibility(&self, solid: &str, kind: EntityKind) -> Option<GroupState> {
239 self.solid(solid)
240 .map(|s| s.visibility.group_state(kind, entity_count(s, kind)))
241 }
242}
243
244impl EngineState {
247 pub fn set_entity_visible(
251 &mut self,
252 solid: &str,
253 kind: EntityKind,
254 index: usize,
255 visible: bool,
256 ) -> bool {
257 let ok = self.scene.set_entity_visible(solid, kind, index, visible);
258 if ok {
259 self.dirty = true;
260 }
261 ok
262 }
263
264 pub fn set_group_visible(&mut self, solid: &str, kind: EntityKind, visible: bool) -> bool {
267 let ok = self.scene.set_group_visible(solid, kind, visible);
268 if ok {
269 self.dirty = true;
270 }
271 ok
272 }
273
274 pub fn entity_visible(&self, solid: &str, kind: EntityKind, index: usize) -> Option<bool> {
276 self.scene.entity_visible(solid, kind, index)
277 }
278
279 pub fn group_visibility(&self, solid: &str, kind: EntityKind) -> Option<GroupState> {
281 self.scene.group_visibility(solid, kind)
282 }
283
284 pub fn scene_visibility_json(&self) -> String {
292 let kinds = [
293 ("faces", EntityKind::Face),
294 ("edges", EntityKind::Edge),
295 ("vertices", EntityKind::Vertex),
296 ];
297 let solids: Vec<serde_json::Value> = self
298 .scene
299 .solids()
300 .iter()
301 .map(|solid| {
302 let mut obj = serde_json::Map::new();
303 obj.insert("name".into(), serde_json::json!(solid.name));
304 obj.insert("visible".into(), serde_json::json!(solid.visible));
305 for (key, kind) in kinds {
306 let count = entity_count(solid, kind);
307 let states: Vec<bool> =
308 (0..count).map(|i| solid.visibility.is_visible(kind, i)).collect();
309 obj.insert(
310 key.into(),
311 serde_json::json!({
312 "group": solid.visibility.group_state(kind, count).as_str(),
313 "states": states,
314 }),
315 );
316 }
317 serde_json::Value::Object(obj)
318 })
319 .collect();
320 serde_json::Value::Array(solids).to_string()
321 }
322}
323
324