@@ -217,8 +217,8 @@ impl ViewVisibility {
217217 #[ inline]
218218 fn update ( & mut self ) {
219219 // Copy the first bit (current) to the second bit position (previous)
220- // Clear the second bit, then set it based on the first bit
221- self . 0 = ( self . 0 & ! 2 ) | ( ( self . 0 & 1 ) << 1 ) ;
220+ // and clear the first bit (current).
221+ self . 0 = ( self . 0 & 1 ) << 1 ;
222222 }
223223}
224224
@@ -1055,4 +1055,122 @@ mod test {
10551055 world. entity ( entity_clone) . get :: < VisibilityClass > ( ) . unwrap ( ) ;
10561056 assert_eq ! ( entity_clone_visibility_class. len( ) , 1 ) ;
10571057 }
1058+
1059+ #[ test]
1060+ fn view_visibility_lifecycle ( ) {
1061+ let mut app = App :: new ( ) ;
1062+ app. add_plugins ( (
1063+ TaskPoolPlugin :: default ( ) ,
1064+ bevy_asset:: AssetPlugin :: default ( ) ,
1065+ bevy_mesh:: MeshPlugin ,
1066+ bevy_transform:: TransformPlugin ,
1067+ VisibilityPlugin ,
1068+ ) ) ;
1069+
1070+ #[ derive( Resource , Default ) ]
1071+ struct ManualMark ( bool ) ;
1072+ #[ derive( Resource , Default ) ]
1073+ struct ObservedChanged ( bool ) ;
1074+ app. init_resource :: < ManualMark > ( ) ;
1075+ app. init_resource :: < ObservedChanged > ( ) ;
1076+
1077+ app. add_systems (
1078+ PostUpdate ,
1079+ (
1080+ ( |mut q : Query < & mut ViewVisibility > , mark : Res < ManualMark > | {
1081+ if mark. 0 {
1082+ for mut v in & mut q {
1083+ v. set_visible ( ) ;
1084+ }
1085+ }
1086+ } )
1087+ . in_set ( VisibilitySystems :: CheckVisibility ) ,
1088+ ( |q : Query < ( ) , Changed < ViewVisibility > > , mut observed : ResMut < ObservedChanged > | {
1089+ if !q. is_empty ( ) {
1090+ observed. 0 = true ;
1091+ }
1092+ } )
1093+ . after ( VisibilitySystems :: MarkNewlyHiddenEntitiesInvisible ) ,
1094+ ) ,
1095+ ) ;
1096+
1097+ let entity = app. world_mut ( ) . spawn ( ViewVisibility :: HIDDEN ) . id ( ) ;
1098+
1099+ // Advance system ticks and clear spawn change
1100+ app. update ( ) ;
1101+ app. world_mut ( ) . resource_mut :: < ObservedChanged > ( ) . 0 = false ;
1102+
1103+ // Frame 1: do nothing
1104+ app. update ( ) ;
1105+ {
1106+ assert ! (
1107+ !app. world( )
1108+ . entity( entity)
1109+ . get:: <ViewVisibility >( )
1110+ . unwrap( )
1111+ . get( ) ,
1112+ "Frame 1: should be hidden"
1113+ ) ;
1114+ assert ! (
1115+ !app. world( ) . resource:: <ObservedChanged >( ) . 0 ,
1116+ "Frame 1: should not be changed"
1117+ ) ;
1118+ }
1119+
1120+ // Frame 2: set entity as visible
1121+ app. world_mut ( ) . resource_mut :: < ManualMark > ( ) . 0 = true ;
1122+ app. update ( ) ;
1123+ {
1124+ assert ! (
1125+ app. world( )
1126+ . entity( entity)
1127+ . get:: <ViewVisibility >( )
1128+ . unwrap( )
1129+ . get( ) ,
1130+ "Frame 2: should be visible"
1131+ ) ;
1132+ assert ! (
1133+ app. world( ) . resource:: <ObservedChanged >( ) . 0 ,
1134+ "Frame 2: should be changed"
1135+ ) ;
1136+ }
1137+
1138+ // Frame 3: do nothing
1139+ app. world_mut ( ) . resource_mut :: < ManualMark > ( ) . 0 = false ;
1140+ app. world_mut ( ) . resource_mut :: < ObservedChanged > ( ) . 0 = false ;
1141+ app. update ( ) ;
1142+ {
1143+ assert ! (
1144+ !app. world( )
1145+ . entity( entity)
1146+ . get:: <ViewVisibility >( )
1147+ . unwrap( )
1148+ . get( ) ,
1149+ "Frame 3: should be hidden"
1150+ ) ;
1151+ assert ! (
1152+ app. world( ) . resource:: <ObservedChanged >( ) . 0 ,
1153+ "Frame 3: should be changed"
1154+ ) ;
1155+ }
1156+
1157+ // Frame 4: do nothing
1158+ app. world_mut ( ) . resource_mut :: < ManualMark > ( ) . 0 = false ;
1159+ app. world_mut ( ) . resource_mut :: < ObservedChanged > ( ) . 0 = false ;
1160+ app. update ( ) ;
1161+ {
1162+ assert ! (
1163+ !app. world( )
1164+ . entity( entity)
1165+ . get:: <ViewVisibility >( )
1166+ . unwrap( )
1167+ . get( ) ,
1168+ "Frame 4: should be hidden"
1169+ ) ;
1170+ assert ! (
1171+ !app. world( ) . resource:: <ObservedChanged >( ) . 0 ,
1172+ "Frame 4: should not be changed"
1173+ ) ;
1174+ }
1175+ }
10581176}
0 commit comments