Skip to content

Commit fe08a66

Browse files
committed
Allow overriding global wireframe setting by adding a WireframeOverride component. (#7309)
1 parent 711efed commit fe08a66

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
@@ -53,15 +53,22 @@ impl Plugin for WireframePlugin {
5353
}
5454
}
5555

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

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

@@ -105,10 +112,7 @@ fn queue_wireframes(
105112
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
106113
pipeline_cache: Res<PipelineCache>,
107114
msaa: Res<Msaa>,
108-
mut material_meshes: ParamSet<(
109-
Query<(Entity, &Handle<Mesh>, &MeshUniform)>,
110-
Query<(Entity, &Handle<Mesh>, &MeshUniform), With<Wireframe>>,
111-
)>,
115+
material_meshes: Query<(Entity, &Handle<Mesh>, &MeshUniform, Option<&Wireframe>)>,
112116
mut views: Query<(&ExtractedView, &VisibleEntities, &mut RenderPhase<Opaque3d>)>,
113117
) {
114118
let draw_custom = opaque_3d_draw_functions.read().id::<DrawWireframes>();
@@ -118,7 +122,7 @@ fn queue_wireframes(
118122

119123
let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
120124
let add_render_phase =
121-
|(entity, mesh_handle, mesh_uniform): (Entity, &Handle<Mesh>, &MeshUniform)| {
125+
|(entity, mesh_handle, mesh_uniform, _): (Entity, &Handle<Mesh>, &MeshUniform, _)| {
122126
if let Some(mesh) = render_meshes.get(mesh_handle) {
123127
let key = view_key
124128
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
@@ -144,21 +148,15 @@ fn queue_wireframes(
144148
}
145149
};
146150

147-
if wireframe_config.global {
148-
let query = material_meshes.p0();
149-
visible_entities
150-
.entities
151-
.iter()
152-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
153-
.for_each(add_render_phase);
154-
} else {
155-
let query = material_meshes.p1();
156-
visible_entities
157-
.entities
158-
.iter()
159-
.filter_map(|visible_entity| query.get(*visible_entity).ok())
160-
.for_each(add_render_phase);
161-
}
151+
visible_entities
152+
.entities
153+
.iter()
154+
.filter_map(|visible_entity| material_meshes.get(*visible_entity).ok())
155+
.filter(|(.., wireframe_override)| {
156+
(wireframe_config.global || *wireframe_override == Some(&Wireframe::AlwaysRender))
157+
&& *wireframe_override != Some(&Wireframe::NeverRender)
158+
})
159+
.for_each(add_render_phase);
162160
}
163161
}
164162

examples/3d/wireframe.rs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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_systems(Startup, setup)
23+
.add_systems(Update, 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(Wireframe::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(Wireframe::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+
/// [`Wireframe::AlwaysRender`], [`Wireframe::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)