Skip to content

Commit

Permalink
Updating docs to get auto-doc-cfg to work and also pull in the crate-…
Browse files Browse the repository at this point in the history
…level docs from the readme.md
  • Loading branch information
recatek committed Jan 18, 2025
1 parent 33afed4 commit e64dab6
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 88 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ readme = "README.md"
keywords = ["ecs", "entity"]
categories = ["data-structures", "game-engines"]

[package.metadata.docs.rs]
all-features = true

[features]
default = []

Expand Down
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,24 @@ The goals for gecs are (in descending priority order):
- Simplicity and focus in features

All of the code that gecs generates in user crates is safe, and users of gecs can
use `#[deny(unsafe_code)]` in their own crates. Note that gecs does use unsafe code
internally to allow for compiler optimizations around known invariants. It is not a
goal of this library to be written entirely in safe Rust.
use `#![forbid(unsafe_code)]` in their own crates. Note that gecs does use unsafe
code internally to allow for compiler optimizations around known invariants. It is
not a goal of this library to be written entirely in safe Rust.

# Getting Started

See the `ecs_world!`, `ecs_find!`, and `ecs_iter!` macros for more information.
See the <code>[ecs_world!]</code> macro for information on how to construct an ECS
world, and the <code>[ecs_find!]</code> and <code>[ecs_iter!]</code> macros for
information on how to perform full ECS queries. See the <code>[World]</code> and
<code>[Archetype]</code> traits to see how to interact directly with the world.

[ecs_world!]: https://docs.rs/gecs/latest/gecs/macro.ecs_world.html
[ecs_find!]: https://docs.rs/gecs/latest/gecs/macro.ecs_find.html
[ecs_iter!]: https://docs.rs/gecs/latest/gecs/macro.ecs_iter.html
[World]: https://docs.rs/gecs/latest/gecs/traits/trait.World.html
[Archetype]: https://docs.rs/gecs/latest/gecs/traits/trait.Archetype.html


The following example creates a world with three components and two archetypes:

```rust
Expand Down
87 changes: 8 additions & 79 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,14 @@
#![allow(clippy::bool_comparison)] // using "== false" is easier to read in some cases
#![allow(clippy::len_zero)] // using "len() > 0" is easier to read in some cases

//! A generated entity component system 🦎
//!
//! The gecs crate provides a compile-time generated, zero-overhead ECS for simulations
//! on a budget. Unlike other ECS libraries, gecs takes a full ECS world structure
//! definition from code and precompiles all queries to achieve better performance with
//! no upfront cost or caching overhead. Queries in gecs can be inspected and checked at
//! compile-time in order to catch what would otherwise be bugs presenting only in tests
//! or execution. However, this comes at the cost of requiring all archetypes to be known
//! and declared at compile-time, so that adding or removing components from entities at
//! runtime isn't currently possible -- hybrid approaches could solve this in the future.
//!
//! The goals for gecs are (in descending priority order):
//! - Fast iteration and find queries
//! - Fast entity creation and destruction
//! - Low, predictable memory overhead
//! - A user-friendly library interface
//! - Simplicity and focus in features
//!
//! All of the code that gecs generates in user crates is safe, and users of gecs can
//! use `#[deny(unsafe_code)]` in their own crates. Note that gecs does use unsafe code
//! internally to allow for compiler optimizations around known invariants. It is not a
//! goal of this library to be written entirely in safe Rust.
//!
//! # Getting Started
//!
//! See the [`ecs_world!`], [`ecs_find!`], and [`ecs_iter!`] macros for more information.
//! The following example creates a world with three components and two archetypes:
//!
//! ```rust
//! use gecs::prelude::*;
//!
//! // Components -- these must be pub because the world is exported as pub as well.
//! pub struct CompA(pub u32);
//! pub struct CompB(pub u32);
//! pub struct CompC(pub u32);
//!
//! ecs_world! {
//! // Declare two archetypes, ArchFoo and ArchBar.
//! ecs_archetype!(ArchFoo, CompA, CompB);
//! ecs_archetype!(ArchBar, CompA, CompC);
//! }
//!
//! fn main() {
//! let mut world = EcsWorld::default(); // Initialize an empty new ECS world.
//!
//! // Add entities to the world by populating their components and receive their handles.
//! let entity_a = world.create::<ArchFoo>((CompA(1), CompB(20)));
//! let entity_b = world.create::<ArchBar>((CompA(3), CompC(40)));
//!
//! // Each archetype now has one entity.
//! assert_eq!(world.archetype::<ArchFoo>().len(), 1);
//! assert_eq!(world.archetype::<ArchBar>().len(), 1);
//!
//! // Look up each entity and check its CompB or CompC value.
//! // We use the is_some() check here to make sure the entity was indeed found.
//! assert!(ecs_find!(world, entity_a, |c: &CompB| assert_eq!(c.0, 20)).is_some());
//! assert!(ecs_find!(world, entity_b, |c: &CompC| assert_eq!(c.0, 40)).is_some());
//!
//! // Add to entity_a's CompA value.
//! ecs_find!(world, entity_a, |c: &mut CompA| { c.0 += 1; });
//!
//! // Sum both entities' CompA values with one iter despite being different archetypes.
//! let mut sum = 0;
//! ecs_iter!(world, |c: &CompA| { sum += c.0 });
//! assert_eq!(sum, 5); // Adding 2 + 3 -- recall that we added 1 to entity_a's CompA.
//!
//! // Collect both entities that have a CompA component.
//! let mut found = Vec::new();
//! ecs_iter!(world, |entity: &EntityAny, _: &CompA| { found.push(*entity); });
//! assert!(found == vec![entity_a.into(), entity_b.into()]);
//!
//! // Destroy both entities -- this will return an Option containing their components.
//! assert!(world.destroy(entity_a).is_some());
//! assert!(world.destroy(entity_b).is_some());
//!
//! // Try to look up a stale entity handle -- this will return None.
//! assert!(ecs_find!(world, entity_a, |_: &Entity<ArchFoo>| { panic!() }).is_none());
//! }
//! ```
#![cfg_attr(docsrs, feature(doc_auto_cfg))]

//! [ecs_world!]: ecs_world!
//! [ecs_find!]: ecs_find!
//! [ecs_iter!]: ecs_iter!
//! [World]: traits::World
//! [Archetype]: traits::Archetype
#![doc = include_str!("../README.md")]

mod archetype;
mod index;
Expand Down
10 changes: 5 additions & 5 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::version::ArchetypeVersion;
#[cfg(doc)]
use crate::entity::EntityDirectAny;

#[cfg(feature = "events")]
#[cfg(any(doc, feature = "events"))]
use crate::entity::EntityAny;

/// The base trait for an ECS world in gecs.
Expand Down Expand Up @@ -132,10 +132,10 @@ pub trait World: Sized {
/// former (now removed) components. A `Some` result means the entity was found and destroyed.
/// A `None` result means the given entity handle was invalid.
///
/// If called with [`EntityAny`] or [`EntityDirectAny`] this instead return `Option<()>` as the
/// return component type tuple can't be known at compile time. To get the components, convert
/// the any-type entity to a known type ahead of time using [`Entity::try_into()`] and the
/// resulting entity type selection enum.
/// If called with [`EntityAny`] or [`EntityDirectAny`] this instead returns `Option<()>` as the
/// return component type tuple can't be known at compile time. To get the components from the
/// entity on destruction, convert the any-type entity into a typed entity before destroying it
/// (see [`ArchetypeSelectEntity`](crate::ArchetypeSelectEntity) for example).
///
/// # Panics
///
Expand Down

0 comments on commit e64dab6

Please sign in to comment.