Skip to content

Disable automatic (ChildOf, <project_name>) on #[derive(Component)]? #289

@dubrowgn

Description

@dubrowgn

Description

After wasting a ton of time trying to figure out why #[flecs(meta)] wasn't working for my component (and why I couldn't use the component in flecscript), I realized I was looking at the wrong component. For example:

#[derive(Clone, Component, Copy, Debug, Default)]
#[flecs(meta)]
pub struct Position { pub x: f32, pub y: f32 }

let world = World::new();
println!("TYPED pos: {:?}", world.component::<Position>());
println!("UN-typed pos: {:?}", world.component_untyped_named("Position"));
TYPED pos: 
  Entity: #33 | "Position"
  Archetype:
    - Component : 1
    - flecs.meta.type : 355
    - flecs.meta.TypeSerializer : 356
    - flecs.meta.struct : 363
    - (Identifier, Name) : 9223372045444710697
    - (Identifier, Symbol) : 9223372045444710698
    - (ChildOf, lua_flecs) : 9223373299575161427
  Children:
    - #596 | "x"
    - #597 | "y"

UN-typed pos: 
  Entity: #34 | "Position"
  Archetype:
    - (Identifier, Name) : 9223372045444710697

Exact same name, completely different components!

Eventually, I realized the derived component is actually a child of lua_flecs (the project name), effectively namespacing them. This was/is:

  1. Surprising and a huge time sink. I don't see this documented anywhere, although I eventually found one example that does use this organizational structure in a query.
  2. A problem because components defined in rust get a different namespace than components defined elsewhere (e.g. flecsript). You get what feels like arbitrary name prefixes depending on where and how the component happens to be defined. Consumers in flecscript have to know where components are defined in order to guess the right prefix. Moving components from flecscript to rust breaks all existing flecscript consumers.

I never did figure out exactly where in the macro magic this is coming from, but I'm assuming flecs is inserting it based on the component name. E.g the following results in something similar:

let world = World::new();
println!("{:?}", world.component_untyped_named("foo::bar"));
  Entity: #38 | "bar"
  Archetype:
    - (Identifier, Name) : 9223372045444710697
    - (ChildOf, foo) : 9223373299575161432

Questions

  1. Is there a way to globally disable adding the ChildOf pair for derived Components? I realized I can opt out per-component with #[flecs(name="Position")], but this is tedious and error prone.
  2. Is there a way to lookup components without accidentally generating a new one? E.g. world.lookup() panics on failure. I expected world.component_untyped_named() to do the same, but it doesn't. Theoretically, you can look them up, but it's surprisingly tricky since all the obvious methods don't work. E.g. world.lookup("Position") panics, world.lookup("lua_flecs.Position") panics, but world.lookup("lua_flecs::Position") does not. Meanwhile query().with((ChildOf, "lua_flecs.Position")) works, but query().with((ChildOf, "lua_flecs::Position")) panics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions