LDKBuiltinSystemId
IDs of builtin systems.
typedef enum LDKBuiltinSystemId{
LDK_SYSTEM_ID_SCENEGRAPH=0x1,
LDK_SYSTEM_ID_USER=0x100
}LDKBuiltinSystemId;
Comet generates system ids and LDKSystemDesc descriptors from annotations
placed before C declarations. Annotations are special single-line comments.
In the examples, replace // @ with //@ (remove the space) before use:
this avoids accidentally feeding these documentation examples to Comet.
Stateless system (the annotated function is the update callback):
// @system name=HealthSystem components=LDKCOMPONENTHealthComponent order=10 void healthsystemupdate(void data, const LDKEntityGroup group, float dt);
Stateful system (the annotated struct contains scene-owned system data):
int damagesysteminitialize(void *data); void damagesystemupdate(void data, const LDKEntityGroup group, float dt); void damagesystemterminate(void *data);
// @system name=DamageSystem components=LDKCOMPONENTHealthComponent update=damagesystemupdate initialize=damagesysteminitialize terminate=damagesystemterminate typedef struct DamageSystem {
// @inspect min=0 label=Damage
float damage;
// @inspect runtime
u32 hits;
} DamageSystem;
Stateful systems must be declared in a header (.h, .hh or .hpp). They require at least one of initialize/init, update or terminate. Function annotations must NOT specify update=: the annotated function is update. They may still specify initialize/init and terminate. Callback declarations must be available to the generated C code.
All supported @system options (space-delimited key=value, one line):
name=ID Public system name (must be a C identifier). Defaults
to the struct typedef name or annotated function name.
components=A,B Required ECS component-type identifiers; no spaces,
duplicates or expressions, maximum 16 identifiers.
If omitted the system has no component requirements.
initialize=fn Optional initialization callback (init=fn also works).
update=fn Update callback for a stateful system only.
terminate=fn Optional termination callback.
flags=EXPR Flags expression, default LDKSYSTEMFLAG_ENABLED.
bucket=EXPR Execution bucket, default LDKSYSTEMBUCKET_UPDATE.
order=EXPR Order within the bucket, default 0.
Available flags: LDKSYSTEMFLAGNONE, LDKSYSTEMFLAGENABLED,
LDKSYSTEMFLAGENGINENATIVE and LDKSYSTEMFLAGRUNWHEN_PAUSED.
Combine flags without spaces using |. ENGINE_NATIVE indicates the
implementation comes from the engine; it is not needed for game systems.
Available buckets: LDKSYSTEMBUCKETPREUPDATE,
LDKSYSTEMBUCKETUPDATE, LDKSYSTEMBUCKETPOST_UPDATE and
LDKSYSTEMBUCKET_RENDER. order specifies execution order in a bucket.
Options such as flags/bucket/order are emitted as C expressions, so their
identifiers must be defined when compiling the generated descriptors.
Callback signatures: int initialize(void *data); // optional void update(void data, const LDKEntityGroup group, float dt); void terminate(void *data); // optional
data is the scene-owned instance for stateful systems; stateless systems
have data_size=0. group is the temporary view of entities matching the
component requirements and is valid during the callback. dt is elapsed
time in seconds. A system can omit update if it is lifecycle-only and
stateful. Systems are registered from generated descriptors, then selected
and started for a scene; creating a struct does not start the system.
Comet generates LDKSYSTEMName and LDKSYSTEMDESC_Name, accessed with
ldk_system_id(Name) and ldk_system_desc(Name). For stateful systems,
Name in those symbols is the typedef name, even if name= changes the
display name; for stateless systems it is name=, or the function name.
System struct fields use the same annotations as component fields: // @inspect readonly | runtime | hidden | slider | enum // @inspect min=N max=N widget=SUFFIX source=field label=Token // @begin_group "Group Name" (nested groups are supported) // @end_group See ldk_component.h for supported field types, widgets, flag behavior, inspector metadata and grouping rules.
All @system key=value options must appear on the annotation's own line.
Comet scans source text directly and does not ignore comment examples or
disabled blocks: avoid spelling a literal marker outside real declarations.
The registry belongs to the engine; game code should not own it directly.
IDs of builtin systems.
typedef enum LDKBuiltinSystemId{
LDK_SYSTEM_ID_SCENEGRAPH=0x1,
LDK_SYSTEM_ID_USER=0x100
}LDKBuiltinSystemId;
Execution bucket for a system update callback. UPDATE is zero intentionally so a zero-initialized descriptor gets the normal/default gameplay bucket.
typedef enum LDKSystemBucket{
LDK_SYSTEM_BUCKET_UPDATE=0,
LDK_SYSTEM_BUCKET_PRE_UPDATE,
LDK_SYSTEM_BUCKET_POST_UPDATE,
LDK_SYSTEM_BUCKET_RENDER,
LDK_SYSTEM_BUCKET_COUNT
}LDKSystemBucket;
typedef enum LDKSystemFlags{
LDK_SYSTEM_FLAG_NONE=0,
LDK_SYSTEM_FLAG_ENABLED=1<<0,
LDK_SYSTEM_FLAG_ENGINE_NATIVE=1<<1,
LDK_SYSTEM_FLAG_RUN_WHEN_PAUSED=1<<2
}LDKSystemFlags;
Stable read-only view of the entity membership bound to a system. The view is valid for the duration of a system update callback. Structural ECS changes performed by a callback are reflected before the next system callback executes. A grouping_id of 0 identifies the empty, unbound group.
typedef struct LDKEntityGroup{
u64 grouping_id;
const LDKEntity *entities;
u32 count;
}LDKEntityGroup;
Callback used to synchronize with system execution.
typedef bool(*LDKSystemCallbackSyncFn)(void *user);
userTrue if the operation succeeds; false otherwise.
Callback called during ECS system initialization.
typedef int(*LDKSystemInitializeFn)(void *data);
dataThe resulting integer value.
Callback called when an ECS system updates a group.
typedef void(*LDKSystemUpdateFn)(void *data, const LDKEntityGroup *group, float dt);
datagroupdtCallback called during ECS system termination.
typedef void(*LDKSystemTerminateFn)(void *data);
datatypedef struct LDKSystemDesc{
u64 id;
const char *name;
u32 flags;
LDKSystemBucket bucket;
i32 order;
u32 data_size;
LDKSystemInitializeFn initialize;
LDKSystemUpdateFn update;
LDKSystemTerminateFn terminate;
const u32 *component_types;
u32 component_count;
}LDKSystemDesc;
typedef struct LDKSystemRegistry{
void *internal;
struct LDKRoot *root;
u8 is_initialized;
u8 is_started;
u8 is_paused;
}LDKSystemRegistry;
Descriptors for systems implemented by the engine. Games own registration.
LDK_API u32 ldk_engine_system_descriptor_count(void);
Number of matching entries.
Get the engine system descriptor.
LDK_API bool ldk_engine_system_descriptor_get(
u32 index,
LDKSystemDesc *out
);
u32 indexLDKSystemDesc *outTrue if the operation succeeds; false otherwise.
Initialize the system registry.
LDK_API bool ldk_system_registry_initialize(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Shut down the system registry.
LDK_API void ldk_system_registry_terminate(LDKSystemRegistry *registry);
LDKSystemRegistry *registryRegister the system registry.
LDK_API bool ldk_system_registry_register(
LDKSystemRegistry *registry,
const LDKSystemDesc *desc
);
LDKSystemRegistry *registryconst LDKSystemDesc *descTrue if the operation succeeds; false otherwise.
Unregister the system registry.
LDK_API bool ldk_system_registry_unregister(
LDKSystemRegistry *registry,
u64 id
);
LDKSystemRegistry *registryu64 idTrue if the operation succeeds; false otherwise.
Find a registered system by its stable ID.
LDK_API bool ldk_system_registry_find_by_id(
LDKSystemRegistry *registry,
u64 id,
LDKSystemDesc *out
);
LDKSystemRegistry *registryu64 idLDKSystemDesc *outTrue if the operation succeeds; false otherwise.
Count registered systems.
LDK_API u32 ldk_system_registry_count(const LDKSystemRegistry *registry);
const LDKSystemRegistry *registryNumber of matching entries.
Get a system registered at a particular index.
LDK_API bool ldk_system_registry_at(
const LDKSystemRegistry *registry,
u32 index,
LDKSystemDesc *out
);
const LDKSystemRegistry *registryu32 indexLDKSystemDesc *outTrue if the operation succeeds; false otherwise.
Clear the state of the system registry.
LDK_API bool ldk_system_registry_clear(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Prepare the bucket lists without initializing individual systems.
LDK_API bool ldk_system_registry_start(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Terminate all active systems in reverse registration order and unprepare.
LDK_API bool ldk_system_registry_stop(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Start/stop a registered system without changing the bucket lists. Repeated start/stop calls succeed without repeating callbacks. A failed initialize callback is followed by terminate so partially initialized state can be released. A failed start leaves other systems unchanged. Stateful systems (data_size > 0) must have data bound before start.
LDK_API bool ldk_system_registry_system_start(
LDKSystemRegistry *registry,
u64 id
);
LDKSystemRegistry *registryu64 idTrue if the operation succeeds; false otherwise.
Stop the system registry system.
LDK_API bool ldk_system_registry_system_stop(
LDKSystemRegistry *registry,
u64 id
);
LDKSystemRegistry *registryu64 idTrue if the operation succeeds; false otherwise.
Check whether the system registry system is started.
LDK_API bool ldk_system_registry_system_is_started(
const LDKSystemRegistry *registry,
u64 id
);
const LDKSystemRegistry *registryu64 idTrue when the queried condition holds; false otherwise.
Suspend only a system's update callback without terminating it. Intended for temporary editor play-mode debugging; the flag is cleared when the system is terminated. This is separate from registry pause.
LDK_API bool ldk_system_registry_system_pause_set(
LDKSystemRegistry *registry,
u64 id,
bool paused
);
Query the system's individual update suspension state.
LDK_API bool ldk_system_registry_system_is_paused(
const LDKSystemRegistry *registry,
u64 id
);
True while a bucket or a system lifecycle callback is executing.
LDK_API bool ldk_system_registry_is_busy(const LDKSystemRegistry *registry);
const LDKSystemRegistry *registryTrue when the queried condition holds; false otherwise.
Bind scene-owned system instance data. The registry never allocates or frees this pointer. Data cannot be replaced while the system is initialized. Passing NULL unbinds the current instance.
LDK_API bool ldk_system_registry_system_data_set(
LDKSystemRegistry *registry,
u64 id,
void *data
);
LDKSystemRegistry *registryu64 idvoid *dataTrue if the operation succeeds; false otherwise.
Get the system registry system data.
LDK_API void * ldk_system_registry_system_data_get(
const LDKSystemRegistry *registry,
u64 id
);
const LDKSystemRegistry *registryu64 idPointer to the requested object or data; NULL when unavailable.
Change the entity group delivered to a registered system's update callback. Engine-internal binding, resolved by the ECS from LDKSystemDesc requirements. Scene start/stop must preserve it. Game code should use the ECS facade. Passing NULL binds the system to the empty group.
LDK_API bool ldk_system_registry_system_group_set(
LDKSystemRegistry *registry,
u64 id,
const LDKEntityGroup *group
);
LDKSystemRegistry *registryu64 idconst LDKEntityGroup *groupTrue if the operation succeeds; false otherwise.
Get the system registry system group.
LDK_API const LDKEntityGroup * ldk_system_registry_system_group_get(
const LDKSystemRegistry *registry,
u64 id
);
const LDKSystemRegistry *registryu64 idPointer to the requested object or data; NULL when unavailable.
Install an engine-side synchronization point invoked after each executed update callback. The system registry does not interpret the callback; the ECS uses it to commit deferred grouping membership changes safely between systems. Passing NULL clears the handler.
LDK_API bool ldk_system_registry_callback_sync_set(
LDKSystemRegistry *registry,
LDKSystemCallbackSyncFn fn,
void *user
);
LDKSystemRegistry *registryLDKSystemCallbackSyncFn fnvoid *userTrue if the operation succeeds; false otherwise.
Suspend/resume execution without terminating individual systems.
LDK_API bool ldk_system_registry_pause(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Resume the system registry.
LDK_API bool ldk_system_registry_resume(LDKSystemRegistry *registry);
LDKSystemRegistry *registryTrue if the operation succeeds; false otherwise.
Check whether the system registry is paused.
LDK_API bool ldk_system_registry_is_paused(const LDKSystemRegistry *registry);
const LDKSystemRegistry *registryTrue when the queried condition holds; false otherwise.
Run initialized, enabled systems whose single update callback belongs to the requested bucket. While paused, only systems with RUN_WHEN_PAUSED execute. Structural and lifecycle changes are forbidden during update and lifecycle callbacks.
LDK_API bool ldk_system_registry_run_bucket(
LDKSystemRegistry *registry,
LDKSystemBucket bucket,
float dt
);
LDKSystemRegistry *registryLDKSystemBucket bucketfloat dtTrue if the operation succeeds; false otherwise.
Check whether a system ID is registered.
LDK_API bool ldk_system_registry_has(
const LDKSystemRegistry *registry,
u64 id
);
const LDKSystemRegistry *registryu64 idTrue when the queried condition holds; false otherwise.