Skip to content

Commit

Permalink
fix!: clear up naming with relation target
Browse files Browse the repository at this point in the history
The use of object is overly generic and is easily confused with its
other meaning. Target is a more natural alternative
  • Loading branch information
ten3roberts committed Oct 18, 2023
1 parent 47534e2 commit c594663
Show file tree
Hide file tree
Showing 17 changed files with 81 additions and 84 deletions.
2 changes: 1 addition & 1 deletion guide/src/diving_deeper/dynamic_components.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ entity as the generation is not needed.
{{ #include ../../../examples/guide/dynamic_components.rs:relation }}
```

When despawning either the relation component or object entity, the "parent",
When despawning either the relation component or target entity, the "parent",
the component is removed from all entities.
6 changes: 3 additions & 3 deletions guide/src/fundamentals/relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A relation is a component which *links* to another `Entity`, similar to a foreig

The links between entities are managed by the ECS itself and will always be valid, see [Lifetime](#lifetime)

The linked entity is referred to as the `object` of a relation, while the entity the component is attached to is called the `subject`.
The linked entity is referred to as the `target` of a relation, while the entity the component is attached to is called the `subject`.

This allows forming hierarchies such as *parent-child* relations for transforms and UI, as well as arbitrary graphs.

Expand All @@ -17,11 +17,11 @@ For example, declaring a child relationship that connects to a parent can be don
{{ #include ../../../examples/guide/relations.rs:relation_basic }}
```

The parameter to the component function determines the object entity or target of the relation.
The parameter to the component function determines the target entity of the relation.

Since the value of the relation in this case is `()`, `set_default` can be used as a shorthand over `set`

Two relations of the same type but with different *objects* behave like two separate components and will not interfere. This allows having many-to-many relationships between entities, if so desired.
Two relations of the same type but with different *targets* behave like two separate components and will not interfere. This allows having many-to-many relationships between entities, if so desired.

This allows constructing many different kinds of graphs inside the ECS.

Expand Down
2 changes: 1 addition & 1 deletion guide/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ and new functionality can be added to existing entities and components.

In Flax, there are 3 fundamental building blocks.

[Entity](https://docs.rs/flax/latest/flax/struct.Entity.html). A unique identifier for the objects of the program. Has a managed lifecycle.
[Entity](https://docs.rs/flax/latest/flax/struct.Entity.html). A unique identifier for the entities of the program. Has a managed lifecycle.

[Component](https://docs.rs/flax/latest/flax/struct.Component.html), data which
can be added to an Entity. Has a unique Id, which works as the key for storing
Expand Down
6 changes: 3 additions & 3 deletions src/cascade/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ fn get_ordered_archetypes(
},
}

// Find relations to other objects, and visit them as well
// Find relations to other targets, and visit them as well
let relations = arch.relations_like(relation);
let mut is_reachable = false;
let mut is_root = true;
for (key, _) in relations {
is_root = false;
let parent = key.object.unwrap();
let target = key.target.unwrap();

let loc = world.location(parent).unwrap();
let loc = world.location(target).unwrap();
// Part of the visited set
if let Some(arch) = archetypes.get(&loc.arch_id) {
if get_ordered_archetypes(world, archetypes, arch_id, arch, relation, visited, ordered)
Expand Down
51 changes: 25 additions & 26 deletions src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ impl<T> ComponentValue for T where T: Send + Sync + 'static {}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ComponentKey {
pub(crate) id: Entity,
/// The object entity if the component is a relation
pub(crate) object: Option<Entity>,
/// The target entity if the component is a relation
pub(crate) target: Option<Entity>,
}

#[cfg(feature = "serde")]
Expand All @@ -49,7 +49,7 @@ impl Serialize for ComponentKey {
{
let mut seq = serializer.serialize_tuple_struct("ComponentId", 2)?;
seq.serialize_field(&self.id)?;
seq.serialize_field(&self.object)?;
seq.serialize_field(&self.target)?;

seq.end()
}
Expand All @@ -71,7 +71,7 @@ impl<'de> Deserialize<'de> for ComponentKey {
) -> smallvec::alloc::fmt::Result {
write!(
formatter,
"A tuple of a component id and optional relation object"
"A tuple of a component id and optional relation target"
)
}

Expand All @@ -82,11 +82,11 @@ impl<'de> Deserialize<'de> for ComponentKey {
let id = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?;
let object = seq
let target = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(1, &self))?;

Ok(ComponentKey::new(id, object))
Ok(ComponentKey::new(id, target))
}
}

Expand All @@ -98,17 +98,17 @@ impl ComponentKey {
/// Returns true if the component is a relation
#[inline]
pub fn is_relation(&self) -> bool {
self.object.is_some()
self.target.is_some()
}

pub(crate) fn new(id: Entity, object: Option<Entity>) -> Self {
Self { id, object }
pub(crate) fn new(id: Entity, target: Option<Entity>) -> Self {
Self { id, target }
}

#[inline]
/// Returns the object of the relation
pub fn object(&self) -> Option<Entity> {
self.object
/// Returns the target of the relation
pub fn target(&self) -> Option<Entity> {
self.target
}

#[inline]
Expand All @@ -126,7 +126,7 @@ impl Display for ComponentKey {

impl Debug for ComponentKey {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self.object {
match self.target {
Some(s) => write!(f, "{}({s})", self.id),
None => Debug::fmt(&self.id, f),
}
Expand All @@ -136,9 +136,8 @@ impl Debug for ComponentKey {
/// Type alias for a function which instantiates a component
pub type ComponentFn<T> = fn() -> Component<T>;

/// Type alias for a function which instantiates a relation with the specified
/// object
pub type RelationFn<T> = fn(object: Entity) -> Component<T>;
/// Type alias for a function which instantiates a relation with the specified target
pub type RelationFn<T> = fn(target: Entity) -> Component<T>;

crate::component! {
pub(crate) dummy,
Expand Down Expand Up @@ -175,17 +174,17 @@ impl<T> Clone for Component<T> {

impl<T> fmt::Debug for Component<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self.key.object {
Some(object) => write!(f, "{}({}) {}", self.vtable.name, object, self.key.id()),
match self.key.target {
Some(target) => write!(f, "{}({}) {}", self.vtable.name, target, self.key.id()),
None => write!(f, "{} {}", self.vtable.name, self.key.id),
}
}
}

impl<T> Display for Component<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self.key.object {
Some(object) => write!(f, "{}({}) {}", self.vtable.name, object, self.key.id()),
match self.key.target {
Some(target) => write!(f, "{}({}) {}", self.vtable.name, target, self.key.id()),
None => write!(f, "{} {}", self.vtable.name, self.key.id),
}
}
Expand Down Expand Up @@ -237,7 +236,7 @@ impl<T: ComponentValue> Component<T> {
}

/// Get the component's base id.
/// This is the id without any relation object
/// This is the id without any relation target
#[inline(always)]
pub fn id(&self) -> Entity {
self.key.id
Expand Down Expand Up @@ -326,9 +325,9 @@ impl<T: ComponentValue> RelationExt<T> for Component<T> {
self.key().id
}

fn of(&self, object: Entity) -> Component<T> {
fn of(&self, target: Entity) -> Component<T> {
Self {
key: ComponentKey::new(self.key().id, Some(object)),
key: ComponentKey::new(self.key().id, Some(target)),
..*self
}
}
Expand Down Expand Up @@ -370,8 +369,8 @@ impl PartialEq for ComponentDesc {

impl core::fmt::Debug for ComponentDesc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.key.object {
Some(object) => write!(f, "{}({}) {}", self.vtable.name, object, self.key.id()),
match self.key.target {
Some(target) => write!(f, "{}({}) {}", self.vtable.name, target, self.key.id()),
None => write!(f, "{} {}", self.vtable.name, self.key.id),
}
}
Expand Down Expand Up @@ -464,7 +463,7 @@ impl ComponentDesc {

#[inline]
pub(crate) fn is_relation(&self) -> bool {
self.key.object.is_some()
self.key.target.is_some()
}

pub(crate) fn get_meta(&self) -> ComponentBuffer {
Expand Down
1 change: 0 additions & 1 deletion src/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub(crate) const DEFAULT_GEN: EntityGen = unsafe { EntityGen::new_unchecked(1) }
#[derive(PartialOrd, Clone, Copy, PartialEq, Eq, Ord, Hash)]
pub struct Entity {
pub(crate) index: EntityIndex,
/// Object
pub(crate) gen: EntityGen,
pub(crate) kind: EntityKind,
}
Expand Down
6 changes: 3 additions & 3 deletions src/fetch/relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ where
let borrows: SmallVec<[_; 4]> = {
data.arch
.relations_like(self.component.id())
.map(|(desc, cell)| (desc.object.unwrap(), cell.borrow()))
.map(|(desc, cell)| (desc.target.unwrap(), cell.borrow()))
.collect()
};

Expand All @@ -48,7 +48,7 @@ where
fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
let relation = self.component.key().id;
dst.extend(data.arch.cells().keys().filter_map(move |k| {
if k.object.is_some() && k.id == relation {
if k.target.is_some() && k.id == relation {
return Some(Access {
kind: AccessKind::Archetype {
id: data.arch_id,
Expand Down Expand Up @@ -107,7 +107,7 @@ where
}
}

/// Iterates the relation object and data for the yielded query item
/// Iterates the relation targets and data for the yielded query item
pub struct RelationsIter<'a, T> {
borrows: slice::Iter<'a, (Entity, CellGuard<'a, [T]>)>,
slot: Slot,
Expand Down
10 changes: 5 additions & 5 deletions src/fetch/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait FetchSource {
fn describe(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
}

/// Selects the fetch value from the first parent/object of the specified relation
/// Selects the fetch value from the first target of the specified relation
pub struct FromRelation {
pub(crate) relation: Entity,
pub(crate) name: &'static str,
Expand All @@ -33,11 +33,11 @@ impl FetchSource for FromRelation {
data: FetchAccessData<'a>,
) -> Option<(ArchetypeId, &'a Archetype, Option<Slot>)> {
for (key, _) in data.arch.relations_like(self.relation) {
let object = key.object().unwrap();
let target = key.target.unwrap();

let loc = data
.world
.location(object)
.location(target)
.expect("Relation contains invalid entity");

let arch = data.world.archetypes.get(loc.arch_id);
Expand Down Expand Up @@ -95,11 +95,11 @@ fn traverse_resolve<'a, 'w, Q: Fetch<'w>>(
}

for (key, _) in data.arch.relations_like(relation) {
let object = key.object().unwrap();
let target = key.target.unwrap();

let loc = data
.world
.location(object)
.location(target)
.expect("Relation contains invalid entity");

let data = FetchAccessData {
Expand Down
18 changes: 9 additions & 9 deletions src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ gen_bitops! {
Nothing[];
Or[T];
RemovedFilter[T];
WithObject[];
WithTarget[];
WithRelation[];
With[];
WithoutRelation[];
Expand Down Expand Up @@ -319,15 +319,15 @@ impl StaticFilter for Without {

#[derive(Debug, Clone)]
/// Yields all entities with the relation of the specified kind
pub(crate) struct WithObject {
pub(crate) object: Entity,
pub(crate) struct WithTarget {
pub(crate) target: Entity,
}

impl<'q> FetchItem<'q> for WithObject {
impl<'q> FetchItem<'q> for WithTarget {
type Item = ();
}

impl<'w> Fetch<'w> for WithObject {
impl<'w> Fetch<'w> for WithTarget {
const MUTABLE: bool = false;

type Prepared = All;
Expand All @@ -341,18 +341,18 @@ impl<'w> Fetch<'w> for WithObject {
}

fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "with (*)({})", self.object)
write!(f, "with (*)({})", self.target)
}

#[inline]
fn access(&self, _: FetchAccessData, _: &mut Vec<Access>) {}
}

impl StaticFilter for WithObject {
impl StaticFilter for WithTarget {
fn filter_static(&self, arch: &Archetype) -> bool {
arch.components().any(|v| {
if let Some(v) = v.key().object {
if v == self.object {
if let Some(v) = v.key().target {
if v == self.target {
return true;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
/// pub(crate) name: type => [ Metadata, ... ],
///
/// // relational component
/// name(object): type
/// name(target): type
///
/// // relation component with metadata/reflection
/// name(object): type => [ Metadata, ... ]
/// name(target): type => [ Metadata, ... ]
///
/// // static entity
/// name,
Expand Down Expand Up @@ -50,7 +50,7 @@
///
/// # Relations
/// A component can be associated to another entity, which declares a relation of the component
/// type between the subject (entity which has the component), and the object (the associated
/// type between the subject (entity which has the component), and the target (the associated
/// entity).
///
/// Relation components with different associated entities are distinct.
Expand Down Expand Up @@ -101,7 +101,7 @@
/// another *generationless* entity id.
///
/// This allows for the parameterization of components with component ids being
/// distinct with across different objects.
/// distinct with across different target.
macro_rules! component {
// Relations
($(#[$outer:meta])* $vis: vis $name: ident( $obj: ident ): $ty: ty $(=> [$($metadata: ty),*])?, $($rest:tt)*) => {
Expand Down
7 changes: 3 additions & 4 deletions src/query/dfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ impl State {
let mut root = true;
for (key, _) in arch.relations_like(relation) {
root = false;
let object = key.object.unwrap();
let target = key.target.unwrap();

self.edges.entry(object).or_default().push(index);
self.edges.entry(target).or_default().push(index);
}

if root {
Expand Down Expand Up @@ -285,7 +285,6 @@ where
F: 'w,
{
while let Some((slot, id, item)) = chunk.next_full() {
let edge_value = edge.map(|v| &v[slot]);
let value = (visit)(item, edge.map(|v| &v[slot]), value);

// Iterate the archetypes which contain all references to `id`
Expand Down Expand Up @@ -545,7 +544,7 @@ mod test {
Query::new((entity_ids(), name()))
.with_strategy(Dfs::new(child_of))
.borrow(&world)
.traverse(&Vec::new(), |(id, name), v, prefix| {
.traverse(&Vec::new(), |(id, name), _, prefix| {
let mut p = prefix.clone();
p.push(name.clone());

Expand Down
Loading

0 comments on commit c594663

Please sign in to comment.