32 releases
0.12.1 | Aug 31, 2024 |
---|---|
0.12.0 | Jan 3, 2024 |
0.11.7 | Jul 3, 2022 |
0.11.6 | Mar 8, 2022 |
0.1.8 | Jun 20, 2021 |
#250 in Game dev
36 downloads per month
Used in 7 crates
(4 directly)
44KB
822 lines
hecs-hierarchy
hecs-hierarchy
Hierarchy implementation for use with the hecs ECS.
Features
- Iterate children of parent
- Lookup parent of child
- Traverse hierarchy depth first
- Traverse hierarchy breadth first
- Traverse ancestors
- Detach child from hierarchy
- Ergonomic tree building
- Reverse iteration
- Sorting
- (Optional) associated data to relation
Motivation
An ECS is a fantastic design principle for designing software which allows a
data oriented design. Most of the time, the ECS is flat with maybe a few
components referencing each other via Entity
ids. Sometimes however, the need
to create and manage proper, well behaved graphs, arises.
This is were hecs-hierarchy comes in and gives the ability to manage directed graphs that can connect entities. This is very useful when developing a UI library using the ECS design pattern, or purely for grouping entities together from the same model.
Usage
Import the Hierarchy trait which extends hecs::World
The trait Hierarchy extends hecs::World with functions for manipulating and iterating the hierarchy tree.
The hierarchy uses a marker type which makes it possible for a single entity to belong to several hierarchy trees.
See the documentation, more specifically the Hierarchy trait
Example usage:
use hecs_hierarchy::*;
// Marker type which allows several hierarchies.
struct Tree;
let mut world = hecs::World::default();
// Create a root entity, there can be several.
let root = world.spawn(("Root",));
// Create a loose entity
let child = world.spawn(("Child 1",));
// Attaches the child to a parent, in this case `root`
world.attach::<Tree>(child, root).unwrap();
// Iterate children
for child in world.children::<Tree>(root) {
let name = world.get::<&&str>(child).unwrap();
println!("Child: {:?} {}", child, *name);
}
// Add a grandchild
world.attach_new::<Tree, _>(child, ("Grandchild",)).unwrap();
// Iterate recursively
for child in world.descendants_depth_first::<Tree>(root) {
let name = world.get::<&&str>(child).unwrap();
println!("Child: {:?} {}", child, *name)
}
// Detach `child` and `grandchild`
world.detach::<Tree>(child).unwrap();
let child2 = world.attach_new::<Tree, _>(root, ("Child 2",)).unwrap();
// Reattach as a child of `child2`
world.attach::<Tree>(child, child2).unwrap();
world.attach_new::<Tree, _>(root, ("Child 3",)).unwrap();
// Hierarchy now looks like this:
// Root
// |-------- Child 3
// |-------- Child 2
// |-------- Child 1
// |-------- Grandchild
Inspiration
This project is heavily inspired by Shipyard
's hierarchy implementation and
exposes a similar API.
Dependencies
~3MB
~51K SLoC