1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use viewport_lib::{
3 AttributeKind, BuiltinColourmap, BuiltinMatcap, ColourmapId, GlyphType, ParamVis,
4 ParamVisMode,
5};
6
7#[derive(Debug, Clone, PartialEq)]
9pub struct TransferFunction {
10 pub opacity_scale: f32,
12 pub threshold: Option<(f32, f32)>,
15}
16
17impl Default for TransferFunction {
18 fn default() -> Self {
19 Self {
20 opacity_scale: 0.5,
21 threshold: None,
22 }
23 }
24}
25
26#[derive(Serialize, Deserialize)]
27struct PersistedTransferFunction {
28 opacity_scale: f32,
29 threshold: Option<(f32, f32)>,
30}
31
32#[derive(Debug, Clone, PartialEq)]
34pub enum ColourMode {
35 Solid([f32; 4]),
37 Colormap {
39 colormap: ColormapSource,
41 scalar_range: Option<(f32, f32)>,
43 },
44 ByAttribute {
50 name: String,
52 kind: AttributeKind,
54 },
55}
56
57#[derive(Serialize, Deserialize)]
58enum PersistedColourMode {
59 Solid([f32; 4]),
60 Colormap {
61 colormap: u8,
62 scalar_range: Option<(f32, f32)>,
63 },
64 ByAttribute {
65 name: String,
66 kind: u8,
67 },
68}
69
70impl Default for ColourMode {
71 fn default() -> Self {
72 Self::Solid([0.4, 0.6, 1.0, 1.0])
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub enum ColormapSource {
79 Builtin(BuiltinColourmap),
81 Uploaded(ColourmapId),
83}
84
85impl Default for ColormapSource {
86 fn default() -> Self {
87 Self::Builtin(BuiltinColourmap::Viridis)
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
93pub enum ShadingMode {
94 Flat,
96 #[default]
98 Smooth,
99 Unlit,
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum MatcapSource {
106 Builtin(BuiltinMatcap),
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub enum SurfaceFaceQuantity {
113 AngleDistortion,
115 AreaDistortion,
117}
118
119impl SurfaceFaceQuantity {
120 pub fn attribute_name(self) -> &'static str {
122 match self {
123 Self::AngleDistortion => "angle_distortion",
124 Self::AreaDistortion => "area_distortion",
125 }
126 }
127}
128
129#[derive(Debug, Clone, Copy, PartialEq)]
131pub struct ParamVisSettings {
132 pub mode: ParamVisMode,
134 pub scale: f32,
136}
137
138#[derive(Serialize, Deserialize)]
139struct PersistedParamVis {
140 mode: u8,
141 scale: f32,
142}
143
144impl Default for ParamVisSettings {
145 fn default() -> Self {
146 Self {
147 mode: ParamVisMode::Checker,
148 scale: 8.0,
149 }
150 }
151}
152
153impl From<ParamVisSettings> for ParamVis {
154 fn from(value: ParamVisSettings) -> Self {
155 Self {
156 mode: value.mode,
157 scale: value.scale,
158 }
159 }
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub enum SurfaceLicVectorField {
165 TangentU,
167 TangentV,
169 Diagonal,
172 Saddle,
175}
176
177impl SurfaceLicVectorField {
178 pub fn attribute_name(self) -> &'static str {
180 match self {
181 Self::TangentU => "tangent_u",
182 Self::TangentV => "tangent_v",
183 Self::Diagonal => "tangent_diagonal",
184 Self::Saddle => "tangent_saddle",
185 }
186 }
187}
188
189#[derive(Debug, Clone, PartialEq)]
191pub struct SurfaceLicSettings {
192 pub vector_field: SurfaceLicVectorField,
194 pub steps: u32,
196 pub step_size: f32,
198 pub strength: f32,
200}
201
202#[derive(Serialize, Deserialize)]
203struct PersistedSurfaceLic {
204 vector_field: u8,
205 steps: u32,
206 step_size: f32,
207 strength: f32,
208}
209
210impl Default for SurfaceLicSettings {
211 fn default() -> Self {
212 Self {
213 vector_field: SurfaceLicVectorField::TangentU,
214 steps: 20,
215 step_size: 1.5,
216 strength: 2.0,
217 }
218 }
219}
220
221#[derive(Debug, Clone, PartialEq)]
223pub struct PlotStyle {
224 pub colour_mode: ColourMode,
226 pub opacity: f32,
228 pub two_sided: bool,
230 pub line_width: f32,
232 pub point_size: f32,
234 pub glyph_scale: f32,
236 pub glyph_type: GlyphType,
238 pub shading: ShadingMode,
240 pub tube_radius: Option<f32>,
243 pub transfer_function: Option<TransferFunction>,
246 pub matcap: Option<MatcapSource>,
248 pub param_vis: Option<ParamVisSettings>,
250 pub face_quantity: Option<SurfaceFaceQuantity>,
252 pub surface_lic: Option<SurfaceLicSettings>,
254}
255
256#[derive(Serialize, Deserialize)]
257struct PersistedPlotStyle {
258 colour_mode: PersistedColourMode,
259 opacity: f32,
260 two_sided: bool,
261 line_width: f32,
262 point_size: f32,
263 glyph_scale: f32,
264 glyph_type: u8,
265 shading: u8,
266 tube_radius: Option<f32>,
267 transfer_function: Option<PersistedTransferFunction>,
268 matcap: Option<u8>,
269 param_vis: Option<PersistedParamVis>,
270 face_quantity: Option<u8>,
271 surface_lic: Option<PersistedSurfaceLic>,
272}
273
274impl Default for PlotStyle {
275 fn default() -> Self {
276 Self {
277 colour_mode: ColourMode::default(),
278 opacity: 1.0,
279 two_sided: false,
280 line_width: 2.0,
281 point_size: 4.0,
282 glyph_scale: 1.0,
283 glyph_type: GlyphType::Arrow,
284 shading: ShadingMode::Smooth,
285 tube_radius: None,
286 transfer_function: None,
287 matcap: None,
288 param_vis: None,
289 face_quantity: None,
290 surface_lic: None,
291 }
292 }
293}
294
295impl Serialize for TransferFunction {
296 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297 where
298 S: Serializer,
299 {
300 PersistedTransferFunction {
301 opacity_scale: self.opacity_scale,
302 threshold: self.threshold,
303 }
304 .serialize(serializer)
305 }
306}
307
308impl<'de> Deserialize<'de> for TransferFunction {
309 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
310 where
311 D: Deserializer<'de>,
312 {
313 let persisted = PersistedTransferFunction::deserialize(deserializer)?;
314 Ok(Self {
315 opacity_scale: persisted.opacity_scale,
316 threshold: persisted.threshold,
317 })
318 }
319}
320
321impl Serialize for ColourMode {
322 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
323 where
324 S: Serializer,
325 {
326 let persisted = match self {
327 Self::Solid(rgba) => PersistedColourMode::Solid(*rgba),
328 Self::Colormap {
329 colormap,
330 scalar_range,
331 } => PersistedColourMode::Colormap {
332 colormap: match colormap {
333 ColormapSource::Builtin(preset) => builtin_colormap_to_u8(*preset),
334 ColormapSource::Uploaded(_) => builtin_colormap_to_u8(BuiltinColourmap::Viridis),
335 },
336 scalar_range: *scalar_range,
337 },
338 Self::ByAttribute { name, kind } => PersistedColourMode::ByAttribute {
339 name: name.clone(),
340 kind: attribute_kind_to_u8(*kind),
341 },
342 };
343 persisted.serialize(serializer)
344 }
345}
346
347impl<'de> Deserialize<'de> for ColourMode {
348 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
349 where
350 D: Deserializer<'de>,
351 {
352 let persisted = PersistedColourMode::deserialize(deserializer)?;
353 Ok(match persisted {
354 PersistedColourMode::Solid(rgba) => Self::Solid(rgba),
355 PersistedColourMode::Colormap {
356 colormap,
357 scalar_range,
358 } => Self::Colormap {
359 colormap: ColormapSource::Builtin(u8_to_builtin_colormap(colormap)),
360 scalar_range,
361 },
362 PersistedColourMode::ByAttribute { name, kind } => Self::ByAttribute {
363 name,
364 kind: u8_to_attribute_kind(kind),
365 },
366 })
367 }
368}
369
370impl Serialize for ParamVisSettings {
371 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
372 where
373 S: Serializer,
374 {
375 PersistedParamVis {
376 mode: param_vis_mode_to_u8(self.mode),
377 scale: self.scale,
378 }
379 .serialize(serializer)
380 }
381}
382
383impl<'de> Deserialize<'de> for ParamVisSettings {
384 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
385 where
386 D: Deserializer<'de>,
387 {
388 let persisted = PersistedParamVis::deserialize(deserializer)?;
389 Ok(Self {
390 mode: u8_to_param_vis_mode(persisted.mode),
391 scale: persisted.scale,
392 })
393 }
394}
395
396impl Serialize for SurfaceLicSettings {
397 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
398 where
399 S: Serializer,
400 {
401 PersistedSurfaceLic {
402 vector_field: surface_lic_vector_field_to_u8(self.vector_field),
403 steps: self.steps,
404 step_size: self.step_size,
405 strength: self.strength,
406 }
407 .serialize(serializer)
408 }
409}
410
411impl<'de> Deserialize<'de> for SurfaceLicSettings {
412 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
413 where
414 D: Deserializer<'de>,
415 {
416 let persisted = PersistedSurfaceLic::deserialize(deserializer)?;
417 Ok(Self {
418 vector_field: u8_to_surface_lic_vector_field(persisted.vector_field),
419 steps: persisted.steps,
420 step_size: persisted.step_size,
421 strength: persisted.strength,
422 })
423 }
424}
425
426impl Serialize for PlotStyle {
427 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
428 where
429 S: Serializer,
430 {
431 PersistedPlotStyle {
432 colour_mode: match &self.colour_mode {
433 ColourMode::Solid(rgba) => PersistedColourMode::Solid(*rgba),
434 ColourMode::Colormap {
435 colormap,
436 scalar_range,
437 } => PersistedColourMode::Colormap {
438 colormap: match colormap {
439 ColormapSource::Builtin(preset) => builtin_colormap_to_u8(*preset),
440 ColormapSource::Uploaded(_) => builtin_colormap_to_u8(BuiltinColourmap::Viridis),
441 },
442 scalar_range: *scalar_range,
443 },
444 ColourMode::ByAttribute { name, kind } => PersistedColourMode::ByAttribute {
445 name: name.clone(),
446 kind: attribute_kind_to_u8(*kind),
447 },
448 },
449 opacity: self.opacity,
450 two_sided: self.two_sided,
451 line_width: self.line_width,
452 point_size: self.point_size,
453 glyph_scale: self.glyph_scale,
454 glyph_type: glyph_type_to_u8(self.glyph_type),
455 shading: shading_to_u8(self.shading),
456 tube_radius: self.tube_radius,
457 transfer_function: self
458 .transfer_function
459 .as_ref()
460 .map(|tf| PersistedTransferFunction {
461 opacity_scale: tf.opacity_scale,
462 threshold: tf.threshold,
463 }),
464 matcap: self.matcap.map(|m| match m {
465 MatcapSource::Builtin(preset) => builtin_matcap_to_u8(preset),
466 }),
467 param_vis: self.param_vis.map(|pv| PersistedParamVis {
468 mode: param_vis_mode_to_u8(pv.mode),
469 scale: pv.scale,
470 }),
471 face_quantity: self.face_quantity.map(surface_face_quantity_to_u8),
472 surface_lic: self.surface_lic.as_ref().map(|lic| PersistedSurfaceLic {
473 vector_field: surface_lic_vector_field_to_u8(lic.vector_field),
474 steps: lic.steps,
475 step_size: lic.step_size,
476 strength: lic.strength,
477 }),
478 }
479 .serialize(serializer)
480 }
481}
482
483impl<'de> Deserialize<'de> for PlotStyle {
484 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
485 where
486 D: Deserializer<'de>,
487 {
488 let persisted = PersistedPlotStyle::deserialize(deserializer)?;
489 Ok(Self {
490 colour_mode: match persisted.colour_mode {
491 PersistedColourMode::Solid(rgba) => ColourMode::Solid(rgba),
492 PersistedColourMode::Colormap {
493 colormap,
494 scalar_range,
495 } => ColourMode::Colormap {
496 colormap: ColormapSource::Builtin(u8_to_builtin_colormap(colormap)),
497 scalar_range,
498 },
499 PersistedColourMode::ByAttribute { name, kind } => ColourMode::ByAttribute {
500 name,
501 kind: u8_to_attribute_kind(kind),
502 },
503 },
504 opacity: persisted.opacity,
505 two_sided: persisted.two_sided,
506 line_width: persisted.line_width,
507 point_size: persisted.point_size,
508 glyph_scale: persisted.glyph_scale,
509 glyph_type: u8_to_glyph_type(persisted.glyph_type),
510 shading: u8_to_shading(persisted.shading),
511 tube_radius: persisted.tube_radius,
512 transfer_function: persisted.transfer_function.map(|tf| TransferFunction {
513 opacity_scale: tf.opacity_scale,
514 threshold: tf.threshold,
515 }),
516 matcap: persisted
517 .matcap
518 .map(|m| MatcapSource::Builtin(u8_to_builtin_matcap(m))),
519 param_vis: persisted.param_vis.map(|pv| ParamVisSettings {
520 mode: u8_to_param_vis_mode(pv.mode),
521 scale: pv.scale,
522 }),
523 face_quantity: persisted.face_quantity.map(u8_to_surface_face_quantity),
524 surface_lic: persisted.surface_lic.map(|lic| SurfaceLicSettings {
525 vector_field: u8_to_surface_lic_vector_field(lic.vector_field),
526 steps: lic.steps,
527 step_size: lic.step_size,
528 strength: lic.strength,
529 }),
530 })
531 }
532}
533
534fn builtin_colormap_to_u8(value: BuiltinColourmap) -> u8 {
535 match value {
536 BuiltinColourmap::Viridis => 0,
537 BuiltinColourmap::Plasma => 1,
538 BuiltinColourmap::Greyscale => 2,
539 BuiltinColourmap::Coolwarm => 3,
540 BuiltinColourmap::Rainbow => 4,
541 BuiltinColourmap::Magma => 5,
542 BuiltinColourmap::Inferno => 6,
543 BuiltinColourmap::Turbo => 7,
544 BuiltinColourmap::Jet => 8,
545 BuiltinColourmap::RdBu => 9,
546 }
547}
548
549fn u8_to_builtin_colormap(value: u8) -> BuiltinColourmap {
550 match value {
551 1 => BuiltinColourmap::Plasma,
552 2 => BuiltinColourmap::Greyscale,
553 3 => BuiltinColourmap::Coolwarm,
554 4 => BuiltinColourmap::Rainbow,
555 5 => BuiltinColourmap::Magma,
556 6 => BuiltinColourmap::Inferno,
557 7 => BuiltinColourmap::Turbo,
558 8 => BuiltinColourmap::Jet,
559 9 => BuiltinColourmap::RdBu,
560 _ => BuiltinColourmap::Viridis,
561 }
562}
563
564fn attribute_kind_to_u8(value: AttributeKind) -> u8 {
565 match value {
566 AttributeKind::Vertex => 0,
567 AttributeKind::Cell => 1,
568 AttributeKind::Face => 2,
569 AttributeKind::FaceColour => 3,
570 AttributeKind::Edge => 4,
571 AttributeKind::Halfedge => 5,
572 AttributeKind::Corner => 6,
573 }
574}
575
576fn u8_to_attribute_kind(value: u8) -> AttributeKind {
577 match value {
578 1 => AttributeKind::Cell,
579 2 => AttributeKind::Face,
580 3 => AttributeKind::FaceColour,
581 4 => AttributeKind::Edge,
582 5 => AttributeKind::Halfedge,
583 6 => AttributeKind::Corner,
584 _ => AttributeKind::Vertex,
585 }
586}
587
588fn shading_to_u8(value: ShadingMode) -> u8 {
589 match value {
590 ShadingMode::Flat => 0,
591 ShadingMode::Smooth => 1,
592 ShadingMode::Unlit => 2,
593 }
594}
595
596fn u8_to_shading(value: u8) -> ShadingMode {
597 match value {
598 0 => ShadingMode::Flat,
599 2 => ShadingMode::Unlit,
600 _ => ShadingMode::Smooth,
601 }
602}
603
604fn glyph_type_to_u8(value: GlyphType) -> u8 {
605 match value {
606 GlyphType::Arrow => 0,
607 GlyphType::Sphere => 1,
608 GlyphType::Cube => 2,
609 }
610}
611
612fn u8_to_glyph_type(value: u8) -> GlyphType {
613 match value {
614 1 => GlyphType::Sphere,
615 2 => GlyphType::Cube,
616 _ => GlyphType::Arrow,
617 }
618}
619
620fn builtin_matcap_to_u8(value: BuiltinMatcap) -> u8 {
621 value as u8
622}
623
624fn u8_to_builtin_matcap(value: u8) -> BuiltinMatcap {
625 match value {
626 1 => BuiltinMatcap::Wax,
627 2 => BuiltinMatcap::Candy,
628 3 => BuiltinMatcap::Flat,
629 4 => BuiltinMatcap::Ceramic,
630 5 => BuiltinMatcap::Jade,
631 6 => BuiltinMatcap::Mud,
632 7 => BuiltinMatcap::Normal,
633 _ => BuiltinMatcap::Clay,
634 }
635}
636
637fn param_vis_mode_to_u8(value: ParamVisMode) -> u8 {
638 match value {
639 ParamVisMode::Checker => 0,
640 ParamVisMode::Grid => 1,
641 ParamVisMode::LocalChecker => 2,
642 ParamVisMode::LocalRadial => 3,
643 }
644}
645
646fn u8_to_param_vis_mode(value: u8) -> ParamVisMode {
647 match value {
648 1 => ParamVisMode::Grid,
649 2 => ParamVisMode::LocalChecker,
650 3 => ParamVisMode::LocalRadial,
651 _ => ParamVisMode::Checker,
652 }
653}
654
655fn surface_face_quantity_to_u8(value: SurfaceFaceQuantity) -> u8 {
656 match value {
657 SurfaceFaceQuantity::AngleDistortion => 0,
658 SurfaceFaceQuantity::AreaDistortion => 1,
659 }
660}
661
662fn u8_to_surface_face_quantity(value: u8) -> SurfaceFaceQuantity {
663 match value {
664 1 => SurfaceFaceQuantity::AreaDistortion,
665 _ => SurfaceFaceQuantity::AngleDistortion,
666 }
667}
668
669fn surface_lic_vector_field_to_u8(value: SurfaceLicVectorField) -> u8 {
670 match value {
671 SurfaceLicVectorField::TangentU => 0,
672 SurfaceLicVectorField::TangentV => 1,
673 SurfaceLicVectorField::Diagonal => 2,
674 SurfaceLicVectorField::Saddle => 3,
675 }
676}
677
678fn u8_to_surface_lic_vector_field(value: u8) -> SurfaceLicVectorField {
679 match value {
680 1 => SurfaceLicVectorField::TangentV,
681 2 => SurfaceLicVectorField::Diagonal,
682 3 => SurfaceLicVectorField::Saddle,
683 _ => SurfaceLicVectorField::TangentU,
684 }
685}