Skip to content

Commit a962240

Browse files
authored
Alternate wireframe override api (#10023)
# Objective #7328 introduced an API to override the global wireframe config. I believe it is flawed for a few reasons. This PR uses a non-breaking API. Instead of making the `Wireframe` an enum I introduced the `NeverRenderWireframe` component. Here's the reason why I think this is better: - Easier to migrate since it doesn't change the old behaviour. Essentially nothing to migrate. Right now this PR is a breaking change but I don't think it has to be. - It's similar to other "per mesh" rendering features like NotShadowCaster/NotShadowReceiver - It doesn't force new users to also think about global vs not global if all they want is to render a wireframe - This would also let you filter at the query definition level instead of filtering when running the query ## Solution - Introduce a `NeverRenderWireframe` component that ignores the global config --- ## Changelog - Added a `NeverRenderWireframe` component that ignores the global `WireframeConfig`
1 parent 2e887b8 commit a962240

File tree

2 files changed

+42
-34
lines changed

2 files changed

+42
-34
lines changed

crates/bevy_pbr/src/wireframe.rs

+35-27
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
use crate::MeshPipeline;
21
use crate::{
3-
DrawMesh, MeshPipelineKey, RenderMeshInstance, RenderMeshInstances, SetMeshBindGroup,
4-
SetMeshViewBindGroup,
2+
DrawMesh, MeshPipeline, MeshPipelineKey, RenderMeshInstance, RenderMeshInstances,
3+
SetMeshBindGroup, SetMeshViewBindGroup,
54
};
65
use bevy_app::Plugin;
76
use bevy_asset::{load_internal_asset, Handle};
87
use bevy_core_pipeline::core_3d::Opaque3d;
98
use bevy_derive::{Deref, DerefMut};
109
use bevy_ecs::{prelude::*, reflect::ReflectComponent};
11-
use bevy_reflect::std_traits::ReflectDefault;
12-
use bevy_reflect::Reflect;
10+
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
1311
use bevy_render::{
1412
extract_resource::{ExtractResource, ExtractResourcePlugin},
1513
mesh::{Mesh, MeshVertexBufferLayout},
@@ -23,8 +21,7 @@ use bevy_render::{
2321
RenderApp, RenderSet,
2422
};
2523
use bevy_render::{Extract, ExtractSchedule, Render};
26-
use bevy_utils::tracing::error;
27-
use bevy_utils::EntityHashMap;
24+
use bevy_utils::{tracing::error, EntityHashSet};
2825

2926
pub const WIREFRAME_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(192598014480025766);
3027

@@ -41,6 +38,7 @@ impl Plugin for WireframePlugin {
4138
);
4239

4340
app.register_type::<Wireframe>()
41+
.register_type::<NoWireframe>()
4442
.register_type::<WireframeConfig>()
4543
.init_resource::<WireframeConfig>()
4644
.add_plugins((ExtractResourcePlugin::<WireframeConfig>::default(),));
@@ -50,6 +48,7 @@ impl Plugin for WireframePlugin {
5048
.add_render_command::<Opaque3d, DrawWireframes>()
5149
.init_resource::<SpecializedMeshPipelines<WireframePipeline>>()
5250
.init_resource::<Wireframes>()
51+
.init_resource::<NoWireframes>()
5352
.add_systems(ExtractSchedule, extract_wireframes)
5453
.add_systems(Render, queue_wireframes.in_set(RenderSet::QueueMeshes));
5554
}
@@ -62,38 +61,46 @@ impl Plugin for WireframePlugin {
6261
}
6362
}
6463

65-
/// Overrides the global [`WireframeConfig`] for a single mesh.
64+
/// Enables wireframe rendering for any entity it is attached to.
65+
/// It will ignore the [`WireframeConfig`] global setting.
66+
///
67+
/// This requires the [`WireframePlugin`] to be enabled.
6668
#[derive(Component, Debug, Clone, Default, Reflect, Eq, PartialEq)]
6769
#[reflect(Component, Default)]
68-
pub enum Wireframe {
69-
/// Always render the wireframe for this entity, regardless of global config.
70-
#[default]
71-
AlwaysRender,
72-
/// Never render the wireframe for this entity, regardless of global config.
73-
NeverRender,
74-
}
70+
pub struct Wireframe;
71+
72+
/// Disables wireframe rendering for any entity it is attached to.
73+
/// It will ignore the [`WireframeConfig`] global setting.
74+
///
75+
/// This requires the [`WireframePlugin`] to be enabled.
76+
#[derive(Component, Debug, Clone, Default, Reflect, Eq, PartialEq)]
77+
#[reflect(Component, Default)]
78+
pub struct NoWireframe;
7579

7680
#[derive(Resource, Debug, Clone, Default, ExtractResource, Reflect)]
7781
#[reflect(Resource)]
7882
pub struct WireframeConfig {
7983
/// Whether to show wireframes for all meshes.
80-
/// Can be overridden for individual meshes by adding a [`Wireframe`] component.
84+
/// Can be overridden for individual meshes by adding a [`Wireframe`] or [`NoWireframe`] component.
8185
pub global: bool,
8286
}
8387

8488
#[derive(Resource, Default, Deref, DerefMut)]
85-
pub struct Wireframes(EntityHashMap<Entity, Wireframe>);
89+
pub struct Wireframes(EntityHashSet<Entity>);
90+
91+
#[derive(Resource, Default, Deref, DerefMut)]
92+
pub struct NoWireframes(EntityHashSet<Entity>);
8693

8794
fn extract_wireframes(
8895
mut wireframes: ResMut<Wireframes>,
89-
query: Extract<Query<(Entity, &Wireframe)>>,
96+
mut no_wireframes: ResMut<NoWireframes>,
97+
wireframe_query: Extract<Query<Entity, With<Wireframe>>>,
98+
no_wireframe_query: Extract<Query<Entity, With<NoWireframe>>>,
9099
) {
91100
wireframes.clear();
92-
wireframes.extend(
93-
query
94-
.iter()
95-
.map(|(entity, wireframe)| (entity, wireframe.clone())),
96-
);
101+
wireframes.extend(wireframe_query.iter());
102+
no_wireframes.clear();
103+
no_wireframes.extend(no_wireframe_query.iter());
97104
}
98105

99106
#[derive(Resource, Clone)]
@@ -137,6 +144,7 @@ fn queue_wireframes(
137144
render_meshes: Res<RenderAssets<Mesh>>,
138145
render_mesh_instances: Res<RenderMeshInstances>,
139146
wireframes: Res<Wireframes>,
147+
no_wireframes: Res<NoWireframes>,
140148
wireframe_config: Res<WireframeConfig>,
141149
wireframe_pipeline: Res<WireframePipeline>,
142150
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
@@ -185,11 +193,11 @@ fn queue_wireframes(
185193
.entities
186194
.iter()
187195
.filter_map(|visible_entity| {
188-
let wireframe_override = wireframes.get(visible_entity);
196+
if no_wireframes.get(visible_entity).is_some() {
197+
return None;
198+
}
189199

190-
if (wireframe_config.global || wireframe_override == Some(&Wireframe::AlwaysRender))
191-
&& wireframe_override != Some(&Wireframe::NeverRender)
192-
{
200+
if wireframe_config.global || wireframes.get(visible_entity).is_some() {
193201
render_mesh_instances
194202
.get(visible_entity)
195203
.map(|mesh_instance| (*visible_entity, mesh_instance))

examples/3d/wireframe.rs

+7-7
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::{NoWireframe, Wireframe, WireframeConfig, WireframePlugin},
55
prelude::*,
66
render::{render_resource::WgpuFeatures, settings::WgpuSettings, RenderPlugin},
77
};
@@ -48,7 +48,7 @@ fn setup(
4848
transform: Transform::from_xyz(-1.0, 0.5, -1.0),
4949
..default()
5050
})
51-
.insert(Wireframe::NeverRender);
51+
.insert(NoWireframe);
5252
// Orange cube: Follows global wireframe setting
5353
commands.spawn(PbrBundle {
5454
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
@@ -64,7 +64,7 @@ fn setup(
6464
transform: Transform::from_xyz(1.0, 0.5, 1.0),
6565
..default()
6666
})
67-
.insert(Wireframe::AlwaysRender);
67+
.insert(Wireframe);
6868

6969
// light
7070
commands.spawn(PointLightBundle {
@@ -83,16 +83,16 @@ fn setup(
8383
struct WireframeToggleTimer(Timer);
8484

8585
/// Periodically turns the global wireframe setting on and off, to show the differences between
86-
/// [`Wireframe::AlwaysRender`], [`Wireframe::NeverRender`], and no override.
86+
/// [`Wireframe`], [`NoWireframe`], and just a mesh.
8787
fn toggle_global_wireframe_setting(
8888
time: Res<Time>,
8989
mut timer: ResMut<WireframeToggleTimer>,
9090
mut wireframe_config: ResMut<WireframeConfig>,
9191
) {
9292
if timer.0.tick(time.delta()).just_finished() {
93-
// The global wireframe config enables drawing of wireframes on every mesh, except those with
94-
// `WireframeOverride::NeverRender`. Meshes with `WireframeOverride::AlwaysRender` will
95-
// always have a wireframe, regardless of the global configuration.
93+
// The global wireframe config enables drawing of wireframes on every mesh,
94+
// except those with `NoWireframe`. Meshes with `Wireframe` will always have a wireframe,
95+
// regardless of the global configuration.
9696
wireframe_config.global = !wireframe_config.global;
9797
}
9898
}

0 commit comments

Comments
 (0)