1use crate::{
2 diff::{Diff, Patch, RealtimeClone},
3 event::ParamData,
4};
5use bevy_platform::sync::atomic::{AtomicU64, Ordering};
6
7#[inline(always)]
11fn increment_counter() -> u64 {
12 static NOTIFY_COUNTER: AtomicU64 = AtomicU64::new(1);
13
14 NOTIFY_COUNTER.fetch_add(1, Ordering::Relaxed)
15}
16
17#[derive(Debug, Clone)]
28pub struct Notify<T> {
29 value: T,
30 counter: u64,
31}
32
33impl<T> Notify<T> {
34 pub fn new(value: T) -> Self {
50 Self {
51 value,
52 counter: increment_counter(),
53 }
54 }
55
56 #[inline(always)]
65 pub fn id(&self) -> u64 {
66 self.counter
67 }
68
69 pub fn as_mut_unsync(&mut self) -> &mut T {
71 &mut self.value
72 }
73
74 pub fn notify(&mut self) {
76 self.counter = increment_counter();
77 }
78}
79
80impl<T> AsRef<T> for Notify<T> {
81 fn as_ref(&self) -> &T {
82 &self.value
83 }
84}
85
86impl<T> AsMut<T> for Notify<T> {
87 fn as_mut(&mut self) -> &mut T {
88 self.counter = increment_counter();
89
90 &mut self.value
91 }
92}
93
94impl<T: Default> Default for Notify<T> {
95 fn default() -> Self {
96 Self::new(T::default())
97 }
98}
99
100impl<T> core::ops::Deref for Notify<T> {
101 type Target = T;
102
103 fn deref(&self) -> &Self::Target {
104 &self.value
105 }
106}
107
108impl<T> core::ops::DerefMut for Notify<T> {
109 fn deref_mut(&mut self) -> &mut Self::Target {
110 self.counter = increment_counter();
111
112 &mut self.value
113 }
114}
115
116impl<T: Copy> Copy for Notify<T> {}
117
118impl<T: RealtimeClone + Send + Sync + 'static> Diff for Notify<T> {
119 fn diff<E: super::EventQueue>(
120 &self,
121 baseline: &Self,
122 path: super::PathBuilder,
123 event_queue: &mut E,
124 ) {
125 if self.counter != baseline.counter {
126 event_queue.push_param(ParamData::any(self.clone()), path);
127 }
128 }
129}
130
131impl<T: RealtimeClone + Send + Sync + 'static> Patch for Notify<T> {
132 type Patch = Self;
133
134 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, super::PatchError> {
135 data.downcast_ref()
136 .ok_or(super::PatchError::InvalidData)
137 .cloned()
138 }
139
140 fn apply(&mut self, patch: Self::Patch) {
141 *self = patch;
142 }
143}
144
145impl<T: PartialEq> PartialEq for Notify<T> {
146 fn eq(&self, other: &Self) -> bool {
147 self.value == other.value && self.counter == other.counter
148 }
149}
150
151#[cfg(test)]
152mod test {
153 use crate::diff::PathBuilder;
154
155 use super::*;
156
157 #[test]
158 fn test_identical_write() {
159 #[cfg(not(feature = "std"))]
160 use bevy_platform::prelude::Vec;
161
162 let baseline = Notify::new(0.5f32);
163 let mut value = baseline;
164
165 let mut events = Vec::new();
166 value.diff(&baseline, PathBuilder::default(), &mut events);
167 assert_eq!(events.len(), 0);
168
169 *value = 0.5f32;
170
171 value.diff(&baseline, PathBuilder::default(), &mut events);
172 assert_eq!(events.len(), 1);
173 }
174}
175
176#[cfg(feature = "bevy_reflect")]
177mod reflect {
178 use super::Notify;
179
180 #[cfg(not(feature = "std"))]
181 use bevy_platform::prelude::{Box, ToString};
182
183 impl<T> bevy_reflect::GetTypeRegistration for Notify<T>
184 where
185 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
186 T: Clone
187 + Default
188 + bevy_reflect::FromReflect
189 + bevy_reflect::TypePath
190 + bevy_reflect::MaybeTyped
191 + bevy_reflect::__macro_exports::RegisterForReflection,
192 {
193 fn get_type_registration() -> bevy_reflect::TypeRegistration {
194 let mut registration = bevy_reflect::TypeRegistration::of::<Self>();
195 registration.insert:: <bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType:: <Self> ::from_type());
196 registration.insert::<bevy_reflect::ReflectFromReflect>(
197 bevy_reflect::FromType::<Self>::from_type(),
198 );
199 registration
200 .insert::<bevy_reflect::prelude::ReflectDefault>(
201 bevy_reflect::FromType::<Self>::from_type(),
202 );
203 registration
204 }
205
206 #[inline(never)]
207 fn register_type_dependencies(registry: &mut bevy_reflect::TypeRegistry) {
208 <T as bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
209 <u64 as bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
210 }
211 }
212
213 impl<T> bevy_reflect::Typed for Notify<T>
214 where
215 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
216 T: Clone
217 + bevy_reflect::FromReflect
218 + bevy_reflect::TypePath
219 + bevy_reflect::MaybeTyped
220 + bevy_reflect::__macro_exports::RegisterForReflection,
221 {
222 #[inline]
223 fn type_info() -> &'static bevy_reflect::TypeInfo {
224 static CELL: bevy_reflect::utility::GenericTypeInfoCell =
225 bevy_reflect::utility::GenericTypeInfoCell::new();
226 CELL.get_or_insert::<Self, _>(|| {
227 bevy_reflect::TypeInfo::Struct(
228 bevy_reflect::StructInfo::new::<Self>(&[
229 bevy_reflect::NamedField::new::<T>("value").with_custom_attributes(
230 bevy_reflect::attributes::CustomAttributes::default(),
231 ),
232 ])
233 .with_custom_attributes(bevy_reflect::attributes::CustomAttributes::default())
234 .with_generics(bevy_reflect::Generics::from_iter([
235 bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(
236 bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T"),
238 )),
239 ])),
240 )
241 })
242 }
243 }
244
245 extern crate alloc;
246 impl<T> bevy_reflect::TypePath for Notify<T>
247 where
248 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
249 T: bevy_reflect::TypePath,
250 {
251 fn type_path() -> &'static str {
252 static CELL: bevy_reflect::utility::GenericTypePathCell =
253 bevy_reflect::utility::GenericTypePathCell::new();
254 CELL.get_or_insert::<Self, _>(|| {
255 ::core::ops::Add::<&str>::add(
256 ::core::ops::Add::<&str>::add(
257 ToString::to_string(::core::concat!(
258 ::core::concat!(
259 ::core::concat!(::core::module_path!(), "::"),
260 "Notify"
261 ),
262 "<"
263 )),
264 <T as bevy_reflect::TypePath>::type_path(),
265 ),
266 ">",
267 )
268 })
269 }
270 fn short_type_path() -> &'static str {
271 static CELL: bevy_reflect::utility::GenericTypePathCell =
272 bevy_reflect::utility::GenericTypePathCell::new();
273 CELL.get_or_insert::<Self, _>(|| {
274 ::core::ops::Add::<&str>::add(
275 ::core::ops::Add::<&str>::add(
276 ToString::to_string(::core::concat!("Notify", "<")),
277 <T as bevy_reflect::TypePath>::short_type_path(),
278 ),
279 ">",
280 )
281 })
282 }
283 fn type_ident() -> Option<&'static str> {
284 Some("Notify")
285 }
286 fn crate_name() -> Option<&'static str> {
287 Some(::core::module_path!().split(':').next().unwrap())
288 }
289 fn module_path() -> Option<&'static str> {
290 Some(::core::module_path!())
291 }
292 }
293
294 impl<T> bevy_reflect::Reflect for Notify<T>
295 where
296 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
297 T: Clone
298 + bevy_reflect::FromReflect
299 + bevy_reflect::TypePath
300 + bevy_reflect::MaybeTyped
301 + bevy_reflect::__macro_exports::RegisterForReflection,
302 {
303 #[inline]
304 fn into_any(self: Box<Self>) -> Box<dyn ::core::any::Any> {
305 self
306 }
307 #[inline]
308 fn as_any(&self) -> &dyn ::core::any::Any {
309 self
310 }
311 #[inline]
312 fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
313 self
314 }
315 #[inline]
316 fn into_reflect(self: Box<Self>) -> Box<dyn bevy_reflect::Reflect> {
317 self
318 }
319 #[inline]
320 fn as_reflect(&self) -> &dyn bevy_reflect::Reflect {
321 self
322 }
323 #[inline]
324 fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
325 self
326 }
327 #[inline]
328 fn set(
329 &mut self,
330 value: Box<dyn bevy_reflect::Reflect>,
331 ) -> Result<(), Box<dyn bevy_reflect::Reflect>> {
332 *self = <dyn bevy_reflect::Reflect>::take(value)?;
333 Ok(())
334 }
335 }
336
337 impl<T> bevy_reflect::Struct for Notify<T>
338 where
339 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
340 T: Clone
341 + bevy_reflect::FromReflect
342 + bevy_reflect::TypePath
343 + bevy_reflect::MaybeTyped
344 + bevy_reflect::__macro_exports::RegisterForReflection,
345 {
346 fn field(&self, name: &str) -> Option<&dyn bevy_reflect::PartialReflect> {
347 match name {
348 "value" => Some(&self.value),
349 _ => None,
350 }
351 }
352
353 fn field_mut(&mut self, name: &str) -> Option<&mut dyn bevy_reflect::PartialReflect> {
354 match name {
355 "value" => Some(self.as_mut()),
356 _ => None,
357 }
358 }
359
360 fn field_at(&self, index: usize) -> Option<&dyn bevy_reflect::PartialReflect> {
361 match index {
362 0usize => Some(&self.value),
363 _ => None,
364 }
365 }
366
367 fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn bevy_reflect::PartialReflect> {
368 match index {
369 0usize => Some(self.as_mut()),
370 _ => None,
371 }
372 }
373
374 fn name_at(&self, index: usize) -> Option<&str> {
375 match index {
376 0usize => Some("value"),
377 _ => None,
378 }
379 }
380
381 fn field_len(&self) -> usize {
382 1usize
383 }
384
385 fn iter_fields<'a>(&'a self) -> bevy_reflect::FieldIter<'a> {
386 bevy_reflect::FieldIter::new(self)
387 }
388
389 fn to_dynamic_struct(&self) -> bevy_reflect::DynamicStruct {
390 let mut dynamic: bevy_reflect::DynamicStruct = Default::default();
391 dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(
392 self,
393 ));
394 dynamic.insert_boxed(
395 "value",
396 bevy_reflect::PartialReflect::to_dynamic(&self.value),
397 );
398 dynamic
399 }
400 }
401
402 impl<T> bevy_reflect::PartialReflect for Notify<T>
403 where
404 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
405 T: Clone
406 + bevy_reflect::FromReflect
407 + bevy_reflect::TypePath
408 + bevy_reflect::MaybeTyped
409 + bevy_reflect::__macro_exports::RegisterForReflection,
410 {
411 #[inline]
412 fn get_represented_type_info(&self) -> Option<&'static bevy_reflect::TypeInfo> {
413 Some(<Self as bevy_reflect::Typed>::type_info())
414 }
415
416 #[inline]
417 fn try_apply(
418 &mut self,
419 value: &dyn bevy_reflect::PartialReflect,
420 ) -> Result<(), bevy_reflect::ApplyError> {
421 if let bevy_reflect::ReflectRef::Struct(struct_value) =
422 bevy_reflect::PartialReflect::reflect_ref(value)
423 {
424 for (i, value) in ::core::iter::Iterator::enumerate(
425 bevy_reflect::Struct::iter_fields(struct_value),
426 ) {
427 let name = bevy_reflect::Struct::name_at(struct_value, i).unwrap();
428 if let Some(v) = bevy_reflect::Struct::field_mut(self, name) {
429 bevy_reflect::PartialReflect::try_apply(v, value)?;
430 }
431 }
432 } else {
433 return Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
434 from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
435 to_kind: bevy_reflect::ReflectKind::Struct,
436 });
437 }
438 Ok(())
439 }
440
441 #[inline]
442 fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
443 bevy_reflect::ReflectKind::Struct
444 }
445
446 #[inline]
447 fn reflect_ref<'a>(&'a self) -> bevy_reflect::ReflectRef<'a> {
448 bevy_reflect::ReflectRef::Struct(self)
449 }
450
451 #[inline]
452 fn reflect_mut<'a>(&'a mut self) -> bevy_reflect::ReflectMut<'a> {
453 bevy_reflect::ReflectMut::Struct(self)
454 }
455
456 #[inline]
457 fn reflect_owned(self: Box<Self>) -> bevy_reflect::ReflectOwned {
458 bevy_reflect::ReflectOwned::Struct(self)
459 }
460
461 #[inline]
462 fn try_into_reflect(
463 self: Box<Self>,
464 ) -> Result<Box<dyn bevy_reflect::Reflect>, Box<dyn bevy_reflect::PartialReflect>> {
465 Ok(self)
466 }
467
468 #[inline]
469 fn try_as_reflect(&self) -> Option<&dyn bevy_reflect::Reflect> {
470 Some(self)
471 }
472
473 #[inline]
474 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn bevy_reflect::Reflect> {
475 Some(self)
476 }
477
478 #[inline]
479 fn into_partial_reflect(self: Box<Self>) -> Box<dyn bevy_reflect::PartialReflect> {
480 self
481 }
482
483 #[inline]
484 fn as_partial_reflect(&self) -> &dyn bevy_reflect::PartialReflect {
485 self
486 }
487
488 #[inline]
489 fn as_partial_reflect_mut(&mut self) -> &mut dyn bevy_reflect::PartialReflect {
490 self
491 }
492
493 fn reflect_partial_eq(&self, value: &dyn bevy_reflect::PartialReflect) -> Option<bool> {
494 (bevy_reflect::struct_partial_eq)(self, value)
495 }
496
497 #[inline]
498 fn reflect_clone(
499 &self,
500 ) -> Result<Box<dyn bevy_reflect::Reflect>, bevy_reflect::ReflectCloneError> {
501 Ok(Box::new(Clone::clone(self)))
502 }
503 }
504
505 impl<T> bevy_reflect::FromReflect for Notify<T>
506 where
507 Notify<T>: ::core::any::Any + ::core::marker::Send + ::core::marker::Sync,
508 T: Default
509 + Clone
510 + bevy_reflect::FromReflect
511 + bevy_reflect::TypePath
512 + bevy_reflect::MaybeTyped
513 + bevy_reflect::__macro_exports::RegisterForReflection,
514 {
515 fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect) -> Option<Self> {
516 if let bevy_reflect::ReflectRef::Struct(ref_struct) =
517 bevy_reflect::PartialReflect::reflect_ref(reflect)
518 {
519 let mut this = <Self as ::core::default::Default>::default();
520 if let Some(field) = (|| {
521 <T as bevy_reflect::FromReflect>::from_reflect(bevy_reflect::Struct::field(
522 ref_struct, "value",
523 )?)
524 })() {
525 this.value = field;
526 }
527 Some(this)
528 } else {
529 None
530 }
531 }
532 }
533}