Skip to main content

dioxus_three/
selection.rs

1//! Selection management for Dioxus Three
2
3use crate::input::EntityId;
4use std::collections::HashSet;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum SelectionMode {
8    #[default]
9    Single,
10    Multiple,
11    Toggle,
12}
13
14#[derive(Debug, Clone, PartialEq)]
15pub struct SelectionStyle {
16    pub outline: bool,
17    pub outline_color: String,
18    pub outline_width: f32,
19    pub highlight: bool,
20    pub highlight_color: String,
21    pub highlight_opacity: f32,
22    pub show_gizmo: bool,
23}
24
25impl Default for SelectionStyle {
26    fn default() -> Self {
27        Self {
28            outline: true,
29            outline_color: "#DEC647".to_string(),
30            outline_width: 2.0,
31            highlight: true,
32            highlight_color: "#DEC647".to_string(),
33            highlight_opacity: 0.3,
34            show_gizmo: true,
35        }
36    }
37}
38
39#[derive(Debug, Clone, PartialEq)]
40pub struct Selection {
41    selected: HashSet<EntityId>,
42    mode: SelectionMode,
43    last_selected: Option<EntityId>,
44}
45
46impl Selection {
47    pub fn new() -> Self {
48        Self::empty()
49    }
50
51    pub fn empty() -> Self {
52        Self {
53            selected: HashSet::new(),
54            mode: SelectionMode::Single,
55            last_selected: None,
56        }
57    }
58
59    pub fn with_mode(mode: SelectionMode) -> Self {
60        Self {
61            selected: HashSet::new(),
62            mode,
63            last_selected: None,
64        }
65    }
66
67    pub fn is_selected(&self, entity: EntityId) -> bool {
68        self.selected.contains(&entity)
69    }
70
71    pub fn select(&mut self, entity: EntityId) {
72        match self.mode {
73            SelectionMode::Single => {
74                self.selected.clear();
75                self.selected.insert(entity);
76            }
77            _ => {
78                self.selected.insert(entity);
79            }
80        }
81        self.last_selected = Some(entity);
82    }
83
84    pub fn toggle(&mut self, entity: EntityId) {
85        if self.selected.contains(&entity) {
86            self.selected.remove(&entity);
87        } else {
88            if self.mode == SelectionMode::Single {
89                self.selected.clear();
90            }
91            self.selected.insert(entity);
92        }
93        self.last_selected = Some(entity);
94    }
95
96    pub fn deselect(&mut self, entity: EntityId) {
97        self.selected.remove(&entity);
98        if self.last_selected == Some(entity) {
99            self.last_selected = self.selected.iter().copied().last();
100        }
101    }
102
103    pub fn clear(&mut self) {
104        self.selected.clear();
105        self.last_selected = None;
106    }
107
108    pub fn count(&self) -> usize {
109        self.selected.len()
110    }
111
112    pub fn has_selection(&self) -> bool {
113        !self.selected.is_empty()
114    }
115
116    pub fn primary(&self) -> Option<EntityId> {
117        self.last_selected
118    }
119
120    pub fn iter(&self) -> impl Iterator<Item = EntityId> + '_ {
121        self.selected.iter().copied()
122    }
123}
124
125impl Default for Selection {
126    fn default() -> Self {
127        Self::new()
128    }
129}