You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation/ChangeDetection.md
+16-4Lines changed: 16 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,15 @@
1
+
# Change Detection
2
+
1
3
## Change Detection
2
4
3
5
To avoid the error-prone manual management of `HasChanged*` tags, Stagehand provides zero-overhead abstractions that automatically toggle these tags when components are modified.
4
6
5
7
To enable these features, components must be defined using Stagehand's macros that are described in the Components manual.
6
8
9
+
### How Change Tags Work
10
+
11
+
For every component defined with a change-tracking macro, Stagehand automatically generates an empty tag struct named `HasChanged<Name>`. For example, `FLOAT(Health)` generates `HasChangedHealth`. This tag is registered with Flecs using `flecs::With`, so it is added to every entity that has the component and is disabled by default. When a modification is detected, Stagehand enables the tag on the affected entity. At the end of each frame (in the `PostRender` pipeline phase), a built-in Stagehand system automatically disables all change tags on all entities, giving them per-frame semantics.
12
+
7
13
Change tracking can be enabled or disabled at component definition time:
8
14
9
15
- Use normal macros (e.g. `FLOAT`, `GODOT_VARIANT`, `VECTOR`) to enable change tracking.
Copy file name to clipboardExpand all lines: documentation/Components.md
+60-32Lines changed: 60 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,86 +1,106 @@
1
-
# Stagehand ECS Patterns & Best Practices
1
+
# Defining and Registering Components
2
2
3
-
Stagehand introduces facilities and patterns to streamline working with components.
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
-
## Defining and Registering Components
5
+
## Manually defined & registered components
6
6
7
-
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.
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.
8
8
9
+
```cpp
10
+
// 1. Define your struct.
11
+
structVelocity {
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.
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.
12
28
13
-
###Primitive C++ Types
29
+
## Primitive C++ Types
14
30
15
-
####`FLOAT(Name, ...)` / `FLOAT_(Name, ...)` - 32-bit (single precision) floating point number
31
+
### `FLOAT(Name, ...)` / `FLOAT_(Name, ...)` - 32-bit (single precision) floating point number
16
32
```cpp
17
33
FLOAT(Health); // Default-initialised to 0.0f.
18
34
FLOAT(MaxHealth, 100.0f); // Initialised with a default value.
19
35
```
20
36
21
-
####`DOUBLE(Name, ...)` / `DOUBLE_(Name, ...)` - 64-bit (double precision) floating point number
37
+
### `DOUBLE(Name, ...)` / `DOUBLE_(Name, ...)` - 64-bit (double precision) floating point number
22
38
```cpp
23
39
DOUBLE(Gravity); // Default-initialised to 0.0.
24
40
DOUBLE(Pi, 3.14159265359); // Initialised with a default value.
25
41
```
26
42
27
-
####`INT8(Name, ...)` / `INT8_(Name, ...)` - 8-bit signed integer
43
+
### `INT8(Name, ...)` / `INT8_(Name, ...)` - 8-bit signed integer
28
44
```cpp
29
45
INT8(Level); // Default-initialised to 0.
30
46
INT8(MaxLevel, 99); // Initialised with a default value.
Registers an existing C++ `enum class` as an ECS component. The optional `UnderlyingType` tells Stagehand which integer type to use for GDScript serialisation; it should match the enum's declared underlying type (defaults to `uint8_t`).
84
104
```cpp
85
105
enumclassAIState { Idle, Patrol, Chase };
86
106
ENUM(AIState); // Defaults to uint8_t underlying type.
Multi-field aggregate struct component with automatic member reflection via Boost.PFR. All fields are individually registered with Flecs and exposed to GDScript as a `Dictionary`. The struct must be an aggregate type: no user-declared constructors, no virtual functions, and no private or protected non-static data members. All field types must be individually convertible to `godot::Variant`.
114
142
```cpp
115
143
STRUCT(PlayerStats, { float age; int rank; }); // Members are default-initialised.
116
144
STRUCT(ColoredPoint, { godot::Vector3 position = godot::Vector3(0, 0, 0); godot::Color color = godot::Color(1, 1, 1); }); // Members initialised with default values.
117
145
STRUCT_(TrackedPosition, { float x = 0.0f; float y = 0.0f; float z = 0.0f; }); // Opt out of change detection.
These macros wrap Godot's built-in Variant types as components. They support both struct-based (Plain Old Data) types and class-based (handle) types.
152
+
These macros wrap Godot's built-in Variant types as components. They support both struct-based (Plain Old Data) types and class-based (handle) types. `GODOT_VARIANT` includes change detection; `GODOT_VARIANT_` opts out of it.
0 commit comments