bevy_inspector_egui/inspector_options/
std_options.rs

1use bevy_ecs::entity::Entity;
2use std::collections::VecDeque;
3
4use crate::InspectorOptions;
5
6use super::{InspectorOptionsType, Target};
7
8macro_rules! impl_options {
9    ($ty:ty => $options:ty) => {
10        impl InspectorOptionsType for $ty {
11            type DeriveOptions = $options;
12            type Options = $options;
13
14            fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
15                options
16            }
17        }
18    };
19}
20macro_rules! impl_options_defer_generic {
21    ($name:ident < $generic:ident >) => {
22        impl<$generic: InspectorOptionsType> InspectorOptionsType for $name<$generic> {
23            type DeriveOptions = <$generic as InspectorOptionsType>::DeriveOptions;
24            type Options = <$generic as InspectorOptionsType>::Options;
25
26            fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
27                $generic::options_from_derive(options)
28            }
29        }
30    };
31}
32
33#[derive(Clone)]
34#[non_exhaustive]
35pub struct NumberOptions<T> {
36    pub min: Option<T>,
37    pub max: Option<T>,
38    pub speed: f32,
39    pub prefix: String,
40    pub suffix: String,
41    pub display: NumberDisplay,
42}
43
44impl<T> Default for NumberOptions<T> {
45    fn default() -> Self {
46        Self {
47            min: None,
48            max: None,
49            speed: 0.0,
50            prefix: String::new(),
51            suffix: String::new(),
52            display: NumberDisplay::default(),
53        }
54    }
55}
56
57#[derive(Clone, Copy, Default)]
58#[non_exhaustive]
59pub enum NumberDisplay {
60    #[default]
61    Drag,
62    Slider,
63}
64
65impl<T> NumberOptions<T> {
66    pub fn between(min: T, max: T) -> NumberOptions<T> {
67        NumberOptions {
68            min: Some(min),
69            max: Some(max),
70            speed: 0.0,
71            prefix: String::new(),
72            suffix: String::new(),
73            display: NumberDisplay::default(),
74        }
75    }
76    pub fn at_least(min: T) -> NumberOptions<T> {
77        NumberOptions {
78            min: Some(min),
79            max: None,
80            speed: 0.0,
81            prefix: String::new(),
82            suffix: String::new(),
83            display: NumberDisplay::default(),
84        }
85    }
86
87    pub fn with_speed(self, speed: f32) -> NumberOptions<T> {
88        NumberOptions { speed, ..self }
89    }
90
91    pub fn map<U>(&self, f: impl Fn(&T) -> U) -> NumberOptions<U> {
92        NumberOptions {
93            #[allow(clippy::redundant_closure)] // false positive
94            min: self.min.as_ref().map(|min| f(min)),
95            max: self.max.as_ref().map(f),
96            speed: self.speed,
97            prefix: self.prefix.clone(),
98            suffix: self.suffix.clone(),
99            display: NumberDisplay::default(),
100        }
101    }
102}
103impl<T: egui::emath::Numeric> NumberOptions<T> {
104    pub fn positive() -> NumberOptions<T> {
105        NumberOptions {
106            min: Some(T::from_f64(0.0)),
107            max: None,
108            speed: 0.0,
109            prefix: String::new(),
110            suffix: String::new(),
111            display: NumberDisplay::default(),
112        }
113    }
114
115    pub fn normalized() -> Self {
116        NumberOptions {
117            min: Some(T::from_f64(0.0)),
118            max: Some(T::from_f64(1.0)),
119            speed: 0.01,
120            prefix: String::new(),
121            suffix: String::new(),
122            display: NumberDisplay::default(),
123        }
124    }
125}
126
127impl_options!(f32 => NumberOptions<f32>);
128impl_options!(f64 => NumberOptions<f64>);
129impl_options!(i8 => NumberOptions<i8>);
130impl_options!(i16 => NumberOptions<i16>);
131impl_options!(i32 => NumberOptions<i32>);
132impl_options!(i64 => NumberOptions<i64>);
133impl_options!(i128 => NumberOptions<i128>);
134impl_options!(isize => NumberOptions<isize>);
135impl_options!(u8 => NumberOptions<u8>);
136impl_options!(u16 => NumberOptions<u16>);
137impl_options!(u32 => NumberOptions<u32>);
138impl_options!(u64 => NumberOptions<u64>);
139impl_options!(u128 => NumberOptions<u128>);
140impl_options!(usize => NumberOptions<usize>);
141
142#[non_exhaustive]
143pub struct RangeOptions<T: InspectorOptionsType> {
144    pub start: T::Options,
145    pub end: T::Options,
146}
147
148impl<T: InspectorOptionsType> Clone for RangeOptions<T> {
149    fn clone(&self) -> Self {
150        Self {
151            start: self.start.clone(),
152            end: self.end.clone(),
153        }
154    }
155}
156
157impl<T: InspectorOptionsType> Default for RangeOptions<T> {
158    fn default() -> Self {
159        Self {
160            start: T::options_from_derive(T::DeriveOptions::default()),
161            end: T::options_from_derive(T::DeriveOptions::default()),
162        }
163    }
164}
165
166impl<T: InspectorOptionsType + 'static> InspectorOptionsType for std::ops::Range<T> {
167    type DeriveOptions = RangeOptions<T>;
168    type Options = RangeOptions<T>;
169
170    fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
171        options
172    }
173}
174impl<T: InspectorOptionsType + 'static> InspectorOptionsType for std::ops::RangeInclusive<T> {
175    type DeriveOptions = RangeOptions<T>;
176    type Options = RangeOptions<T>;
177
178    fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
179        options
180    }
181}
182
183#[derive(Default, Clone)]
184#[non_exhaustive]
185pub struct QuatOptions {
186    pub display: QuatDisplay,
187}
188
189#[derive(Copy, Clone, Default)]
190pub enum QuatDisplay {
191    Raw,
192    #[default]
193    Euler,
194    YawPitchRoll,
195    AxisAngle,
196}
197
198impl_options!(bevy_math::Quat => QuatOptions);
199
200#[derive(Clone)]
201#[non_exhaustive]
202pub struct EntityOptions {
203    pub display: EntityDisplay,
204    pub despawnable: bool,
205}
206
207impl Default for EntityOptions {
208    fn default() -> Self {
209        Self {
210            display: EntityDisplay::default(),
211            despawnable: true,
212        }
213    }
214}
215
216#[derive(Copy, Clone, Default)]
217#[non_exhaustive]
218pub enum EntityDisplay {
219    Id,
220    #[default]
221    Components,
222}
223
224impl_options!(Entity => EntityOptions);
225
226impl<T: InspectorOptionsType> InspectorOptionsType for Option<T> {
227    type DeriveOptions = T::DeriveOptions;
228    type Options = InspectorOptions;
229
230    fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
231        let inner_options = T::options_from_derive(options);
232
233        let mut inspector_options = InspectorOptions::new();
234        inspector_options.insert(
235            Target::VariantField {
236                variant_index: 1, // Some
237                field_index: 0,
238            },
239            inner_options,
240        );
241
242        inspector_options
243    }
244}
245
246impl_options_defer_generic!(Vec<T>);
247impl_options_defer_generic!(VecDeque<T>);
248
249impl<T: InspectorOptionsType, const N: usize> InspectorOptionsType for [T; N] {
250    type DeriveOptions = T::DeriveOptions;
251    type Options = T::Options;
252
253    fn options_from_derive(options: Self::DeriveOptions) -> Self::Options {
254        T::options_from_derive(options)
255    }
256}