use std::borrow::Borrow;
use std::{
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
ops::{Deref, DerefMut},
};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::change_detection::MaybeLocation;
use bevy_ecs::component::Mutable;
use bevy_ecs::query::EcsAccessType;
use bevy_ecs::relationship::RelationshipSourceCollection;
use bevy_ecs::{
archetype::Archetype,
change_detection::Tick,
component::{ComponentId, Components},
entity::{EntityMapper, MapEntities},
prelude::*,
query::{FilteredAccess, IterQueryData, QueryData, ReadOnlyQueryData, WorldQuery},
storage::{Table, TableRow},
system::EntityCommands,
world::unsafe_world_cell::UnsafeWorldCell,
};
use bevy_reflect::Reflect;
use crate::{Any, CastInto, Kind};
#[derive(Reflect)]
pub struct Instance<T: Kind>(Entity, #[reflect(ignore)] PhantomData<T>);
impl<T: Kind> Instance<T> {
pub const PLACEHOLDER: Self = Self(Entity::PLACEHOLDER, PhantomData);
pub unsafe fn from_entity_unchecked(entity: Entity) -> Self {
Self(entity, PhantomData)
}
pub fn entity(&self) -> Entity {
self.0
}
pub fn cast_into<U: Kind>(self) -> Instance<U>
where
T: CastInto<U>,
{
unsafe { T::cast(self) }
}
pub fn cast_into_any(self) -> Instance<Any> {
unsafe { self.cast_into_unchecked() }
}
pub unsafe fn cast_into_unchecked<U: Kind>(self) -> Instance<U> {
Instance::from_entity_unchecked(self.entity())
}
#[deprecated(note = "use `Instance::<T>::from_entity_unchecked` instead")]
pub unsafe fn as_entity_mut(&mut self) -> &mut Entity {
&mut self.0
}
}
impl<T: Component> Instance<T> {
pub fn from_entity(entity: EntityRef) -> Option<Self> {
if entity.contains::<T>() {
Some(unsafe { Self::from_entity_unchecked(entity.id()) })
} else {
None
}
}
}
impl<T: Kind> Clone for Instance<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Kind> Copy for Instance<T> {}
impl<T: Kind> fmt::Debug for Instance<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}({:?})", T::debug_name(), self.0)
}
}
impl<T: Kind> fmt::Display for Instance<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}({}v{})",
T::debug_name(),
self.0.index(),
self.0.generation()
)
}
}
impl<T: Kind> Hash for Instance<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T: Kind, U: Kind> PartialEq<Instance<U>> for Instance<T> {
fn eq(&self, other: &Instance<U>) -> bool {
self.0 == other.0
}
}
impl<T: Kind> PartialEq<Entity> for Instance<T> {
fn eq(&self, other: &Entity) -> bool {
self.0 == *other
}
}
impl<T: Kind> PartialEq<Instance<T>> for Entity {
fn eq(&self, other: &Instance<T>) -> bool {
other == self
}
}
impl<T: Kind> Eq for Instance<T> {}
impl<T: Kind> PartialOrd for Instance<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: Kind> Ord for Instance<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<T: Kind> Deref for Instance<T> {
type Target = Entity;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Kind> Borrow<Entity> for Instance<T> {
fn borrow(&self) -> &Entity {
&self.0
}
}
unsafe impl<T: Kind> WorldQuery for Instance<T> {
type Fetch<'a> = <T::Filter as WorldQuery>::Fetch<'a>;
type State = <T::Filter as WorldQuery>::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
<T::Filter as WorldQuery>::shrink_fetch(fetch)
}
unsafe fn init_fetch<'w>(
world: UnsafeWorldCell<'w>,
state: &Self::State,
last_change_tick: Tick,
change_tick: Tick,
) -> Self::Fetch<'w> {
<T::Filter as WorldQuery>::init_fetch(world, state, last_change_tick, change_tick)
}
const IS_DENSE: bool = <T::Filter as WorldQuery>::IS_DENSE;
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
archetype: &'w Archetype,
table: &'w Table,
) {
<T::Filter as WorldQuery>::set_archetype(fetch, state, archetype, table)
}
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
<T::Filter as WorldQuery>::set_table(fetch, state, table)
}
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
<T::Filter as WorldQuery>::update_component_access(state, access)
}
fn get_state(components: &Components) -> Option<Self::State> {
<T::Filter as WorldQuery>::get_state(components)
}
fn init_state(world: &mut World) -> Self::State {
<T::Filter as WorldQuery>::init_state(world)
}
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
<T::Filter as WorldQuery>::matches_component_set(state, set_contains_id)
}
}
unsafe impl<T: Kind> IterQueryData for Instance<T> {}
unsafe impl<T: Kind> ReadOnlyQueryData for Instance<T> {}
unsafe impl<T: Kind> QueryData for Instance<T> {
type ReadOnly = Self;
const IS_READ_ONLY: bool = <Entity as QueryData>::IS_READ_ONLY;
const IS_ARCHETYPAL: bool = <Entity as QueryData>::IS_ARCHETYPAL;
type Item<'w, 's> = Self;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(Instance::from_entity_unchecked(entity))
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
std::iter::empty()
}
}
impl<T: Kind> MapEntities for Instance<T> {
fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
self.0 = entity_mapper.get_mapped(self.0);
}
}
impl<T: Kind> From<Instance<T>> for Entity {
fn from(instance: Instance<T>) -> Self {
instance.entity()
}
}
impl<T: Kind> RelationshipSourceCollection for Instance<T> {
type SourceIter<'a> = <Entity as RelationshipSourceCollection>::SourceIter<'a>;
fn new() -> Self {
Self::PLACEHOLDER
}
fn with_capacity(_capacity: usize) -> Self {
Self::new()
}
fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
fn add(&mut self, entity: Entity) -> bool {
self.0.add(entity)
}
fn remove(&mut self, entity: Entity) -> bool {
self.0.remove(entity)
}
fn iter(&self) -> Self::SourceIter<'_> {
self.0.iter()
}
fn len(&self) -> usize {
self.0.len()
}
fn clear(&mut self) {
self.0.clear();
}
fn shrink_to_fit(&mut self) {
self.0.shrink_to_fit();
}
fn extend_from_iter(&mut self, entities: impl IntoIterator<Item = Entity>) {
self.0.extend_from_iter(entities)
}
}
impl From<Entity> for Instance<Any> {
fn from(entity: Entity) -> Self {
Self(entity, PhantomData)
}
}
impl<T: Kind> ContainsEntity for Instance<T> {
fn entity(&self) -> Entity {
self.entity()
}
}
pub trait ContainsInstance<T: Kind> {
fn instance(&self) -> Instance<T>;
fn entity(&self) -> Entity {
self.instance().entity()
}
}
pub struct InstanceRef<'a, T: Component>(Instance<T>, &'a T);
unsafe impl<T: Component> WorldQuery for InstanceRef<'_, T> {
type Fetch<'w> = <(Instance<T>, &'static T) as WorldQuery>::Fetch<'w>;
type State = <(Instance<T>, &'static T) as WorldQuery>::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
<(Instance<T>, &T) as WorldQuery>::shrink_fetch(fetch)
}
unsafe fn init_fetch<'w>(
world: UnsafeWorldCell<'w>,
state: &Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
<(Instance<T>, &T) as WorldQuery>::init_fetch(world, state, last_run, this_run)
}
const IS_DENSE: bool = <(Instance<T>, &T) as WorldQuery>::IS_DENSE;
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
archetype: &'w Archetype,
table: &'w Table,
) {
<(Instance<T>, &T) as WorldQuery>::set_archetype(fetch, state, archetype, table)
}
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
<(Instance<T>, &T) as WorldQuery>::set_table(fetch, state, table)
}
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
<(Instance<T>, &T) as WorldQuery>::update_component_access(state, access)
}
fn init_state(world: &mut World) -> Self::State {
<(Instance<T>, &T) as WorldQuery>::init_state(world)
}
fn get_state(components: &Components) -> Option<Self::State> {
<(Instance<T>, &T) as WorldQuery>::get_state(components)
}
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
<(Instance<T>, &T) as WorldQuery>::matches_component_set(state, set_contains_id)
}
}
unsafe impl<T: Component> QueryData for InstanceRef<'_, T> {
type ReadOnly = Self;
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = <&'static T as QueryData>::IS_ARCHETYPAL;
type Item<'w, 's> = InstanceRef<'w, T>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
InstanceRef(item.0, item.1)
}
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
<(Instance<T>, &T) as QueryData>::fetch(state, fetch, entity, table_row)
.map(|(instance, data)| InstanceRef(instance, data))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
<(Instance<T>, &T) as QueryData>::iter_access(state)
}
}
unsafe impl<T: Component> IterQueryData for InstanceRef<'_, T> {}
unsafe impl<T: Component> ReadOnlyQueryData for InstanceRef<'_, T> {}
impl<'a, T: Component> InstanceRef<'a, T> {
pub fn from_entity(entity: EntityRef<'a>) -> Option<Self> {
Some(Self(
unsafe { Instance::from_entity_unchecked(entity.id()) },
entity.get()?,
))
}
pub unsafe fn from_entity_unchecked(entity: EntityRef<'a>) -> Self {
Self(
Instance::from_entity_unchecked(entity.id()),
entity.get().unwrap(),
)
}
}
impl<T: Component> Clone for InstanceRef<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Component> Copy for InstanceRef<'_, T> {}
impl<T: Component> From<InstanceRef<'_, T>> for Instance<T> {
fn from(item: InstanceRef<T>) -> Self {
item.instance()
}
}
impl<T: Component> From<&InstanceRef<'_, T>> for Instance<T> {
fn from(item: &InstanceRef<T>) -> Self {
item.instance()
}
}
impl<T: Component> PartialEq for InstanceRef<'_, T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T: Component> PartialEq<Entity> for InstanceRef<'_, T> {
fn eq(&self, other: &Entity) -> bool {
self.0 == *other
}
}
impl<T: Component> PartialEq<InstanceRef<'_, T>> for Entity {
fn eq(&self, other: &InstanceRef<'_, T>) -> bool {
other == self
}
}
impl<T: Component, U: Component> PartialEq<Instance<U>> for InstanceRef<'_, T>
where
U: CastInto<T>,
{
fn eq(&self, other: &Instance<U>) -> bool {
*self.0 == *other
}
}
impl<T: Component, U: Component> PartialEq<InstanceRef<'_, U>> for Instance<T>
where
U: CastInto<T>,
{
fn eq(&self, other: &InstanceRef<'_, U>) -> bool {
*self == other.instance()
}
}
impl<T: Component> Eq for InstanceRef<'_, T> {}
impl<T: Component> Deref for InstanceRef<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.1
}
}
impl<T: Component> AsRef<Instance<T>> for InstanceRef<'_, T> {
fn as_ref(&self) -> &Instance<T> {
&self.0
}
}
impl<T: Component> AsRef<T> for InstanceRef<'_, T> {
fn as_ref(&self) -> &T {
self.1
}
}
impl<T: Component> ContainsInstance<T> for InstanceRef<'_, T> {
fn instance(&self) -> Instance<T> {
self.0
}
}
pub struct InstanceMut<'a, T: Component>(Instance<T>, Mut<'a, T>);
unsafe impl<T: Component> WorldQuery for InstanceMut<'_, T> {
type Fetch<'w> = <(Instance<T>, &'static mut T) as WorldQuery>::Fetch<'w>;
type State = <(Instance<T>, &'static mut T) as WorldQuery>::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
<(Instance<T>, &mut T) as WorldQuery>::shrink_fetch(fetch)
}
unsafe fn init_fetch<'w>(
world: UnsafeWorldCell<'w>,
state: &Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
<(Instance<T>, &mut T) as WorldQuery>::init_fetch(world, state, last_run, this_run)
}
const IS_DENSE: bool = <(Instance<T>, &T) as WorldQuery>::IS_DENSE;
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
archetype: &'w Archetype,
table: &'w Table,
) {
<(Instance<T>, &mut T) as WorldQuery>::set_archetype(fetch, state, archetype, table)
}
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
<(Instance<T>, &mut T) as WorldQuery>::set_table(fetch, state, table)
}
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
<(Instance<T>, &T) as WorldQuery>::update_component_access(state, access)
}
fn init_state(world: &mut World) -> Self::State {
<(Instance<T>, &T) as WorldQuery>::init_state(world)
}
fn get_state(components: &Components) -> Option<Self::State> {
<(Instance<T>, &T) as WorldQuery>::get_state(components)
}
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
<(Instance<T>, &T) as WorldQuery>::matches_component_set(state, set_contains_id)
}
}
unsafe impl<'b, T: Component<Mutability = Mutable>> QueryData for InstanceMut<'b, T> {
type ReadOnly = InstanceRef<'b, T>;
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = <&'static mut T as QueryData>::IS_ARCHETYPAL;
type Item<'w, 's> = InstanceMut<'w, T>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
InstanceMut(item.0, item.1)
}
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
<(Instance<T>, &mut T) as QueryData>::fetch(state, fetch, entity, table_row)
.map(|(instance, data)| InstanceMut(instance, data))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
<(Instance<T>, &mut T) as QueryData>::iter_access(state)
}
}
impl<'a, T: Component<Mutability = Mutable>> InstanceMut<'a, T> {
pub fn from_entity(entity: EntityMut<'a>) -> Option<Self> {
let id = entity.id();
let data = entity.into_mut()?;
Some(Self(
unsafe { Instance::from_entity_unchecked(id) },
data,
))
}
pub unsafe fn from_entity_unchecked(entity: EntityMut<'a>) -> Self {
let id = entity.id();
let data = entity.into_mut().unwrap();
Self(Instance::from_entity_unchecked(id), data)
}
}
impl<T: Component> From<InstanceMut<'_, T>> for Instance<T> {
fn from(item: InstanceMut<T>) -> Self {
item.instance()
}
}
impl<T: Component> From<&InstanceMut<'_, T>> for Instance<T> {
fn from(item: &InstanceMut<T>) -> Self {
item.instance()
}
}
impl<T: Component> PartialEq for InstanceMut<'_, T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T: Component> PartialEq<Entity> for InstanceMut<'_, T> {
fn eq(&self, other: &Entity) -> bool {
self.0 == *other
}
}
impl<T: Component> PartialEq<InstanceMut<'_, T>> for Entity {
fn eq(&self, other: &InstanceMut<'_, T>) -> bool {
other == self
}
}
impl<T: Component, U: Component> PartialEq<Instance<U>> for InstanceMut<'_, T>
where
U: CastInto<T>,
{
fn eq(&self, other: &Instance<U>) -> bool {
*self.0 == *other
}
}
impl<T: Component, U: Component> PartialEq<InstanceMut<'_, U>> for Instance<T>
where
U: CastInto<T>,
{
fn eq(&self, other: &InstanceMut<'_, U>) -> bool {
*self == other.instance()
}
}
impl<T: Component> Eq for InstanceMut<'_, T> {}
impl<T: Component> Deref for InstanceMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.1.as_ref()
}
}
impl<T: Component> DerefMut for InstanceMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.1.as_mut()
}
}
impl<T: Component> AsRef<Instance<T>> for InstanceMut<'_, T> {
fn as_ref(&self) -> &Instance<T> {
&self.0
}
}
impl<T: Component> AsRef<T> for InstanceMut<'_, T> {
fn as_ref(&self) -> &T {
self.1.as_ref()
}
}
impl<T: Component> AsMut<T> for InstanceMut<'_, T> {
fn as_mut(&mut self) -> &mut T {
self.1.as_mut()
}
}
impl<T: Component> DetectChanges for InstanceMut<'_, T> {
fn is_added(&self) -> bool {
self.1.is_added()
}
fn is_changed(&self) -> bool {
self.1.is_changed()
}
fn last_changed(&self) -> Tick {
self.1.last_changed()
}
fn added(&self) -> Tick {
self.1.added()
}
fn changed_by(&self) -> MaybeLocation {
self.1.changed_by()
}
fn is_added_after(&self, other: Tick) -> bool {
self.1.is_added_after(other)
}
fn is_changed_after(&self, other: Tick) -> bool {
self.1.is_changed_after(other)
}
}
impl<T: Component> DetectChangesMut for InstanceMut<'_, T> {
type Inner = T;
fn set_changed(&mut self) {
self.1.set_changed();
}
fn set_last_changed(&mut self, last_changed: Tick) {
self.1.set_last_changed(last_changed);
}
fn bypass_change_detection(&mut self) -> &mut Self::Inner {
self.1.bypass_change_detection()
}
fn set_added(&mut self) {
self.1.set_added();
}
fn set_last_added(&mut self, last_added: Tick) {
self.1.set_last_added(last_added);
}
}
impl<T: Component> ContainsInstance<T> for InstanceMut<'_, T> {
fn instance(&self) -> Instance<T> {
self.0
}
}
pub trait GetInstanceCommands<T: Kind> {
fn instance(&mut self, instance: Instance<T>) -> InstanceCommands<'_, T>;
}
impl<T: Kind> GetInstanceCommands<T> for Commands<'_, '_> {
fn instance(&mut self, instance: Instance<T>) -> InstanceCommands<'_, T> {
InstanceCommands(self.entity(instance.entity()), PhantomData)
}
}
pub struct InstanceCommands<'a, T: Kind>(EntityCommands<'a>, PhantomData<T>);
impl<'a, T: Kind> InstanceCommands<'a, T> {
pub unsafe fn from_entity_unchecked(entity: EntityCommands<'a>) -> Self {
Self(entity, PhantomData)
}
pub fn from_entity(entity: EntityRef, commands: &'a mut Commands) -> Option<Self>
where
T: Component,
{
if entity.contains::<T>() {
Some(Self(commands.entity(entity.id()), PhantomData))
} else {
None
}
}
pub fn instance(&self) -> Instance<T> {
unsafe { Instance::from_entity_unchecked(self.id()) }
}
pub fn as_entity(&mut self) -> &mut EntityCommands<'a> {
&mut self.0
}
pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
self.0.insert(bundle);
self
}
pub fn remove<U: Component>(&mut self) -> &mut Self {
self.0.remove::<U>();
self
}
pub fn try_remove<U: Component>(&mut self) -> &mut Self {
self.0.try_remove::<U>();
self
}
pub fn reborrow(&mut self) -> InstanceCommands<'_, T> {
InstanceCommands(self.0.reborrow(), PhantomData)
}
pub fn cast_into<U: Kind>(self) -> InstanceCommands<'a, U>
where
T: CastInto<U>,
{
unsafe { InstanceCommands::from_entity_unchecked(self.0) }
}
}
impl<'a, T: Kind> From<InstanceCommands<'a, T>> for Instance<T> {
fn from(commands: InstanceCommands<'a, T>) -> Self {
commands.instance()
}
}
impl<'a, T: Kind> From<&InstanceCommands<'a, T>> for Instance<T> {
fn from(commands: &InstanceCommands<'a, T>) -> Self {
commands.instance()
}
}
impl<'a, T: Kind> Deref for InstanceCommands<'a, T> {
type Target = EntityCommands<'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Kind> DerefMut for InstanceCommands<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: Kind> ContainsInstance<T> for InstanceCommands<'_, T> {
fn instance(&self) -> Instance<T> {
self.instance()
}
}
#[macro_export]
macro_rules! impl_entity_event_from_instance {
($name:ident < $($gen:tt),+ $(,)? > $(where $($where:tt)+)? ) => {
$crate::impl_entity_event_from_instance!($name<$($gen),+> { .instance, .. } $(where $($where)+)?);
};
($name:ident < $($gen:tt),+ $(,)? > { .$field:ident, .. } $(where $($where:tt)+)? ) => {
impl<$($gen),+> EntityEvent for $name<$($gen),+>
$(where $($where)+)? {
fn event_target(&self) -> Entity {
self.$field.entity()
}
}
};
($name:ident) => {
$crate::impl_entity_event_from_instance!($name { .instance, .. });
};
($name:ident { .$field:ident, .. }) => {
impl EntityEvent for $name {
fn event_target(&self) -> Entity {
self.$field.entity()
}
}
}
}
#[test]
fn test_impl_entity_event_from_instance() {
#![allow(unused)]
#[derive(Event)]
struct Foo {
instance: Instance<Any>,
}
#[derive(Event)]
struct Bar {
inst: Instance<Any>,
}
#[derive(Event)]
struct Baz<T: Kind> {
instance: Instance<T>,
}
#[derive(Event)]
struct Bat<T: Kind> {
inst: Instance<T>,
}
impl_entity_event_from_instance!(Foo);
impl_entity_event_from_instance!(Bar { .inst, .. });
impl_entity_event_from_instance!(Baz<T> where T: Kind);
impl_entity_event_from_instance!(Bat<T> { .inst, .. } where T: Kind);
}
#[doc(hidden)]
#[derive(Deref, DerefMut, Reflect)]
pub struct InstanceVec<T: Kind>(Vec<Instance<T>>);
impl<T: Kind> Default for InstanceVec<T> {
fn default() -> Self {
Self(Vec::new())
}
}
impl<T: Kind> InstanceVec<T> {
#[doc(hidden)]
pub fn with_capacity(capacity: usize) -> Self {
Self(Vec::with_capacity(capacity))
}
}
impl<T: Kind> MapEntities for InstanceVec<T> {
fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
let olds: Vec<_> = self.0.drain(..).collect();
for old in olds {
let new_entity = entity_mapper.get_mapped(old.entity());
let new = unsafe { Instance::from_entity_unchecked(new_entity) };
self.0.push(new);
}
}
}
impl<T: Kind> RelationshipSourceCollection for InstanceVec<T> {
type SourceIter<'a>
= std::iter::Map<std::slice::Iter<'a, Instance<T>>, fn(&Instance<T>) -> Entity>
where
Self: 'a;
fn new() -> Self {
Self::default()
}
fn with_capacity(capacity: usize) -> Self {
Self::with_capacity(capacity)
}
fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
fn add(&mut self, entity: Entity) -> bool {
self.0
.push(unsafe { Instance::from_entity_unchecked(entity) });
true
}
fn remove(&mut self, entity: Entity) -> bool {
let Some(index) = self.0.iter().position(|i| *i == entity) else {
return false;
};
self.0.swap_remove(index);
true
}
fn iter(&self) -> Self::SourceIter<'_> {
self.0.iter().map(|i| i.entity())
}
fn len(&self) -> usize {
self.0.len()
}
fn clear(&mut self) {
self.0.clear()
}
fn shrink_to_fit(&mut self) {
self.0.shrink_to_fit()
}
fn extend_from_iter(&mut self, entities: impl IntoIterator<Item = Entity>) {
self.0.extend(
entities
.into_iter()
.map(|entity| unsafe { Instance::from_entity_unchecked(entity) }),
)
}
}
#[cfg(test)]
mod test_instance_vec {
use super::*;
use bevy::prelude::*;
use moonshine_util::expect::Expect;
use crate::prelude::*;
#[derive(Component)]
struct Person;
#[derive(Component)]
struct Potato;
#[derive(Component, Deref)]
#[require(Expect<Person>)] #[relationship_target(relationship = FriendOf)]
struct Friends(
InstanceVec<Person>,
);
#[derive(Component)]
#[require(Expect<Person>)] #[relationship(relationship_target = Friends)]
struct FriendOf(
pub Entity,
);
#[test]
fn test_instance_vec_relationship() {
let mut app = App::new();
app.add_plugins(MinimalPlugins);
let w = app.world_mut();
let p0 = w.spawn_instance(Person).instance();
let p1 = w.spawn_instance(Person).instance();
w.entity_mut(*p1).insert(FriendOf(*p0));
let fs = w.get::<Friends>(*p0).expect("Person 0 must have Friends");
let f: Instance<Person> = *fs.first().expect("Person 0 must have at least 1 friend");
assert_eq!(f, p1, "Person 1 must be a friend of Person 0");
}
#[test]
#[should_panic]
fn test_instance_vec_relationship_panic_1() {
let mut app = App::new();
app.add_plugins(MinimalPlugins);
let w = app.world_mut();
let potato = w.spawn_instance(Potato).instance();
let person = w.spawn_instance(Person).instance();
w.entity_mut(*person).insert(FriendOf(*potato));
}
#[test]
#[should_panic]
fn test_instance_vec_relationship_panic_2() {
let mut app = App::new();
app.add_plugins(MinimalPlugins);
let w = app.world_mut();
let potato = w.spawn_instance(Potato).instance();
let person = w.spawn_instance(Person).instance();
w.entity_mut(*potato).insert(FriendOf(*person));
}
}