1#![allow(clippy::type_complexity)]
2
3extern crate self as oxide_ecs;
4
5pub use oxide_ecs_derive::{Component, Resource, ScheduleLabel};
6
7pub mod component {
8 pub trait Component: 'static {}
9}
10
11pub mod resource {
12 pub trait Resource: 'static {}
13}
14
15pub mod entity {
16 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
17 pub struct Entity {
18 pub(crate) index: u32,
19 pub(crate) generation: u32,
20 }
21
22 impl Entity {
23 pub fn index(self) -> u32 {
24 self.index
25 }
26
27 pub fn generation(self) -> u32 {
28 self.generation
29 }
30 }
31}
32
33pub mod query {
34 use std::marker::PhantomData;
35
36 pub struct With<T>(pub(crate) PhantomData<T>);
37 pub struct Without<T>(pub(crate) PhantomData<T>);
38
39 impl<T> Default for With<T> {
40 fn default() -> Self {
41 Self(PhantomData)
42 }
43 }
44
45 impl<T> Default for Without<T> {
46 fn default() -> Self {
47 Self(PhantomData)
48 }
49 }
50}
51
52pub mod schedule {
53 use super::world::World;
54
55 pub trait ScheduleLabel: 'static {}
56
57 pub type SystemFn = fn(&mut World);
58
59 #[derive(Default)]
60 pub struct Schedule {
61 systems: Vec<SystemFn>,
62 }
63
64 impl Schedule {
65 pub fn new() -> Self {
66 Self::default()
67 }
68
69 pub fn add_system(&mut self, system: SystemFn) {
70 self.systems.push(system);
71 }
72
73 pub fn run(&mut self, world: &mut World) {
74 for system in &self.systems {
75 system(world);
76 }
77 }
78 }
79}
80
81pub mod system {
82 use std::marker::PhantomData;
83 use std::ops::{Deref, DerefMut};
84
85 use crate::component::Component;
86 use crate::entity::Entity;
87 use crate::resource::Resource;
88 use crate::world::{Bundle, World};
89
90 pub trait SystemParam: Sized {
91 unsafe fn fetch(world: *mut World, commands: *mut CommandQueue) -> Self;
97 }
98
99 trait DeferredCommand {
100 fn apply(self: Box<Self>, world: &mut World);
101 }
102
103 impl<F> DeferredCommand for F
104 where
105 F: FnOnce(&mut World) + 'static,
106 {
107 fn apply(self: Box<Self>, world: &mut World) {
108 (*self)(world);
109 }
110 }
111
112 #[derive(Default)]
113 pub struct CommandQueue {
114 commands: Vec<Box<dyn DeferredCommand>>,
115 }
116
117 impl CommandQueue {
118 pub fn new() -> Self {
119 Self::default()
120 }
121
122 pub fn push<F>(&mut self, command: F)
123 where
124 F: FnOnce(&mut World) + 'static,
125 {
126 self.commands.push(Box::new(command));
127 }
128
129 pub fn is_empty(&self) -> bool {
130 self.commands.is_empty()
131 }
132
133 pub fn apply(&mut self, world: &mut World) {
134 let commands = std::mem::take(&mut self.commands);
135 for command in commands {
136 command.apply(world);
137 }
138 }
139 }
140
141 pub struct Commands {
142 queue: *mut CommandQueue,
143 }
144
145 impl Commands {
146 pub fn new(queue: *mut CommandQueue) -> Self {
147 Self { queue }
148 }
149
150 pub fn spawn<B>(&mut self, bundle: B)
151 where
152 B: Bundle + 'static,
153 {
154 unsafe { &mut *self.queue }.push(move |world| {
155 let _ = world.spawn(bundle);
156 });
157 }
158
159 pub fn entity(&mut self, entity: Entity) -> EntityCommands {
160 EntityCommands {
161 entity,
162 queue: self.queue,
163 }
164 }
165
166 pub fn despawn(&mut self, entity: Entity) {
167 unsafe { &mut *self.queue }.push(move |world| {
168 let _ = world.despawn(entity);
169 });
170 }
171 }
172
173 pub struct EntityCommands {
174 entity: Entity,
175 queue: *mut CommandQueue,
176 }
177
178 impl EntityCommands {
179 pub fn insert<B>(&mut self, bundle: B) -> &mut Self
180 where
181 B: Bundle + 'static,
182 {
183 let entity = self.entity;
184 unsafe { &mut *self.queue }.push(move |world| {
185 if world.contains(entity) {
186 world.entity_mut(entity).insert(bundle);
187 }
188 });
189 self
190 }
191
192 pub fn remove<T>(&mut self) -> &mut Self
193 where
194 T: Component,
195 {
196 let entity = self.entity;
197 unsafe { &mut *self.queue }.push(move |world| {
198 if world.contains(entity) {
199 let _ = world.remove::<T>(entity);
200 }
201 });
202 self
203 }
204
205 pub fn despawn(&mut self) -> &mut Self {
206 let entity = self.entity;
207 unsafe { &mut *self.queue }.push(move |world| {
208 let _ = world.despawn(entity);
209 });
210 self
211 }
212 }
213
214 pub struct Res<T>(*const T, PhantomData<T>);
215
216 impl<T> Deref for Res<T> {
217 type Target = T;
218
219 fn deref(&self) -> &Self::Target {
220 unsafe { &*self.0 }
221 }
222 }
223
224 pub struct ResMut<T>(*mut T, PhantomData<T>);
225
226 impl<T> Deref for ResMut<T> {
227 type Target = T;
228
229 fn deref(&self) -> &Self::Target {
230 unsafe { &*self.0 }
231 }
232 }
233
234 impl<T> DerefMut for ResMut<T> {
235 fn deref_mut(&mut self) -> &mut Self::Target {
236 unsafe { &mut *self.0 }
237 }
238 }
239
240 pub struct Query<Q> {
241 world: *mut World,
242 marker: PhantomData<Q>,
243 }
244
245 impl<Q> Query<Q> {
246 fn new(world: *mut World) -> Self {
247 Self {
248 world,
249 marker: PhantomData,
250 }
251 }
252 }
253
254 impl<T: Component> Query<&T> {
255 pub fn iter(&mut self) -> impl Iterator<Item = &T> {
256 let world = unsafe { &mut *self.world };
257 let mut query = world.query::<&T>();
258 query.iter(&*world).collect::<Vec<_>>().into_iter()
259 }
260 }
261
262 impl<T: Component> Query<&mut T> {
263 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
264 let world = unsafe { &mut *self.world };
265 let mut query = world.query::<&mut T>();
266 query.iter_mut(world).collect::<Vec<_>>().into_iter()
267 }
268 }
269
270 impl<A: Component, B: Component> Query<(&A, &B)> {
271 pub fn iter(&mut self) -> impl Iterator<Item = (&A, &B)> {
272 let world = unsafe { &mut *self.world };
273 let mut query = world.query::<(&A, &B)>();
274 query.iter(&*world).collect::<Vec<_>>().into_iter()
275 }
276 }
277
278 impl<A: Component, B: Component> Query<(&mut A, &mut B)> {
279 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&mut A, &mut B)> {
280 let world = unsafe { &mut *self.world };
281 let mut query = world.query::<(&mut A, &mut B)>();
282 query.iter_mut(world).collect::<Vec<_>>().into_iter()
283 }
284 }
285
286 impl<A: Component, B: Component> Query<(&mut A, &B)> {
287 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&mut A, &B)> {
288 let world = unsafe { &mut *self.world };
289 let mut query = world.query::<(&mut A, &B)>();
290 query.iter_mut(world).collect::<Vec<_>>().into_iter()
291 }
292 }
293
294 impl<A: Component, B: Component> Query<(&A, &mut B)> {
295 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&A, &mut B)> {
296 let world = unsafe { &mut *self.world };
297 let mut query = world.query::<(&A, &mut B)>();
298 query.iter_mut(world).collect::<Vec<_>>().into_iter()
299 }
300 }
301
302 impl<T: 'static> SystemParam for Res<T> {
303 unsafe fn fetch(world: *mut World, _commands: *mut CommandQueue) -> Self {
304 let world = unsafe { &mut *world };
305 let value = world.resource::<T>() as *const T;
306 Res(value, PhantomData)
307 }
308 }
309
310 impl<T: 'static> SystemParam for ResMut<T> {
311 unsafe fn fetch(world: *mut World, _commands: *mut CommandQueue) -> Self {
312 let world = unsafe { &mut *world };
313 let value = world.resource_mut::<T>() as *mut T;
314 ResMut(value, PhantomData)
315 }
316 }
317
318 impl<Q: 'static> SystemParam for Query<Q> {
319 unsafe fn fetch(world: *mut World, _commands: *mut CommandQueue) -> Self {
320 Query::new(world)
321 }
322 }
323
324 impl SystemParam for Commands {
325 unsafe fn fetch(_world: *mut World, commands: *mut CommandQueue) -> Self {
326 Commands::new(commands)
327 }
328 }
329
330 #[derive(Clone, Debug)]
331 pub struct State<T> {
332 current: T,
333 next: Option<T>,
334 }
335
336 impl<T> State<T> {
337 pub fn new(initial: T) -> Self {
338 Self {
339 current: initial,
340 next: None,
341 }
342 }
343
344 pub fn current(&self) -> &T {
345 &self.current
346 }
347
348 pub fn next(&self) -> Option<&T> {
349 self.next.as_ref()
350 }
351
352 pub fn set(&mut self, value: T) {
353 self.current = value;
354 self.next = None;
355 }
356
357 pub fn set_next(&mut self, value: T) {
358 self.next = Some(value);
359 }
360
361 pub fn apply_transition(&mut self) -> bool {
362 if let Some(next) = self.next.take() {
363 self.current = next;
364 true
365 } else {
366 false
367 }
368 }
369 }
370
371 impl<T: 'static> Resource for State<T> {}
372
373 pub struct System {
374 run: Box<dyn FnMut(&mut World, &mut CommandQueue)>,
375 run_condition: Option<Box<dyn FnMut(&World) -> bool>>,
376 }
377
378 impl System {
379 pub fn new<F>(run: F) -> Self
380 where
381 F: FnMut(&mut World, &mut CommandQueue) + 'static,
382 {
383 Self {
384 run: Box::new(run),
385 run_condition: None,
386 }
387 }
388
389 pub fn with_condition<F>(mut self, condition: F) -> Self
390 where
391 F: FnMut(&World) -> bool + 'static,
392 {
393 self.run_condition = Some(Box::new(condition));
394 self
395 }
396
397 pub fn run(&mut self, world: &mut World, commands: &mut CommandQueue) {
398 if let Some(condition) = self.run_condition.as_mut() {
399 if !(condition)(&*world) {
400 return;
401 }
402 }
403
404 (self.run)(world, commands);
405 }
406 }
407
408 pub trait IntoSystem<Marker = ()> {
409 fn into_system(self) -> System;
410 }
411
412 impl IntoSystem for System {
413 fn into_system(self) -> System {
414 self
415 }
416 }
417
418 impl<F> IntoSystem<fn(&mut World)> for F
419 where
420 F: FnMut(&mut World) + 'static,
421 {
422 fn into_system(mut self) -> System {
423 System::new(move |world, _commands| self(world))
424 }
425 }
426
427 macro_rules! impl_into_system {
428 ($($param:ident),+) => {
429 impl<Func, $($param),+> IntoSystem<fn($($param),+)> for Func
430 where
431 Func: FnMut($($param),+) + 'static,
432 $($param: SystemParam + 'static),+
433 {
434 #[allow(non_snake_case)]
435 fn into_system(mut self) -> System {
436 System::new(move |world, commands| {
437 let world_ptr = world as *mut World;
438 let commands_ptr = commands as *mut CommandQueue;
439 unsafe {
440 $(let $param = <$param as SystemParam>::fetch(world_ptr, commands_ptr);)+
441 self($($param),+);
442 }
443 })
444 }
445 }
446 };
447 }
448
449 impl_into_system!(A);
450 impl_into_system!(A, B);
451 impl_into_system!(A, B, C);
452 impl_into_system!(A, B, C, D);
453 impl_into_system!(A, B, C, D, E);
454
455 pub trait IntoSystemExt<Marker>: IntoSystem<Marker> + Sized {
456 fn run_if<C>(self, condition: C) -> System
457 where
458 C: FnMut(&World) -> bool + 'static,
459 {
460 self.into_system().with_condition(condition)
461 }
462 }
463
464 impl<T, Marker> IntoSystemExt<Marker> for T where T: IntoSystem<Marker> + Sized {}
465
466 pub fn in_state<T>(target: T) -> impl FnMut(&World) -> bool
467 where
468 T: Clone + PartialEq + 'static,
469 {
470 move |world: &World| world.resource::<State<T>>().current().eq(&target)
471 }
472}
473
474pub mod world {
475 use super::component::Component;
476 use super::entity::Entity;
477 use super::query::{With, Without};
478 use std::any::{Any, TypeId};
479 use std::collections::HashMap;
480 use std::marker::PhantomData;
481
482 trait StorageDyn: Any {
483 fn remove_entity(&mut self, entity: Entity);
484 fn as_any(&self) -> &dyn Any;
485 fn as_any_mut(&mut self) -> &mut dyn Any;
486 }
487
488 struct Storage<T: Component> {
489 sparse: Vec<Option<usize>>,
490 dense_entities: Vec<Entity>,
491 dense_data: Vec<T>,
492 }
493
494 impl<T: Component> Default for Storage<T> {
495 fn default() -> Self {
496 Self {
497 sparse: Vec::new(),
498 dense_entities: Vec::new(),
499 dense_data: Vec::new(),
500 }
501 }
502 }
503
504 impl<T: Component> Storage<T> {
505 fn ensure_sparse_capacity(&mut self, entity: Entity) {
506 let index = entity.index as usize;
507 if self.sparse.len() <= index {
508 self.sparse.resize(index + 1, None);
509 }
510 }
511
512 fn insert(&mut self, entity: Entity, component: T) {
513 self.ensure_sparse_capacity(entity);
514 let index = entity.index as usize;
515
516 if let Some(dense_index) = self.sparse[index] {
517 if self.dense_entities.get(dense_index).copied() == Some(entity) {
518 self.dense_data[dense_index] = component;
519 return;
520 }
521 }
522
523 let dense_index = self.dense_data.len();
524 self.dense_entities.push(entity);
525 self.dense_data.push(component);
526 self.sparse[index] = Some(dense_index);
527 }
528
529 fn get(&self, entity: Entity) -> Option<&T> {
530 let dense_index = self.sparse.get(entity.index as usize).copied().flatten()?;
531 if self.dense_entities.get(dense_index).copied() == Some(entity) {
532 self.dense_data.get(dense_index)
533 } else {
534 None
535 }
536 }
537
538 fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
539 let dense_index = self.sparse.get(entity.index as usize).copied().flatten()?;
540 if self.dense_entities.get(dense_index).copied() == Some(entity) {
541 self.dense_data.get_mut(dense_index)
542 } else {
543 None
544 }
545 }
546
547 fn get_mut_ptr(&mut self, entity: Entity) -> Option<*mut T> {
548 self.get_mut(entity).map(|value| value as *mut T)
549 }
550
551 fn remove(&mut self, entity: Entity) -> Option<T> {
552 let index = entity.index as usize;
553 let dense_index = self.sparse.get(index).copied().flatten()?;
554
555 if self.dense_entities.get(dense_index).copied() != Some(entity) {
556 return None;
557 }
558
559 self.sparse[index] = None;
560
561 let removed_entity = self.dense_entities.swap_remove(dense_index);
562 let removed_component = self.dense_data.swap_remove(dense_index);
563
564 debug_assert_eq!(removed_entity, entity);
565
566 if dense_index < self.dense_entities.len() {
567 let moved_entity = self.dense_entities[dense_index];
568 self.sparse[moved_entity.index as usize] = Some(dense_index);
569 }
570
571 Some(removed_component)
572 }
573
574 fn entities(&self) -> &[Entity] {
575 &self.dense_entities
576 }
577
578 fn values(&self) -> impl Iterator<Item = &T> {
579 self.dense_data.iter()
580 }
581
582 fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
583 self.dense_data.iter_mut()
584 }
585
586 fn contains_entity(&self, entity: Entity) -> bool {
587 self.get(entity).is_some()
588 }
589 }
590
591 impl<T: Component> StorageDyn for Storage<T> {
592 fn remove_entity(&mut self, entity: Entity) {
593 self.remove(entity);
594 }
595
596 fn as_any(&self) -> &dyn Any {
597 self
598 }
599
600 fn as_any_mut(&mut self) -> &mut dyn Any {
601 self
602 }
603 }
604
605 pub trait Bundle {
606 fn insert_into(self, world: &mut World, entity: Entity);
607 }
608
609 impl<C: Component> Bundle for C {
610 fn insert_into(self, world: &mut World, entity: Entity) {
611 world.insert_component(entity, self);
612 }
613 }
614
615 macro_rules! impl_bundle_tuple {
616 ($($name:ident),+) => {
617 impl<$($name: Component),+> Bundle for ($($name,)+) {
618 #[allow(non_snake_case)]
619 fn insert_into(self, world: &mut World, entity: Entity) {
620 let ($($name,)+) = self;
621 $(world.insert_component(entity, $name);)+
622 }
623 }
624 };
625 }
626
627 impl_bundle_tuple!(A, B);
628 impl_bundle_tuple!(A, B, C);
629 impl_bundle_tuple!(A, B, C, D);
630 impl_bundle_tuple!(A, B, C, D, E);
631
632 pub struct World {
633 next_index: u32,
634 generations: Vec<u32>,
635 free_indices: Vec<u32>,
636 storages: HashMap<TypeId, Box<dyn StorageDyn>>,
637 resources: HashMap<TypeId, Box<dyn Any>>,
638 non_send_resources: HashMap<TypeId, Box<dyn Any>>,
639 }
640
641 impl Default for World {
642 fn default() -> Self {
643 Self::new()
644 }
645 }
646
647 impl World {
648 pub fn new() -> Self {
649 Self {
650 next_index: 0,
651 generations: Vec::new(),
652 free_indices: Vec::new(),
653 storages: HashMap::new(),
654 resources: HashMap::new(),
655 non_send_resources: HashMap::new(),
656 }
657 }
658
659 pub fn spawn<B: Bundle>(&mut self, bundle: B) -> EntityMut<'_> {
660 let entity = self.alloc_entity();
661 bundle.insert_into(self, entity);
662 EntityMut {
663 world: self,
664 entity,
665 }
666 }
667
668 pub fn entity_mut(&mut self, entity: Entity) -> EntityMut<'_> {
669 assert!(self.contains(entity), "entity {:?} is not alive", entity);
670 EntityMut {
671 world: self,
672 entity,
673 }
674 }
675
676 pub fn contains(&self, entity: Entity) -> bool {
677 self.generations
678 .get(entity.index as usize)
679 .map(|g| *g == entity.generation)
680 .unwrap_or(false)
681 }
682
683 pub fn despawn(&mut self, entity: Entity) -> bool {
684 if !self.contains(entity) {
685 return false;
686 }
687 for storage in self.storages.values_mut() {
688 storage.remove_entity(entity);
689 }
690 if let Some(generation) = self.generations.get_mut(entity.index as usize) {
691 *generation = generation.saturating_add(1);
692 }
693 self.free_indices.push(entity.index);
694 true
695 }
696
697 pub fn get<T: Component>(&self, entity: Entity) -> Option<&T> {
698 if !self.contains(entity) {
699 return None;
700 }
701 self.storage::<T>()?.get(entity)
702 }
703
704 pub fn get_mut<T: Component>(&mut self, entity: Entity) -> Option<&mut T> {
705 if !self.contains(entity) {
706 return None;
707 }
708 self.storage_mut::<T>()?.get_mut(entity)
709 }
710
711 pub fn remove<T: Component>(&mut self, entity: Entity) -> Option<T> {
712 if !self.contains(entity) {
713 return None;
714 }
715 self.storage_mut::<T>()?.remove(entity)
716 }
717
718 pub fn insert_resource<T: 'static>(&mut self, value: T) {
719 self.resources.insert(TypeId::of::<T>(), Box::new(value));
720 }
721
722 pub fn resource<T: 'static>(&self) -> &T {
723 self.resources
724 .get(&TypeId::of::<T>())
725 .and_then(|boxed| boxed.downcast_ref::<T>())
726 .expect("resource not found")
727 }
728
729 pub fn resource_mut<T: 'static>(&mut self) -> &mut T {
730 self.resources
731 .get_mut(&TypeId::of::<T>())
732 .and_then(|boxed| boxed.downcast_mut::<T>())
733 .expect("resource not found")
734 }
735
736 pub fn init_resource<T: Default + 'static>(&mut self) {
737 if !self.resources.contains_key(&TypeId::of::<T>()) {
738 self.insert_resource(T::default());
739 }
740 }
741
742 pub fn contains_resource<T: 'static>(&self) -> bool {
743 self.resources.contains_key(&TypeId::of::<T>())
744 }
745
746 pub fn insert_non_send_resource<T: 'static>(&mut self, value: T) {
747 self.non_send_resources
748 .insert(TypeId::of::<T>(), Box::new(value));
749 }
750
751 pub fn get_non_send_resource<T: 'static>(&self) -> Option<&T> {
752 self.non_send_resources
753 .get(&TypeId::of::<T>())
754 .and_then(|boxed| boxed.downcast_ref::<T>())
755 }
756
757 pub fn get_non_send_resource_mut<T: 'static>(&mut self) -> Option<&mut T> {
758 self.non_send_resources
759 .get_mut(&TypeId::of::<T>())
760 .and_then(|boxed| boxed.downcast_mut::<T>())
761 }
762
763 pub fn query<Q>(&mut self) -> QueryState<Q> {
764 QueryState {
765 marker: PhantomData,
766 }
767 }
768
769 pub fn query_filtered<Q, F>(&mut self) -> FilteredQueryState<Q, F> {
770 FilteredQueryState {
771 marker: PhantomData,
772 }
773 }
774
775 fn alloc_entity(&mut self) -> Entity {
776 if let Some(index) = self.free_indices.pop() {
777 let generation = self.generations[index as usize];
778 return Entity { index, generation };
779 }
780
781 let index = self.next_index;
782 self.next_index += 1;
783 self.generations.push(0);
784 Entity {
785 index,
786 generation: 0,
787 }
788 }
789
790 fn insert_component<T: Component>(&mut self, entity: Entity, component: T) {
791 assert!(self.contains(entity), "entity {:?} is not alive", entity);
792 self.ensure_storage::<T>().insert(entity, component);
793 }
794
795 fn ensure_storage<T: Component>(&mut self) -> &mut Storage<T> {
796 let type_id = TypeId::of::<T>();
797 self.storages
798 .entry(type_id)
799 .or_insert_with(|| Box::new(Storage::<T>::default()));
800 self.storage_mut::<T>().expect("storage created")
801 }
802
803 fn storage<T: Component>(&self) -> Option<&Storage<T>> {
804 self.storages
805 .get(&TypeId::of::<T>())
806 .and_then(|storage| storage.as_any().downcast_ref::<Storage<T>>())
807 }
808
809 fn storage_mut<T: Component>(&mut self) -> Option<&mut Storage<T>> {
810 self.storages
811 .get_mut(&TypeId::of::<T>())
812 .and_then(|storage| storage.as_any_mut().downcast_mut::<Storage<T>>())
813 }
814 }
815
816 pub struct EntityMut<'w> {
817 world: &'w mut World,
818 entity: Entity,
819 }
820
821 impl<'w> EntityMut<'w> {
822 pub fn id(&self) -> Entity {
823 self.entity
824 }
825
826 pub fn insert<B: Bundle>(&mut self, bundle: B) -> &mut Self {
827 bundle.insert_into(self.world, self.entity);
828 self
829 }
830
831 pub fn get<T: Component>(&self) -> Option<&T> {
832 self.world.get::<T>(self.entity)
833 }
834
835 pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
836 self.world.get_mut::<T>(self.entity)
837 }
838
839 pub fn remove<T: Component>(&mut self) -> Option<T> {
840 self.world.remove::<T>(self.entity)
841 }
842 }
843
844 pub struct QueryState<Q> {
845 marker: PhantomData<Q>,
846 }
847
848 impl<T: Component> QueryState<&T> {
849 pub fn iter<'w>(&mut self, world: &'w World) -> impl Iterator<Item = &'w T> {
850 world
851 .storage::<T>()
852 .map(|storage| storage.values())
853 .into_iter()
854 .flatten()
855 }
856 }
857
858 impl<T: Component> QueryState<&mut T> {
859 pub fn iter_mut<'w>(&mut self, world: &'w mut World) -> impl Iterator<Item = &'w mut T> {
860 world
861 .storage_mut::<T>()
862 .map(|storage| storage.values_mut())
863 .into_iter()
864 .flatten()
865 }
866 }
867
868 pub struct TupleIter2<'w, A: Component, B: Component> {
869 entities: Vec<Entity>,
870 index: usize,
871 a: Option<&'w Storage<A>>,
872 b: Option<&'w Storage<B>>,
873 }
874
875 impl<'w, A: Component, B: Component> Iterator for TupleIter2<'w, A, B> {
876 type Item = (&'w A, &'w B);
877
878 fn next(&mut self) -> Option<Self::Item> {
879 let (Some(a_storage), Some(b_storage)) = (self.a, self.b) else {
880 return None;
881 };
882
883 while self.index < self.entities.len() {
884 let entity = self.entities[self.index];
885 self.index += 1;
886 if let (Some(a), Some(b)) = (a_storage.get(entity), b_storage.get(entity)) {
887 return Some((a, b));
888 }
889 }
890 None
891 }
892 }
893
894 pub struct TupleIterMut2<'w, A: Component, B: Component> {
895 entities: Vec<Entity>,
896 index: usize,
897 a: *mut Storage<A>,
898 b: *mut Storage<B>,
899 marker: PhantomData<&'w mut (A, B)>,
900 }
901
902 impl<'w, A: Component, B: Component> Iterator for TupleIterMut2<'w, A, B> {
903 type Item = (&'w mut A, &'w mut B);
904
905 fn next(&mut self) -> Option<Self::Item> {
906 if self.a.is_null() || self.b.is_null() {
907 return None;
908 }
909
910 while self.index < self.entities.len() {
911 let entity = self.entities[self.index];
912 self.index += 1;
913 unsafe {
914 let a_storage = &mut *self.a;
915 let b_storage = &mut *self.b;
916 let a_ptr = match a_storage.get_mut_ptr(entity) {
917 Some(value) => value,
918 None => continue,
919 };
920 let b_ptr = match b_storage.get_mut_ptr(entity) {
921 Some(value) => value,
922 None => continue,
923 };
924 return Some((&mut *a_ptr, &mut *b_ptr));
925 }
926 }
927 None
928 }
929 }
930
931 impl<A: Component, B: Component> QueryState<(&A, &B)> {
932 pub fn iter<'w>(&mut self, world: &'w World) -> TupleIter2<'w, A, B> {
933 let a_storage = world.storage::<A>();
934 let b_storage = world.storage::<B>();
935
936 let entities = a_storage
937 .map(|storage| storage.entities().to_vec())
938 .unwrap_or_default();
939
940 TupleIter2 {
941 entities,
942 index: 0,
943 a: a_storage,
944 b: b_storage,
945 }
946 }
947 }
948
949 impl<A: Component, B: Component> QueryState<(&mut A, &mut B)> {
950 pub fn iter_mut<'w>(&mut self, world: &'w mut World) -> TupleIterMut2<'w, A, B> {
951 assert_ne!(
952 TypeId::of::<A>(),
953 TypeId::of::<B>(),
954 "duplicate mutable query type"
955 );
956
957 let a_type = TypeId::of::<A>();
958 let b_type = TypeId::of::<B>();
959
960 let a_storage = {
961 let Some(a_dyn) = world.storages.get_mut(&a_type) else {
962 return TupleIterMut2 {
963 entities: Vec::new(),
964 index: 0,
965 a: std::ptr::null_mut(),
966 b: std::ptr::null_mut(),
967 marker: PhantomData,
968 };
969 };
970
971 a_dyn
972 .as_any_mut()
973 .downcast_mut::<Storage<A>>()
974 .expect("storage type mismatch") as *mut Storage<A>
975 };
976
977 let b_storage = {
978 let Some(b_dyn) = world.storages.get_mut(&b_type) else {
979 return TupleIterMut2 {
980 entities: Vec::new(),
981 index: 0,
982 a: std::ptr::null_mut(),
983 b: std::ptr::null_mut(),
984 marker: PhantomData,
985 };
986 };
987
988 b_dyn
989 .as_any_mut()
990 .downcast_mut::<Storage<B>>()
991 .expect("storage type mismatch") as *mut Storage<B>
992 };
993
994 if a_storage.is_null() || b_storage.is_null() {
995 return TupleIterMut2 {
996 entities: Vec::new(),
997 index: 0,
998 a: std::ptr::null_mut(),
999 b: std::ptr::null_mut(),
1000 marker: PhantomData,
1001 };
1002 }
1003
1004 let entities = unsafe { (&*a_storage).entities().to_vec() };
1005
1006 TupleIterMut2 {
1007 entities,
1008 index: 0,
1009 a: a_storage,
1010 b: b_storage,
1011 marker: PhantomData,
1012 }
1013 }
1014 }
1015
1016 pub struct TupleIterMutRef2<'w, A: Component, B: Component> {
1017 entities: Vec<Entity>,
1018 index: usize,
1019 a: *mut Storage<A>,
1020 b: *const Storage<B>,
1021 marker: PhantomData<(&'w mut A, &'w B)>,
1022 }
1023
1024 impl<'w, A: Component, B: Component> Iterator for TupleIterMutRef2<'w, A, B> {
1025 type Item = (&'w mut A, &'w B);
1026
1027 fn next(&mut self) -> Option<Self::Item> {
1028 if self.a.is_null() || self.b.is_null() {
1029 return None;
1030 }
1031
1032 while self.index < self.entities.len() {
1033 let entity = self.entities[self.index];
1034 self.index += 1;
1035 unsafe {
1036 let a_storage = &mut *self.a;
1037 let b_storage = &*self.b;
1038 let a_ptr = match a_storage.get_mut_ptr(entity) {
1039 Some(value) => value,
1040 None => continue,
1041 };
1042 let b_ref = match b_storage.get(entity) {
1043 Some(value) => value,
1044 None => continue,
1045 };
1046 return Some((&mut *a_ptr, b_ref));
1047 }
1048 }
1049 None
1050 }
1051 }
1052
1053 impl<A: Component, B: Component> QueryState<(&mut A, &B)> {
1054 pub fn iter_mut<'w>(&mut self, world: &'w mut World) -> TupleIterMutRef2<'w, A, B> {
1055 assert_ne!(
1056 TypeId::of::<A>(),
1057 TypeId::of::<B>(),
1058 "mixed mutable/immutable query cannot use the same component type"
1059 );
1060
1061 let a_type = TypeId::of::<A>();
1062 let b_type = TypeId::of::<B>();
1063
1064 let a_storage = {
1065 let Some(a_dyn) = world.storages.get_mut(&a_type) else {
1066 return TupleIterMutRef2 {
1067 entities: Vec::new(),
1068 index: 0,
1069 a: std::ptr::null_mut(),
1070 b: std::ptr::null(),
1071 marker: PhantomData,
1072 };
1073 };
1074
1075 a_dyn
1076 .as_any_mut()
1077 .downcast_mut::<Storage<A>>()
1078 .expect("storage type mismatch") as *mut Storage<A>
1079 };
1080
1081 let b_storage = {
1082 let Some(b_dyn) = world.storages.get(&b_type) else {
1083 return TupleIterMutRef2 {
1084 entities: Vec::new(),
1085 index: 0,
1086 a: std::ptr::null_mut(),
1087 b: std::ptr::null(),
1088 marker: PhantomData,
1089 };
1090 };
1091
1092 b_dyn
1093 .as_any()
1094 .downcast_ref::<Storage<B>>()
1095 .expect("storage type mismatch") as *const Storage<B>
1096 };
1097
1098 let entities = unsafe { (&*a_storage).entities().to_vec() };
1099
1100 TupleIterMutRef2 {
1101 entities,
1102 index: 0,
1103 a: a_storage,
1104 b: b_storage,
1105 marker: PhantomData,
1106 }
1107 }
1108 }
1109
1110 pub struct TupleIterRefMut2<'w, A: Component, B: Component> {
1111 entities: Vec<Entity>,
1112 index: usize,
1113 a: *const Storage<A>,
1114 b: *mut Storage<B>,
1115 marker: PhantomData<(&'w A, &'w mut B)>,
1116 }
1117
1118 impl<'w, A: Component, B: Component> Iterator for TupleIterRefMut2<'w, A, B> {
1119 type Item = (&'w A, &'w mut B);
1120
1121 fn next(&mut self) -> Option<Self::Item> {
1122 if self.a.is_null() || self.b.is_null() {
1123 return None;
1124 }
1125
1126 while self.index < self.entities.len() {
1127 let entity = self.entities[self.index];
1128 self.index += 1;
1129 unsafe {
1130 let a_storage = &*self.a;
1131 let b_storage = &mut *self.b;
1132 let a_ref = match a_storage.get(entity) {
1133 Some(value) => value,
1134 None => continue,
1135 };
1136 let b_ptr = match b_storage.get_mut_ptr(entity) {
1137 Some(value) => value,
1138 None => continue,
1139 };
1140 return Some((a_ref, &mut *b_ptr));
1141 }
1142 }
1143 None
1144 }
1145 }
1146
1147 impl<A: Component, B: Component> QueryState<(&A, &mut B)> {
1148 pub fn iter_mut<'w>(&mut self, world: &'w mut World) -> TupleIterRefMut2<'w, A, B> {
1149 assert_ne!(
1150 TypeId::of::<A>(),
1151 TypeId::of::<B>(),
1152 "mixed immutable/mutable query cannot use the same component type"
1153 );
1154
1155 let a_type = TypeId::of::<A>();
1156 let b_type = TypeId::of::<B>();
1157
1158 let a_storage = {
1159 let Some(a_dyn) = world.storages.get(&a_type) else {
1160 return TupleIterRefMut2 {
1161 entities: Vec::new(),
1162 index: 0,
1163 a: std::ptr::null(),
1164 b: std::ptr::null_mut(),
1165 marker: PhantomData,
1166 };
1167 };
1168
1169 a_dyn
1170 .as_any()
1171 .downcast_ref::<Storage<A>>()
1172 .expect("storage type mismatch") as *const Storage<A>
1173 };
1174
1175 let b_storage = {
1176 let Some(b_dyn) = world.storages.get_mut(&b_type) else {
1177 return TupleIterRefMut2 {
1178 entities: Vec::new(),
1179 index: 0,
1180 a: std::ptr::null(),
1181 b: std::ptr::null_mut(),
1182 marker: PhantomData,
1183 };
1184 };
1185
1186 b_dyn
1187 .as_any_mut()
1188 .downcast_mut::<Storage<B>>()
1189 .expect("storage type mismatch") as *mut Storage<B>
1190 };
1191
1192 let entities = unsafe { (&*a_storage).entities().to_vec() };
1193
1194 TupleIterRefMut2 {
1195 entities,
1196 index: 0,
1197 a: a_storage,
1198 b: b_storage,
1199 marker: PhantomData,
1200 }
1201 }
1202 }
1203
1204 pub struct FilteredQueryState<Q, F> {
1205 marker: PhantomData<(Q, F)>,
1206 }
1207
1208 pub struct EntityWithWithoutIter {
1209 entities: Vec<Entity>,
1210 index: usize,
1211 }
1212
1213 impl Iterator for EntityWithWithoutIter {
1214 type Item = Entity;
1215
1216 fn next(&mut self) -> Option<Self::Item> {
1217 if self.index >= self.entities.len() {
1218 return None;
1219 }
1220 let item = self.entities[self.index];
1221 self.index += 1;
1222 Some(item)
1223 }
1224 }
1225
1226 impl<T: Component, U: Component> FilteredQueryState<Entity, (With<T>, Without<U>)> {
1227 pub fn iter(&mut self, world: &World) -> EntityWithWithoutIter {
1228 let mut entities = Vec::new();
1229 if let Some(with_storage) = world.storage::<T>() {
1230 for entity in with_storage.entities().iter().copied() {
1231 let has_without = world
1232 .storage::<U>()
1233 .map(|storage| storage.contains_entity(entity))
1234 .unwrap_or(false);
1235 if !has_without {
1236 entities.push(entity);
1237 }
1238 }
1239 }
1240 EntityWithWithoutIter { entities, index: 0 }
1241 }
1242 }
1243}
1244
1245pub mod prelude {
1246 pub use crate::component::Component;
1247 pub use crate::entity::Entity;
1248 pub use crate::query::{With, Without};
1249 pub use crate::resource::Resource;
1250 pub use crate::schedule::ScheduleLabel;
1251 pub use crate::system::{
1252 in_state, CommandQueue, Commands, IntoSystem, IntoSystemExt, Query, Res, ResMut, State,
1253 System, SystemParam,
1254 };
1255 pub use crate::world::World;
1256}
1257
1258#[cfg(test)]
1259mod tests {
1260 use crate::query::{With, Without};
1261 use crate::system::{
1262 in_state, CommandQueue, Commands, IntoSystem, IntoSystemExt, Query, ResMut, State,
1263 };
1264 use crate::world::World;
1265 use crate::{Component, Resource};
1266
1267 #[derive(Component, Debug, PartialEq)]
1268 struct Position(i32);
1269
1270 #[derive(Component, Debug, PartialEq)]
1271 struct Velocity(i32);
1272
1273 #[derive(Resource, Default)]
1274 struct Tick(u64);
1275
1276 #[test]
1277 fn spawn_insert_remove_and_despawn_work() {
1278 let mut world = World::new();
1279 let entity = world.spawn((Position(1), Velocity(2))).id();
1280
1281 assert_eq!(world.get::<Position>(entity).map(|v| v.0), Some(1));
1282 assert_eq!(world.get::<Velocity>(entity).map(|v| v.0), Some(2));
1283
1284 let removed = world.remove::<Velocity>(entity);
1285 assert_eq!(removed.map(|v| v.0), Some(2));
1286 assert!(world.get::<Velocity>(entity).is_none());
1287
1288 assert!(world.despawn(entity));
1289 assert!(!world.contains(entity));
1290 assert!(world.get::<Position>(entity).is_none());
1291 }
1292
1293 #[test]
1294 fn resources_and_non_send_resources_work() {
1295 let mut world = World::new();
1296 world.init_resource::<Tick>();
1297 world.resource_mut::<Tick>().0 = 7;
1298 assert_eq!(world.resource::<Tick>().0, 7);
1299
1300 world.insert_non_send_resource(String::from("watcher"));
1301 assert_eq!(
1302 world.get_non_send_resource::<String>().map(String::as_str),
1303 Some("watcher")
1304 );
1305 }
1306
1307 #[test]
1308 fn query_and_filtered_query_work() {
1309 let mut world = World::new();
1310 let a = world.spawn((Position(1), Velocity(10))).id();
1311 let b = world.spawn(Position(2)).id();
1312
1313 {
1314 let mut query = world.query::<(&mut Position, &mut Velocity)>();
1315 for (position, velocity) in query.iter_mut(&mut world) {
1316 position.0 += velocity.0;
1317 }
1318 }
1319
1320 assert_eq!(world.get::<Position>(a).map(|v| v.0), Some(11));
1321 assert_eq!(world.get::<Position>(b).map(|v| v.0), Some(2));
1322
1323 let mut filtered =
1324 world.query_filtered::<crate::entity::Entity, (With<Position>, Without<Velocity>)>();
1325 let entities: Vec<_> = filtered.iter(&world).collect();
1326 assert_eq!(entities, vec![b]);
1327 }
1328
1329 fn movement_system(mut tick: ResMut<Tick>, mut query: Query<(&mut Position, &Velocity)>) {
1330 tick.0 += 1;
1331 for (position, velocity) in query.iter_mut() {
1332 position.0 += velocity.0;
1333 }
1334 }
1335
1336 #[test]
1337 fn into_system_extracts_params_from_signature() {
1338 let mut world = World::new();
1339 world.insert_resource(Tick::default());
1340 let entity = world.spawn((Position(1), Velocity(2))).id();
1341
1342 let mut system = movement_system.into_system();
1343 let mut commands = CommandQueue::new();
1344 system.run(&mut world, &mut commands);
1345 commands.apply(&mut world);
1346
1347 assert_eq!(world.resource::<Tick>().0, 1);
1348 assert_eq!(world.get::<Position>(entity).map(|p| p.0), Some(3));
1349 }
1350
1351 fn spawn_with_commands(mut commands: Commands) {
1352 commands.spawn(Position(42));
1353 }
1354
1355 #[test]
1356 fn commands_are_deferred_until_applied() {
1357 let mut world = World::new();
1358
1359 let mut system = spawn_with_commands.into_system();
1360 let mut queue = CommandQueue::new();
1361 system.run(&mut world, &mut queue);
1362
1363 {
1364 let mut query = world.query::<&Position>();
1365 assert!(query.iter(&world).next().is_none());
1366 }
1367
1368 queue.apply(&mut world);
1369
1370 let mut query = world.query::<&Position>();
1371 assert_eq!(query.iter(&world).count(), 1);
1372 }
1373
1374 #[derive(Clone, Debug, PartialEq, Eq)]
1375 enum AppState {
1376 Menu,
1377 Playing,
1378 }
1379
1380 fn gated_tick(mut tick: ResMut<Tick>) {
1381 tick.0 += 1;
1382 }
1383
1384 #[test]
1385 fn run_if_in_state_gates_system_execution() {
1386 let mut world = World::new();
1387 world.insert_resource(Tick::default());
1388 world.insert_resource(State::new(AppState::Menu));
1389
1390 let mut system = gated_tick.run_if(in_state(AppState::Playing));
1391 let mut queue = CommandQueue::new();
1392
1393 system.run(&mut world, &mut queue);
1394 assert_eq!(world.resource::<Tick>().0, 0);
1395
1396 world
1397 .resource_mut::<State<AppState>>()
1398 .set(AppState::Playing);
1399 system.run(&mut world, &mut queue);
1400 assert_eq!(world.resource::<Tick>().0, 1);
1401 }
1402}