Skip to content

Commit 8f171bf

Browse files
committed
Allow overriding global wireframe setting by adding a WireframeOverride component. (#7309)
1 parent 7d5f89c commit 8f171bf

File tree

2 files changed

+82
-40
lines changed

2 files changed

+82
-40
lines changed

crates/bevy_pbr/src/wireframe.rs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ impl Plugin for WireframePlugin {
3636
Shader::from_wgsl
3737
);
3838

39-
app.register_type::<Wireframe>()
39+
app.register_type::<WireframeOverride>()
4040
.register_type::<WireframeConfig>()
4141
.init_resource::<WireframeConfig>()
4242
.add_plugin(ExtractResourcePlugin::<WireframeConfig>::default())
43-
.add_plugin(ExtractComponentPlugin::<Wireframe>::default());
43+
.add_plugin(ExtractComponentPlugin::<WireframeOverride>::default());
4444

4545
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
4646
render_app
@@ -52,15 +52,22 @@ impl Plugin for WireframePlugin {
5252
}
5353
}
5454

55-
/// Controls whether an entity should rendered in wireframe-mode if the [`WireframePlugin`] is enabled
56-
#[derive(Component, Debug, Clone, Default, ExtractComponent, Reflect)]
55+
/// Overrides the global [`WireframeConfig`] for a single mesh.
56+
#[derive(Component, Debug, Clone, Default, ExtractComponent, Reflect, Eq, PartialEq)]
5757
#[reflect(Component, Default)]
58-
pub struct Wireframe;
58+
pub enum WireframeOverride {
59+
/// Always render the wireframe for this entity, regardless of global config.
60+
#[default]
61+
AlwaysRender,
62+
/// Never render the wireframe for this entity, regardless of global config.
63+
NeverRender,
64+
}
5965

6066
#[derive(Resource, Debug, Clone, Default, ExtractResource, Reflect)]
6167
#[reflect(Resource)]
6268
pub struct WireframeConfig {
63-
/// Whether to show wireframes for all meshes. If `false`, only meshes with a [Wireframe] component will be rendered.
69+
/// Whether to show wireframes for all meshes.
70+
/// Can be overridden for individual meshes by adding a [`WireframeOverride`] component.
6471
pub global: bool,
6572
}
6673

@@ -104,9 +111,11 @@ fn queue_wireframes(
104111
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
105112
pipeline_cache: Res<PipelineCache>,
106113
msaa: Res<Msaa>,
107-
mut material_meshes: ParamSet<(
108-
Query<(Entity, &Handle<Mesh>, &MeshUniform)>,
109-
Query<(Entity, &Handle<Mesh>, &MeshUniform), With<Wireframe>>,
114+
material_meshes: Query<(
115+
Entity,
116+
&Handle<Mesh>,
117+
&MeshUniform,
118+
Option<&WireframeOverride>,
110119
)>,
111120
mut views: Query<(&ExtractedView, &VisibleEntities, &mut RenderPhase<Opaque3d>)>,
112121
) {
@@ -117,7 +126,7 @@ fn queue_wireframes(
117126

118127
let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
119128
let add_render_phase =
120-
|(entity, mesh_handle, mesh_uniform): (Entity, &Handle<Mesh>, &MeshUniform)| {
129+
|(entity, mesh_handle, mesh_uniform, _): (Entity, &Handle<Mesh>, &MeshUniform, _)| {
121130
if let Some(mesh) = render_meshes.get(mesh_handle) {
122131
let key = view_key
123132
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
@@ -143,21 +152,17 @@ fn queue_wireframes(
143152
}
144153
};
145154

146-
if wireframe_config.global {
147-
let query = material_meshes.p0();
148-
visible_entities
149-
.entities
150-
.iter()
151-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
152-
.for_each(add_render_phase);
153-
} else {
154-
let query = material_meshes.p1();
155-
visible_entities
156-
.entities
157-
.iter()
158-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
159-
.for_each(add_render_phase);
160-
}
155+
visible_entities
156+
.entities
157+
.iter()
158+
.filter_map(|visible_entity| material_meshes.get(*visible_entity).ok())
159+
.filter(|mesh| {
160+
let wireframe_override = mesh.3;
161+
(wireframe_config.global
162+
|| wireframe_override == Some(&WireframeOverride::AlwaysRender))
163+
&& wireframe_override != Some(&WireframeOverride::NeverRender)
164+
})
165+
.for_each(add_render_phase);
161166
}
162167
}
163168

examples/3d/wireframe.rs

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Showcases wireframe rendering.
22
33
use bevy::{
4-
pbr::wireframe::{Wireframe, WireframeConfig, WireframePlugin},
4+
pbr::wireframe::{WireframeConfig, WireframeOverride, WireframePlugin},
55
prelude::*,
66
render::{render_resource::WgpuFeatures, settings::WgpuSettings, RenderPlugin},
77
};
@@ -15,36 +15,54 @@ fn main() {
1515
},
1616
}))
1717
.add_plugin(WireframePlugin)
18+
.insert_resource(WireFrameToggleTimer(Timer::from_seconds(
19+
1.0,
20+
TimerMode::Repeating,
21+
)))
1822
.add_startup_system(setup)
23+
.add_system(toggle_global_wireframe_setting)
1924
.run();
2025
}
2126

2227
/// set up a simple 3D scene
2328
fn setup(
2429
mut commands: Commands,
25-
mut wireframe_config: ResMut<WireframeConfig>,
2630
mut meshes: ResMut<Assets<Mesh>>,
2731
mut materials: ResMut<Assets<StandardMaterial>>,
2832
) {
29-
// To draw the wireframe on all entities, set this to 'true'
30-
wireframe_config.global = false;
3133
// plane
3234
commands.spawn(PbrBundle {
33-
mesh: meshes.add(shape::Plane::from_size(5.0).into()),
34-
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
35+
mesh: meshes.add(Mesh::from(shape::Plane::from_size(5.0))),
36+
material: materials.add(Color::rgb(0.3, 0.3, 0.5).into()),
37+
..default()
38+
});
39+
40+
// Red cube: Never renders a wireframe
41+
commands
42+
.spawn(PbrBundle {
43+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
44+
material: materials.add(Color::rgb(0.8, 0.1, 0.1).into()),
45+
transform: Transform::from_xyz(-1.0, 0.5, -1.0),
46+
..default()
47+
})
48+
.insert(WireframeOverride::NeverRender);
49+
// Orange cube: Follows global wireframe setting
50+
commands.spawn(PbrBundle {
51+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
52+
material: materials.add(Color::rgb(0.8, 0.8, 0.1).into()),
53+
transform: Transform::from_xyz(0.0, 0.5, 0.0),
3554
..default()
3655
});
37-
// cube
38-
commands.spawn((
39-
PbrBundle {
56+
// Green cube: Always renders a wireframe
57+
commands
58+
.spawn(PbrBundle {
4059
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
41-
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
42-
transform: Transform::from_xyz(0.0, 0.5, 0.0),
60+
material: materials.add(Color::rgb(0.1, 0.8, 0.1).into()),
61+
transform: Transform::from_xyz(1.0, 0.5, 1.0),
4362
..default()
44-
},
45-
// This enables wireframe drawing on this entity
46-
Wireframe,
47-
));
63+
})
64+
.insert(WireframeOverride::AlwaysRender);
65+
4866
// light
4967
commands.spawn(PointLightBundle {
5068
transform: Transform::from_xyz(4.0, 8.0, 4.0),
@@ -56,3 +74,22 @@ fn setup(
5674
..default()
5775
});
5876
}
77+
78+
/// This timer is used to periodically toggle the wireframe rendering.
79+
#[derive(Resource)]
80+
struct WireFrameToggleTimer(Timer);
81+
82+
/// Periodically turns the global wireframe setting on and off, to show the differences between
83+
/// [`WireframeOverride::AlwaysRender`], [`WireframeOverride::NeverRender`], and no override.
84+
fn toggle_global_wireframe_setting(
85+
time: Res<Time>,
86+
mut timer: ResMut<WireFrameToggleTimer>,
87+
mut wireframe_config: ResMut<WireframeConfig>,
88+
) {
89+
if timer.0.tick(time.delta()).just_finished() {
90+
// The global wireframe config enables drawing of wireframes on every mesh, except those with
91+
// `WireframeOverride::NeverRender`. Meshes with `WireframeOverride::AlwaysRender` will
92+
// always have a wireframe, regardless of the global configuration.
93+
wireframe_config.global = !wireframe_config.global;
94+
}
95+
}

0 commit comments

Comments
 (0)