@@ -43,6 +43,7 @@ pub struct SystemMeta {
43
43
is_send : bool ,
44
44
has_deferred : bool ,
45
45
pub ( crate ) last_run : Tick ,
46
+ warn_policy : WarnPolicy ,
46
47
#[ cfg( feature = "trace" ) ]
47
48
pub ( crate ) system_span : Span ,
48
49
#[ cfg( feature = "trace" ) ]
@@ -59,6 +60,7 @@ impl SystemMeta {
59
60
is_send : true ,
60
61
has_deferred : false ,
61
62
last_run : Tick :: new ( 0 ) ,
63
+ warn_policy : WarnPolicy :: Once ,
62
64
#[ cfg( feature = "trace" ) ]
63
65
system_span : info_span ! ( "system" , name = name) ,
64
66
#[ cfg( feature = "trace" ) ]
@@ -75,6 +77,7 @@ impl SystemMeta {
75
77
/// Sets the name of of this system.
76
78
///
77
79
/// Useful to give closure systems more readable and unique names for debugging and tracing.
80
+ #[ inline]
78
81
pub fn set_name ( & mut self , new_name : impl Into < Cow < ' static , str > > ) {
79
82
let new_name: Cow < ' static , str > = new_name. into ( ) ;
80
83
#[ cfg( feature = "trace" ) ]
@@ -108,9 +111,70 @@ impl SystemMeta {
108
111
109
112
/// Marks the system as having deferred buffers like [`Commands`](`super::Commands`)
110
113
/// This lets the scheduler insert [`apply_deferred`](`crate::prelude::apply_deferred`) systems automatically.
114
+ #[ inline]
111
115
pub fn set_has_deferred ( & mut self ) {
112
116
self . has_deferred = true ;
113
117
}
118
+
119
+ /// Changes the warn policy.
120
+ #[ inline]
121
+ pub fn set_warn_policy ( & mut self , warn_policy : WarnPolicy ) {
122
+ self . warn_policy = warn_policy;
123
+ }
124
+
125
+ /// Advances the warn policy after validation failed.
126
+ #[ inline]
127
+ pub fn advance_warn_policy ( & mut self ) {
128
+ self . warn_policy . advance ( ) ;
129
+ }
130
+
131
+ /// Emits a warning about inaccessible system param if policy allows it.
132
+ #[ inline]
133
+ pub fn try_warn < P > ( & self )
134
+ where
135
+ P : SystemParam ,
136
+ {
137
+ self . warn_policy . try_warn :: < P > ( & self . name ) ;
138
+ }
139
+ }
140
+
141
+ /// State machine for emitting warnings when [system params are invalid](System::validate_param).
142
+ #[ derive( Clone , Copy ) ]
143
+ pub enum WarnPolicy {
144
+ /// No warning should ever be emitted.
145
+ Never ,
146
+ /// The warning will be emitted once and status will update to [`Self::Never`].
147
+ Once ,
148
+ /// The warning will be emitted every time.
149
+ Always ,
150
+ }
151
+
152
+ impl WarnPolicy {
153
+ /// Advances the warn policy after validation failed.
154
+ #[ inline]
155
+ fn advance ( & mut self ) {
156
+ * self = match self {
157
+ Self :: Never => Self :: Never ,
158
+ Self :: Once => Self :: Never ,
159
+ Self :: Always => Self :: Always ,
160
+ } ;
161
+ }
162
+
163
+ /// Emits a warning about inaccessible system param if policy allows it.
164
+ #[ inline]
165
+ fn try_warn < P > ( & self , name : & str )
166
+ where
167
+ P : SystemParam ,
168
+ {
169
+ if matches ! ( self , Self :: Never ) {
170
+ return ;
171
+ }
172
+ bevy_utils:: tracing:: warn!(
173
+ "System {0} will not run because it requested inaccessible system parameter {1}" ,
174
+ name,
175
+ std:: any:: type_name:: <P >( )
176
+ ) ;
177
+ }
114
178
}
115
179
116
180
// TODO: Actually use this in FunctionSystem. We should probably only do this once Systems are constructed using a World reference
@@ -657,9 +721,13 @@ where
657
721
}
658
722
659
723
#[ inline]
660
- unsafe fn validate_param_unsafe ( & self , world : UnsafeWorldCell ) -> bool {
724
+ unsafe fn validate_param_unsafe ( & mut self , world : UnsafeWorldCell ) -> bool {
661
725
let param_state = self . param_state . as_ref ( ) . expect ( Self :: PARAM_MESSAGE ) ;
662
- F :: Param :: validate_param ( param_state, & self . system_meta , world)
726
+ let is_valid = unsafe { F :: Param :: validate_param ( param_state, & self . system_meta , world) } ;
727
+ if !is_valid {
728
+ self . system_meta . advance_warn_policy ( ) ;
729
+ }
730
+ is_valid
663
731
}
664
732
665
733
#[ inline]
0 commit comments