Component metadata

The keen eyed of you may have noticed that ComponentId is the same as Entity.

This is a design choice; a component is also an entity, and as such, exists in the world.

This brings some interesting possibilities which are not possible in other ECS systems, mainly: components can have components.

This allows the components to be queried just as they were normal entities, which allows reflection.

For example, a component can itself have a component which knows how to Debug::fmt the component value, another component could be used to serialize a value.

While components could be added to components through the conventional [World::set] syntax, it can quickly become a spaghetti of init functions for each library to add the required components, or metadata to the exported components.

This is where the component macro comes into play. The component function acquires a globally free Entity and assigns that to the strongly typed component. When the component is first inserted into the world it can insert so called metadata to the component.

#![allow(unused)]

fn main() {
    component! {
        /// An entity's health.
        /// Provides the Debug bundle, which adds the `debug_visitor` component.
        health: f32 => [ flax::Debuggable ],
    }

    // After adding the component, the associate metadata of the `health`
    // component is added to the world.
    world.set(id, health(), 100.0)?;

    let component_name = world.get(health().id(), name())?;
    println!("The name of the component is {component_name:?}");

    // Print the state of the world
    println!("World: {world:#?}");
    // Prints:
    //
    // World: {
    //     1v2: {},
    //     2v1: {},
    //     3v1: {},
    //     4v1: {},
    //     5v1: {},
    //     6v1: {},
    //     7v1: {},
    //     8v1: {},
    //     9v1: {},
    //     10v1: {},
    //     11v1: {
    //         "position": _,
    //         "health": 100.0,
    //     },
    // }

}

The

#![allow(unused)]
fn main() {
component: type => [ Meta, Meta, Meta ]
}

syntax is used to add metadata to the component.

The component component, and the name component is always present.

Debug

If a component has the flax::Debuggable component, the component and value for each entity will be present when debug formatting the world.

Name

Every component has a name, which is the same as the declaration.

Custom metadata

Custom metadata can be added to a component by creating a struct which implements MetaData, which is responsible of adding the appropriate components.

Note: Do not use conditional compilation for these structs as this leaks the cfg directives to any uses of the metadata in the component macro. Instead, conditionally add, or do not add, the component in the attach method.

A common example of this is serde, prefer to not add the serializer component and still define Serialize and making it no-op when serde is not enabled.