Skip to content

Commit 6703d88

Browse files
committed
Allow overriding global wireframe setting by adding a WireframeOverride component. (#7309)
1 parent ede5848 commit 6703d88

File tree

2 files changed

+73
-38
lines changed

2 files changed

+73
-38
lines changed

crates/bevy_pbr/src/wireframe.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,22 @@ impl Plugin for WireframePlugin {
6060
}
6161
}
6262

63-
/// Controls whether an entity should rendered in wireframe-mode if the [`WireframePlugin`] is enabled
64-
#[derive(Component, Debug, Clone, Default, ExtractComponent, Reflect)]
63+
/// Overrides the global [`WireframeConfig`] for a single mesh.
64+
#[derive(Component, Debug, Clone, Default, ExtractComponent, Reflect, Eq, PartialEq)]
6565
#[reflect(Component, Default)]
66-
pub struct Wireframe;
66+
pub enum Wireframe {
67+
/// Always render the wireframe for this entity, regardless of global config.
68+
#[default]
69+
AlwaysRender,
70+
/// Never render the wireframe for this entity, regardless of global config.
71+
NeverRender,
72+
}
6773

6874
#[derive(Resource, Debug, Clone, Default, ExtractResource, Reflect)]
6975
#[reflect(Resource)]
7076
pub struct WireframeConfig {
71-
/// Whether to show wireframes for all meshes. If `false`, only meshes with a [Wireframe] component will be rendered.
77+
/// Whether to show wireframes for all meshes.
78+
/// Can be overridden for individual meshes by adding a [`Wireframe`] component.
7279
pub global: bool,
7380
}
7481

@@ -116,10 +123,7 @@ fn queue_wireframes(
116123
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
117124
pipeline_cache: Res<PipelineCache>,
118125
msaa: Res<Msaa>,
119-
mut material_meshes: ParamSet<(
120-
Query<(Entity, &Handle<Mesh>, &MeshUniform)>,
121-
Query<(Entity, &Handle<Mesh>, &MeshUniform), With<Wireframe>>,
122-
)>,
126+
material_meshes: Query<(Entity, &Handle<Mesh>, &MeshUniform, Option<&Wireframe>)>,
123127
mut views: Query<(&ExtractedView, &VisibleEntities, &mut RenderPhase<Opaque3d>)>,
124128
) {
125129
let draw_custom = opaque_3d_draw_functions.read().id::<DrawWireframes>();
@@ -129,7 +133,7 @@ fn queue_wireframes(
129133

130134
let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
131135
let add_render_phase =
132-
|(entity, mesh_handle, mesh_uniform): (Entity, &Handle<Mesh>, &MeshUniform)| {
136+
|(entity, mesh_handle, mesh_uniform, _): (Entity, &Handle<Mesh>, &MeshUniform, _)| {
133137
if let Some(mesh) = render_meshes.get(mesh_handle) {
134138
let key = view_key
135139
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
@@ -155,21 +159,15 @@ fn queue_wireframes(
155159
}
156160
};
157161

158-
if wireframe_config.global {
159-
let query = material_meshes.p0();
160-
visible_entities
161-
.entities
162-
.iter()
163-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
164-
.for_each(add_render_phase);
165-
} else {
166-
let query = material_meshes.p1();
167-
visible_entities
168-
.entities
169-
.iter()
170-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
171-
.for_each(add_render_phase);
172-
}
162+
visible_entities
163+
.entities
164+
.iter()
165+
.filter_map(|visible_entity| material_meshes.get(*visible_entity).ok())
166+
.filter(|(.., wireframe_override)| {
167+
(wireframe_config.global || *wireframe_override == Some(&Wireframe::AlwaysRender))
168+
&& *wireframe_override != Some(&Wireframe::NeverRender)
169+
})
170+
.for_each(add_render_phase);
173171
}
174172
}
175173

examples/3d/wireframe.rs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,54 @@ fn main() {
1717
}),
1818
WireframePlugin,
1919
))
20+
.insert_resource(WireframeToggleTimer(Timer::from_seconds(
21+
1.0,
22+
TimerMode::Repeating,
23+
)))
2024
.add_systems(Startup, setup)
25+
.add_systems(Update, toggle_global_wireframe_setting)
2126
.run();
2227
}
2328

2429
/// set up a simple 3D scene
2530
fn setup(
2631
mut commands: Commands,
27-
mut wireframe_config: ResMut<WireframeConfig>,
2832
mut meshes: ResMut<Assets<Mesh>>,
2933
mut materials: ResMut<Assets<StandardMaterial>>,
3034
) {
31-
// To draw the wireframe on all entities, set this to 'true'
32-
wireframe_config.global = false;
3335
// plane
3436
commands.spawn(PbrBundle {
35-
mesh: meshes.add(shape::Plane::from_size(5.0).into()),
36-
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
37+
mesh: meshes.add(Mesh::from(shape::Plane::from_size(5.0))),
38+
material: materials.add(Color::rgb(0.3, 0.3, 0.5).into()),
39+
..default()
40+
});
41+
42+
// Red cube: Never renders a wireframe
43+
commands
44+
.spawn(PbrBundle {
45+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
46+
material: materials.add(Color::rgb(0.8, 0.1, 0.1).into()),
47+
transform: Transform::from_xyz(-1.0, 0.5, -1.0),
48+
..default()
49+
})
50+
.insert(Wireframe::NeverRender);
51+
// Orange cube: Follows global wireframe setting
52+
commands.spawn(PbrBundle {
53+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
54+
material: materials.add(Color::rgb(0.8, 0.8, 0.1).into()),
55+
transform: Transform::from_xyz(0.0, 0.5, 0.0),
3756
..default()
3857
});
39-
// cube
40-
commands.spawn((
41-
PbrBundle {
58+
// Green cube: Always renders a wireframe
59+
commands
60+
.spawn(PbrBundle {
4261
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
43-
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
44-
transform: Transform::from_xyz(0.0, 0.5, 0.0),
62+
material: materials.add(Color::rgb(0.1, 0.8, 0.1).into()),
63+
transform: Transform::from_xyz(1.0, 0.5, 1.0),
4564
..default()
46-
},
47-
// This enables wireframe drawing on this entity
48-
Wireframe,
49-
));
65+
})
66+
.insert(Wireframe::AlwaysRender);
67+
5068
// light
5169
commands.spawn(PointLightBundle {
5270
transform: Transform::from_xyz(4.0, 8.0, 4.0),
@@ -58,3 +76,22 @@ fn setup(
5876
..default()
5977
});
6078
}
79+
80+
/// This timer is used to periodically toggle the wireframe rendering.
81+
#[derive(Resource)]
82+
struct WireframeToggleTimer(Timer);
83+
84+
/// Periodically turns the global wireframe setting on and off, to show the differences between
85+
/// [`Wireframe::AlwaysRender`], [`Wireframe::NeverRender`], and no override.
86+
fn toggle_global_wireframe_setting(
87+
time: Res<Time>,
88+
mut timer: ResMut<WireframeToggleTimer>,
89+
mut wireframe_config: ResMut<WireframeConfig>,
90+
) {
91+
if timer.0.tick(time.delta()).just_finished() {
92+
// The global wireframe config enables drawing of wireframes on every mesh, except those with
93+
// `WireframeOverride::NeverRender`. Meshes with `WireframeOverride::AlwaysRender` will
94+
// always have a wireframe, regardless of the global configuration.
95+
wireframe_config.global = !wireframe_config.global;
96+
}
97+
}

0 commit comments

Comments
 (0)