-
-
Notifications
You must be signed in to change notification settings - Fork 441
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f46b4e8
commit 9560ed5
Showing
9 changed files
with
353 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef DYNAMIC_BUFFER_H | ||
#define DYNAMIC_BUFFER_H | ||
|
||
/* This generated file contains includes for project dependencies */ | ||
#include "dynamic_buffer/bake_config.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif | ||
|
24 changes: 24 additions & 0 deletions
24
examples/c/53_dynamic_buffer/include/dynamic_buffer/bake_config.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
) | ||
(.) | ||
.|. | ||
| | | ||
_.--| |--._ | ||
.-'; ;`-'& ; `&. | ||
\ & ; & &_/ | ||
|"""---...---"""| | ||
\ | | | | | | | / | ||
`---.|.|.|.---' | ||
* This file is generated by bake.lang.c for your convenience. Headers of | ||
* dependencies will automatically show up in this file. Include bake_config.h | ||
* in your main project file. Do not edit! */ | ||
|
||
#ifndef DYNAMIC_BUFFER_BAKE_CONFIG_H | ||
#define DYNAMIC_BUFFER_BAKE_CONFIG_H | ||
|
||
/* Headers of public dependencies */ | ||
#include <flecs.h> | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"id": "dynamic_buffer", | ||
"type": "application", | ||
"value": { | ||
"author": "Jane Doe", | ||
"description": "A simple hello world flecs application", | ||
"public": false, | ||
"use": [ | ||
"flecs" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <dynamic_buffer.h> | ||
|
||
typedef struct { | ||
float x, y; | ||
} Position; | ||
|
||
/* Non-POD component type with a dynamic buffer */ | ||
typedef struct { | ||
int *data; | ||
size_t count; | ||
} DynamicBuffer; | ||
|
||
/* Lifecycle callbacks for the DynamicBuffer. These ensure that when a component | ||
* is created, destructed, copied or moved no memory corruption or leakage | ||
* happens. */ | ||
ECS_CTOR(DynamicBuffer, ptr, { | ||
printf("DynamicBuffer::ctor\n"); | ||
ptr->data = NULL; | ||
ptr->count = 0; | ||
}) | ||
|
||
ECS_DTOR(DynamicBuffer, ptr, { | ||
printf("DynamicBuffer::dtor\n"); | ||
free(ptr->data); | ||
}) | ||
|
||
ECS_COPY(DynamicBuffer, dst, src, { | ||
printf("DynamicBuffer::copy\n"); | ||
if (dst->data) { | ||
free(dst->data); | ||
} | ||
|
||
size_t size = sizeof(int) * src->count; | ||
dst->data = malloc(size); | ||
dst->count = src->count; | ||
memcpy(dst->data, src->data, size); | ||
}) | ||
|
||
ECS_MOVE(DynamicBuffer, dst, src, { | ||
printf("DynamicBuffer::move\n"); | ||
if (dst->data) { | ||
free(dst->data); | ||
} | ||
|
||
dst->data = src->data; | ||
dst->count = src->count; | ||
|
||
src->data = NULL; | ||
src->count = 0; | ||
}) | ||
|
||
/* Forward declare component handles */ | ||
ECS_COMPONENT_DECLARE(Position); | ||
ECS_COMPONENT_DECLARE(DynamicBuffer); | ||
|
||
/* Add an element to a new or existing buffer */ | ||
void add_elem(ecs_world_t *ecs, ecs_entity_t e, int value) { | ||
DynamicBuffer *ptr = ecs_get_mut(ecs, e, DynamicBuffer, NULL); | ||
|
||
ptr->count ++; | ||
ptr->data = realloc(ptr->data, ptr->count * sizeof(int)); | ||
ptr->data[ptr->count - 1] = value; | ||
} | ||
|
||
/* Remove element from buffer */ | ||
void remove_elem(ecs_world_t *ecs, ecs_entity_t e, size_t elem) { | ||
DynamicBuffer *ptr = ecs_get_mut(ecs, e, DynamicBuffer, NULL); | ||
|
||
size_t last = ptr->count - 1; | ||
|
||
if (last >= elem) { | ||
if (last - elem) { | ||
ptr->data[elem] = ptr->data[last]; | ||
} | ||
|
||
ptr->count --; | ||
} | ||
} | ||
|
||
/* Get element from a buffer */ | ||
int* get_elem(ecs_world_t *ecs, ecs_entity_t e, size_t elem) { | ||
const DynamicBuffer *ptr = ecs_get(ecs, e, DynamicBuffer); | ||
|
||
if (ptr && (ptr->count > elem)) { | ||
return &ptr->data[elem]; | ||
} else { | ||
return NULL; | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
ecs_world_t *ecs = ecs_init_w_args(argc, argv); | ||
|
||
/* Register ids for forward declared components */ | ||
ECS_COMPONENT_DEFINE(ecs, Position); | ||
ECS_COMPONENT_DEFINE(ecs, DynamicBuffer); | ||
|
||
/* Register lifecycle functions for comopnent */ | ||
ecs_set_component_actions(ecs, DynamicBuffer, { | ||
ecs_ctor(DynamicBuffer), | ||
ecs_dtor(DynamicBuffer), | ||
ecs_copy(DynamicBuffer), | ||
ecs_move(DynamicBuffer), | ||
NULL /* optional context */ | ||
}); | ||
|
||
ecs_entity_t e = ecs_new_id(ecs); | ||
|
||
/* Add 3 elements to the buffer. The first add will add the DynamicBuffer | ||
* element to the entity. */ | ||
add_elem(ecs, e, 10); | ||
add_elem(ecs, e, 20); | ||
add_elem(ecs, e, 30); | ||
|
||
printf("Elem 1 = %d\n", *get_elem(ecs, e, 1)); | ||
|
||
/* Remove element. This will move the last element from the buffer to the | ||
* removed element. */ | ||
remove_elem(ecs, e, 1); | ||
|
||
printf("Elem 1 = %d (after remove)\n", *get_elem(ecs, e, 1)); | ||
|
||
/* Add component. This causes the entity to move between tables, and will | ||
* invoke DynamicComponent::move to copy the component value from the src to | ||
* the dst table. This also invokes DynamicComponent::ctor to construct the | ||
* component in the dst table. */ | ||
ecs_add(ecs, e, Position); | ||
|
||
/* This will invoke DynamicComponent::dtor. */ | ||
return ecs_fini(ecs); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef DYNAMIC_BUFFER_H | ||
#define DYNAMIC_BUFFER_H | ||
|
||
/* This generated file contains includes for project dependencies */ | ||
#include "dynamic_buffer/bake_config.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif | ||
|
24 changes: 24 additions & 0 deletions
24
examples/cpp/53_dynamic_buffer/include/dynamic_buffer/bake_config.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
) | ||
(.) | ||
.|. | ||
| | | ||
_.--| |--._ | ||
.-'; ;`-'& ; `&. | ||
\ & ; & &_/ | ||
|"""---...---"""| | ||
\ | | | | | | | / | ||
`---.|.|.|.---' | ||
* This file is generated by bake.lang.c for your convenience. Headers of | ||
* dependencies will automatically show up in this file. Include bake_config.h | ||
* in your main project file. Do not edit! */ | ||
|
||
#ifndef DYNAMIC_BUFFER_BAKE_CONFIG_H | ||
#define DYNAMIC_BUFFER_BAKE_CONFIG_H | ||
|
||
/* Headers of public dependencies */ | ||
#include <flecs.h> | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"id": "dynamic_buffer", | ||
"type": "application", | ||
"value": { | ||
"author": "Jane Doe", | ||
"description": "A simple hello world flecs application", | ||
"public": false, | ||
"use": [ | ||
"flecs" | ||
], | ||
"language": "c++" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#include <dynamic_buffer.h> | ||
#include <iostream> | ||
|
||
struct Position { | ||
float x, y; | ||
}; | ||
|
||
/* Non-POD type. Don't use std::vector on purpose to demonstrate how a type | ||
* can register its own lifecycle actions. */ | ||
struct DynamicBuffer { | ||
DynamicBuffer() : data(nullptr), count(0) { | ||
std::cout << "DynamicBuffer::ctor" << std::endl; | ||
} | ||
|
||
~DynamicBuffer() { | ||
std::cout << "DynamicBuffer::dtor" << std::endl; | ||
free(data); | ||
} | ||
|
||
DynamicBuffer& operator=(const DynamicBuffer& src) { | ||
std::cout << "DynamicBuffer::copy" << std::endl; | ||
if (data) { | ||
free(data); | ||
} | ||
|
||
size_t size = sizeof(int) * src.count; | ||
data = static_cast<int*>(malloc(size)); | ||
count = src.count; | ||
memcpy(data, src.data, size); | ||
|
||
return *this; | ||
} | ||
|
||
DynamicBuffer& operator=(DynamicBuffer&& src) { | ||
std::cout << "DynamicBuffer::move" << std::endl; | ||
if (data) { | ||
free(data); | ||
} | ||
|
||
data = src.data; | ||
count = src.count; | ||
|
||
src.data = nullptr; | ||
src.count = 0; | ||
|
||
return *this; | ||
} | ||
|
||
int *data; | ||
size_t count; | ||
}; | ||
|
||
/* Add an element to a new or existing buffer */ | ||
void add_elem(flecs::entity e, int value) { | ||
DynamicBuffer *ptr = e.get_mut<DynamicBuffer>(); | ||
|
||
ptr->count ++; | ||
ptr->data = static_cast<int*>(realloc(ptr->data, ptr->count * sizeof(int))); | ||
ptr->data[ptr->count - 1] = value; | ||
} | ||
|
||
/* Remove element from buffer */ | ||
void remove_elem(flecs::entity e, size_t elem) { | ||
DynamicBuffer *ptr = e.get_mut<DynamicBuffer>(); | ||
|
||
size_t last = ptr->count - 1; | ||
|
||
if (last >= elem) { | ||
if (last - elem) { | ||
ptr->data[elem] = ptr->data[last]; | ||
} | ||
|
||
ptr->count --; | ||
} | ||
} | ||
|
||
/* Get element from a buffer */ | ||
int* get_elem(flecs::entity e, size_t elem) { | ||
const DynamicBuffer *ptr = e.get<DynamicBuffer>(); | ||
|
||
if (ptr && (ptr->count > elem)) { | ||
return &ptr->data[elem]; | ||
} else { | ||
return NULL; | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
flecs::world ecs(argc, argv); | ||
|
||
auto e = ecs.entity(); | ||
|
||
/* Add 3 elements to the buffer. The first add will add the DynamicBuffer | ||
* element to the entity. */ | ||
add_elem(e, 10); | ||
add_elem(e, 20); | ||
add_elem(e, 30); | ||
|
||
std::cout << "Elem 1 = " << *get_elem(e, 1) << std::endl; | ||
|
||
/* Remove element. This will move the last element from the buffer to the | ||
* removed element. */ | ||
remove_elem(e, 1); | ||
|
||
std::cout << "Elem 1 = " << *get_elem(e, 1) << " (after remove)" << std::endl; | ||
|
||
/* Add component. This causes the entity to move between tables, and will | ||
* invoke DynamicComponent::move to copy the component value from the src to | ||
* the dst table. This also invokes DynamicComponent::ctor to construct the | ||
* component in the dst table. */ | ||
e.add<Position>(); | ||
|
||
/* World gets cleaned up, which invokes DynamicComponent::dtor. */ | ||
} |