ECS improvements!
This commit is contained in:
@@ -8,4 +8,4 @@
|
|||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
|
||||||
camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||||
ecscomponent_t CAMERA_COMPONENT = ecsComponentInit(CAMERA_DATA);
|
ecscomponent_t CAMERA_COMPONENT = ecsComponentInit(CAMERA_DATA, NULL);
|
||||||
|
@@ -20,7 +20,7 @@ extern ecscomponent_t CAMERA_COMPONENT;
|
|||||||
*
|
*
|
||||||
* @param id The ID of the entity to initialize the camera for.
|
* @param id The ID of the entity to initialize the camera for.
|
||||||
*/
|
*/
|
||||||
#define cameraAdd(id) ecsComponentDataAdd(&CAMERA_COMPONENT, id)
|
#define cameraAdd(id) ((camera_t*)ecsComponentDataAdd(&CAMERA_COMPONENT, id))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the camera component data for a specific entity.
|
* Gets the camera component data for a specific entity.
|
||||||
@@ -28,7 +28,7 @@ extern ecscomponent_t CAMERA_COMPONENT;
|
|||||||
* @param id The ID of the entity to get the camera data for.
|
* @param id The ID of the entity to get the camera data for.
|
||||||
* @return Pointer to the camera data for the entity.
|
* @return Pointer to the camera data for the entity.
|
||||||
*/
|
*/
|
||||||
#define cameraGet(id) ecsComponentDataGet(&CAMERA_COMPONENT, id)
|
#define cameraGet(id) ((camera_t*)ecsComponentDataGet(&CAMERA_COMPONENT, id))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the camera component has data for a specific entity.
|
* Checks if the camera component has data for a specific entity.
|
||||||
|
@@ -7,4 +7,5 @@
|
|||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ecssystem.c
|
ecssystem.c
|
||||||
|
ecscomponent.c
|
||||||
)
|
)
|
@@ -12,8 +12,12 @@
|
|||||||
bool_t ecsComponentDataHas(const ecscomponent_t *cmp, const ecsid_t id) {
|
bool_t ecsComponentDataHas(const ecscomponent_t *cmp, const ecsid_t id) {
|
||||||
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
||||||
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
||||||
|
assertTrue(
|
||||||
|
(cmp->componentFlags & ECS_COMPONENT_FLAG_INITIALIZED) != 0,
|
||||||
|
"Component must be initialized before checking data."
|
||||||
|
);
|
||||||
|
|
||||||
return cmp->entityFlags[id] != 0;
|
return cmp->entityFlags[id] & ECS_COMPONENT_ENTITY_FLAG_USED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * ecsComponentDataGet(const ecscomponent_t *cmp, const ecsid_t id) {
|
void * ecsComponentDataGet(const ecscomponent_t *cmp, const ecsid_t id) {
|
||||||
@@ -23,9 +27,16 @@ void * ecsComponentDataGet(const ecscomponent_t *cmp, const ecsid_t id) {
|
|||||||
return (void *)((uint8_t *)cmp->data + (id * cmp->dataSize));
|
return (void *)((uint8_t *)cmp->data + (id * cmp->dataSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void * ecsComponentDataAdd(const ecscomponent_t *cmp, const ecsid_t id) {
|
void * ecsComponentDataAdd(ecscomponent_t *cmp, const ecsid_t id) {
|
||||||
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
||||||
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
||||||
|
|
||||||
|
// Initialize the component if it hasn't been initialized yet.
|
||||||
|
if((cmp->componentFlags & ECS_COMPONENT_FLAG_INITIALIZED) == 0) {
|
||||||
|
if(cmp->componentInit) cmp->componentInit();
|
||||||
|
cmp->componentFlags |= ECS_COMPONENT_FLAG_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
assertFalse(ecsComponentDataHas(cmp, id), "Entity already has data.");
|
assertFalse(ecsComponentDataHas(cmp, id), "Entity already has data.");
|
||||||
|
|
||||||
// Zero out the entity's data.
|
// Zero out the entity's data.
|
||||||
@@ -35,7 +46,7 @@ void * ecsComponentDataAdd(const ecscomponent_t *cmp, const ecsid_t id) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Mark the entity as having data.
|
// Mark the entity as having data.
|
||||||
cmp->entityFlags[id] = ECS_COMPONENT_FLAG_USED;
|
cmp->entityFlags[id] = ECS_COMPONENT_ENTITY_FLAG_USED;
|
||||||
|
|
||||||
return ecsComponentDataGet(cmp, id);
|
return ecsComponentDataGet(cmp, id);
|
||||||
}
|
}
|
||||||
@@ -43,6 +54,10 @@ void * ecsComponentDataAdd(const ecscomponent_t *cmp, const ecsid_t id) {
|
|||||||
void ecsComponentDataRemove(ecscomponent_t *cmp, const ecsid_t id) {
|
void ecsComponentDataRemove(ecscomponent_t *cmp, const ecsid_t id) {
|
||||||
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
||||||
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid entity ID.");
|
||||||
|
assertTrue(
|
||||||
|
(cmp->componentFlags & ECS_COMPONENT_FLAG_INITIALIZED) != 0,
|
||||||
|
"Component must be initialized before removing data."
|
||||||
|
);
|
||||||
assertTrue(ecsComponentDataHas(cmp, id), "Entity does not have data.");
|
assertTrue(ecsComponentDataHas(cmp, id), "Entity does not have data.");
|
||||||
|
|
||||||
// Clear the entity's data flag.
|
// Clear the entity's data flag.
|
||||||
|
@@ -8,25 +8,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ecs/ecsentity.h"
|
#include "ecs/ecsentity.h"
|
||||||
|
|
||||||
#define ECS_COMPONENT_FLAG_USED (1 << 0)
|
#define ECS_COMPONENT_ENTITY_FLAG_USED (1 << 0)
|
||||||
|
|
||||||
|
#define ECS_COMPONENT_FLAG_INITIALIZED (1 << 0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data;
|
void *data;
|
||||||
size_t dataSize;
|
size_t dataSize;
|
||||||
uint8_t entityFlags[ECS_ENTITY_COUNT_MAX];
|
uint8_t entityFlags[ECS_ENTITY_COUNT_MAX];
|
||||||
|
uint8_t componentFlags;
|
||||||
|
|
||||||
|
void (*componentInit)();
|
||||||
} ecscomponent_t;
|
} ecscomponent_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an ECS Component.
|
* Initializes an ECS Component.
|
||||||
*
|
*
|
||||||
* @param dataPointer Pointer to the data that the component owns.
|
* @param dPointer Pointer to the data that the component owns.
|
||||||
|
* @param cInit Function to call to initialize the component.
|
||||||
*/
|
*/
|
||||||
#define ecsComponentInit(dataPointer) \
|
#define ecsComponentInit(dPointer, cInit) \
|
||||||
(ecscomponent_t){ \
|
(ecscomponent_t){ \
|
||||||
.data = dataPointer, \
|
.data = dPointer, \
|
||||||
.dataSize = (sizeof(*dataPointer) / ECS_ENTITY_COUNT_MAX), \
|
.dataSize = sizeof(*dPointer), \
|
||||||
.entityFlags = {0} \
|
.entityFlags = 0, \
|
||||||
};
|
.componentFlags = 0, \
|
||||||
|
.componentInit = cInit \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the component has data for a specific entity.
|
* Checks if the component has data for a specific entity.
|
||||||
@@ -52,7 +60,7 @@ void * ecsComponentDataGet(const ecscomponent_t *cmp, const ecsid_t id);
|
|||||||
* @param cmp Pointer to the ecscomponent_t.
|
* @param cmp Pointer to the ecscomponent_t.
|
||||||
* @param id The ID of the entity to add data for.
|
* @param id The ID of the entity to add data for.
|
||||||
*/
|
*/
|
||||||
void * ecsComponentDataAdd(const ecscomponent_t *cmp, const ecsid_t id);
|
void * ecsComponentDataAdd(ecscomponent_t *cmp, const ecsid_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes data for a specific entity in the component.
|
* Removes data for a specific entity in the component.
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
#include "ecs/ecssystem.h"
|
#include "ecs/ecssystem.h"
|
||||||
#include "scene/scenetree.h"
|
#include "scene/scenetree.h"
|
||||||
|
|
||||||
|
#include "scene/test/scenetest.h"
|
||||||
|
|
||||||
engine_t ENGINE;
|
engine_t ENGINE;
|
||||||
|
|
||||||
errorret_t engineInit(void) {
|
errorret_t engineInit(void) {
|
||||||
@@ -26,6 +28,9 @@ errorret_t engineInit(void) {
|
|||||||
sceneTreeInit();
|
sceneTreeInit();
|
||||||
errorChain(displayInit());
|
errorChain(displayInit());
|
||||||
|
|
||||||
|
ecsid_t sceneTest = sceneTestAdd();
|
||||||
|
sceneTreeChildAdd(ECS_SYSTEM.root, sceneTest);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,29 +7,36 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
scenetree_t SCENE_TREE;
|
scenetreenode_t SCENE_TREE_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||||
|
ecscomponent_t SCENE_TREE_COMPONENT = ecsComponentInit(
|
||||||
|
SCENE_TREE_DATA,
|
||||||
|
sceneTreeInit
|
||||||
|
);
|
||||||
|
|
||||||
void sceneTreeInit(void) {
|
void sceneTreeInit(void) {
|
||||||
memoryZero(&SCENE_TREE, sizeof(scenetree_t));
|
|
||||||
|
|
||||||
// Default all items to have no parent
|
// Default all items to have no parent
|
||||||
for (ecsid_t i = 0; i < ECS_ENTITY_COUNT_MAX; i++) {
|
for (ecsid_t i = 0; i < ECS_ENTITY_COUNT_MAX; i++) {
|
||||||
SCENE_TREE.items[i].parent = -1;
|
SCENE_TREE_DATA[i].parent = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ecsid_t sceneTreeParentGet(const ecsid_t child) {
|
ecsid_t sceneTreeParentGet(const ecsid_t child) {
|
||||||
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
||||||
return SCENE_TREE.items[child].parent;
|
return SCENE_TREE_DATA[child].parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t sceneTreeChildGetAll(const ecsid_t id, ecsid_t *children) {
|
uint8_t sceneTreeChildGetAll(const ecsid_t id, ecsid_t *children) {
|
||||||
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
assertTrue(id >= 0 && id < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
||||||
|
|
||||||
const scenetreenode_t *node = &SCENE_TREE.items[id];
|
if(children == NULL) return SCENE_TREE_DATA[id].childCount;
|
||||||
if(children == NULL) return node->childCount;
|
|
||||||
|
|
||||||
return node->childCount;
|
memoryCopy(
|
||||||
|
children,
|
||||||
|
SCENE_TREE_DATA[id].children,
|
||||||
|
sizeof(ecsid_t) * SCENE_TREE_DATA[id].childCount
|
||||||
|
);
|
||||||
|
|
||||||
|
return SCENE_TREE_DATA[id].childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
||||||
@@ -45,7 +52,7 @@ void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
|||||||
"Child cannot be a deep child of itself."
|
"Child cannot be a deep child of itself."
|
||||||
);
|
);
|
||||||
|
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE.items[parent];
|
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
||||||
assertTrue(parentNode->childCount < SCENE_ITEM_CHILD_MAX, "Parent full.");
|
assertTrue(parentNode->childCount < SCENE_ITEM_CHILD_MAX, "Parent full.");
|
||||||
|
|
||||||
// Add child to parent's children array
|
// Add child to parent's children array
|
||||||
@@ -53,7 +60,7 @@ void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
|||||||
parentNode->childCount++;
|
parentNode->childCount++;
|
||||||
|
|
||||||
// Set child's parent
|
// Set child's parent
|
||||||
SCENE_TREE.items[child].parent = parent;
|
SCENE_TREE_DATA[child].parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceneTreeChildRemove(
|
void sceneTreeChildRemove(
|
||||||
@@ -64,8 +71,8 @@ void sceneTreeChildRemove(
|
|||||||
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
||||||
assertTrue(parent != child, "Child cannot be a child of itself.");
|
assertTrue(parent != child, "Child cannot be a child of itself.");
|
||||||
|
|
||||||
scenetreenode_t *childNode = &SCENE_TREE.items[child];
|
scenetreenode_t *childNode = &SCENE_TREE_DATA[child];
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE.items[parent];
|
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
||||||
assertTrue(childNode->parent == parent, "Child does not belong to parent");
|
assertTrue(childNode->parent == parent, "Child does not belong to parent");
|
||||||
assertTrue(parentNode->childCount > 0, "Parent has no children");
|
assertTrue(parentNode->childCount > 0, "Parent has no children");
|
||||||
|
|
||||||
@@ -88,10 +95,10 @@ void sceneTreeChildRemove(
|
|||||||
void sceneTreeChildRemoveAll(const ecsid_t parent) {
|
void sceneTreeChildRemoveAll(const ecsid_t parent) {
|
||||||
assertTrue(parent >= 0 && parent < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
assertTrue(parent >= 0 && parent < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
||||||
|
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE.items[parent];
|
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
||||||
for(uint8_t i = 0; i < parentNode->childCount; i++) {
|
for(uint8_t i = 0; i < parentNode->childCount; i++) {
|
||||||
ecsid_t child = parentNode->children[i];
|
ecsid_t child = parentNode->children[i];
|
||||||
SCENE_TREE.items[child].parent = -1;
|
SCENE_TREE_DATA[child].parent = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset child count
|
// Reset child count
|
||||||
@@ -106,11 +113,11 @@ bool_t sceneTreeChildInTree(
|
|||||||
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
||||||
assertTrue(parent != child, "Child cannot be a child of itself.");
|
assertTrue(parent != child, "Child cannot be a child of itself.");
|
||||||
|
|
||||||
scenetreenode_t *childNode = &SCENE_TREE.items[child];
|
scenetreenode_t *childNode = &SCENE_TREE_DATA[child];
|
||||||
while(childNode) {
|
while(childNode) {
|
||||||
if(childNode->parent == parent) return true;
|
if(childNode->parent == parent) return true;
|
||||||
if(childNode->parent == -1) break; // No parent means we've reached the root
|
if(childNode->parent == -1) break; // No parent means we've reached the root
|
||||||
childNode = &SCENE_TREE.items[childNode->parent];
|
childNode = &SCENE_TREE_DATA[childNode->parent];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "ecs/ecsentity.h"
|
#include "ecs/ecscomponent.h"
|
||||||
|
|
||||||
#define SCENE_ITEM_CHILD_MAX 16
|
#define SCENE_ITEM_CHILD_MAX 16
|
||||||
|
|
||||||
@@ -16,11 +16,8 @@ typedef struct {
|
|||||||
ecsid_t parent;
|
ecsid_t parent;
|
||||||
} scenetreenode_t;
|
} scenetreenode_t;
|
||||||
|
|
||||||
typedef struct scene_s {
|
extern scenetreenode_t SCENE_TREE_DATA[ECS_ENTITY_COUNT_MAX];
|
||||||
scenetreenode_t items[ECS_ENTITY_COUNT_MAX];
|
extern ecscomponent_t SCENE_TREE_COMPONENT;
|
||||||
} scenetree_t;
|
|
||||||
|
|
||||||
extern scenetree_t SCENE_TREE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the scene tree.
|
* Initialize the scene tree.
|
||||||
|
Reference in New Issue
Block a user