Skip to content
Snippets Groups Projects
Verified Commit 1a652ae5 authored by Louis's avatar Louis :fire:
Browse files

Import from Cryptikkvania

parent d3671c88
No related branches found
No related tags found
No related merge requests found
/target
/Cargo.lock
[package]
name = "micro_bevy_world_utils"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
/// `micro_bevy_world_utils` packages some common functions used to interrogate the world state from
/// exclusive bevy systems. One frequent use case for these functions is in implementing a monolithic
/// physics collisions processor.
///
/// ## World Interrogation
///
/// ## World Mutation
///
/// - `send_event`: Send an event
///
/// ## Entity Sorting
///
/// There are several functions that take the form "get_{specifier}_{specifier}_entities", such as
/// `get_left_right_entities`. These are used to sort two entities according to which specified
/// components they contain, or to fetch the _parent_ of one or both entities matching the criteria.
///
/// `{specifier}` takes the following form: `[any_](left|right)[[_any]_parent]`
///
/// - `any_` implies that no components need to be matched for that side of the query to be
/// successful. This would be equivalent to supplying `()` to the version without `any_`
/// - `_parent` implies that the returned entity for that side will, if a match is found, be the
/// _parent_ entity of the matching input entity.
///
/// **N.B.** The left component will always be queried first
///
/// ### Examples
///
/// - `get_left_right_entities`: Match entities to the left and right components
/// - `get_left_any_right_parent`: Match against the left component, and match the parent of the second entity against the right component
/// - `get_left_right_any_parent`: Match entities to the left and right components, but return the _parent_ entity of the right entity
///
use bevy_ecs::{
component::Component,
entity::Entity,
event::EventWriter,
query::{With, ReadOnlyWorldQuery},
system::{Query, SystemState},
world::World,
};
use bevy_hierarchy::Parent;
pub type Left = Entity;
pub type Right = Entity;
pub type SortedEntities = (Left, Right);
fn inner_get_left_right_entities<
LeftSide: ReadOnlyWorldQuery + 'static,
RightSide: ReadOnlyWorldQuery + '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: ReadOnlyWorldQuery + 'static,
RightSide: ReadOnlyWorldQuery + 'static,
ParentSide: ReadOnlyWorldQuery + 'static,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
let mut state = SystemState::<(
Query<(), LeftSide>,
Query<&Parent, RightSide>,
Query<(), ParentSide>,
)>::new(world);
let (left_query, right_query, parent_query) = state.get(world);
if left_query.contains(*first) {
if let Ok(parent) = right_query.get(*second) {
let parent = parent.get();
if parent_query.contains(parent) {
return Some((*first, parent));
}
}
} else if left_query.contains(*second) {
if let Ok(parent) = right_query.get(*first) {
let parent = parent.get();
if parent_query.contains(parent) {
return Some((*second, parent));
}
}
}
None
}
fn inner_get_left_parent_right_parent_entities<
LeftSide: ReadOnlyWorldQuery + 'static,
LeftParent: ReadOnlyWorldQuery + 'static,
RightSide: ReadOnlyWorldQuery + 'static,
RightParent: ReadOnlyWorldQuery + 'static,
>(
world: &mut World,
first: &Entity,
second: &Entity,
) -> Option<SortedEntities> {
let mut state = SystemState::<(
Query<&Parent, LeftSide>,
Query<&Parent, 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.get()) {
if let Ok(right_parent) = right_query.get(*second) {
if right_parent_query.contains(right_parent.get()) {
return Some((left_parent.get(), right_parent.get()));
}
}
}
} else if let Ok(left_parent) = left_query.get(*second) {
if left_parent_query.contains(left_parent.get()) {
if let Ok(right_parent) = right_query.get(*first) {
if right_parent_query.contains(right_parent.get()) {
return Some((left_parent.get(), right_parent.get()));
}
}
}
}
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,
)
}
/// Send an event to the appropriate event writer. Writer type is derived from the
/// second parameter passed in, and must be registered with the application before
/// trying to send.
///
/// ## Example
///
/// ```rust
/// # use bevy_ecs::world::World;
///
/// struct MyEventType {
/// message: usize
/// }
///
/// // Do some app setup
///
/// use micro_bevy_world_utils::send_event;
/// pub fn my_world_system(world: &mut World) {
/// // Do some processing here
/// send_event(world, MyEventType { message: 1234 });
/// }
/// ```
pub fn send_event<Event: Sync + Send + 'static>(world: &mut World, event: Event) {
SystemState::<(EventWriter<Event>)>::new(world)
.get_mut(world)
.send(event);
}
/// Clone the data from a specific component of the target entity, as long as that entity
/// has that component and the component itself implements `Clone`
///
/// ## Example
///
/// ```rust
///
/// ```
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
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment