Skip to content

Commit

Permalink
Merge pull request #19 from iiYese/dev
Browse files Browse the repository at this point in the history
0.5
  • Loading branch information
iiYese committed Nov 8, 2023
2 parents 82d79fb + 00de73f commit a088820
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 72 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aery"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
authors = ["iiYese iiyese@outlook.com"]
repository = "https://github.com/iiYese/aery"
Expand All @@ -12,7 +12,7 @@ readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy = "0.11"
bevy = "0.12"
smallvec = "1.11.0"
aery_macros = { path = "macros", version = "0.3.0-dev" }
aquamarine = "0.3.2"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ fn tick_devices(
### Version table
| Bevy version | Aery verison |
|--------------|--------------|
| 0.11 | 0.4 |
| 0.11 | 0.3 |
| 0.12 | 0.5 |
| 0.11 | 0.3 - 0.4 |
| 0.10 | 0.1 - 0.2 |

### Credits
Expand Down
35 changes: 28 additions & 7 deletions src/edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use bevy::{
entity::Entity,
query::{Or, With, Without, WorldQuery},
system::{Command, CommandQueue, Resource},
world::{EntityMut, World},
world::{EntityWorldMut, World},
},
//hierarchy::{Children, Parent},
hierarchy::{Children, Parent},
log::warn,
prelude::{Deref, DerefMut},
};
Expand Down Expand Up @@ -86,6 +86,14 @@ impl<R: Relation> Default for Targets<R> {
#[allow(missing_docs)]
pub type EdgeIter<'a> = std::iter::Copied<std::slice::Iter<'a, Entity>>;

/// Edges world query for hierarchy compatibility
#[derive(WorldQuery)]
pub struct HierarchyEdges {
pub(crate) hosts: Option<&'static Children>,
pub(crate) target: Option<&'static Parent>,
pub(crate) _filter: Or<(With<Children>, With<Parent>)>,
}

/// World query to get the edge info of a Relation.
#[derive(WorldQuery)]
pub struct Edges<R: Relation> {
Expand All @@ -102,6 +110,22 @@ pub trait EdgeInfo {
fn targets(&self) -> &[Entity];
}

impl EdgeInfo for HierarchyEdgesItem<'_> {
fn hosts(&self) -> &[Entity] {
match self.hosts {
Some(hosts) => hosts,
None => &[],
}
}

fn targets(&self) -> &[Entity] {
match self.target {
Some(target) => target.as_slice(),
None => &[],
}
}
}

impl<R: Relation> EdgeInfo for EdgesItem<'_, R> {
fn hosts(&self) -> &[Entity] {
match self.hosts {
Expand Down Expand Up @@ -135,9 +159,6 @@ impl<E: EdgeInfo> EdgeInfo for Option<E> {
}
}

// TODO: bevy 0.12
// impl EdgeInfo for Hierarchy

#[derive(Component, Default, Deref, DerefMut)]
pub(crate) struct OnDelete {
#[deref]
Expand Down Expand Up @@ -646,7 +667,7 @@ impl<R: Relation> Command for Withdraw<R> {
}
}

/// An extension API for [`EntityMut`] to sugar using relation commands.
/// An extension API for [`EntityWorldMut`] to sugar using relation commands.
pub trait RelationCommands {
/// [`Set`] a relationship target.
fn set<R: Relation>(&mut self, target: Entity) -> &mut Self;
Expand All @@ -662,7 +683,7 @@ pub trait RelationCommands {

#[rustfmt::skip]
#[allow(clippy::let_unit_value)]
impl RelationCommands for EntityMut<'_> {
impl RelationCommands for EntityWorldMut<'_> {
fn set<R: Relation>(&mut self, target: Entity) -> &mut Self {
let _ = R::ZST_OR_PANIC;

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ pub mod prelude {
utils::{EdgeSide, Relations, Up},
FoldBreadth, Join, Track, TrackSelf, Traverse,
},
relation::{CleanupPolicy, Relation, ZstOrPanic},
scope::{EntityMutExt, Scope},
relation::{CleanupPolicy, Hierarchy, Relation, ZstOrPanic},
scope::{AeryEntityWorldMutExt, Scope, AeryEntityCommandsExt},
tuple_traits::{Joinable, RelationSet},
};
#[doc(no_inline)]
Expand Down
2 changes: 1 addition & 1 deletion src/operations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl<Control, Edge, Starts> TrackSelf for TraverseAnd<Control, Edge, Starts> {
}
}

/// Track the last seen from a query when traversing an edge. This is useful in scenarios
/// Track the last seen item from a query when traversing an edge. This is useful in scenarios
/// where you mightn't have a component on every entity in a hierarchy. For instance it might not
/// make sense for a component to be on every entity or even an immediate ancestor meaning spam
/// propogation isn't viable. Scroll areas in UI are one example of this.
Expand Down
32 changes: 30 additions & 2 deletions src/operations/utils.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{
edges::EdgeIter,
relation::{Relation, RelationId},
relation::{Hierarchy, Relation, RelationId},
tuple_traits::*,
};

use bevy::ecs::{entity::Entity, query::WorldQuery};

use std::marker::PhantomData;
use std::{any::TypeId, marker::PhantomData};

/// Struct to track metadat for a join operation.
pub struct JoinWith<Relations, JoinEdges, JoinItems> {
Expand Down Expand Up @@ -95,6 +95,34 @@ pub trait EdgeSide {
RelationsItem<'i, RS>: RelationEntries;
}

impl EdgeSide for Hierarchy {
fn entities<'i, 'r, RS>(relations: &'r RelationsItem<'i, RS>) -> EdgeIter<'r>
where
'i: 'r,
RS: RelationSet,
RelationsItem<'i, RS>: RelationEntries,
{
relations
.hosts(RelationId(TypeId::of::<Hierarchy>()))
.iter()
.copied()
}
}

impl EdgeSide for Up<Hierarchy> {
fn entities<'i, 'r, RS>(relations: &'r RelationsItem<'i, RS>) -> EdgeIter<'r>
where
'i: 'r,
RS: RelationSet,
RelationsItem<'i, RS>: RelationEntries,
{
relations
.targets(RelationId(TypeId::of::<Hierarchy>()))
.iter()
.copied()
}
}

impl<R: Relation> EdgeSide for R {
fn entities<'i, 'r, RS>(relations: &'r RelationsItem<'i, RS>) -> EdgeIter<'r>
where
Expand Down
77 changes: 72 additions & 5 deletions src/relation.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::Var;
use core::any::TypeId;

// TODO 0.12 impl for Hierarchy

/// Type ID of a relation.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct RelationId(pub(crate) TypeId);
Expand All @@ -21,6 +19,12 @@ impl<R: Relation> From<R> for Var<RelationId> {
}
}

impl From<Hierarchy> for Var<RelationId> {
fn from(_: Hierarchy) -> Self {
Self::Val(RelationId(TypeId::of::<Hierarchy>()))
}
}

/// Hack to ensure relation types are indeed ZSTs
pub trait ZstOrPanic: Sized {
#[allow(missing_docs)]
Expand Down Expand Up @@ -153,6 +157,37 @@ pub enum CleanupPolicy {
/// for more information. This isn't necessarily good or bad. Archetype fragmentation is a more
/// advanced topic but to keep it short and simple the archetype fragmentation is comparable to
/// `bevy_hierarchy` if it supported multiple hierarchy types.
/// ## Derive examples
/// ```
/// use aery::prelude::*;
///
/// // Simple derive with defaults:
/// // - Orphaning
/// // - Exclusive
/// // - Asymmetric
/// #[derive(Relation)]
/// struct R;
///
/// // Override edge exclusivity
/// #[derive(Relation)]
/// #[aery(Poly)]
/// struct Poly;
///
/// // Override edge symmetry
/// #[derive(Relation)]
/// #[aery(Symmetric)]
/// struct Symmetric;
///
/// // Override cleanup policy
/// #[derive(Relation)]
/// #[aery(Recursive)] // Available: Counted, Recursive, Total
/// struct Recursive;
///
/// // Override multiple properties
/// #[derive(Relation)]
/// #[aery(Poly, Symmetric, Counted)]
/// struct Multi;
/// ```
pub trait Relation: 'static + Sized + Send + Sync {
/// How to clean up entities and relations when an entity with a relation is despawned
/// or when a relation is unset.
Expand All @@ -172,6 +207,38 @@ pub trait Relation: 'static + Sized + Send + Sync {
const SYMMETRIC: bool = false;
}

// TODO: Enable for 0.12
// For hierarchy compatibility
//pub struct Hierarchy;
/// For compatibility with bevy_hierarchy.
/// **WARNING:**
/// - Hierarchy cleanup does not clean aery relations.
/// - Aery cleanup policies do not clean up hierarchy edges.
/// ## Query example
/// ```
/// use bevy::prelude::*;
/// use aery::prelude::*;
///
/// #[derive(Component)]
/// struct A {
/// // ..
/// }
///
/// #[derive(Component)]
/// struct B {
/// // ..
/// }
///
/// #[derive(Relation)]
/// struct R;
///
/// fn sys(
/// a_query: Query<&A>,
/// b_query: Query<(&B, Relations<(Hierarchy, R)>)>, // Can use alone or along side relations
/// roots: Query<Entity, (With<Children>, Without<Parent>)>
/// ) {
/// b_query.traverse::<Hierarchy>(roots.iter()).for_each(|b, edges| {
/// edges.join::<R>(&a_query).for_each(|a| {
/// // ..
/// });
/// })
/// }
/// ```
pub struct Hierarchy;
Loading

0 comments on commit a088820

Please sign in to comment.