Skip to content

Commit

Permalink
Allow overriding global wireframe setting by adding a WireframeOverri…
Browse files Browse the repository at this point in the history
…de component. (#7309)
  • Loading branch information
Wcubed committed Jul 15, 2023
1 parent ede5848 commit 6703d88
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 38 deletions.
46 changes: 22 additions & 24 deletions crates/bevy_pbr/src/wireframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,22 @@ impl Plugin for WireframePlugin {
}
}

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

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

Expand Down Expand Up @@ -116,10 +123,7 @@ fn queue_wireframes(
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
pipeline_cache: Res<PipelineCache>,
msaa: Res<Msaa>,
mut material_meshes: ParamSet<(
Query<(Entity, &Handle<Mesh>, &MeshUniform)>,
Query<(Entity, &Handle<Mesh>, &MeshUniform), With<Wireframe>>,
)>,
material_meshes: Query<(Entity, &Handle<Mesh>, &MeshUniform, Option<&Wireframe>)>,
mut views: Query<(&ExtractedView, &VisibleEntities, &mut RenderPhase<Opaque3d>)>,
) {
let draw_custom = opaque_3d_draw_functions.read().id::<DrawWireframes>();
Expand All @@ -129,7 +133,7 @@ fn queue_wireframes(

let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
let add_render_phase =
|(entity, mesh_handle, mesh_uniform): (Entity, &Handle<Mesh>, &MeshUniform)| {
|(entity, mesh_handle, mesh_uniform, _): (Entity, &Handle<Mesh>, &MeshUniform, _)| {
if let Some(mesh) = render_meshes.get(mesh_handle) {
let key = view_key
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
Expand All @@ -155,21 +159,15 @@ fn queue_wireframes(
}
};

if wireframe_config.global {
let query = material_meshes.p0();
visible_entities
.entities
.iter()
.filter_map(|visible_entity| query.get(*visible_entity).ok())
.for_each(add_render_phase);
} else {
let query = material_meshes.p1();
visible_entities
.entities
.iter()
.filter_map(|visible_entity| query.get(*visible_entity).ok())
.for_each(add_render_phase);
}
visible_entities
.entities
.iter()
.filter_map(|visible_entity| material_meshes.get(*visible_entity).ok())
.filter(|(.., wireframe_override)| {
(wireframe_config.global || *wireframe_override == Some(&Wireframe::AlwaysRender))
&& *wireframe_override != Some(&Wireframe::NeverRender)
})
.for_each(add_render_phase);
}
}

Expand Down
65 changes: 51 additions & 14 deletions examples/3d/wireframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,54 @@ fn main() {
}),
WireframePlugin,
))
.insert_resource(WireframeToggleTimer(Timer::from_seconds(
1.0,
TimerMode::Repeating,
)))
.add_systems(Startup, setup)
.add_systems(Update, toggle_global_wireframe_setting)
.run();
}

/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut wireframe_config: ResMut<WireframeConfig>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// To draw the wireframe on all entities, set this to 'true'
wireframe_config.global = false;
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(shape::Plane::from_size(5.0).into()),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
mesh: meshes.add(Mesh::from(shape::Plane::from_size(5.0))),
material: materials.add(Color::rgb(0.3, 0.3, 0.5).into()),
..default()
});

// Red cube: Never renders a wireframe
commands
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.1, 0.1).into()),
transform: Transform::from_xyz(-1.0, 0.5, -1.0),
..default()
})
.insert(Wireframe::NeverRender);
// Orange cube: Follows global wireframe setting
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.8, 0.1).into()),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// cube
commands.spawn((
PbrBundle {
// Green cube: Always renders a wireframe
commands
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
material: materials.add(Color::rgb(0.1, 0.8, 0.1).into()),
transform: Transform::from_xyz(1.0, 0.5, 1.0),
..default()
},
// This enables wireframe drawing on this entity
Wireframe,
));
})
.insert(Wireframe::AlwaysRender);

// light
commands.spawn(PointLightBundle {
transform: Transform::from_xyz(4.0, 8.0, 4.0),
Expand All @@ -58,3 +76,22 @@ fn setup(
..default()
});
}

/// This timer is used to periodically toggle the wireframe rendering.
#[derive(Resource)]
struct WireframeToggleTimer(Timer);

/// Periodically turns the global wireframe setting on and off, to show the differences between
/// [`Wireframe::AlwaysRender`], [`Wireframe::NeverRender`], and no override.
fn toggle_global_wireframe_setting(
time: Res<Time>,
mut timer: ResMut<WireframeToggleTimer>,
mut wireframe_config: ResMut<WireframeConfig>,
) {
if timer.0.tick(time.delta()).just_finished() {
// The global wireframe config enables drawing of wireframes on every mesh, except those with
// `WireframeOverride::NeverRender`. Meshes with `WireframeOverride::AlwaysRender` will
// always have a wireframe, regardless of the global configuration.
wireframe_config.global = !wireframe_config.global;
}
}

0 comments on commit 6703d88

Please sign in to comment.