Use WireframeColor to override global color (#13034)

# Objective

- The docs says the WireframeColor is supposed to override the default
global color but it doesn't.

## Solution

- Use WireframeColor to override global color like docs said it was
supposed to do.
- Updated the example to document this feature
- I also took the opportunity to clean up the code a bit

Fixes #13032
This commit is contained in:
IceSentry 2024-04-20 09:59:12 -04:00 committed by GitHub
parent b3d3daad5a
commit 8403c41c67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 51 additions and 24 deletions

View file

@ -64,6 +64,10 @@ pub struct Wireframe;
/// it will still affect the color of the wireframe when [`WireframeConfig::global`] is set to true.
///
/// This overrides the [`WireframeConfig::default_color`].
//
// TODO: consider caching materials based on this color.
// This could blow up in size if people use random colored wireframes for each mesh.
// It will also be important to remove unused materials from the cache.
#[derive(Component, Debug, Clone, Default, Reflect)]
#[reflect(Component, Default)]
pub struct WireframeColor {
@ -155,19 +159,12 @@ fn apply_wireframe_material(
}
}
let mut wireframes_to_spawn = vec![];
for (e, wireframe_color) in &wireframes {
let material = if let Some(wireframe_color) = wireframe_color {
materials.add(WireframeMaterial {
color: wireframe_color.color.into(),
})
} else {
// If there's no color specified we can use the global material since it's already set to use the default_color
global_material.handle.clone()
};
wireframes_to_spawn.push((e, material));
let mut material_to_spawn = vec![];
for (e, maybe_color) in &wireframes {
let material = get_wireframe_material(maybe_color, &mut materials, &global_material);
material_to_spawn.push((e, material));
}
commands.insert_or_spawn_batch(wireframes_to_spawn);
commands.insert_or_spawn_batch(material_to_spawn);
}
type WireframeFilter = (With<Handle<Mesh>>, Without<Wireframe>, Without<NoWireframe>);
@ -176,16 +173,21 @@ type WireframeFilter = (With<Handle<Mesh>>, Without<Wireframe>, Without<NoWirefr
fn apply_global_wireframe_material(
mut commands: Commands,
config: Res<WireframeConfig>,
meshes_without_material: Query<Entity, (WireframeFilter, Without<Handle<WireframeMaterial>>)>,
meshes_without_material: Query<
(Entity, Option<&WireframeColor>),
(WireframeFilter, Without<Handle<WireframeMaterial>>),
>,
meshes_with_global_material: Query<Entity, (WireframeFilter, With<Handle<WireframeMaterial>>)>,
global_material: Res<GlobalWireframeMaterial>,
mut materials: ResMut<Assets<WireframeMaterial>>,
) {
if config.global {
let mut material_to_spawn = vec![];
for e in &meshes_without_material {
for (e, maybe_color) in &meshes_without_material {
let material = get_wireframe_material(maybe_color, &mut materials, &global_material);
// We only add the material handle but not the Wireframe component
// This makes it easy to detect which mesh is using the global material and which ones are user specified
material_to_spawn.push((e, global_material.handle.clone()));
material_to_spawn.push((e, material));
}
commands.insert_or_spawn_batch(material_to_spawn);
} else {
@ -195,6 +197,22 @@ fn apply_global_wireframe_material(
}
}
/// Gets an handle to a wireframe material with a fallback on the default material
fn get_wireframe_material(
maybe_color: Option<&WireframeColor>,
wireframe_materials: &mut Assets<WireframeMaterial>,
global_material: &GlobalWireframeMaterial,
) -> Handle<WireframeMaterial> {
if let Some(wireframe_color) = maybe_color {
wireframe_materials.add(WireframeMaterial {
color: wireframe_color.color.into(),
})
} else {
// If there's no color specified we can use the global material since it's already set to use the default_color
global_material.handle.clone()
}
}
#[derive(Default, AsBindGroup, TypePath, Debug, Clone, Asset)]
pub struct WireframeMaterial {
#[uniform(0)]
@ -213,7 +231,9 @@ impl Material for WireframeMaterial {
_key: MaterialPipelineKey<Self>,
) -> Result<(), SpecializedMeshPipelineError> {
descriptor.primitive.polygon_mode = PolygonMode::Line;
descriptor.depth_stencil.as_mut().unwrap().bias.slope_scale = 1.0;
if let Some(depth_stencil) = descriptor.depth_stencil.as_mut() {
depth_stencil.bias.slope_scale = 1.0;
}
Ok(())
}
}

View file

@ -54,13 +54,6 @@ fn setup(
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// plane
commands.spawn(PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::from(BLUE)),
..default()
});
// Red cube: Never renders a wireframe
commands.spawn((
PbrBundle {
@ -92,6 +85,20 @@ fn setup(
WireframeColor { color: LIME.into() },
));
// plane
commands.spawn((
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
material: materials.add(Color::from(BLUE)),
..default()
},
// You can insert this component without the `Wireframe` component
// to override the color of the global wireframe for this mesh
WireframeColor {
color: BLACK.into(),
},
));
// light
commands.spawn(PointLightBundle {
transform: Transform::from_xyz(2.0, 4.0, 2.0),
@ -119,7 +126,7 @@ fn setup(
fn update_colors(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut config: ResMut<WireframeConfig>,
mut wireframe_colors: Query<&mut WireframeColor>,
mut wireframe_colors: Query<&mut WireframeColor, With<Wireframe>>,
mut text: Query<&mut Text>,
) {
text.single_mut().sections[0].value = format!(