rapier_testbed3d_f64/testbed/
state.rs1use bitflags::bitflags;
4
5use crate::physics::{PhysicsSnapshot, RapierBroadPhaseType};
6use crate::save::SerializableTestbedState;
7use crate::settings::ExampleSettings;
8
9#[derive(Default, PartialEq, Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
11pub enum RunMode {
12 Running,
13 #[default]
14 Stop,
15 Step,
16}
17
18#[derive(Copy, Clone, PartialEq, Eq, Debug)]
24pub enum Transition {
25 Quit,
26 Switch,
27}
28
29bitflags! {
30 #[derive(Copy, Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
32 pub struct TestbedStateFlags: u32 {
33 const SLEEP = 1 << 0;
34 const SUB_STEPPING = 1 << 1;
35 const SHAPES = 1 << 2;
36 const JOINTS = 1 << 3;
37 const AABBS = 1 << 4;
38 const CONTACT_POINTS = 1 << 5;
39 const CONTACT_NORMALS = 1 << 6;
40 const CENTER_OF_MASSES = 1 << 7;
41 const WIREFRAME = 1 << 8;
42 const STATISTICS = 1 << 9;
43 const DRAW_SURFACES = 1 << 10;
44 }
45}
46
47impl Default for TestbedStateFlags {
48 fn default() -> Self {
49 TestbedStateFlags::DRAW_SURFACES | TestbedStateFlags::SLEEP
50 }
51}
52
53bitflags! {
54 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
60 pub struct TestbedActionFlags: u32 {
61 const RESET_WORLD_GRAPHICS = 1 << 0;
62 const TAKE_SNAPSHOT = 1 << 4;
63 const RESTORE_SNAPSHOT = 1 << 5;
64 const APP_STARTED = 1 << 6;
65 const FRAME_SCENE = 1 << 7;
68 }
69}
70
71#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
73pub enum UiTab {
74 #[default]
75 Examples,
76 Settings,
77 Performance,
78}
79
80#[derive(Clone, Debug)]
82pub struct ExampleEntry {
83 pub name: &'static str,
84 pub group: &'static str,
85}
86
87impl ExampleEntry {
88 pub fn new(group: &'static str, name: &'static str) -> Self {
89 Self { name, group }
90 }
91}
92
93pub struct TestbedState {
95 pub running: RunMode,
96 pub can_grab_behind_ground: bool,
97 pub prev_flags: TestbedStateFlags,
98 pub flags: TestbedStateFlags,
99 pub action_flags: TestbedActionFlags,
100 pub transition: Option<Transition>,
102 pub preserve_settings_on_switch: bool,
106 pub examples: Vec<ExampleEntry>,
108 pub example_groups: Vec<&'static str>,
110 pub selected_display_index: usize,
112 pub example_settings: ExampleSettings,
113 pub broad_phase_type: RapierBroadPhaseType,
114 pub snapshot: Option<PhysicsSnapshot>,
115 pub timestep_id: usize,
119 pub camera_locked: bool,
120 pub selected_tab: UiTab,
121 pub prev_save_data: SerializableTestbedState,
122 pub up_axis: rapier::math::Vector,
128 #[cfg(feature = "parallel")]
132 pub physics_thread_pool: Option<std::sync::Arc<rapier::rayon::ThreadPool>>,
133}
134
135impl Default for TestbedState {
136 fn default() -> Self {
137 let flags = TestbedStateFlags::default();
138 Self {
139 running: RunMode::Running,
140 can_grab_behind_ground: false,
141 snapshot: None,
142 timestep_id: 0,
143 prev_flags: flags,
144 flags,
145 action_flags: TestbedActionFlags::APP_STARTED,
146 transition: None,
147 preserve_settings_on_switch: false,
148 examples: Vec::new(),
149 example_groups: Vec::new(),
150 example_settings: ExampleSettings::default(),
151 selected_display_index: 0,
152 broad_phase_type: RapierBroadPhaseType::default(),
153 camera_locked: false,
154 selected_tab: UiTab::default(),
155 prev_save_data: SerializableTestbedState::default(),
156 up_axis: rapier::math::Vector::Y,
157 #[cfg(feature = "parallel")]
158 physics_thread_pool: None,
159 }
160 }
161}
162
163impl TestbedState {
164 pub fn set_examples(&mut self, examples: Vec<ExampleEntry>) {
166 use indexmap::IndexSet;
167
168 let mut groups: IndexSet<&'static str> = IndexSet::new();
169 for example in &examples {
170 groups.insert(example.group);
171 }
172
173 let mut ordered = Vec::new();
174 for group in &groups {
175 for example in &examples {
176 if example.group == *group {
177 ordered.push(example.clone());
178 }
179 }
180 }
181
182 self.example_groups = groups.into_iter().collect();
183 self.examples = ordered;
184 }
185}