|
2 | 2 |
|
3 | 3 | Through macros, boilerplate-free component definition and registration of components is possible. The macros also handle the per-component setup of [automatic change detection](ChangeDetection.md) behind the scenes. Appending an underscore to a macro name (e.g., `FLOAT_` instead of `FLOAT`) opts out of change detection for that component. |
4 | 4 |
|
5 | | -## Manually defined & registered components |
| 5 | +## Method chaining with `.then` |
6 | 6 |
|
7 | | -When none of the macro categories below fit your needs — for example, when defining a component that inherits from an arbitrary base class or requires custom Flecs hooks — you can register components manually using the `REGISTER` macro together with the Flecs and Stagehand APIs directly. |
| 7 | +All component definition macros return a `ComponentRegistrar<T>` object that exposes a `.then()` method. This allows you to chain additional Flecs configuration onto the component immediately at the definition site, without needing a separate `REGISTER` block. The callable passed to `.then()` receives the `flecs::component<T>` handle, so any operation available on it can be used. Multiple `.then()` calls can be chained and are executed in order during world initialization. |
8 | 8 |
|
9 | 9 | ```cpp |
10 | | -// 1. Define your struct. |
11 | | -struct Velocity { |
12 | | - float x = 0.0f; |
13 | | - float y = 0.0f; |
14 | | - float z = 0.0f; |
15 | | -}; |
16 | | - |
17 | | -// 2. Register it. stagehand::register_component<T>() enables GDScript get/set access. |
18 | | -REGISTER([](flecs::world& world) { |
19 | | - world.component<Velocity>() |
20 | | - .member<float>("x") |
21 | | - .member<float>("y") |
22 | | - .member<float>("z"); |
23 | | - stagehand::register_component<Velocity>("Velocity"); |
24 | | -}); |
| 10 | +// Make a component a world singleton. |
| 11 | +FLOAT(GlobalTimescale, 1.0f) |
| 12 | + .then([](auto c) { c.add(flecs::Singleton); }); |
| 13 | + |
| 14 | +// Attach lifecycle hooks. |
| 15 | +STRUCT_(PhysicsBody, { uint64_t body_id = 0; float mass = 1.0f; }) |
| 16 | + .then([](auto c) { |
| 17 | + c.on_add([](PhysicsBody& body) { |
| 18 | + body.body_id = Physics::create_body(body.mass); |
| 19 | + }); |
| 20 | + c.on_remove([](PhysicsBody& body) { |
| 21 | + Physics::destroy_body(body.body_id); |
| 22 | + }); |
| 23 | + }); |
| 24 | + |
| 25 | +// Add a Flecs trait or relationship to the component itself. |
| 26 | +GODOT_VARIANT(WorldTransform, godot::Transform3D) |
| 27 | + .then([](auto c) { c.add(flecs::OnInstantiate, flecs::Inherit); }); |
25 | 28 | ``` |
26 | 29 |
|
27 | | -Change detection is not set up automatically with manual registration. To add it, declare a tag struct and call `stagehand::internal::register_change_detection_for_component<T, ChangeTag>(world)` inside your `REGISTER` block. |
| 30 | +The following sections describe all the macros available with examples of their usage. |
28 | 31 |
|
29 | 32 | ## Primitive C++ Types |
30 | 33 |
|
@@ -292,3 +295,28 @@ GODOT_VARIANT(CustomSignal, godot::Signal, godot::Signal()); |
292 | 295 | GODOT_VARIANT(PhysicsBodyRID, godot::RID); |
293 | 296 | GODOT_VARIANT(MaterialRID, godot::RID, godot::RID()); |
294 | 297 | ``` |
| 298 | + |
| 299 | +## Manually Defining and Registered Components |
| 300 | + |
| 301 | +```cpp |
| 302 | +// 1. Define your component data structure |
| 303 | +struct Destination { |
| 304 | + float x = 0.0f; |
| 305 | + float y = 0.0f; |
| 306 | + float z = 0.0f; |
| 307 | +}; |
| 308 | + |
| 309 | +// 2. Register it the normal Flecs way |
| 310 | +REGISTER([](flecs::world& world) { |
| 311 | + world.component<Destination>() |
| 312 | + // Reflection info needs to be manually added |
| 313 | + .member<float>("x") |
| 314 | + .member<float>("y") |
| 315 | + .member<float>("z"); |
| 316 | + |
| 317 | + // stagehand::register_component<T>() enables GDScript get/set access. |
| 318 | + stagehand::register_component<Destination>("Destination"); |
| 319 | +}); |
| 320 | +``` |
| 321 | +
|
| 322 | +Change detection is not set up automatically with manual registration. To add it, you would need to declare a tag struct and call `stagehand::internal::register_change_detection_for_component<T, ChangeTag>(world)` inside your `REGISTER` block. |
0 commit comments