Skip to content

Commit f807e2f

Browse files
committed
Add MoveBundle command
1 parent 98938a8 commit f807e2f

File tree

1 file changed

+135
-0
lines changed
  • crates/bevy_ecs/src/system/commands

1 file changed

+135
-0
lines changed

crates/bevy_ecs/src/system/commands/mod.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,95 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
548548
self
549549
}
550550

551+
/// Moves a [`Bundle`] to a target entity.
552+
///
553+
/// # Example
554+
///
555+
/// ```
556+
/// # use bevy_ecs::prelude::*;
557+
/// #
558+
/// # #[derive(Component)]
559+
/// # struct Dummy;
560+
/// #
561+
/// # #[derive(Bundle)]
562+
/// # struct Cargo {
563+
/// # _dummy: Dummy
564+
/// # }
565+
/// #
566+
/// # #[derive(Component)]
567+
/// # struct NextDestination { entity: Entity }
568+
/// #
569+
/// fn transport(mut commands: Commands, query: Query<(Entity, &NextDestination)>) {
570+
/// for (source, NextDestination { entity: target }) in query.iter() {
571+
/// commands.entity(source).move_bundle_to::<Cargo>(*target);
572+
/// }
573+
/// }
574+
/// ```
575+
pub fn move_bundle_to<T: Bundle>(&mut self, target: Entity) -> &mut Self {
576+
assert!(
577+
self.commands.entities.contains(target),
578+
"Attempting to move bundle {:?} from entity {:?} to entity {:?}, which doesn't exist.",
579+
std::any::type_name::<T>(),
580+
self.entity,
581+
target
582+
);
583+
self.commands.add(MoveBundle::<T> {
584+
source: self.entity,
585+
target,
586+
_bundle: PhantomData,
587+
});
588+
self
589+
}
590+
591+
/// Moves a [`Component`] to a target entity.
592+
///
593+
/// # Example
594+
///
595+
/// ```
596+
/// # use bevy_ecs::prelude::*;
597+
/// #
598+
/// # #[derive(Component)]
599+
/// # struct Charge;
600+
/// #
601+
/// # #[derive(Component)]
602+
/// # struct ConnectedTo { entity: Entity }
603+
/// #
604+
/// fn conduction(mut commands: Commands, query: Query<(Entity, &ConnectedTo), With<Charge>>) {
605+
/// for (source, ConnectedTo { entity: target }) in query.iter() {
606+
/// commands.entity(source).move_to::<Charge>(*target);
607+
/// }
608+
/// }
609+
/// ```
610+
pub fn move_to<C: Component>(&mut self, target: Entity) -> &mut Self {
611+
self.move_bundle_to::<(C,)>(target)
612+
}
613+
614+
/// Moves a [`Bundle`] from a source entity.
615+
///
616+
/// See [`move_bundle_to`](EntityCommands::move_bundle_to).
617+
pub fn move_bundle_from<T: Bundle>(&mut self, source: Entity) -> &mut Self {
618+
assert!(
619+
self.commands.entities.contains(self.entity),
620+
"Attempting to move bundle {:?} from entity {:?} to entity {:?}, which doesn't exist.",
621+
std::any::type_name::<T>(),
622+
source,
623+
self.entity
624+
);
625+
self.commands.add(MoveBundle::<T> {
626+
source,
627+
target: self.entity,
628+
_bundle: PhantomData,
629+
});
630+
self
631+
}
632+
633+
/// Moves a [`Component`] from a source entity.
634+
///
635+
/// See [`move_to`](EntityCommands::move_to).
636+
pub fn move_from<C: Component>(&mut self, source: Entity) -> &mut Self {
637+
self.move_bundle_from::<(C,)>(source)
638+
}
639+
551640
/// Despawns the entity.
552641
///
553642
/// See [`World::despawn`] for more details.
@@ -692,6 +781,52 @@ where
692781
}
693782
}
694783

784+
pub struct MoveBundle<T> {
785+
pub source: Entity,
786+
pub target: Entity,
787+
_bundle: PhantomData<T>,
788+
}
789+
790+
impl<T> MoveBundle<T> {
791+
/// Creates a new [`MoveBundle`] with given source and target IDs.
792+
pub fn new(source: Entity, target: Entity) -> Self {
793+
Self {
794+
source,
795+
target,
796+
_bundle: PhantomData,
797+
}
798+
}
799+
}
800+
801+
impl<T> Command for MoveBundle<T>
802+
where
803+
T: Bundle + 'static,
804+
{
805+
fn write(self, world: &mut World) {
806+
let bundle_opt = if let Some(mut source) = world.get_entity_mut(self.source) {
807+
source.remove_bundle::<T>()
808+
} else {
809+
panic!("Could not move a bundle (of type `{}`) from entity {:?} because it doesn't exist in this World.\n\
810+
If this command was added to a newly spawned entity, ensure that you have not despawned that entity within the same stage.\n\
811+
This may have occurred due to system order ambiguity, or if the spawning system has multiple command buffers", std::any::type_name::<T>(), self.source);
812+
};
813+
814+
let bundle = if let Some(some) = bundle_opt {
815+
some
816+
} else {
817+
return;
818+
};
819+
820+
if let Some(mut target) = world.get_entity_mut(self.target) {
821+
target.insert_bundle(bundle);
822+
} else {
823+
panic!("Could not move a bundle (of type `{}`) to entity {:?} because it doesn't exist in this World.\n\
824+
If this command was added to a newly spawned entity, ensure that you have not despawned that entity within the same stage.\n\
825+
This may have occurred due to system order ambiguity, or if the spawning system has multiple command buffers", std::any::type_name::<T>(), self.target);
826+
}
827+
}
828+
}
829+
695830
#[derive(Debug)]
696831
pub struct Insert<T> {
697832
pub entity: Entity,

0 commit comments

Comments
 (0)