@@ -4,6 +4,7 @@ use bevy_asset::{load_internal_asset, Asset, Assets, Handle};
4
4
use bevy_ecs:: prelude:: * ;
5
5
use bevy_reflect:: { std_traits:: ReflectDefault , Reflect , TypePath , TypeUuid } ;
6
6
use bevy_render:: {
7
+ color:: Color ,
7
8
extract_resource:: ExtractResource ,
8
9
mesh:: { Mesh , MeshVertexBufferLayout } ,
9
10
prelude:: Shader ,
@@ -25,7 +26,6 @@ pub const WIREFRAME_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(19259
25
26
/// This is a native only feature.
26
27
#[ derive( Debug , Default ) ]
27
28
pub struct WireframePlugin ;
28
-
29
29
impl Plugin for WireframePlugin {
30
30
fn build ( & self , app : & mut bevy_app:: App ) {
31
31
load_internal_asset ! (
@@ -43,7 +43,12 @@ impl Plugin for WireframePlugin {
43
43
. add_systems ( Startup , setup_global_wireframe_material)
44
44
. add_systems (
45
45
Update ,
46
- ( apply_global_wireframe_material, apply_wireframe_material) ,
46
+ (
47
+ global_color_changed. run_if ( resource_changed :: < WireframeConfig > ( ) ) ,
48
+ wireframe_color_changed,
49
+ apply_wireframe_material,
50
+ apply_global_wireframe_material. run_if ( resource_changed :: < WireframeConfig > ( ) ) ,
51
+ ) ,
47
52
) ;
48
53
}
49
54
}
@@ -56,6 +61,17 @@ impl Plugin for WireframePlugin {
56
61
#[ reflect( Component , Default ) ]
57
62
pub struct Wireframe ;
58
63
64
+ /// Sets the color of the [`Wireframe`] of the entity it is attached to.
65
+ /// If this component is present but there's no [`Wireframe`] component,
66
+ /// it will still affect the color of the wireframe when [`WireframeConfig::global`] is set to true.
67
+ ///
68
+ /// This overrides the [`WireframeConfig::default_color`].
69
+ #[ derive( Component , Debug , Clone , Default , Reflect ) ]
70
+ #[ reflect( Component , Default ) ]
71
+ pub struct WireframeColor {
72
+ pub color : Color ,
73
+ }
74
+
59
75
/// Disables wireframe rendering for any entity it is attached to.
60
76
/// It will ignore the [`WireframeConfig`] global setting.
61
77
///
@@ -70,6 +86,10 @@ pub struct WireframeConfig {
70
86
/// Whether to show wireframes for all meshes.
71
87
/// Can be overridden for individual meshes by adding a [`Wireframe`] or [`NoWireframe`] component.
72
88
pub global : bool ,
89
+ /// If [`Self::global`] is set, any [`Entity`] that does not have a [`Wireframe`] component attached to it will have
90
+ /// wireframes using this color. Otherwise, this will be the fallback color for any entity that has a [`Wireframe`],
91
+ /// but no [`WireframeColor`].
92
+ pub default_color : Color ,
73
93
}
74
94
75
95
#[ derive( Resource ) ]
@@ -81,19 +101,53 @@ struct GlobalWireframeMaterial {
81
101
fn setup_global_wireframe_material (
82
102
mut commands : Commands ,
83
103
mut materials : ResMut < Assets < WireframeMaterial > > ,
104
+ config : Res < WireframeConfig > ,
84
105
) {
85
106
// Create the handle used for the global material
86
107
commands. insert_resource ( GlobalWireframeMaterial {
87
- handle : materials. add ( WireframeMaterial { } ) ,
108
+ handle : materials. add ( WireframeMaterial {
109
+ color : config. default_color ,
110
+ } ) ,
88
111
} ) ;
89
112
}
90
113
114
+ /// Updates the wireframe material of all entities without a [`WireframeColor`] or without a [`Wireframe`] component
115
+ fn global_color_changed (
116
+ config : Res < WireframeConfig > ,
117
+ mut materials : ResMut < Assets < WireframeMaterial > > ,
118
+ global_material : Res < GlobalWireframeMaterial > ,
119
+ ) {
120
+ if let Some ( global_material) = materials. get_mut ( & global_material. handle ) {
121
+ global_material. color = config. default_color ;
122
+ }
123
+ }
124
+
125
+ /// Updates the wireframe material when the color in [`WireframeColor`] changes
126
+ #[ allow( clippy:: type_complexity) ]
127
+ fn wireframe_color_changed (
128
+ mut materials : ResMut < Assets < WireframeMaterial > > ,
129
+ mut colors_changed : Query <
130
+ ( & mut Handle < WireframeMaterial > , & WireframeColor ) ,
131
+ ( With < Wireframe > , Changed < WireframeColor > ) ,
132
+ > ,
133
+ ) {
134
+ for ( mut handle, wireframe_color) in & mut colors_changed {
135
+ * handle = materials. add ( WireframeMaterial {
136
+ color : wireframe_color. color ,
137
+ } ) ;
138
+ }
139
+ }
140
+
91
141
/// Applies or remove the wireframe material to any mesh with a [`Wireframe`] component.
92
142
fn apply_wireframe_material (
93
143
mut commands : Commands ,
94
144
mut materials : ResMut < Assets < WireframeMaterial > > ,
95
- wireframes : Query < Entity , ( With < Wireframe > , Without < Handle < WireframeMaterial > > ) > ,
145
+ wireframes : Query <
146
+ ( Entity , Option < & WireframeColor > ) ,
147
+ ( With < Wireframe > , Without < Handle < WireframeMaterial > > ) ,
148
+ > ,
96
149
mut removed_wireframes : RemovedComponents < Wireframe > ,
150
+ global_material : Res < GlobalWireframeMaterial > ,
97
151
) {
98
152
for e in removed_wireframes. read ( ) {
99
153
if let Some ( mut commands) = commands. get_entity ( e) {
@@ -102,8 +156,16 @@ fn apply_wireframe_material(
102
156
}
103
157
104
158
let mut wireframes_to_spawn = vec ! [ ] ;
105
- for e in & wireframes {
106
- wireframes_to_spawn. push ( ( e, materials. add ( WireframeMaterial { } ) ) ) ;
159
+ for ( e, wireframe_color) in & wireframes {
160
+ let material = if let Some ( wireframe_color) = wireframe_color {
161
+ materials. add ( WireframeMaterial {
162
+ color : wireframe_color. color ,
163
+ } )
164
+ } else {
165
+ // If there's no color specified we can use the global material since it's already set to use the default_color
166
+ global_material. handle . clone ( )
167
+ } ;
168
+ wireframes_to_spawn. push ( ( e, material) ) ;
107
169
}
108
170
commands. insert_or_spawn_batch ( wireframes_to_spawn) ;
109
171
}
@@ -118,10 +180,6 @@ fn apply_global_wireframe_material(
118
180
meshes_with_global_material : Query < Entity , ( WireframeFilter , With < Handle < WireframeMaterial > > ) > ,
119
181
global_material : Res < GlobalWireframeMaterial > ,
120
182
) {
121
- if !config. is_changed ( ) {
122
- return ;
123
- }
124
-
125
183
if config. global {
126
184
let mut material_to_spawn = vec ! [ ] ;
127
185
for e in & meshes_without_material {
@@ -130,7 +188,7 @@ fn apply_global_wireframe_material(
130
188
material_to_spawn. push ( ( e, global_material. handle . clone ( ) ) ) ;
131
189
}
132
190
commands. insert_or_spawn_batch ( material_to_spawn) ;
133
- } else if !config . global {
191
+ } else {
134
192
for e in & meshes_with_global_material {
135
193
commands. entity ( e) . remove :: < Handle < WireframeMaterial > > ( ) ;
136
194
}
@@ -139,7 +197,10 @@ fn apply_global_wireframe_material(
139
197
140
198
#[ derive( Default , AsBindGroup , TypeUuid , TypePath , Debug , Clone , Asset ) ]
141
199
#[ uuid = "9e694f70-9963-4418-8bc1-3474c66b13b8" ]
142
- struct WireframeMaterial { }
200
+ pub struct WireframeMaterial {
201
+ #[ uniform( 0 ) ]
202
+ pub color : Color ,
203
+ }
143
204
144
205
impl Material for WireframeMaterial {
145
206
fn fragment_shader ( ) -> ShaderRef {
0 commit comments