1use bevy::prelude::*;
39
40pub trait Lens<T> {
69 fn lerp(&mut self, target: Mut<'_, T>, ratio: f32);
75}
76
77#[cfg(feature = "bevy_text")]
82#[derive(Debug, Copy, Clone, PartialEq)]
83pub struct TextColorLens {
84 pub start: Color,
86 pub end: Color,
88}
89
90#[cfg(feature = "bevy_text")]
91impl Lens<TextColor> for TextColorLens {
92 fn lerp(&mut self, mut target: Mut<TextColor>, ratio: f32) {
93 target.0 = self.start.mix(&self.end, ratio);
94 }
95}
96
97#[derive(Debug, Copy, Clone, PartialEq)]
102pub struct TransformPositionLens {
103 pub start: Vec3,
105 pub end: Vec3,
107}
108
109impl Lens<Transform> for TransformPositionLens {
110 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
111 target.translation = self.start.lerp(self.end, ratio);
112 }
113}
114
115#[derive(Debug, Copy, Clone, PartialEq)]
133pub struct TransformRotationLens {
134 pub start: Quat,
136 pub end: Quat,
138}
139
140impl Lens<Transform> for TransformRotationLens {
141 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
142 target.rotation = self.start.slerp(self.end, ratio);
143 }
144}
145
146#[derive(Debug, Copy, Clone, PartialEq)]
159pub struct TransformRotateXLens {
160 pub start: f32,
162 pub end: f32,
164}
165
166impl Lens<Transform> for TransformRotateXLens {
167 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
168 let angle = (self.end - self.start).mul_add(ratio, self.start);
169 target.rotation = Quat::from_rotation_x(angle);
170 }
171}
172
173#[derive(Debug, Copy, Clone, PartialEq)]
186pub struct TransformRotateYLens {
187 pub start: f32,
189 pub end: f32,
191}
192
193impl Lens<Transform> for TransformRotateYLens {
194 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
195 let angle = (self.end - self.start).mul_add(ratio, self.start);
196 target.rotation = Quat::from_rotation_y(angle);
197 }
198}
199
200#[derive(Debug, Copy, Clone, PartialEq)]
213pub struct TransformRotateZLens {
214 pub start: f32,
216 pub end: f32,
218}
219
220impl Lens<Transform> for TransformRotateZLens {
221 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
222 let angle = (self.end - self.start).mul_add(ratio, self.start);
223 target.rotation = Quat::from_rotation_z(angle);
224 }
225}
226
227#[derive(Debug, Copy, Clone, PartialEq)]
243pub struct TransformRotateAdditiveXLens {
244 pub base_rotation: Quat,
247 pub start: f32,
249 pub end: f32,
251}
252
253impl Lens<Transform> for TransformRotateAdditiveXLens {
254 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
255 let angle = (self.end - self.start).mul_add(ratio, self.start);
256 target.rotation = self.base_rotation * Quat::from_rotation_x(angle);
257 }
258}
259
260#[derive(Debug, Copy, Clone, PartialEq)]
276pub struct TransformRotateAdditiveYLens {
277 pub base_rotation: Quat,
280 pub start: f32,
282 pub end: f32,
284}
285
286impl Lens<Transform> for TransformRotateAdditiveYLens {
287 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
288 let angle = (self.end - self.start).mul_add(ratio, self.start);
289 target.rotation = self.base_rotation * Quat::from_rotation_y(angle);
290 }
291}
292
293#[derive(Debug, Copy, Clone, PartialEq)]
309pub struct TransformRotateAdditiveZLens {
310 pub base_rotation: Quat,
313 pub start: f32,
315 pub end: f32,
317}
318
319impl Lens<Transform> for TransformRotateAdditiveZLens {
320 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
321 let angle = (self.end - self.start).mul_add(ratio, self.start);
322 target.rotation = self.base_rotation * Quat::from_rotation_z(angle);
323 }
324}
325
326#[derive(Debug, Copy, Clone, PartialEq)]
343pub struct TransformRotateAxisLens {
344 pub axis: Vec3,
346 pub start: f32,
348 pub end: f32,
350}
351
352impl Lens<Transform> for TransformRotateAxisLens {
353 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
354 let angle = (self.end - self.start).mul_add(ratio, self.start);
355 target.rotation = Quat::from_axis_angle(self.axis, angle);
356 }
357}
358
359#[derive(Debug, Copy, Clone, PartialEq)]
364pub struct TransformScaleLens {
365 pub start: Vec3,
367 pub end: Vec3,
369}
370
371impl Lens<Transform> for TransformScaleLens {
372 fn lerp(&mut self, mut target: Mut<Transform>, ratio: f32) {
373 target.scale = self.start + (self.end - self.start) * ratio;
374 }
375}
376
377#[cfg(feature = "bevy_ui")]
382#[derive(Debug, Copy, Clone, PartialEq)]
383pub struct UiPositionLens {
384 pub start: UiRect,
386 pub end: UiRect,
388}
389
390#[cfg(feature = "bevy_ui")]
391fn lerp_val(start: &Val, end: &Val, ratio: f32) -> Val {
392 match (start, end) {
393 (Val::Percent(start), Val::Percent(end)) => {
394 Val::Percent((end - start).mul_add(ratio, *start))
395 }
396 (Val::Px(start), Val::Px(end)) => Val::Px((end - start).mul_add(ratio, *start)),
397 (Val::Vw(start), Val::Vw(end)) => Val::Vw((end - start).mul_add(ratio, *start)),
398 (Val::Vh(start), Val::Vh(end)) => Val::Vh((end - start).mul_add(ratio, *start)),
399 (Val::VMin(start), Val::VMin(end)) => Val::VMin((end - start).mul_add(ratio, *start)),
400 (Val::VMax(start), Val::VMax(end)) => Val::VMax((end - start).mul_add(ratio, *start)),
401 _ => *start,
402 }
403}
404
405#[cfg(feature = "bevy_ui")]
406impl Lens<Node> for UiPositionLens {
407 fn lerp(&mut self, mut target: Mut<Node>, ratio: f32) {
408 target.left = lerp_val(&self.start.left, &self.end.left, ratio);
409 target.right = lerp_val(&self.start.right, &self.end.right, ratio);
410 target.top = lerp_val(&self.start.top, &self.end.top, ratio);
411 target.bottom = lerp_val(&self.start.bottom, &self.end.bottom, ratio);
412 }
413}
414
415#[cfg(feature = "bevy_ui")]
417#[derive(Debug, Copy, Clone, PartialEq)]
418pub struct UiBackgroundColorLens {
419 pub start: Color,
421 pub end: Color,
423}
424
425#[cfg(feature = "bevy_ui")]
426impl Lens<BackgroundColor> for UiBackgroundColorLens {
427 fn lerp(&mut self, mut target: Mut<BackgroundColor>, ratio: f32) {
428 target.0 = self.start.mix(&self.end, ratio);
429 }
430}
431
432#[cfg(feature = "bevy_sprite")]
437#[derive(Debug, Copy, Clone, PartialEq)]
438pub struct ColorMaterialColorLens {
439 pub start: Color,
441 pub end: Color,
443}
444
445#[cfg(feature = "bevy_sprite")]
446impl Lens<ColorMaterial> for ColorMaterialColorLens {
447 fn lerp(&mut self, mut target: Mut<ColorMaterial>, ratio: f32) {
448 target.color = self.start.mix(&self.end, ratio);
449 }
450}
451
452#[cfg(feature = "bevy_sprite")]
457#[derive(Debug, Copy, Clone, PartialEq)]
458pub struct SpriteColorLens {
459 pub start: Color,
461 pub end: Color,
463}
464
465#[cfg(feature = "bevy_sprite")]
466impl Lens<Sprite> for SpriteColorLens {
467 fn lerp(&mut self, mut target: Mut<Sprite>, ratio: f32) {
468 let value = self.start.mix(&self.end, ratio);
469 target.color = value;
470 }
471}
472
473#[cfg(test)]
474mod tests {
475 use std::f32::consts::TAU;
476
477 #[cfg(any(feature = "bevy_sprite", feature = "bevy_text"))]
478 use bevy::color::palettes::css::{BLUE, RED};
479 use bevy::ecs::{change_detection::MaybeLocation, component::Tick};
480
481 use super::*;
482
483 #[cfg(feature = "bevy_text")]
484 #[test]
485 fn text_color() {
486 let mut lens = TextColorLens {
487 start: RED.into(),
488 end: BLUE.into(),
489 };
490
491 let mut text_color = TextColor::default();
492
493 {
494 let mut added = Tick::new(0);
495 let mut last_changed = Tick::new(0);
496 let mut caller = MaybeLocation::caller();
497 let target = Mut::new(
498 &mut text_color,
499 &mut added,
500 &mut last_changed,
501 Tick::new(0),
502 Tick::new(0),
503 caller.as_mut(),
504 );
505
506 lens.lerp(target, 0.);
507 }
508 assert_eq!(text_color.0, RED.into());
509
510 {
511 let mut added = Tick::new(0);
512 let mut last_changed = Tick::new(0);
513 let mut caller = MaybeLocation::caller();
514 let target = Mut::new(
515 &mut text_color,
516 &mut added,
517 &mut last_changed,
518 Tick::new(0),
519 Tick::new(0),
520 caller.as_mut(),
521 );
522
523 lens.lerp(target, 1.);
524 }
525 assert_eq!(text_color.0, BLUE.into());
526
527 {
528 let mut added = Tick::new(0);
529 let mut last_changed = Tick::new(0);
530 let mut caller = MaybeLocation::caller();
531 let target = Mut::new(
532 &mut text_color,
533 &mut added,
534 &mut last_changed,
535 Tick::new(0),
536 Tick::new(0),
537 caller.as_mut(),
538 );
539
540 lens.lerp(target, 0.3);
541 }
542 assert_eq!(text_color.0, Color::srgba(0.7, 0., 0.3, 1.0));
543 }
544
545 #[test]
546 fn transform_position() {
547 let mut lens = TransformPositionLens {
548 start: Vec3::ZERO,
549 end: Vec3::new(1., 2., -4.),
550 };
551 let mut transform = Transform::default();
552
553 {
554 let mut added = Tick::new(0);
555 let mut last_changed = Tick::new(0);
556 let mut caller = MaybeLocation::caller();
557 let target = Mut::new(
558 &mut transform,
559 &mut added,
560 &mut last_changed,
561 Tick::new(0),
562 Tick::new(0),
563 caller.as_mut(),
564 );
565
566 lens.lerp(target, 0.);
567 }
568 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
569 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
570 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
571
572 {
573 let mut added = Tick::new(0);
574 let mut last_changed = Tick::new(0);
575 let mut caller = MaybeLocation::caller();
576 let target = Mut::new(
577 &mut transform,
578 &mut added,
579 &mut last_changed,
580 Tick::new(0),
581 Tick::new(0),
582 caller.as_mut(),
583 );
584
585 lens.lerp(target, 1.);
586 }
587 assert!(transform
588 .translation
589 .abs_diff_eq(Vec3::new(1., 2., -4.), 1e-5));
590 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
591 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
592
593 {
594 let mut added = Tick::new(0);
595 let mut last_changed = Tick::new(0);
596 let mut caller = MaybeLocation::caller();
597 let target = Mut::new(
598 &mut transform,
599 &mut added,
600 &mut last_changed,
601 Tick::new(0),
602 Tick::new(0),
603 caller.as_mut(),
604 );
605
606 lens.lerp(target, 0.3);
607 }
608 assert!(transform
609 .translation
610 .abs_diff_eq(Vec3::new(0.3, 0.6, -1.2), 1e-5));
611 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
612 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
613 }
614
615 #[test]
616 fn transform_rotation() {
617 let mut lens = TransformRotationLens {
618 start: Quat::IDENTITY,
619 end: Quat::from_rotation_z(100_f32.to_radians()),
620 };
621 let mut transform = Transform::default();
622
623 {
624 let mut added = Tick::new(0);
625 let mut last_changed = Tick::new(0);
626 let mut caller = MaybeLocation::caller();
627 let target = Mut::new(
628 &mut transform,
629 &mut added,
630 &mut last_changed,
631 Tick::new(0),
632 Tick::new(0),
633 caller.as_mut(),
634 );
635
636 lens.lerp(target, 0.);
637 }
638 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
639 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
640 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
641
642 {
643 let mut added = Tick::new(0);
644 let mut last_changed = Tick::new(0);
645 let mut caller = MaybeLocation::caller();
646 let target = Mut::new(
647 &mut transform,
648 &mut added,
649 &mut last_changed,
650 Tick::new(0),
651 Tick::new(0),
652 caller.as_mut(),
653 );
654
655 lens.lerp(target, 1.);
656 }
657 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
658 assert!(transform
659 .rotation
660 .abs_diff_eq(Quat::from_rotation_z(100_f32.to_radians()), 1e-5));
661 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
662
663 {
664 let mut added = Tick::new(0);
665 let mut last_changed = Tick::new(0);
666 let mut caller = MaybeLocation::caller();
667 let target = Mut::new(
668 &mut transform,
669 &mut added,
670 &mut last_changed,
671 Tick::new(0),
672 Tick::new(0),
673 caller.as_mut(),
674 );
675
676 lens.lerp(target, 0.3);
677 }
678 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
679 assert!(transform
680 .rotation
681 .abs_diff_eq(Quat::from_rotation_z(30_f32.to_radians()), 1e-5));
682 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
683 }
684
685 #[test]
686 fn transform_rotate_x() {
687 let mut lens = TransformRotateXLens {
688 start: 0.,
689 end: 1440_f32.to_radians(), };
691 let mut transform = Transform::default();
692
693 for (index, ratio) in [0., 0.25, 0.5, 0.75, 1.].iter().enumerate() {
694 {
695 let mut added = Tick::new(0);
696 let mut last_changed = Tick::new(0);
697 let mut caller = MaybeLocation::caller();
698 let target = Mut::new(
699 &mut transform,
700 &mut added,
701 &mut last_changed,
702 Tick::new(0),
703 Tick::new(0),
704 caller.as_mut(),
705 );
706
707 lens.lerp(target, *ratio);
708 }
709 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
710 if index == 1 || index == 3 {
711 assert!(transform
715 .rotation
716 .abs_diff_eq(Quat::from_xyzw(0., 0., 0., -1.), 1e-5));
717 } else {
718 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
719 }
720 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
721 }
722
723 {
724 let mut added = Tick::new(0);
725 let mut last_changed = Tick::new(0);
726 let mut caller = MaybeLocation::caller();
727 let target = Mut::new(
728 &mut transform,
729 &mut added,
730 &mut last_changed,
731 Tick::new(0),
732 Tick::new(0),
733 caller.as_mut(),
734 );
735
736 lens.lerp(target, 0.1);
737 }
738 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
739 assert!(transform
740 .rotation
741 .abs_diff_eq(Quat::from_rotation_x(0.1 * (4. * TAU)), 1e-5));
742 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
743 }
744
745 #[test]
746 fn transform_rotate_y() {
747 let mut lens = TransformRotateYLens {
748 start: 0.,
749 end: 1440_f32.to_radians(), };
751 let mut transform = Transform::default();
752
753 for (index, ratio) in [0., 0.25, 0.5, 0.75, 1.].iter().enumerate() {
754 {
755 let mut added = Tick::new(0);
756 let mut last_changed = Tick::new(0);
757 let mut caller = MaybeLocation::caller();
758 let target = Mut::new(
759 &mut transform,
760 &mut added,
761 &mut last_changed,
762 Tick::new(0),
763 Tick::new(0),
764 caller.as_mut(),
765 );
766
767 lens.lerp(target, *ratio);
768 }
769 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
770 if index == 1 || index == 3 {
771 assert!(transform
775 .rotation
776 .abs_diff_eq(Quat::from_xyzw(0., 0., 0., -1.), 1e-5));
777 } else {
778 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
779 }
780 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
781 }
782
783 {
784 let mut added = Tick::new(0);
785 let mut last_changed = Tick::new(0);
786 let mut caller = MaybeLocation::caller();
787 let target = Mut::new(
788 &mut transform,
789 &mut added,
790 &mut last_changed,
791 Tick::new(0),
792 Tick::new(0),
793 caller.as_mut(),
794 );
795
796 lens.lerp(target, 0.1);
797 }
798 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
799 assert!(transform
800 .rotation
801 .abs_diff_eq(Quat::from_rotation_y(0.1 * (4. * TAU)), 1e-5));
802 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
803 }
804
805 #[test]
806 fn transform_rotate_z() {
807 let mut lens = TransformRotateZLens {
808 start: 0.,
809 end: 1440_f32.to_radians(), };
811 let mut transform = Transform::default();
812
813 for (index, ratio) in [0., 0.25, 0.5, 0.75, 1.].iter().enumerate() {
814 {
815 let mut added = Tick::new(0);
816 let mut last_changed = Tick::new(0);
817 let mut caller = MaybeLocation::caller();
818 let target = Mut::new(
819 &mut transform,
820 &mut added,
821 &mut last_changed,
822 Tick::new(0),
823 Tick::new(0),
824 caller.as_mut(),
825 );
826
827 lens.lerp(target, *ratio);
828 }
829 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
830 if index == 1 || index == 3 {
831 assert!(transform
835 .rotation
836 .abs_diff_eq(Quat::from_xyzw(0., 0., 0., -1.), 1e-5));
837 } else {
838 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
839 }
840 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
841 }
842
843 {
844 let mut added = Tick::new(0);
845 let mut last_changed = Tick::new(0);
846 let mut caller = MaybeLocation::caller();
847 let target = Mut::new(
848 &mut transform,
849 &mut added,
850 &mut last_changed,
851 Tick::new(0),
852 Tick::new(0),
853 caller.as_mut(),
854 );
855
856 lens.lerp(target, 0.1);
857 }
858 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
859 assert!(transform
860 .rotation
861 .abs_diff_eq(Quat::from_rotation_z(0.1 * (4. * TAU)), 1e-5));
862 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
863 }
864
865 #[test]
866 fn transform_rotate_axis() {
867 let axis = Vec3::ONE.normalize();
868 let mut lens = TransformRotateAxisLens {
869 axis,
870 start: 0.,
871 end: 1440_f32.to_radians(), };
873 let mut transform = Transform::default();
874
875 for (index, ratio) in [0., 0.25, 0.5, 0.75, 1.].iter().enumerate() {
876 {
877 let mut added = Tick::new(0);
878 let mut last_changed = Tick::new(0);
879 let mut caller = MaybeLocation::caller();
880 let target = Mut::new(
881 &mut transform,
882 &mut added,
883 &mut last_changed,
884 Tick::new(0),
885 Tick::new(0),
886 caller.as_mut(),
887 );
888
889 lens.lerp(target, *ratio);
890 }
891 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
892 if index == 1 || index == 3 {
893 assert!(transform
897 .rotation
898 .abs_diff_eq(Quat::from_xyzw(0., 0., 0., -1.), 1e-5));
899 } else {
900 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
901 }
902 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
903 }
904
905 {
906 let mut added = Tick::new(0);
907 let mut last_changed = Tick::new(0);
908 let mut caller = MaybeLocation::caller();
909 let target = Mut::new(
910 &mut transform,
911 &mut added,
912 &mut last_changed,
913 Tick::new(0),
914 Tick::new(0),
915 caller.as_mut(),
916 );
917
918 lens.lerp(target, 0.1);
919 }
920 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
921 assert!(transform
922 .rotation
923 .abs_diff_eq(Quat::from_axis_angle(axis, 0.1 * (4. * TAU)), 1e-5));
924 assert!(transform.scale.abs_diff_eq(Vec3::ONE, 1e-5));
925 }
926
927 #[test]
928 fn transform_scale() {
929 let mut lens = TransformScaleLens {
930 start: Vec3::ZERO,
931 end: Vec3::new(1., 2., -4.),
932 };
933 let mut transform = Transform::default();
934
935 {
936 let mut added = Tick::new(0);
937 let mut last_changed = Tick::new(0);
938 let mut caller = MaybeLocation::caller();
939 let target = Mut::new(
940 &mut transform,
941 &mut added,
942 &mut last_changed,
943 Tick::new(0),
944 Tick::new(0),
945 caller.as_mut(),
946 );
947
948 lens.lerp(target, 0.);
949 }
950 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
951 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
952 assert!(transform.scale.abs_diff_eq(Vec3::ZERO, 1e-5));
953
954 {
955 let mut added = Tick::new(0);
956 let mut last_changed = Tick::new(0);
957 let mut caller = MaybeLocation::caller();
958 let target = Mut::new(
959 &mut transform,
960 &mut added,
961 &mut last_changed,
962 Tick::new(0),
963 Tick::new(0),
964 caller.as_mut(),
965 );
966
967 lens.lerp(target, 1.);
968 }
969 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
970 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
971 assert!(transform.scale.abs_diff_eq(Vec3::new(1., 2., -4.), 1e-5));
972
973 {
974 let mut added = Tick::new(0);
975 let mut last_changed = Tick::new(0);
976 let mut caller = MaybeLocation::caller();
977 let target = Mut::new(
978 &mut transform,
979 &mut added,
980 &mut last_changed,
981 Tick::new(0),
982 Tick::new(0),
983 caller.as_mut(),
984 );
985
986 lens.lerp(target, 0.3);
987 }
988 assert!(transform.translation.abs_diff_eq(Vec3::ZERO, 1e-5));
989 assert!(transform.rotation.abs_diff_eq(Quat::IDENTITY, 1e-5));
990 assert!(transform.scale.abs_diff_eq(Vec3::new(0.3, 0.6, -1.2), 1e-5));
991 }
992
993 #[cfg(feature = "bevy_ui")]
994 #[test]
995 fn ui_position() {
996 let mut lens = UiPositionLens {
997 start: UiRect {
998 left: Val::Px(0.),
999 top: Val::Px(0.),
1000 right: Val::Auto,
1001 bottom: Val::Percent(25.),
1002 },
1003 end: UiRect {
1004 left: Val::Px(1.),
1005 top: Val::Px(5.),
1006 right: Val::Auto,
1007 bottom: Val::Percent(45.),
1008 },
1009 };
1010 let mut node = Node::default();
1011
1012 {
1013 let mut added = Tick::new(0);
1014 let mut last_changed = Tick::new(0);
1015 let mut caller = MaybeLocation::caller();
1016 let target = Mut::new(
1017 &mut node,
1018 &mut added,
1019 &mut last_changed,
1020 Tick::new(0),
1021 Tick::new(0),
1022 caller.as_mut(),
1023 );
1024
1025 lens.lerp(target, 0.);
1026 }
1027 assert_eq!(node.left, Val::Px(0.));
1028 assert_eq!(node.top, Val::Px(0.));
1029 assert_eq!(node.right, Val::Auto);
1030 assert_eq!(node.bottom, Val::Percent(25.));
1031
1032 {
1033 let mut added = Tick::new(0);
1034 let mut last_changed = Tick::new(0);
1035 let mut caller = MaybeLocation::caller();
1036 let target = Mut::new(
1037 &mut node,
1038 &mut added,
1039 &mut last_changed,
1040 Tick::new(0),
1041 Tick::new(0),
1042 caller.as_mut(),
1043 );
1044
1045 lens.lerp(target, 1.);
1046 }
1047 assert_eq!(node.left, Val::Px(1.));
1048 assert_eq!(node.top, Val::Px(5.));
1049 assert_eq!(node.right, Val::Auto);
1050 assert_eq!(node.bottom, Val::Percent(45.));
1051
1052 {
1053 let mut added = Tick::new(0);
1054 let mut last_changed = Tick::new(0);
1055 let mut caller = MaybeLocation::caller();
1056 let target = Mut::new(
1057 &mut node,
1058 &mut added,
1059 &mut last_changed,
1060 Tick::new(0),
1061 Tick::new(0),
1062 caller.as_mut(),
1063 );
1064
1065 lens.lerp(target, 0.3);
1066 }
1067 assert_eq!(node.left, Val::Px(0.3));
1068 assert_eq!(node.top, Val::Px(1.5));
1069 assert_eq!(node.right, Val::Auto);
1070 assert_eq!(node.bottom, Val::Percent(31.));
1071 }
1072
1073 #[cfg(feature = "bevy_sprite")]
1074 #[test]
1075 fn colormaterial_color() {
1076 let mut lens = ColorMaterialColorLens {
1077 start: RED.into(),
1078 end: BLUE.into(),
1079 };
1080 let mut assets = Assets::default();
1081 let handle = assets.add(ColorMaterial {
1082 color: Color::WHITE,
1083 texture: None,
1084 ..default()
1085 });
1086
1087 {
1088 let mut added = Tick::new(0);
1089 let mut last_changed = Tick::new(0);
1090 let mut caller = MaybeLocation::caller();
1091 let asset = assets.get_mut(handle.id()).unwrap();
1092 let target = Mut::new(
1093 asset,
1094 &mut added,
1095 &mut last_changed,
1096 Tick::new(0),
1097 Tick::new(0),
1098 caller.as_mut(),
1099 );
1100 lens.lerp(target, 0.);
1101 }
1102 assert_eq!(assets.get(handle.id()).unwrap().color, RED.into());
1103
1104 {
1105 let mut added = Tick::new(0);
1106 let mut last_changed = Tick::new(0);
1107 let mut caller = MaybeLocation::caller();
1108 let asset = assets.get_mut(handle.id()).unwrap();
1109 let target = Mut::new(
1110 asset,
1111 &mut added,
1112 &mut last_changed,
1113 Tick::new(0),
1114 Tick::new(0),
1115 caller.as_mut(),
1116 );
1117 lens.lerp(target, 1.);
1118 }
1119 assert_eq!(assets.get(handle.id()).unwrap().color, BLUE.into());
1120
1121 {
1122 let mut added = Tick::new(0);
1123 let mut last_changed = Tick::new(0);
1124 let mut caller = MaybeLocation::caller();
1125 let asset = assets.get_mut(handle.id()).unwrap();
1126 let target = Mut::new(
1127 asset,
1128 &mut added,
1129 &mut last_changed,
1130 Tick::new(0),
1131 Tick::new(0),
1132 caller.as_mut(),
1133 );
1134 lens.lerp(target, 0.3);
1135 }
1136 assert_eq!(
1137 assets.get(handle.id()).unwrap().color,
1138 Color::srgba(0.7, 0., 0.3, 1.0)
1139 );
1140 }
1141
1142 #[cfg(feature = "bevy_sprite")]
1143 #[test]
1144 fn sprite_color() {
1145 let mut lens = SpriteColorLens {
1146 start: RED.into(),
1147 end: BLUE.into(),
1148 };
1149 let mut sprite = Sprite {
1150 color: Color::WHITE,
1151 ..default()
1152 };
1153
1154 {
1155 let mut added = Tick::new(0);
1156 let mut last_changed = Tick::new(0);
1157 let mut caller = MaybeLocation::caller();
1158 let target = Mut::new(
1159 &mut sprite,
1160 &mut added,
1161 &mut last_changed,
1162 Tick::new(0),
1163 Tick::new(0),
1164 caller.as_mut(),
1165 );
1166
1167 lens.lerp(target, 0.);
1168 }
1169 assert_eq!(sprite.color, RED.into());
1170
1171 {
1172 let mut added = Tick::new(0);
1173 let mut last_changed = Tick::new(0);
1174 let mut caller = MaybeLocation::caller();
1175 let target = Mut::new(
1176 &mut sprite,
1177 &mut added,
1178 &mut last_changed,
1179 Tick::new(0),
1180 Tick::new(0),
1181 caller.as_mut(),
1182 );
1183
1184 lens.lerp(target, 1.);
1185 }
1186 assert_eq!(sprite.color, BLUE.into());
1187
1188 {
1189 let mut added = Tick::new(0);
1190 let mut last_changed = Tick::new(0);
1191 let mut caller = MaybeLocation::caller();
1192 let target = Mut::new(
1193 &mut sprite,
1194 &mut added,
1195 &mut last_changed,
1196 Tick::new(0),
1197 Tick::new(0),
1198 caller.as_mut(),
1199 );
1200
1201 lens.lerp(target, 0.3);
1202 }
1203 assert_eq!(sprite.color, Color::srgba(0.7, 0., 0.3, 1.0));
1204 }
1205}