use flax::{filter::Or, *}; use itertools::Itertools; use std::sync::Arc; component! { a: f32, b: String, c: Arc, d: &'static str, } #[test] fn filters() { let mut world = World::new(); let id1 = EntityBuilder::new() .set(a(), 0.4) .set(b(), "Hello, World!".to_string()) .spawn(&mut world); let shared = Arc::new(829); let id2 = EntityBuilder::new() .set(b(), "Foo".to_string()) .set(c(), shared) .spawn(&mut world); let mut builder = EntityBuilder::new(); let others = (0..10) .map(|i| builder.set(a(), i as f32).spawn(&mut world)) .collect_vec(); let mut query = Query::new(a().cloned()).filter(a().modified()); let items = query.borrow(&world).iter().collect_vec(); // All changed entities assert_eq!(items.len(), 11); eprintln!("Current change: {}", world.change_tick()); world.set(id1, a(), 34.0).unwrap(); eprintln!("Current change: {}", world.change_tick()); let items = query.borrow(&world).iter().collect_vec(); assert_eq!(items, &[34.0]); others[3..7].iter().for_each(|id| { let mut a = world.get_mut(*id, a()).unwrap(); *a = -*a; }); let items = query.borrow(&world).iter().collect_vec(); eprintln!("Items: {items:?}"); assert_eq!(items, &[-3.0, -4.0, -5.0, -6.0]); others[3..5].iter().for_each(|id| { let mut a = world.get_mut(*id, a()).unwrap(); *a *= 10.0; }); let items = query.borrow(&world).iter().collect_vec(); assert_eq!(items, &[-30.0, -40.0]); // Construct a new interted query let mut query = Query::new(a().cloned().added()); let items = query .borrow(&world) .iter() .sorted_by_key(|v| (v * 256.0) as i64) .collect_vec(); assert_eq!( items, &[-40.0, -30.0, -6.0, -5.0, 0.0, 1.0, 2.0, 7.0, 8.0, 9.0, 34.0] ); world.set(id2, a(), 29.5).unwrap(); assert_eq!(query.collect_vec(&world), &[29.5]); world.set(id2, a(), 29.5).unwrap(); assert_eq!(query.collect_vec(&world), &[]); } #[test] fn combinations() { let mut world = World::new(); component! { a: i32, } let mut builder = EntityBuilder::new(); let ids = (0..100) .map(|i| { builder.set(a(), i as _); builder.set_default(b()); if i % 3 == 0 { builder.get_mut(b()).unwrap().push_str("Fizz"); } if i % 5 == 0 { builder.get_mut(b()).unwrap().push_str("Buzz"); } if i % 2 == 0 { builder.set(d(), "Foo"); } builder.spawn(&mut world) }) .collect_vec(); let mut query = Query::new(entity_ids()).filter(a().modified() | b().modified()); // eprintln!("Items: {:?}", query.iter(&world).sorted().collect_vec()); assert_eq!(query.borrow(&world).iter().sorted().collect_vec(), ids); for &id in &ids[50..67] { *world.get_mut(id, a()).unwrap() *= -2; } let items = query.borrow(&world).iter().sorted().collect_vec(); eprintln!("Items: {items:?}"); assert_eq!(items, ids[50..67]); let items = query.borrow(&world).iter().sorted().collect_vec(); assert_eq!(items, []); for &id in &ids[20..43] { *world.get_mut(id, a()).unwrap() *= -2; } for &id in &ids[40..89] { world.get_mut(id, b()).unwrap().push_str("..."); } let items = query.borrow(&world).iter().sorted().collect_vec(); assert_eq!(items, ids[20..89]); } #[test] fn bitops() { let mut world = World::new(); let id1 = Entity::builder() .set(a(), 4.5) .set(b(), "foo".into()) .spawn(&mut world); let id2 = Entity::builder() .set(a(), 8.1) .set(d(), "bar") .spawn(&mut world); let id3 = Entity::builder() .set(a(), -5.1) .set(c(), Arc::new(5)) .spawn(&mut world); assert_eq!( Query::new(entity_ids()) .filter(a().gt(1.1) & a().lt(5.0)) .borrow(&world) .iter() .sorted() .collect_vec(), vec![id1] ); assert_eq!( Query::new(entity_ids()) .filter((a().gt(1.1) & a().lt(5.0)) | (d().without() & b().without())) .borrow(&world) .iter() .sorted() .collect_vec(), vec![id1, id3] ); assert_eq!( Query::new(entity_ids()) .filter((a().cmp(|&v: &f32| v > 5.1 && v < 9.0)) | (d().without() & b().without())) .borrow(&world) .iter() .sorted() .collect_vec(), vec![id2, id3] ); } #[test] fn sparse_or() { let mut world = World::new(); let ids = (0..10) .map(|_| { Entity::builder() .set(a(), 5.4) .set(b(), "Foo".into()) .spawn(&mut world) }) .collect_vec(); let mut query = Query::new(entity_ids()).filter(a().modified() | b().modified()); assert_eq!(query.borrow(&world).iter().collect_vec(), ids); // ###-------- // --###---## world.set(ids[0], a(), 7.1).unwrap(); world.set(ids[1], a(), 7.1).unwrap(); world.set(ids[2], a(), 7.1).unwrap(); world.set(ids[2], b(), "Bar".into()).unwrap(); world.set(ids[3], b(), "Bar".into()).unwrap(); world.set(ids[4], b(), "Bar".into()).unwrap(); world.set(ids[8], b(), "Bar".into()).unwrap(); world.set(ids[9], b(), "Bar".into()).unwrap(); { let mut batches = query.borrow(&world); let batches = batches.iter_batched(); let slots = batches.map(|v| v.collect_vec()).collect_vec(); assert_eq!(slots, &[&ids[0..=2], &ids[3..=4], &ids[8..=9]]); } // Check access compatability let system_a = System::builder() .with_query(query) .build(|_query: QueryBorrow| {}) .boxed(); let system_b = System::builder() .with_query(Query::new(a().as_mut())) .build(|_query: QueryBorrow<_, _>| {}) .boxed(); let mut schedule = Schedule::from([system_a, system_b]); let batches = schedule.batch_info(&world); assert_eq!(batches.len(), 2); } #[test] fn sparse_and() { let mut world = World::new(); let ids = (0..10) .map(|_| { Entity::builder() .set(a(), 5.4) .set(b(), "Foo".into()) .spawn(&mut world) }) .collect_vec(); let _ = (0..10) .map(|_| { Entity::builder() .set(a(), 5.4) .set(c(), Arc::new(5)) .spawn(&mut world) }) .collect_vec(); let mut query = Query::new(entity_ids()).filter(a().modified() & b().modified()); assert_eq!(query.borrow(&world).iter().collect_vec(), ids); // ###-------- // --###---## world.set(ids[0], a(), 7.1).unwrap(); world.set(ids[1], a(), 7.1).unwrap(); world.set(ids[2], a(), 7.1).unwrap(); world.set(ids[2], b(), "Bar".into()).unwrap(); world.set(ids[3], b(), "Bar".into()).unwrap(); world.set(ids[4], b(), "Bar".into()).unwrap(); world.set(ids[8], b(), "Bar".into()).unwrap(); world.set(ids[9], b(), "Bar".into()).unwrap(); { let mut batches = query.borrow(&world); let mut batches = batches.iter_batched(); assert_eq!(batches.next().unwrap().collect_vec(), ids[2..=2]); assert!(batches.next().is_none()); } // Check access compatability let system_a = System::builder() .with_query(query) .build(|_query: QueryBorrow| {}) .boxed(); let system_b = System::builder() .with_query(Query::new(a().as_mut()).with(c())) .build(|_query: QueryBorrow<_, _>| {}) .boxed(); let mut schedule = Schedule::from([system_a, system_b]); let batches = schedule.batch_info(&world); assert_eq!(batches.len(), 1); } #[test] fn entity_filter() { component! { index: usize, } let mut world = World::new(); let ids = (0..10) .map(|i| { Entity::builder() .set(a(), 5.4) .set(index(), i) .set(b(), "Foo".into()) .spawn(&mut world) }) .collect_vec(); let ids2 = (10..20) .map(|i| { Entity::builder() .set(a(), 5.4) .set(index(), i) .spawn(&mut world) }) .collect_vec(); let ids3 = (20..40) .map(|i| Entity::builder().set(index(), i).spawn(&mut world)) .collect_vec(); let mut query = Query::new(index().copied()).filter(Or((ids[5], ids2[7]))); assert_eq!(query.borrow(&world).iter().sorted().collect_vec(), &[5, 17]); let mut query = Query::new((entity_ids(), Or((ids[5], ids2[7])).satisfied())); let all_ids = ids.iter().chain(ids2.iter()).chain(ids3.iter()); let expected = all_ids .map(|&id| (id, id == ids[5] || id == ids2[7])) .collect_vec(); assert_eq!(query.borrow(&world).iter().sorted().collect_vec(), expected); }