use bevy_ecs::{
component::Component,
entity::Entity,
message::MessageWriter,
query::{QueryFilter, With},
system::{Query, SystemState},
world::World,
};
use bevy_ecs::hierarchy::ChildOf;
pub type Left = Entity;
pub type Right = Entity;
pub type SortedEntities = (Left, Right);
fn inner_get_left_right_entities<
LeftSide: QueryFilter + 'static,
RightSide: QueryFilter + 'static,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
let mut state = SystemState::<(Query<(), LeftSide>, Query<(), RightSide>)>::new(world);
let (left_query, right_query) = state.get(world);
if left_query.contains(*first) && right_query.contains(*second) {
Some((*first, *second))
} else if left_query.contains(*second) && right_query.contains(*first) {
Some((*second, *first))
} else {
None
}
}
fn inner_get_left_right_parent_entities<
LeftSide: QueryFilter + 'static,
RightSide: QueryFilter + 'static,
ParentSide: QueryFilter + 'static,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
let mut state = SystemState::<(
Query<(), LeftSide>,
Query<&ChildOf, RightSide>,
Query<(), ParentSide>,
)>::new(world);
let (left_query, right_query, parent_query) = state.get(world);
if left_query.contains(*first) {
if let Ok(related) = right_query.get(*second) {
let parent = related.parent();
if parent_query.contains(parent) {
return Some((*first, parent));
}
}
} else if left_query.contains(*second) {
if let Ok(related) = right_query.get(*first) {
let parent = related.parent();
if parent_query.contains(parent) {
return Some((*second, parent));
}
}
}
None
}
fn inner_get_left_parent_right_parent_entities<
LeftSide: QueryFilter + 'static,
LeftParent: QueryFilter + 'static,
RightSide: QueryFilter + 'static,
RightParent: QueryFilter + 'static,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
let mut state = SystemState::<(
Query<&ChildOf, LeftSide>,
Query<&ChildOf, RightSide>,
Query<(), LeftParent>,
Query<(), RightParent>,
)>::new(world);
let (left_query, right_query, left_parent_query, right_parent_query) = state.get(world);
if let Ok(left_parent) = left_query.get(*first) {
if left_parent_query.contains(left_parent.parent()) {
if let Ok(right_parent) = right_query.get(*second) {
if right_parent_query.contains(right_parent.parent()) {
return Some((left_parent.parent(), right_parent.parent()));
}
}
}
} else if let Ok(left_parent) = left_query.get(*second) {
if left_parent_query.contains(left_parent.parent()) {
if let Ok(right_parent) = right_query.get(*first) {
if right_parent_query.contains(right_parent.parent()) {
return Some((left_parent.parent(), right_parent.parent()));
}
}
}
}
None
}
pub fn get_left_right_entities<LeftSide: Component, RightSide: Component>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
inner_get_left_right_entities::<With<LeftSide>, With<RightSide>>(world, first, second)
}
pub fn get_left_right_parent_entities<
LeftSide: Component,
RightSide: Component,
ParentSide: Component,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
inner_get_left_right_parent_entities::<With<LeftSide>, With<RightSide>, With<ParentSide>>(
world, first, second,
)
}
pub fn get_left_any_right_entities<LeftComponent: Component>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
inner_get_left_right_entities::<With<LeftComponent>, ()>(world, first, second)
}
pub fn get_left_parent_right_parent_entities<
LeftSide: Component,
LeftParent: Component,
RightSide: Component,
RightParent: Component,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
inner_get_left_parent_right_parent_entities::<
With<LeftSide>,
With<LeftParent>,
With<RightSide>,
With<RightParent>,
>(world, first, second)
}
pub fn get_any_left_parent_any_right_parent_entities<
LeftParent: Component,
RightParent: Component,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
inner_get_left_parent_right_parent_entities::<(), With<LeftParent>, (), With<RightParent>>(
world, first, second,
)
}
pub fn send_message<Event: bevy_ecs::message::Message + Sync + Send + 'static>(
world: &mut World,
event: Event,
) {
SystemState::<MessageWriter<Event>>::new(world)
.get_mut(world)
.write(event);
}
#[doc(hidden)]
#[deprecated(note = "Use send_message instead; this function will be removed in a future version")]
pub fn send_event<Event: bevy_ecs::message::Message + Sync + Send + 'static>(
world: &mut World,
event: Event,
) {
send_message(world, event)
}
pub fn clone_entity_component<C: Component + Clone>(
world: &mut World,
entity: &Entity,
) -> Option<C> {
let mut state = SystemState::<Query<&'static C>>::new(world);
let query = state.get(world);
let item = query.get(*entity);
if let Ok(value) = item {
Some(value.clone())
} else {
None
}
}