Aller au contenu

Ressources

Une ressource est une valeur stockée une seule fois par monde. Utilisez-la pour le temps, la configuration, l’entrée utilisateur ou un état partagé ; utilisez un composant pour les données propres à chaque entité.

ECS_RESOURCE_DECLARE(Time, { float dt; });
ECS_RESOURCE_DEFINE(Time);
ECS_RESOURCE_REGISTER(Time);
ecs_set_resource(Time, { .dt = 0.016f });
const Time *time = ecs_get_resource_read(Time);

Les helpers get supposent que la ressource existe. Utilisez les variantes try si son absence est possible. Une ressource C++ est accessible comme ecs::res<const Time> dans un callback de système.

static void Tick(ecs_iter_t *it) {
const Time *time = ecs_get_resource_read(Time);
(void)it;
/* utiliser time->dt */
}

Les ressources n’ajoutent pas de terme à la requête et ne consomment pas d’index de champ.

ecs_has_resource, has() et leurs variantes par identifiant testent la présence. ecs_remove_resource, remove() et les hooks de ressource permettent de gérer la fin de vie. Les handles sont empruntés au monde et ne doivent pas être utilisés après ecs_fini().

Une ressource absente peut être créée à la demande :

if (!ecs_has_resource(Time)) {
ecs_set_resource(Time, { .dt = 0.016f });
}
ecs_remove_resource(Time);

La suppression d’une ressource absente est sans effet. Les fonctions get assertent si la ressource n’existe pas ; utilisez try_get ou try_resource si cette situation est normale.

En C, résolvez la ressource avant la boucle sur le lot :

static void move_system(ecs_iter_t *it) {
const Time *time = ecs_get_resource_read(Time);
Position *positions = ecs_field(it, 0);
const Velocity *velocities = ecs_field(it, 1);
for (uint32_t i = 0; i < it->count; i++) {
positions[i].x += velocities[i].x * time->dt;
}
}

La ressource peut être déclarée dans query.resources comme métadonnée d’accès, mais elle n’est ni un component, ni un field, ni un critère d’archetype ; le système ci-dessus ne correspond qu’aux entités portant Position et Velocity.

Les helpers typés reposent sur un espace d’identifiants de ressources séparé :

void ecs_set_resource_rid(ecs_resource_t id, const void *data);
void *ecs_resource_rid(ecs_resource_t id);
void *ecs_try_resource_rid(ecs_resource_t id);
bool ecs_has_resource_rid(ecs_resource_t id);
void ecs_remove_resource_rid(ecs_resource_t id);

Cette API sert principalement au code générique et aux modules qui ne connaissent pas le type au moment de la compilation.

Les ressources ont deux hooks dédiés :

  • on_set s’exécute lors de l’écriture d’une ressource ;
  • on_remove s’exécute lors de sa suppression et lors de ecs_fini() si elle existe encore.

Les callbacks reçoivent uniquement un pointeur vers la valeur :

static void on_time_set(const void *data) {
const Time *time = data;
if (time->dt < 0.0f) {
/* enregistrer ou refuser la valeur */
}
}

L’accès à une ressource est un accès direct par ecs_resource_t et coûte O(1). La valeur est stockée une seule fois dans le monde, indépendamment des tables. Dans un système C chaud, récupérez-la une fois avant la boucle et réutilisez le pointeur pour tout le lot.

En C++ typé, ecs::res<const T> déclare EcsIn et ecs::res<T> déclare EcsInOut dans query.resources. Dans les deux cas, aucun terme component n’est créé.