2022-12-13 04:36:51 +00:00
|
|
|
/*
|
|
|
|
ecs.h
|
|
|
|
|
|
|
|
Entity Component System
|
|
|
|
|
|
|
|
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
Date: 2022/10/07
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __QF_ecs_h
|
|
|
|
#define __QF_ecs_h
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2022-12-13 13:58:44 +00:00
|
|
|
#include "QF/darray.h"
|
2022-12-13 04:36:51 +00:00
|
|
|
#include "QF/qtypes.h"
|
|
|
|
#include "QF/progs.h"//FIXME for PR_RESMAP
|
|
|
|
|
|
|
|
#include "QF/ecs/component.h"
|
|
|
|
#include "QF/ecs/hierarchy.h"
|
|
|
|
|
|
|
|
/** \defgroup ecs Entity Component System
|
|
|
|
\ingroup utils
|
|
|
|
*/
|
|
|
|
///@{
|
|
|
|
|
|
|
|
#define ENT_GROW 1024
|
|
|
|
#define COMP_GROW 128
|
2022-12-18 12:11:21 +00:00
|
|
|
#define RANGE_GROW 32
|
2022-12-13 04:36:51 +00:00
|
|
|
#define ENT_IDBITS 20
|
|
|
|
#define nullent (~0u)
|
|
|
|
|
|
|
|
typedef struct ecs_pool_s {
|
|
|
|
uint32_t *sparse; // indexed by entity id, holds index to dense/data
|
|
|
|
uint32_t *dense; // holds entity id
|
|
|
|
void *data; // component data
|
|
|
|
uint32_t count; // number of components/dense entity ids
|
|
|
|
uint32_t max_count; // current capacity for components/entity ids
|
|
|
|
} ecs_pool_t;
|
|
|
|
|
2022-12-13 13:58:44 +00:00
|
|
|
typedef struct DARRAY_TYPE(component_t) componentset_t;
|
|
|
|
|
2022-12-18 12:11:21 +00:00
|
|
|
typedef struct ecs_range_s {
|
2022-12-20 08:56:08 +00:00
|
|
|
uint32_t start;
|
2022-12-18 12:11:21 +00:00
|
|
|
uint32_t end;
|
|
|
|
} ecs_range_t;
|
|
|
|
|
|
|
|
typedef struct ecs_subpool_s {
|
|
|
|
uint32_t *rangeids;
|
|
|
|
uint32_t *sorted;
|
2022-12-20 08:56:08 +00:00
|
|
|
uint32_t *ranges;
|
2022-12-18 12:11:21 +00:00
|
|
|
uint32_t next;
|
|
|
|
uint32_t available;
|
|
|
|
uint32_t num_ranges;
|
|
|
|
uint32_t max_ranges;
|
|
|
|
} ecs_subpool_t;
|
|
|
|
|
2022-12-13 04:36:51 +00:00
|
|
|
typedef struct ecs_registry_s {
|
2022-12-18 12:11:21 +00:00
|
|
|
ecs_pool_t *comp_pools;
|
2022-12-13 04:36:51 +00:00
|
|
|
uint32_t *entities;
|
2022-12-18 12:11:21 +00:00
|
|
|
ecs_subpool_t *subpools;
|
2022-12-13 04:36:51 +00:00
|
|
|
uint32_t next;
|
|
|
|
uint32_t available;
|
|
|
|
uint32_t num_entities;
|
|
|
|
uint32_t max_entities;
|
2022-12-13 13:58:44 +00:00
|
|
|
componentset_t components;
|
2022-12-13 04:36:51 +00:00
|
|
|
PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way
|
|
|
|
} ecs_registry_t;
|
|
|
|
|
2022-12-14 13:28:45 +00:00
|
|
|
/** Tie an ECS system to a registry.
|
|
|
|
|
|
|
|
Keeps the registry using the system and the system's component base
|
|
|
|
together.
|
|
|
|
*/
|
|
|
|
typedef struct ecs_system_s {
|
|
|
|
ecs_registry_t *reg;
|
|
|
|
uint32_t base;
|
|
|
|
} ecs_system_t;
|
|
|
|
|
2022-12-20 08:56:08 +00:00
|
|
|
#include "QF/ecs/entity.h"
|
|
|
|
|
|
|
|
#define ECSINLINE GNU89INLINE inline
|
|
|
|
|
2022-12-13 04:36:51 +00:00
|
|
|
ecs_registry_t *ECS_NewRegistry (void);
|
|
|
|
void ECS_DelRegistry (ecs_registry_t *registry);
|
2022-12-13 13:58:44 +00:00
|
|
|
uint32_t ECS_RegisterComponents (ecs_registry_t *registry,
|
|
|
|
const component_t *components,
|
|
|
|
uint32_t count);
|
|
|
|
void ECS_CreateComponentPools (ecs_registry_t *registry);
|
|
|
|
|
2022-12-13 04:36:51 +00:00
|
|
|
|
|
|
|
#ifndef __compar_d_fn_t_defined
|
|
|
|
#define __compar_d_fn_t_defined
|
|
|
|
typedef int (*__compar_d_fn_t)(const void *, const void *, void *);
|
|
|
|
#endif
|
|
|
|
void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component,
|
|
|
|
__compar_d_fn_t cmp, void *arg);
|
|
|
|
|
|
|
|
uint32_t ECS_NewEntity (ecs_registry_t *registry);
|
|
|
|
void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent);
|
|
|
|
void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component);
|
|
|
|
|
2022-12-18 12:11:21 +00:00
|
|
|
uint32_t ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component);
|
|
|
|
void ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component,
|
|
|
|
uint32_t id);
|
2022-12-20 08:56:08 +00:00
|
|
|
ECSINLINE ecs_range_t ECS_GetSubpoolRange (ecs_registry_t *registry,
|
|
|
|
uint32_t component, uint32_t id);
|
2022-12-18 12:11:21 +00:00
|
|
|
|
2022-12-13 04:36:51 +00:00
|
|
|
#undef ECSINLINE
|
2022-12-20 08:56:08 +00:00
|
|
|
#ifndef IMPLEMENT_ECS_Funcs
|
|
|
|
#define ECSINLINE GNU89INLINE inline
|
|
|
|
#else
|
|
|
|
#define ECSINLINE VISIBLE
|
|
|
|
#endif
|
2022-12-13 04:36:51 +00:00
|
|
|
|
2022-12-20 08:56:08 +00:00
|
|
|
ECSINLINE
|
|
|
|
ecs_range_t
|
|
|
|
ECS_GetSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id)
|
|
|
|
{
|
|
|
|
ecs_subpool_t *subpool = ®istry->subpools[component];
|
|
|
|
uint32_t ind = subpool->sorted[Ent_Index (id)];
|
|
|
|
ecs_range_t range = {
|
|
|
|
.start = ind ? subpool->ranges[ind - 1] : 0,
|
|
|
|
.end = subpool->ranges[ind],
|
|
|
|
};
|
|
|
|
return range;
|
|
|
|
}
|
2022-12-13 04:36:51 +00:00
|
|
|
|
2022-12-20 08:56:08 +00:00
|
|
|
#undef ECSINLINE
|
|
|
|
|
|
|
|
///@}
|
2022-12-13 04:36:51 +00:00
|
|
|
|
|
|
|
#endif//__QF_ecs_h
|