1use core::ops::{RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
2
3use egui::emath::Numeric;
4
5use crate::{EguiProbe, Style, option::option_probe_with};
6
7pub struct StepUnset;
9
10pub struct EguiProbeRange<'a, T, R, S = StepUnset> {
12 pub value: &'a mut T,
13 pub range: R,
14 pub step: S,
15}
16
17pub fn non_negative<N: Numeric>(value: &mut N) -> EguiProbeRange<'_, N, RangeFrom<N>> {
18 EguiProbeRange {
19 value,
20 range: N::from_f64(0.0)..,
21 step: StepUnset,
22 }
23}
24
25macro_rules! impl_for_num_types {
58 ($num_type:ident) => {
59 impl EguiProbe for $num_type {
60 #[inline(always)]
61 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
62 ui.add(egui::DragValue::new(self))
63 }
64 }
65
66 impl EguiProbe for EguiProbeRange<'_, $num_type, RangeFull> {
67 #[inline(always)]
68 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
69 let range = $num_type::MIN..=$num_type::MAX;
70 ui.add(egui::DragValue::new(self.value).range(range))
71 }
72 }
73
74 impl EguiProbe for EguiProbeRange<'_, $num_type, RangeFrom<$num_type>> {
75 #[inline(always)]
76 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
77 let range = self.range.start..=$num_type::MAX;
78 let mut changed = false;
79 let mut r = ui.horizontal(|ui| {
80 changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
81 ui.weak(format!("{}..", self.range.start));
82 }).response;
83
84 if changed {
85 r.mark_changed();
86 }
87
88 r
89 }
90 }
91
92 impl EguiProbe for EguiProbeRange<'_, $num_type, RangeToInclusive<$num_type>> {
93 #[inline(always)]
94 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
95 let range = $num_type::MIN..=self.range.end;
96 let mut changed = false;
97 let mut r = ui.horizontal(|ui| {
98 changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
99 ui.weak(format!("..={}", self.range.end));
100 }).response;
101
102 if changed {
103 r.mark_changed();
104 }
105
106 r
107 }
108 }
109
110 impl EguiProbe for EguiProbeRange<'_, $num_type, RangeInclusive<$num_type>> {
111 #[inline(always)]
112 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
113 let range = self.range.clone();
114 let mut changed = false;
115 let mut r = ui.horizontal(|ui| {
116 changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
117 ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
118 }).response;
119
120 if changed {
121 r.mark_changed();
122 }
123
124 r
125 }
126 }
127
128 impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFull> {
129 #[inline(always)]
130 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
131 let range = $num_type::MIN..=$num_type::MAX;
132 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
133 ui.add(egui::DragValue::new(value).range(range))
134 })
135 }
136 }
137
138 impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFrom<$num_type>> {
139 #[inline(always)]
140 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
141 let range = self.range.start..=$num_type::MAX;
142 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
143 let r = ui.add(egui::DragValue::new(value).range(range));
144 ui.weak(format!("{}..", self.range.start));
145 r
146 })
147 }
148 }
149
150 impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeToInclusive<$num_type>> {
151 #[inline(always)]
152 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
153 let range = $num_type::MIN..=self.range.end;
154 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
155 let r = ui.add(egui::DragValue::new(value).range(range));
156 ui.weak(format!("..={}", self.range.end));
157 r
158 })
159 }
160 }
161
162 impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeInclusive<$num_type>> {
163 #[inline(always)]
164 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
165 let range = self.range.clone();
166 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
167 let r = ui.add(egui::DragValue::new(value).range(range));
168 ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
169 r
170 })
171 }
172 }
173
174
175
176
177
178
179
180 impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeFull, S> where S: Copy + Into<f64> {
181 #[inline(always)]
182 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
183 let range = $num_type::MIN..=$num_type::MAX;
184 ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into()))
185 }
186 }
187
188 impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeFrom<$num_type>, S> where S: Copy + Into<f64> {
189 #[inline(always)]
190 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
191 let range = self.range.start..=$num_type::MAX;
192 let mut changed = false;
193 let mut r = ui.horizontal(|ui| {
194 changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
195 ui.weak(format!("{}..", self.range.start));
196 }).response;
197
198 if changed {
199 r.mark_changed();
200 }
201
202 r
203 }
204 }
205
206 impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeToInclusive<$num_type>, S> where S: Copy + Into<f64> {
207 #[inline(always)]
208 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
209 let range = $num_type::MIN..=self.range.end;
210 let mut changed = false;
211 let mut r = ui.horizontal(|ui| {
212 changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
213 ui.weak(format!("..={}", self.range.end));
214 }).response;
215
216 if changed {
217 r.mark_changed();
218 }
219
220 r
221 }
222 }
223
224 impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeInclusive<$num_type>, S> where S: Copy + Into<f64> {
225 #[inline(always)]
226 fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
227 let range = self.range.clone();
228 let mut changed = false;
229 let mut r = ui.horizontal(|ui| {
230 changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
231 ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
232 }).response;
233
234 if changed {
235 r.mark_changed();
236 }
237
238 r
239 }
240 }
241
242 impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFull, S> where S: Copy + Into<f64> {
243 #[inline(always)]
244 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
245 let range = $num_type::MIN..=$num_type::MAX;
246 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
247 ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()))
248 })
249 }
250 }
251
252 impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFrom<$num_type>, S> where S: Copy + Into<f64> {
253 #[inline(always)]
254 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
255 let range = self.range.start..=$num_type::MAX;
256 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
257 let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
258 ui.weak(format!("{}..", self.range.start));
259 r
260 })
261 }
262 }
263
264 impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeToInclusive<$num_type>, S> where S: Copy + Into<f64> {
265 #[inline(always)]
266 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
267 let range = $num_type::MIN..=self.range.end;
268 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
269 let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
270 ui.weak(format!("..={}", self.range.end));
271 r
272 })
273 }
274 }
275
276 impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeInclusive<$num_type>, S> where S: Copy + Into<f64> {
277 #[inline(always)]
278 fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
279 let range = self.range.clone();
280 option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
281 let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
282 ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
283 r
284 })
285 }
286 }
287 };
288
289 ($($num_type:ident),*) => {
290 $(impl_for_num_types!($num_type);)*
291 };
292}
293
294impl_for_num_types!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);