Skip to content

Commit 255a24f

Browse files
committed
Improve example
1 parent 628e369 commit 255a24f

File tree

2 files changed

+195
-19
lines changed

2 files changed

+195
-19
lines changed

crates/avian3d/examples/bvh.rs

Lines changed: 193 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use bevy::{
1212
color::palettes::tailwind::GRAY_400,
1313
feathers::{
1414
FeathersPlugins,
15-
controls::{SliderProps, radio, slider},
15+
constants::fonts::{BOLD, REGULAR},
16+
controls::{SliderProps, checkbox, radio, slider},
1617
dark_theme::create_dark_theme,
1718
theme::UiTheme,
1819
},
@@ -31,7 +32,13 @@ fn main() {
3132

3233
// Add plugins relevant to the example.
3334
app.add_plugins((
34-
DefaultPlugins,
35+
DefaultPlugins.build().set(WindowPlugin {
36+
primary_window: Some(Window {
37+
title: "App".to_string(),
38+
..default()
39+
}),
40+
..default()
41+
}),
3542
FeathersPlugins,
3643
ExampleCommonPlugin,
3744
PhysicsDebugPlugin,
@@ -55,7 +62,11 @@ fn main() {
5562

5663
// Configure gizmos and initialize example settings.
5764
app.insert_gizmo_config(
58-
PhysicsGizmos::none().with_aabb_color(GRAY_400.into()),
65+
PhysicsGizmos {
66+
aabb_color: Some(GRAY_400.into()),
67+
collider_tree_color: Some(Color::WHITE),
68+
..PhysicsGizmos::none()
69+
},
5970
GizmoConfig {
6071
line: GizmoLineConfig {
6172
width: 0.5,
@@ -164,34 +175,125 @@ fn move_random(mut query: Query<&mut Position>, settings: Res<BvhExampleSettings
164175

165176
// === UI Setup ===
166177

178+
#[derive(Component)]
179+
struct OptimizationModeRadio(TreeOptimizationMode);
180+
167181
#[derive(Component)]
168182
struct GridSizeRadio(usize);
169183

170184
// TODO: Change optimization settings at runtime.
171-
fn setup_ui(mut commands: Commands, settings: Res<BvhExampleSettings>) {
185+
fn setup_ui(
186+
mut commands: Commands,
187+
settings: Res<BvhExampleSettings>,
188+
asset_server: Res<AssetServer>,
189+
) {
190+
let regular: Handle<Font> = asset_server.load(REGULAR);
191+
let bold: Handle<Font> = asset_server.load(BOLD);
192+
172193
commands.spawn((
173194
Name::new("Example Settings UI"),
174195
Node {
175196
position_type: PositionType::Absolute,
176197
bottom: Val::Px(5.0),
177-
left: Val::Px(5.0),
198+
right: Val::Px(5.0),
178199
width: Val::Px(270.0),
179200
padding: UiRect::all(Val::Px(10.0)),
180201
border_radius: BorderRadius::all(Val::Px(5.0)),
181202
flex_direction: FlexDirection::Column,
182-
row_gap: Val::Px(20.0),
203+
row_gap: Val::Px(15.0),
183204
..default()
184205
},
185206
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)),
186207
children![
187208
(
188209
Node {
189210
flex_direction: FlexDirection::Column,
190-
row_gap: Val::Px(10.0),
211+
row_gap: Val::Px(5.0),
191212
..default()
192213
},
193214
children![
194-
(Text::new("Grid Size"), TextFont::from_font_size(16.0)),
215+
(
216+
Text::new("Optimization Mode"),
217+
TextFont::from_font_size(14.0).with_font(bold.clone())
218+
),
219+
(
220+
Node {
221+
display: Display::Flex,
222+
flex_direction: FlexDirection::Column,
223+
row_gap: px(5),
224+
..default()
225+
},
226+
RadioGroup,
227+
observe(
228+
|value_change: On<ValueChange<Entity>>,
229+
radio_buttons: Query<
230+
(Entity, &OptimizationModeRadio),
231+
With<RadioButton>,
232+
>,
233+
mut settings: ResMut<ColliderTreeOptimization>,
234+
mut commands: Commands| {
235+
for (entity, optimization_mode) in radio_buttons.iter() {
236+
if entity == value_change.value {
237+
commands.entity(entity).insert(Checked);
238+
if optimization_mode.0 == settings.optimization_mode {
239+
continue;
240+
}
241+
settings.optimization_mode = optimization_mode.0;
242+
commands.run_system_cached(clear_scene);
243+
commands.run_system_cached(setup_scene);
244+
} else {
245+
commands.entity(entity).remove::<Checked>();
246+
}
247+
}
248+
}
249+
),
250+
children![
251+
radio(
252+
OptimizationModeRadio(TreeOptimizationMode::Reinsert),
253+
Spawn((
254+
Text::new("Reinsert"),
255+
TextFont::from_font_size(13.0).with_font(regular.clone())
256+
))
257+
),
258+
radio(
259+
OptimizationModeRadio(TreeOptimizationMode::PartialRebuild),
260+
Spawn((
261+
Text::new("Partial Rebuild"),
262+
TextFont::from_font_size(13.0).with_font(regular.clone())
263+
))
264+
),
265+
radio(
266+
OptimizationModeRadio(TreeOptimizationMode::FullRebuild),
267+
Spawn((
268+
Text::new("Full Rebuild"),
269+
TextFont::from_font_size(13.0).with_font(regular.clone())
270+
))
271+
),
272+
radio(
273+
(
274+
Checked,
275+
OptimizationModeRadio(TreeOptimizationMode::default())
276+
),
277+
Spawn((
278+
Text::new("Adaptive"),
279+
TextFont::from_font_size(13.0).with_font(regular.clone())
280+
))
281+
),
282+
]
283+
),
284+
],
285+
),
286+
(
287+
Node {
288+
flex_direction: FlexDirection::Column,
289+
row_gap: Val::Px(5.0),
290+
..default()
291+
},
292+
children![
293+
(
294+
Text::new("Grid Size"),
295+
TextFont::from_font_size(14.0).with_font(bold.clone())
296+
),
195297
(
196298
Node {
197299
display: Display::Flex,
@@ -224,15 +326,24 @@ fn setup_ui(mut commands: Commands, settings: Res<BvhExampleSettings>) {
224326
children![
225327
radio(
226328
GridSizeRadio(10),
227-
Spawn((Text::new("10x10"), TextFont::from_font_size(14.0)))
329+
Spawn((
330+
Text::new("10x10"),
331+
TextFont::from_font_size(13.0).with_font(regular.clone())
332+
))
228333
),
229334
radio(
230335
(Checked, GridSizeRadio(50)),
231-
Spawn((Text::new("50x50"), TextFont::from_font_size(14.0)))
336+
Spawn((
337+
Text::new("50x50"),
338+
TextFont::from_font_size(13.0).with_font(regular.clone())
339+
))
232340
),
233341
radio(
234342
GridSizeRadio(100),
235-
Spawn((Text::new("100x100"), TextFont::from_font_size(14.0)))
343+
Spawn((
344+
Text::new("100x100"),
345+
TextFont::from_font_size(13.0).with_font(regular.clone())
346+
))
236347
),
237348
]
238349
),
@@ -241,17 +352,20 @@ fn setup_ui(mut commands: Commands, settings: Res<BvhExampleSettings>) {
241352
(
242353
Node {
243354
flex_direction: FlexDirection::Column,
244-
row_gap: Val::Px(10.0),
355+
row_gap: Val::Px(5.0),
245356
..default()
246357
},
247358
children![
248-
(Text::new("Move Fraction"), TextFont::from_font_size(16.0)),
359+
(
360+
Text::new("Move Fraction"),
361+
TextFont::from_font_size(14.0).with_font(bold.clone())
362+
),
249363
(
250364
slider(
251365
SliderProps {
252366
min: 0.0,
253367
max: 1.0,
254-
value: settings.delta_fraction,
368+
value: settings.move_fraction,
255369
},
256370
(SliderStep(0.05), SliderPrecision(2)),
257371
),
@@ -268,11 +382,14 @@ fn setup_ui(mut commands: Commands, settings: Res<BvhExampleSettings>) {
268382
(
269383
Node {
270384
flex_direction: FlexDirection::Column,
271-
row_gap: Val::Px(10.0),
385+
row_gap: Val::Px(5.0),
272386
..default()
273387
},
274388
children![
275-
(Text::new("Delta Fraction"), TextFont::from_font_size(16.0)),
389+
(
390+
Text::new("Delta Fraction"),
391+
TextFont::from_font_size(14.0).with_font(bold.clone())
392+
),
276393
(
277394
slider(
278395
SliderProps {
@@ -291,7 +408,66 @@ fn setup_ui(mut commands: Commands, settings: Res<BvhExampleSettings>) {
291408
),
292409
)
293410
],
294-
)
411+
),
412+
(
413+
Node {
414+
flex_direction: FlexDirection::Column,
415+
row_gap: Val::Px(5.0),
416+
..default()
417+
},
418+
children![
419+
(
420+
Text::new("BVH Debug Rendering"),
421+
TextFont::from_font_size(14.0).with_font(bold)
422+
),
423+
(
424+
checkbox(
425+
Checked,
426+
Spawn((
427+
Text::new("Draw Internal Nodes"),
428+
TextFont::from_font_size(13.0).with_font(regular.clone())
429+
))
430+
),
431+
observe(
432+
|change: On<ValueChange<bool>>,
433+
mut gizmo_store: ResMut<GizmoConfigStore>,
434+
mut commands: Commands| {
435+
let gizmo_config = gizmo_store.config_mut::<PhysicsGizmos>().1;
436+
if change.value {
437+
gizmo_config.collider_tree_color = Some(Color::WHITE);
438+
commands.entity(change.source).insert(Checked);
439+
} else {
440+
gizmo_config.collider_tree_color = None;
441+
commands.entity(change.source).remove::<Checked>();
442+
}
443+
},
444+
)
445+
),
446+
(
447+
checkbox(
448+
Checked,
449+
Spawn((
450+
Text::new("Draw Leaf Nodes"),
451+
TextFont::from_font_size(13.0).with_font(regular)
452+
))
453+
),
454+
observe(
455+
|change: On<ValueChange<bool>>,
456+
mut gizmo_store: ResMut<GizmoConfigStore>,
457+
mut commands: Commands| {
458+
let gizmo_config = gizmo_store.config_mut::<PhysicsGizmos>().1;
459+
if change.value {
460+
gizmo_config.aabb_color = Some(GRAY_400.into());
461+
commands.entity(change.source).insert(Checked);
462+
} else {
463+
gizmo_config.aabb_color = None;
464+
commands.entity(change.source).remove::<Checked>();
465+
}
466+
},
467+
)
468+
)
469+
],
470+
),
295471
],
296472
));
297473
}

src/collider_tree/optimization.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Plugin for ColliderTreeOptimizationPlugin {
3030
}
3131

3232
/// Settings for optimizing the dynamic [`ColliderTree`].
33-
#[derive(Resource, Debug, Default, Reflect)]
33+
#[derive(Resource, Debug, Default, PartialEq, Reflect)]
3434
pub struct ColliderTreeOptimization {
3535
/// If `true`, tree optimization will be performed in-place with minimal allocations.
3636
/// This has the downside that the tree will be unavailable for [spatial queries]
@@ -56,7 +56,7 @@ pub struct ColliderTreeOptimization {
5656
}
5757

5858
/// The optimization mode for a dynamic [`ColliderTree`].
59-
#[derive(Clone, Copy, Debug, Reflect)]
59+
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
6060
pub enum TreeOptimizationMode {
6161
/// The tree is optimized by reinserting [moved proxies](`MovedProxies`).
6262
///

0 commit comments

Comments
 (0)