update flecs to 2.3.2
parent
5d9f44f2b0
commit
3dc99c9198
|
@ -151,7 +151,7 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1
|
|||
|
||||
ECS_IMPORT(world.ecs, General);
|
||||
ECS_IMPORT(world.ecs, Net);
|
||||
world.ecs_update = ecs_query_new(world.ecs, "Net.ClientInfo, general.Position");
|
||||
world.ecs_update = ecs_query_new(world.ecs, "net.ClientInfo, general.Position");
|
||||
|
||||
int32_t world_build_status = world_gen();
|
||||
ZPL_ASSERT(world_build_status >= 0);
|
||||
|
@ -218,7 +218,7 @@ static void world_tracker_update(uint8_t ticker, uint32_t freq, uint8_t radius)
|
|||
|
||||
|
||||
int32_t world_update() {
|
||||
ecs_progress(world.ecs, platform_frametime());
|
||||
ecs_progress(world.ecs, 0.0f);
|
||||
|
||||
world_tracker_update(0, WORLD_TRACKER_UPDATE_FAST_MS, 2);
|
||||
world_tracker_update(1, WORLD_TRACKER_UPDATE_NORMAL_MS, 4);
|
||||
|
|
|
@ -100,7 +100,6 @@ void flecs_dash_init() {
|
|||
ECS_IMPORT(world_ecs(), FlecsSystemsCivetweb);
|
||||
|
||||
ecs_set(world_ecs(), 0, EcsDashServer, {.port = 27001});
|
||||
// ecs_set_target_fps(world_ecs(), 60);
|
||||
}
|
||||
|
||||
void game_init(int8_t play_mode, uint32_t num_viewers, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
|
||||
|
@ -119,6 +118,7 @@ void game_init(int8_t play_mode, uint32_t num_viewers, int32_t seed, uint16_t bl
|
|||
world_setup_pkt_handlers(pkt_reader, sp_pkt_writer);
|
||||
world_init(seed, block_size, chunk_size, chunk_amount);
|
||||
if (is_dash_enabled) flecs_dash_init();
|
||||
ecs_set_target_fps(world_ecs(), 60);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < num_viewers; i++) {
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
flecs
|
||||
CHANGELOG
|
||||
=======================================================================
|
||||
|
||||
RELEASE NOTES: https://github.com/SanderMertens/flecs/releases
|
||||
REPO: https://github.com/SanderMertens/flecs/commits/master
|
||||
COMMUNITY: https://discord.gg/MRSAZqb
|
||||
DOCS: https://flecs.docsforge.com/
|
||||
FAQ: https://github.com/SanderMertens/flecs/blob/master/docs/FAQ.md
|
||||
QUICKSTART: https://github.com/SanderMertens/flecs/blob/master/docs/Quickstart.md
|
||||
MANUAL: https://github.com/SanderMertens/flecs/blob/master/docs/Manual.md
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 2.3.2 (Released 2021-02-23)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
## Improvements
|
||||
- replace iostream with initializer_list (C++ API, thanks @ikrima!)
|
||||
- ensure entity::m_id is initialized to 0 (C++ API, thanks @ikrima!)
|
||||
- use ecs_os_malloc instead of new (C++ API, thanks @ikrima!)
|
||||
- remove superfluous copies of lambda functions (C++ API, thanks @ikrima!)
|
||||
- add CHANGELOG (thanks @ikrima!)
|
||||
|
||||
## Bugfixes
|
||||
- fix matching for queries with shared componnents when base entity is deleted
|
||||
- fix various issues with component registration in C++
|
||||
- fix issue with setting target FPS on Apple M1 (thanks @prime31!)
|
||||
- fix issues with CMake file (thanks @Spacelm!)
|
||||
- fix crash when creating & deleting queries
|
||||
- guarantee that id returned by new_component_id is unused
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 2.3.1 (Released 2021-02-02)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
## Improvements
|
||||
- Improved lerp example
|
||||
- Added OS API example C++ (thanks @mcmlevi!)
|
||||
- Upgraded cmake buildfiles (thanks @rawbby!)
|
||||
- Clarified text in README describing API/ABI stability
|
||||
|
||||
## Bugfixes
|
||||
- Fix crash when using overlapping UnSet systems
|
||||
- Fix issue with passing incorrect row to UnSet systems
|
||||
- Added .hpp files to cmake install
|
||||
- Fixed issue with using get_mut with traits
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 2.3.0 (Released 2021-01-17)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
## Highlights
|
||||
- Big performance improvements & reduced memory usage for applications with lots of tables, such as when using hierarchies
|
||||
- Component enabling/disabling allows for quick component mutations without moving entities between archetypes
|
||||
- New statistics addon for retrieving metrics from running world (replaces stats module)
|
||||
|
||||
Thanks to @randy408, @sh-dave, @kevinresol, @jasonliang-dev and @Alexandre-P-J for submitting PRs! 🎉
|
||||
|
||||
Thanks to @ikrima and @jtferson for writing two awesome testimonials on using Flecs with Unreal Engine 4 🙏 :
|
||||
- https://bebylon.dev/blog/ecs-flecs-ue4/
|
||||
- https://jtferson.github.io/blog/flecs_and_unreal/
|
||||
|
||||
Thanks to the new Flecs sponsors ❤️ :
|
||||
- @Zifkan
|
||||
- @TFlippy
|
||||
- @Hexlord
|
||||
|
||||
## Breaking changes
|
||||
- calling ecs_get for a tag will no longer return NULL, but will assert
|
||||
- statistics module is removed in favor of easier to use statistics addon
|
||||
- unused table_offset member is removed from iterator
|
||||
|
||||
## Deprecated features
|
||||
- ecs_entity() macro is now deprecated, use ecs_typeid()
|
||||
|
||||
## Features
|
||||
- Direct access addon, which provides fast access to underlying storage
|
||||
- Added singleton API to C++ world class
|
||||
- Added orphaning for subqueries, which allows an application to check if a parent query still exists
|
||||
- Added ecs_get_typeid function to get the component id for traits
|
||||
- The type used for time keeping is now customizable
|
||||
- New statistics addon for retrieving metrics from running world
|
||||
- Added get_parent function that accepts entity/tag
|
||||
- Added component enabling/disabling
|
||||
- Added support for sorting on shared components
|
||||
|
||||
## Improvements
|
||||
- Improved ecs_delete performance (reduced entity index accesses from 2 to 1)
|
||||
- C & C++ code compiles warning-free with more warning flags, for more compiler versions & more platforms
|
||||
- Improved error messages when application passes invalid entity id
|
||||
- Made include paths relative so source code is easier to integrate with bazel
|
||||
- Fixed typos in documentation
|
||||
- Improve error message when trying to add 0 as base entity (using ECS_INSTANCEOF)
|
||||
- Add check for conflicting source modifier in OR expressions
|
||||
- Extended documentation, added new examples and fixed typos
|
||||
- Removed dead/redundant code
|
||||
- Improved performance of ecs_get
|
||||
- Add sanitizer & custom builds to CI, remove Travis CI builds
|
||||
- Don't add Name component when provided name for entity is NULL
|
||||
- Allow flecs::system instances to be (re)created from entity id
|
||||
- Added godbolt "try online" badge to README
|
||||
- Improve allocation strategy of vector datastructure
|
||||
- Improved performance for checking if entity id is a number
|
||||
- Added missing query functions to C++ API for sorting
|
||||
- Improved performance of table creation by two orders of magnitude
|
||||
- Reduced memory footprint of table graph by a factor 60
|
||||
- Added example to demonstrate world merging with direct access API
|
||||
- Added more inline documentation for datastructures
|
||||
- Added assert when trying to instantiate child as instance
|
||||
- Improve errors when invalid operation is invoked on iterator
|
||||
- Throw assert when invoking ecs_modified on entity that does not have the component
|
||||
- Allow for type lookups in systems, as long as the type already exists
|
||||
- Add return types to ecs_defer_begin and ecs_defer_end to obtain defer status of world
|
||||
- Remove redundant table_offset member from ecs_iter_t
|
||||
- Improved portability of POSIX OS API example
|
||||
|
||||
## Bugfixes
|
||||
- Fixed issues with subqueries and query rematching
|
||||
- Corrected wrong return type of ecs_column_size (was ecs_entity_t, is now size_t)
|
||||
- Add missing \0 when appending to application buffer with strbuf datastructure
|
||||
- Fixed crash when instantiating an empty prefab
|
||||
- Fixed issue with shared tags and queries using each() in the C++ API
|
||||
- Fixed issue with instantiating empty child table
|
||||
- Fixed issue with ecs_bulk_new and traits
|
||||
- Fixed issue when using ecs_entity_str with small buffers
|
||||
- Fixed bug when adding trait to entity with switch
|
||||
- Fixed name conflicts in amalgamated source
|
||||
- Fixed path lookup in ecs_import
|
||||
- Fixed EXPORT macro's in OS API examples
|
||||
- Fixed issue with restoring worlds that have recycled ids
|
||||
- Added missing EXPORT macro's to API functions
|
||||
- Fixed assert after deleting entities from restored world
|
||||
- Removed obsolete assert from ecs_modified
|
||||
- Added missing statement to finalize system in C++
|
||||
- Fixed issues with removing case values
|
||||
- Fixed issues in C++ API with implicit component registration
|
||||
- Fixed assert when removing from switch list
|
||||
- Fixed bug where obtaining type from entity would generate a new entity id
|
||||
- Fixed incorrect description of ecs_delete in manual
|
||||
- Fixed issues with custom builds
|
|
@ -646,6 +646,7 @@ struct ecs_world_t {
|
|||
bool quit_workers; /* Signals worker threads to quit */
|
||||
bool in_progress; /* Is world being progressed */
|
||||
bool is_merging; /* Is world currently being merged */
|
||||
bool is_fini; /* Is the world being cleaned up? */
|
||||
bool auto_merge; /* Are stages auto-merged by ecs_progress */
|
||||
bool measure_frame_time; /* Time spent on each frame */
|
||||
bool measure_system_time; /* Time spent by each system */
|
||||
|
@ -678,7 +679,7 @@ ecs_type_t ecs_bootstrap_type(
|
|||
ecs_new_component(world, ecs_typeid(name), #name, sizeof(name), ECS_ALIGNOF(name))
|
||||
|
||||
#define ecs_bootstrap_tag(world, name)\
|
||||
ecs_set(world, name, EcsName, {.value = &#name[ecs_os_strlen("Ecs")], .symbol = #name});\
|
||||
ecs_set(world, name, EcsName, {.value = &#name[ecs_os_strlen("Ecs")], .symbol = (char*)#name});\
|
||||
ecs_add_entity(world, name, ECS_CHILDOF | ecs_get_scope(world))
|
||||
|
||||
|
||||
|
@ -998,6 +999,7 @@ void ecs_table_clear_silent(
|
|||
|
||||
/* Clear table data. Don't call OnRemove handlers. */
|
||||
void ecs_table_clear_data(
|
||||
ecs_world_t *world,
|
||||
ecs_table_t *table,
|
||||
ecs_data_t *data);
|
||||
|
||||
|
@ -2102,6 +2104,7 @@ void register_un_set(
|
|||
int32_t matched_table_index)
|
||||
{
|
||||
(void)world;
|
||||
table->flags |= EcsTableHasUnSet;
|
||||
add_monitor(&table->un_set_all, query, matched_table_index);
|
||||
}
|
||||
|
||||
|
@ -2273,6 +2276,10 @@ void dtor_component(
|
|||
int32_t row,
|
||||
int32_t count)
|
||||
{
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* An old component is destructed */
|
||||
ecs_xtor_t dtor;
|
||||
if (cdata && (dtor = cdata->lifecycle.dtor)) {
|
||||
|
@ -2311,28 +2318,26 @@ static
|
|||
void run_remove_actions(
|
||||
ecs_world_t * world,
|
||||
ecs_table_t * table,
|
||||
ecs_data_t * data,
|
||||
int32_t row,
|
||||
int32_t count,
|
||||
bool dtor_only)
|
||||
int32_t count)
|
||||
{
|
||||
if (count) {
|
||||
if (!dtor_only) {
|
||||
ecs_run_monitors(world, table, NULL, row, count, table->un_set_all);
|
||||
}
|
||||
|
||||
dtor_all_components(world, table, data, row, count);
|
||||
}
|
||||
}
|
||||
|
||||
void ecs_table_clear_data(
|
||||
ecs_table_t * table,
|
||||
ecs_data_t * data)
|
||||
ecs_world_t *world,
|
||||
ecs_table_t *table,
|
||||
ecs_data_t *data)
|
||||
{
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t count = ecs_table_data_count(data);
|
||||
dtor_all_components(world, table, data, 0, count);
|
||||
|
||||
ecs_column_t *columns = data->columns;
|
||||
if (columns) {
|
||||
int32_t c, column_count = table->column_count;
|
||||
|
@ -2384,7 +2389,7 @@ void ecs_table_clear_silent(
|
|||
|
||||
int32_t count = ecs_vector_count(data->entities);
|
||||
|
||||
ecs_table_clear_data(table, table->data);
|
||||
ecs_table_clear_data(world, table, data);
|
||||
|
||||
if (count) {
|
||||
ecs_table_activate(world, table, 0, false);
|
||||
|
@ -2399,18 +2404,18 @@ void ecs_table_clear(
|
|||
ecs_table_t * table)
|
||||
{
|
||||
ecs_data_t *data = ecs_table_get_data(table);
|
||||
|
||||
if (data) {
|
||||
run_remove_actions(
|
||||
world, table, data, 0, ecs_table_data_count(data), false);
|
||||
run_remove_actions(world, table, 0, ecs_table_data_count(data));
|
||||
|
||||
ecs_entity_t *entities = ecs_vector_first(data->entities, ecs_entity_t);
|
||||
int32_t i, count = ecs_vector_count(data->entities);
|
||||
for(i = 0; i < count; i ++) {
|
||||
ecs_eis_delete(world, entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ecs_table_clear_silent(world, table);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unset all components in table. This function is called before a table is
|
||||
|
@ -2435,11 +2440,10 @@ void ecs_table_free(
|
|||
(void)world;
|
||||
ecs_data_t *data = ecs_table_get_data(table);
|
||||
if (data) {
|
||||
run_remove_actions(
|
||||
world, table, data, 0, ecs_table_data_count(data), false);
|
||||
run_remove_actions(world, table, 0, ecs_table_data_count(data));
|
||||
ecs_table_clear_data(world, table, data);
|
||||
}
|
||||
|
||||
ecs_table_clear_data(table, table->data);
|
||||
ecs_table_clear_edges(world, table);
|
||||
|
||||
ecs_os_free(table->lo_edges);
|
||||
|
@ -3430,8 +3434,8 @@ void ecs_table_swap(
|
|||
|
||||
static
|
||||
void merge_vector(
|
||||
ecs_vector_t ** dst_out,
|
||||
ecs_vector_t * src,
|
||||
ecs_vector_t **dst_out,
|
||||
ecs_vector_t *src,
|
||||
int16_t size,
|
||||
int16_t alignment)
|
||||
{
|
||||
|
@ -3463,6 +3467,61 @@ void merge_vector(
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
void merge_column(
|
||||
ecs_world_t *world,
|
||||
ecs_table_t *table,
|
||||
ecs_data_t *data,
|
||||
int32_t column_id,
|
||||
ecs_vector_t *src)
|
||||
{
|
||||
ecs_entity_t *entities = ecs_vector_first(data->entities, ecs_entity_t);
|
||||
ecs_c_info_t *c_info = table->c_info[column_id];
|
||||
ecs_column_t *column = &data->columns[column_id];
|
||||
ecs_vector_t *dst = column->data;
|
||||
int16_t size = column->size;
|
||||
int16_t alignment = column->alignment;
|
||||
int32_t dst_count = ecs_vector_count(dst);
|
||||
|
||||
if (!dst_count) {
|
||||
if (dst) {
|
||||
ecs_vector_free(dst);
|
||||
}
|
||||
|
||||
column->data = src;
|
||||
|
||||
/* If the new table is not empty, copy the contents from the
|
||||
* src into the dst. */
|
||||
} else {
|
||||
int32_t src_count = ecs_vector_count(src);
|
||||
ecs_vector_set_count_t(&dst, size, alignment, dst_count + src_count);
|
||||
column->data = dst;
|
||||
|
||||
/* Construct new values */
|
||||
if (c_info) {
|
||||
ctor_component(
|
||||
world, c_info, column, entities, dst_count, src_count);
|
||||
}
|
||||
|
||||
void *dst_ptr = ecs_vector_first_t(dst, size, alignment);
|
||||
void *src_ptr = ecs_vector_first_t(src, size, alignment);
|
||||
|
||||
dst_ptr = ECS_OFFSET(dst_ptr, size * dst_count);
|
||||
|
||||
/* Move values into column */
|
||||
ecs_move_t move;
|
||||
if (c_info && (move = c_info->lifecycle.move)) {
|
||||
move(world, c_info->component, entities, entities,
|
||||
dst_ptr, src_ptr, ecs_to_size_t(size), src_count,
|
||||
c_info->lifecycle.ctx);
|
||||
} else {
|
||||
ecs_os_memcpy(dst_ptr, src_ptr, size * src_count);
|
||||
}
|
||||
|
||||
ecs_vector_free(src);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void merge_table_data(
|
||||
ecs_world_t * world,
|
||||
|
@ -3517,10 +3576,8 @@ void merge_table_data(
|
|||
}
|
||||
|
||||
if (new_component == old_component) {
|
||||
merge_vector(
|
||||
&new_columns[i_new].data, old_columns[i_old].data, size,
|
||||
alignment);
|
||||
|
||||
merge_column(world, new_table, new_data, i_new,
|
||||
old_columns[i_old].data);
|
||||
old_columns[i_old].data = NULL;
|
||||
|
||||
/* Mark component column as dirty */
|
||||
|
@ -3643,7 +3700,7 @@ ecs_data_t* ecs_table_merge(
|
|||
|
||||
/* If there is nothing to merge to, just clear the old table */
|
||||
if (!new_table) {
|
||||
ecs_table_clear_data(old_table, old_data);
|
||||
ecs_table_clear_data(world, old_table, old_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -3711,9 +3768,8 @@ void ecs_table_replace_data(
|
|||
|
||||
if (table_data) {
|
||||
prev_count = ecs_vector_count(table_data->entities);
|
||||
run_remove_actions(
|
||||
world, table, table_data, 0, ecs_table_data_count(table_data), false);
|
||||
ecs_table_clear_data(table, table_data);
|
||||
run_remove_actions(world, table, 0, ecs_table_data_count(table_data));
|
||||
ecs_table_clear_data(world, table, table_data);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
|
@ -3801,6 +3857,10 @@ void ecs_table_notify(
|
|||
ecs_table_t * table,
|
||||
ecs_table_event_t * event)
|
||||
{
|
||||
if (world->is_fini) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(event->kind) {
|
||||
case EcsTableQueryMatch:
|
||||
register_query(
|
||||
|
@ -4211,7 +4271,6 @@ void ecs_run_monitors(
|
|||
}
|
||||
|
||||
ecs_assert(!(dst_table->flags & EcsTableIsPrefab), ECS_INTERNAL_ERROR, NULL);
|
||||
(void)dst_table;
|
||||
|
||||
if (!v_src_monitors) {
|
||||
ecs_vector_each(v_dst_monitors, ecs_matched_query_t, monitor, {
|
||||
|
@ -4241,7 +4300,7 @@ void ecs_run_monitors(
|
|||
}
|
||||
}
|
||||
|
||||
if (src->query->system == system) {
|
||||
if (src && src->query->system == system) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4830,7 +4889,7 @@ int32_t move_entity(
|
|||
/* If entity was moved, invoke UnSet monitors for each component that
|
||||
* the entity no longer has */
|
||||
ecs_run_monitors(world, dst_table, src_table->un_set_all,
|
||||
dst_row, 1, dst_table->un_set_all);
|
||||
src_row, 1, dst_table->un_set_all);
|
||||
|
||||
ecs_run_remove_actions(
|
||||
world, src_table, src_data, src_row, 1, removed, false);
|
||||
|
@ -5474,12 +5533,20 @@ ecs_entity_t ecs_new_component_id(
|
|||
ECS_INVALID_WHILE_ITERATING, NULL);
|
||||
}
|
||||
|
||||
ecs_entity_t id;
|
||||
|
||||
if (world->stats.last_component_id < ECS_HI_COMPONENT_ID) {
|
||||
do {
|
||||
id = world->stats.last_component_id ++;
|
||||
} while (ecs_exists(world, id) && id < ECS_HI_COMPONENT_ID);
|
||||
}
|
||||
|
||||
if (world->stats.last_component_id >= ECS_HI_COMPONENT_ID) {
|
||||
/* If the low component ids are depleted, return a regular entity id */
|
||||
return ecs_new_id(world);
|
||||
} else {
|
||||
return world->stats.last_component_id ++;
|
||||
id = ecs_new_id(world);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
ecs_entity_t ecs_new_w_type(
|
||||
|
@ -5678,10 +5745,15 @@ void ecs_delete(
|
|||
ecs_record_t *r = ecs_sparse_remove_get(
|
||||
world->store.entity_index, ecs_record_t, entity);
|
||||
if (r) {
|
||||
ecs_entity_info_t info;
|
||||
ecs_entity_info_t info = {0};
|
||||
set_info_from_record(entity, &info, r);
|
||||
if (info.is_watched) {
|
||||
ecs_delete_children(world, entity);
|
||||
|
||||
if (r->table) {
|
||||
ecs_entities_t to_remove = ecs_type_to_entities(r->table->type);
|
||||
update_component_monitors(world, entity, NULL, &to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
/* If entity has components, remove them */
|
||||
|
@ -6469,7 +6541,7 @@ void flush_bulk_new(
|
|||
int c, c_count = op->components.count;
|
||||
for (c = 0; c < c_count; c ++) {
|
||||
ecs_entity_t component = components[c];
|
||||
const EcsComponent *cptr = ecs_get(world, component, EcsComponent);
|
||||
const EcsComponent *cptr = ecs_component_from_id(world, component);
|
||||
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
|
||||
size_t size = ecs_to_size_t(cptr->size);
|
||||
void *ptr, *data = bulk_data[c];
|
||||
|
@ -6844,7 +6916,7 @@ bool ecs_defer_bulk_new(
|
|||
defer_data = ecs_os_malloc(ECS_SIZEOF(void*) * c_count);
|
||||
for (c = 0; c < c_count; c ++) {
|
||||
ecs_entity_t comp = components[c];
|
||||
const EcsComponent *cptr = ecs_get(world, comp, EcsComponent);
|
||||
const EcsComponent *cptr = ecs_component_from_id(world, comp);
|
||||
ecs_assert(cptr != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
ecs_size_t size = cptr->size;
|
||||
|
@ -6931,7 +7003,7 @@ bool ecs_defer_set(
|
|||
if (stage->defer) {
|
||||
world->set_count ++;
|
||||
if (!size) {
|
||||
const EcsComponent *cptr = ecs_get(world, component, EcsComponent);
|
||||
const EcsComponent *cptr = ecs_component_from_id(world, component);
|
||||
ecs_assert(cptr != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
size = cptr->size;
|
||||
}
|
||||
|
@ -8873,9 +8945,11 @@ ecs_entity_t ecs_new_module(
|
|||
e = ecs_new_from_fullpath(world, module_path);
|
||||
|
||||
EcsName *name_ptr = ecs_get_mut(world, e, EcsName, NULL);
|
||||
name_ptr->symbol = name;
|
||||
ecs_os_free(name_ptr->symbol);
|
||||
|
||||
ecs_os_free(module_path);
|
||||
/* Assign full path to symbol. This allows for modules to be redefined
|
||||
* in C++ without causing name conflicts */
|
||||
name_ptr->symbol = module_path;
|
||||
}
|
||||
|
||||
ecs_entity_t result = ecs_new_component(world, e, NULL, size, alignment);
|
||||
|
@ -9219,7 +9293,12 @@ void ecs_get_world_stats(
|
|||
record_counter(&s->pipeline_build_count_total, t, world->stats.pipeline_build_count_total);
|
||||
record_counter(&s->systems_ran_frame, t, world->stats.systems_ran_frame);
|
||||
|
||||
record_gauge(&s->fps, t, 1.0f / (delta_world_time / (float)delta_frame_count));
|
||||
if (delta_world_time != 0.0 && delta_frame_count != 0.0) {
|
||||
record_gauge(
|
||||
&s->fps, t, 1.0f / (delta_world_time / (float)delta_frame_count));
|
||||
} else {
|
||||
record_gauge(&s->fps, t, 0);
|
||||
}
|
||||
|
||||
record_gauge(&s->entity_count, t, ecs_sparse_count(world->store.entity_index));
|
||||
record_gauge(&s->component_count, t, ecs_count_entity(world, ecs_typeid(EcsComponent)));
|
||||
|
@ -9630,6 +9709,7 @@ void ecs_snapshot_restore(
|
|||
|
||||
for (t = 0; t < table_count; t ++) {
|
||||
ecs_table_t *table = ecs_sparse_get(world->store.tables, ecs_table_t, t);
|
||||
|
||||
if (table->flags & EcsTableHasBuiltins) {
|
||||
continue;
|
||||
}
|
||||
|
@ -9659,7 +9739,7 @@ void ecs_snapshot_restore(
|
|||
|
||||
/* Always delete entity, so that even if the entity is
|
||||
* in the current table, there won't be duplicates */
|
||||
ecs_table_delete(world, r->table, data, row, false);
|
||||
ecs_table_delete(world, r->table, data, row, true);
|
||||
} else {
|
||||
ecs_eis_set_generation(world, *e_ptr);
|
||||
}
|
||||
|
@ -9785,7 +9865,7 @@ void ecs_snapshot_free(
|
|||
int32_t i, count = ecs_vector_count(snapshot->tables);
|
||||
for (i = 0; i < count; i ++) {
|
||||
ecs_table_leaf_t *leaf = &tables[i];
|
||||
ecs_table_clear_data(leaf->table, leaf->data);
|
||||
ecs_table_clear_data(snapshot->world, leaf->table, leaf->data);
|
||||
ecs_os_free(leaf->data);
|
||||
}
|
||||
|
||||
|
@ -11233,6 +11313,7 @@ ecs_world_t *ecs_mini(void) {
|
|||
world->quit_workers = false;
|
||||
world->in_progress = false;
|
||||
world->is_merging = false;
|
||||
world->is_fini = false;
|
||||
world->auto_merge = true;
|
||||
world->measure_frame_time = false;
|
||||
world->measure_system_time = false;
|
||||
|
@ -11581,9 +11662,12 @@ void fini_misc(
|
|||
int ecs_fini(
|
||||
ecs_world_t *world)
|
||||
{
|
||||
assert(world->magic == ECS_WORLD_MAGIC);
|
||||
assert(!world->in_progress);
|
||||
assert(!world->is_merging);
|
||||
ecs_assert(world->magic == ECS_WORLD_MAGIC, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(!world->in_progress, ECS_INVALID_OPERATION, NULL);
|
||||
ecs_assert(!world->is_merging, ECS_INVALID_OPERATION, NULL);
|
||||
ecs_assert(!world->is_fini, ECS_INVALID_OPERATION, NULL);
|
||||
|
||||
world->is_fini = true;
|
||||
|
||||
fini_unset_tables(world);
|
||||
|
||||
|
@ -17249,10 +17333,22 @@ void ecs_query_free(
|
|||
});
|
||||
|
||||
ecs_vector_each(query->empty_tables, ecs_matched_table_t, table, {
|
||||
if (!(query->flags & EcsQueryIsSubquery)) {
|
||||
ecs_table_notify(world, table->iter_data.table, &(ecs_table_event_t){
|
||||
.kind = EcsTableQueryUnmatch,
|
||||
.query = query
|
||||
});
|
||||
}
|
||||
free_matched_table(table);
|
||||
});
|
||||
|
||||
ecs_vector_each(query->tables, ecs_matched_table_t, table, {
|
||||
if (!(query->flags & EcsQueryIsSubquery)) {
|
||||
ecs_table_notify(world, table->iter_data.table, &(ecs_table_event_t){
|
||||
.kind = EcsTableQueryUnmatch,
|
||||
.query = query
|
||||
});
|
||||
}
|
||||
free_matched_table(table);
|
||||
});
|
||||
|
||||
|
@ -19887,7 +19983,7 @@ uint64_t ecs_os_time_now(void) {
|
|||
QueryPerformanceCounter(&qpc_t);
|
||||
now = (uint64_t)(qpc_t.QuadPart / _ecs_os_time_win_freq);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
now = mach_absolute_time();
|
||||
now = (uint64_t) int64_muldiv((int64_t)mach_absolute_time(), (int64_t)_ecs_os_time_osx_timebase.numer, (int64_t)_ecs_os_time_osx_timebase.denom);
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
@ -22408,10 +22504,14 @@ void ecs_set_symbol(
|
|||
|
||||
const char *e_name = ecs_name_from_symbol(world, name);
|
||||
|
||||
ecs_set(world, e, EcsName, {
|
||||
.value = e_name,
|
||||
.symbol = name
|
||||
});
|
||||
EcsName *name_ptr = ecs_get_mut(world, e, EcsName, NULL);
|
||||
name_ptr->value = e_name;
|
||||
|
||||
if (name_ptr->symbol) {
|
||||
ecs_os_free(name_ptr->symbol);
|
||||
}
|
||||
|
||||
name_ptr->symbol = ecs_os_strdup(name);
|
||||
}
|
||||
|
||||
ecs_entity_t ecs_lookup_w_id(
|
||||
|
@ -22518,6 +22618,7 @@ ecs_entity_t ecs_new_component(
|
|||
ecs_assert(world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
assert(world->magic == ECS_WORLD_MAGIC);
|
||||
bool in_progress = world->in_progress;
|
||||
bool found = false;
|
||||
|
||||
/* If world is in progress component may be registered, but only when not
|
||||
* in multithreading mode. */
|
||||
|
@ -22533,7 +22634,7 @@ ecs_entity_t ecs_new_component(
|
|||
ecs_entity_t result = ecs_lookup_w_id(world, e, name);
|
||||
if (!result) {
|
||||
result = ecs_new_component_id(world);
|
||||
ecs_set_symbol(world, result, name);
|
||||
found = true;
|
||||
}
|
||||
|
||||
/* ecs_new_component_id does not add the scope, so add it explicitly */
|
||||
|
@ -22542,6 +22643,10 @@ ecs_entity_t ecs_new_component(
|
|||
ecs_add_entity(world, result, ECS_CHILDOF | scope);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
ecs_set_symbol(world, result, name);
|
||||
}
|
||||
|
||||
bool added = false;
|
||||
EcsComponent *ptr = ecs_get_mut(world, result, EcsComponent, &added);
|
||||
|
||||
|
@ -22622,6 +22727,7 @@ static ECS_CTOR(EcsName, ptr, {
|
|||
|
||||
static ECS_DTOR(EcsName, ptr, {
|
||||
ecs_os_free(ptr->alloc_value);
|
||||
ecs_os_free(ptr->symbol);
|
||||
ptr->value = NULL;
|
||||
ptr->alloc_value = NULL;
|
||||
ptr->symbol = NULL;
|
||||
|
@ -22633,6 +22739,11 @@ static ECS_COPY(EcsName, dst, src, {
|
|||
dst->alloc_value = NULL;
|
||||
}
|
||||
|
||||
if (dst->symbol) {
|
||||
ecs_os_free(dst->symbol);
|
||||
dst->symbol = NULL;
|
||||
}
|
||||
|
||||
if (src->alloc_value) {
|
||||
dst->alloc_value = ecs_os_strdup(src->alloc_value);
|
||||
dst->value = dst->alloc_value;
|
||||
|
@ -22640,10 +22751,20 @@ static ECS_COPY(EcsName, dst, src, {
|
|||
dst->alloc_value = NULL;
|
||||
dst->value = src->value;
|
||||
}
|
||||
dst->symbol = src->symbol;
|
||||
|
||||
if (src->symbol) {
|
||||
dst->symbol = ecs_os_strdup(src->symbol);
|
||||
}
|
||||
})
|
||||
|
||||
static ECS_MOVE(EcsName, dst, src, {
|
||||
if (dst->alloc_value) {
|
||||
ecs_os_free(dst->alloc_value);
|
||||
}
|
||||
if (dst->symbol) {
|
||||
ecs_os_free(dst->symbol);
|
||||
}
|
||||
|
||||
dst->value = src->value;
|
||||
dst->alloc_value = src->alloc_value;
|
||||
dst->symbol = src->symbol;
|
||||
|
@ -22691,7 +22812,7 @@ void _bootstrap_component(
|
|||
c_info[index].size = size;
|
||||
c_info[index].alignment = alignment;
|
||||
id_data[index].value = &id[ecs_os_strlen("Ecs")]; /* Skip prefix */
|
||||
id_data[index].symbol = id;
|
||||
id_data[index].symbol = ecs_os_strdup(id);
|
||||
id_data[index].alloc_value = NULL;
|
||||
}
|
||||
|
||||
|
@ -22771,9 +22892,16 @@ void ecs_bootstrap(
|
|||
ecs_table_t *table = bootstrap_component_table(world);
|
||||
assert(table != NULL);
|
||||
|
||||
bootstrap_component(world, table, EcsName);
|
||||
bootstrap_component(world, table, EcsComponent);
|
||||
bootstrap_component(world, table, EcsType);
|
||||
bootstrap_component(world, table, EcsName);
|
||||
|
||||
ecs_set_component_actions(world, EcsName, {
|
||||
.ctor = ecs_ctor(EcsName),
|
||||
.dtor = ecs_dtor(EcsName),
|
||||
.copy = ecs_copy(EcsName),
|
||||
.move = ecs_move(EcsName)
|
||||
});
|
||||
|
||||
world->stats.last_component_id = EcsFirstUserComponentId;
|
||||
world->stats.last_id = EcsFirstUserEntityId;
|
||||
|
@ -22789,13 +22917,6 @@ void ecs_bootstrap(
|
|||
ecs_bootstrap_tag(world, EcsHidden);
|
||||
ecs_bootstrap_tag(world, EcsDisabled);
|
||||
|
||||
ecs_set_component_actions(world, EcsName, {
|
||||
.ctor = ecs_ctor(EcsName),
|
||||
.dtor = ecs_dtor(EcsName),
|
||||
.copy = ecs_copy(EcsName),
|
||||
.move = ecs_move(EcsName)
|
||||
});
|
||||
|
||||
/* Initialize scopes */
|
||||
ecs_set(world, EcsFlecs, EcsName, {.value = "flecs"});
|
||||
ecs_add_entity(world, EcsFlecs, EcsModule);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
/* FLECS_CUSTOM_BUILD should be defined when manually selecting features */
|
||||
// #define FLECS_CUSTOM_BUILD
|
||||
|
||||
/* If this is a regular, non-custom build, build all modules and addons. */
|
||||
#ifndef FLECS_CUSTOM_BUILD
|
||||
/* Modules */
|
||||
#define FLECS_SYSTEM
|
||||
|
@ -748,7 +749,7 @@ ecs_vector_t* _ecs_vector_copy(
|
|||
#ifdef __cplusplus
|
||||
#ifndef FLECS_NO_CPP
|
||||
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace flecs {
|
||||
|
||||
|
@ -1349,7 +1350,8 @@ void ecs_map_memory(
|
|||
#ifdef __cplusplus
|
||||
#ifndef FLECS_NO_CPP
|
||||
|
||||
#include <iostream>
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
|
||||
namespace flecs {
|
||||
|
||||
|
@ -1968,10 +1970,18 @@ FLECS_API
|
|||
void ecs_os_set_api_defaults(void);
|
||||
|
||||
/* Memory management */
|
||||
#define ecs_os_malloc(size) ecs_os_api.malloc_(size);
|
||||
#define ecs_os_free(ptr) ecs_os_api.free_(ptr);
|
||||
#ifndef ecs_os_malloc
|
||||
#define ecs_os_malloc(size) ecs_os_api.malloc_(size)
|
||||
#endif
|
||||
#ifndef ecs_os_free
|
||||
#define ecs_os_free(ptr) ecs_os_api.free_(ptr)
|
||||
#endif
|
||||
#ifndef ecs_os_realloc
|
||||
#define ecs_os_realloc(ptr, size) ecs_os_api.realloc_(ptr, size)
|
||||
#endif
|
||||
#ifndef ecs_os_calloc
|
||||
#define ecs_os_calloc(size) ecs_os_api.calloc_(size)
|
||||
#endif
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define ecs_os_alloca(size) _alloca((size_t)(size))
|
||||
#else
|
||||
|
@ -1979,7 +1989,9 @@ void ecs_os_set_api_defaults(void);
|
|||
#endif
|
||||
|
||||
/* Strings */
|
||||
#ifndef ecs_os_strdup
|
||||
#define ecs_os_strdup(str) ecs_os_api.strdup_(str)
|
||||
#endif
|
||||
#define ecs_os_strlen(str) (ecs_size_t)strlen(str)
|
||||
#define ecs_os_strcmp(str1, str2) strcmp(str1, str2)
|
||||
#define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, (size_t)(num))
|
||||
|
@ -3003,7 +3015,7 @@ int32_t ecs_type_trait_index_of(
|
|||
/** Entity name. */
|
||||
typedef struct EcsName {
|
||||
const char *value; /**< Entity name */
|
||||
const char *symbol; /**< Optional symbol name, if it differs from name */
|
||||
char *symbol; /**< Optional symbol name, if it differs from name */
|
||||
char *alloc_value; /**< If set, value will be freed on destruction */
|
||||
} EcsName;
|
||||
|
||||
|
@ -7805,6 +7817,38 @@ FLECS_API void ecs_gauge_reduce(
|
|||
#include <sstream>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
// Macros so that C++ new calls can allocate using ecs_os_api memory allocation functions
|
||||
// Rationale:
|
||||
// - Using macros here instead of a templated function bc clients might override ecs_os_malloc
|
||||
// to contain extra debug info like source tracking location. Using a template function
|
||||
// in that scenario would collapse all source location into said function vs. the
|
||||
// actual call site
|
||||
// - FLECS_PLACEMENT_NEW(): exists to remove any naked new calls/make it easy to identify any regressions
|
||||
// by grepping for new/delete
|
||||
#define FLECS_PLACEMENT_NEW(_ptr, _type) ::new(flecs::_::placement_new_tag, _ptr) _type
|
||||
#define FLECS_NEW(_type) FLECS_PLACEMENT_NEW(ecs_os_malloc(sizeof(_type)), _type)
|
||||
#define FLECS_DELETE(_ptr) \
|
||||
do { \
|
||||
if (_ptr) { \
|
||||
flecs::_::destruct_obj(_ptr); \
|
||||
ecs_os_free(_ptr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
namespace flecs {
|
||||
namespace _
|
||||
{
|
||||
// Dummy Placement new tag to disambiguate from any other operator new overrides
|
||||
struct placement_new_tag_t{};
|
||||
constexpr placement_new_tag_t placement_new_tag{};
|
||||
template<class Ty> inline void destruct_obj(Ty* _ptr) { _ptr->~Ty(); }
|
||||
}
|
||||
}
|
||||
|
||||
inline void* operator new(size_t, flecs::_::placement_new_tag_t, void* _ptr) noexcept { return _ptr; }
|
||||
inline void operator delete(void*, flecs::_::placement_new_tag_t, void*) noexcept { }
|
||||
|
||||
namespace flecs {
|
||||
|
||||
|
@ -9470,7 +9514,7 @@ public:
|
|||
base_type& disable() const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[](world_t *world, entity_t id) {
|
||||
ecs_enable(world, id, true);
|
||||
ecs_enable(world, id, false);
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
}
|
||||
|
@ -9556,10 +9600,13 @@ public:
|
|||
const base_type& set(T&& value) const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[&value](world_t *world, entity_t id) {
|
||||
auto comp_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
ecs_set_ptr_w_entity(
|
||||
world, id, _::component_info<T>::id(world), sizeof(T), &value);
|
||||
world, id, comp_id, sizeof(T), &value);
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
}
|
||||
|
@ -9575,10 +9622,13 @@ public:
|
|||
const base_type& set(const T& value) const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[&value](world_t *world, entity_t id) {
|
||||
auto comp_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
ecs_set_ptr_w_entity(
|
||||
world, id, _::component_info<T>::id(world), sizeof(T), &value);
|
||||
world, id, comp_id, sizeof(T), &value);
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
}
|
||||
|
@ -9595,11 +9645,13 @@ public:
|
|||
const base_type& set_trait(const T& value) const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[&value](world_t *world, entity_t id) {
|
||||
auto t_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
ecs_set_ptr_w_entity(world, id,
|
||||
ecs_trait(_::component_info<C>::id(world),
|
||||
_::component_info<T>::id(world)),
|
||||
ecs_trait(_::component_info<C>::id(world), t_id),
|
||||
sizeof(T), &value);
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
|
@ -9642,15 +9694,17 @@ public:
|
|||
const base_type& patch(std::function<void(T&, bool)> func) const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[&func](world_t *world, entity_t id) {
|
||||
auto comp_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
bool is_added;
|
||||
T *ptr = static_cast<T*>(ecs_get_mut_w_entity(
|
||||
world, id, _::component_info<T>::id(world), &is_added));
|
||||
world, id, comp_id, &is_added));
|
||||
if (ptr) {
|
||||
func(*ptr, !is_added);
|
||||
ecs_modified_w_entity(world, id, _::component_info<T>::id(world));
|
||||
ecs_modified_w_entity(world, id, comp_id);
|
||||
}
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
|
@ -9668,15 +9722,17 @@ public:
|
|||
const base_type& patch(std::function<void(T&)> func) const {
|
||||
static_cast<base_type*>(this)->invoke(
|
||||
[&func](world_t *world, entity_t id) {
|
||||
auto comp_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
bool is_added;
|
||||
T *ptr = static_cast<T*>(ecs_get_mut_w_entity(
|
||||
world, id, _::component_info<T>::id(world), &is_added));
|
||||
world, id, comp_id, &is_added));
|
||||
if (ptr) {
|
||||
func(*ptr);
|
||||
ecs_modified_w_entity(world, id, _::component_info<T>::id(world));
|
||||
ecs_modified_w_entity(world, id, comp_id);
|
||||
}
|
||||
});
|
||||
return *static_cast<base_type*>(this);
|
||||
|
@ -9702,11 +9758,13 @@ public:
|
|||
, m_entity( entity )
|
||||
, m_ref()
|
||||
{
|
||||
auto comp_id = _::component_info<T>::id(world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
ecs_get_ref_w_entity(
|
||||
m_world, &m_ref, m_entity, _::component_info<T>::id(world));
|
||||
m_world, &m_ref, m_entity, comp_id);
|
||||
}
|
||||
|
||||
const T* operator->() {
|
||||
|
@ -9763,11 +9821,7 @@ public:
|
|||
*/
|
||||
explicit entity(world_t *world)
|
||||
: m_world( world )
|
||||
{
|
||||
if (m_world) {
|
||||
m_id = ecs_new_w_type(m_world, 0);
|
||||
}
|
||||
}
|
||||
, m_id( world ? ecs_new_w_type(world, 0) : 0 ) { }
|
||||
|
||||
/** Create a named entity.
|
||||
* Named entities can be looked up with the lookup functions. Entity names
|
||||
|
@ -9998,10 +10052,14 @@ public:
|
|||
const T* get() const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<const T*>(
|
||||
ecs_get_w_entity(m_world, m_id, _::component_info<T>::id(m_world)));
|
||||
ecs_get_w_entity(m_world, m_id, comp_id));
|
||||
}
|
||||
|
||||
/** Get component value (untyped).
|
||||
|
@ -10042,11 +10100,14 @@ public:
|
|||
T* get_mut(bool *is_added = nullptr) const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<T*>(
|
||||
ecs_get_mut_w_entity(
|
||||
m_world, m_id, _::component_info<T>::id(m_world), is_added));
|
||||
ecs_get_mut_w_entity(m_world, m_id, comp_id, is_added));
|
||||
}
|
||||
|
||||
/** Get mutable component value (untyped).
|
||||
|
@ -10092,10 +10153,14 @@ public:
|
|||
const T* get_trait() const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto t_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<const T*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
|
||||
_::component_info<C>::id(m_world), _::component_info<T>::id(m_world))));
|
||||
_::component_info<C>::id(m_world), t_id)));
|
||||
}
|
||||
|
||||
/** Get trait value.
|
||||
|
@ -10109,10 +10174,14 @@ public:
|
|||
const T* get_trait(flecs::entity component) const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<const T*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
|
||||
component.id(), _::component_info<T>::id(m_world))));
|
||||
component.id(), comp_id)));
|
||||
}
|
||||
|
||||
/** Get trait tag value.
|
||||
|
@ -10129,10 +10198,14 @@ public:
|
|||
const C* get_trait_tag(flecs::entity trait) const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<C>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<C>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<const C*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
|
||||
_::component_info<C>::id(m_world), trait.id())));
|
||||
comp_id, trait.id())));
|
||||
}
|
||||
|
||||
/** Get trait tag value (untyped).
|
||||
|
@ -10166,14 +10239,16 @@ public:
|
|||
T* get_trait_mut(bool *is_added = nullptr) const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto t_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<T*>(
|
||||
ecs_get_mut_w_entity(
|
||||
m_world, m_id, ecs_trait(
|
||||
_::component_info<C>::id(m_world),
|
||||
_::component_info<T>::id(m_world)),
|
||||
is_added));
|
||||
m_world, m_id, ecs_trait(_::component_info<C>::id(m_world),
|
||||
t_id), is_added));
|
||||
}
|
||||
|
||||
/** Get mutable trait value.
|
||||
|
@ -10191,14 +10266,15 @@ public:
|
|||
T* get_trait_mut(flecs::entity component, bool *is_added = nullptr) const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return static_cast<T*>(
|
||||
ecs_get_mut_w_entity(
|
||||
m_world, m_id, ecs_trait(
|
||||
_::component_info<T>::id(m_world),
|
||||
component.id()),
|
||||
is_added));
|
||||
m_world, m_id, ecs_trait( comp_id, component.id()), is_added));
|
||||
}
|
||||
|
||||
/** Get mutable trait tag value.
|
||||
|
@ -10236,9 +10312,13 @@ public:
|
|||
void modified() const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
auto comp_id = _::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_modified_w_entity(m_world, m_id, _::component_info<T>::id(m_world));
|
||||
|
||||
ecs_modified_w_entity(m_world, m_id, comp_id);
|
||||
}
|
||||
|
||||
/** Signal that component was modified.
|
||||
|
@ -10272,8 +10352,13 @@ public:
|
|||
ref<T> get_ref() const {
|
||||
ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
|
||||
ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
// Ensure component is registered
|
||||
_::component_info<T>::id(m_world);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0,
|
||||
ECS_INVALID_PARAMETER, NULL);
|
||||
|
||||
return ref<T>(m_world, m_id);
|
||||
}
|
||||
|
||||
|
@ -10938,10 +11023,37 @@ namespace _
|
|||
return typeName;
|
||||
}
|
||||
};
|
||||
#elif
|
||||
#else
|
||||
#error "implicit component registration not supported"
|
||||
#endif
|
||||
|
||||
// Translate a typename into a langauge-agnostic identifier. This allows for
|
||||
// registration of components/modules across language boundaries.
|
||||
template <typename T>
|
||||
struct symbol_helper
|
||||
{
|
||||
static char* symbol(void) {
|
||||
const char *name = name_helper<T>::name();
|
||||
|
||||
// Symbol is same as name, but with '::' replaced with '.'
|
||||
char *ptr, *sym = ecs_os_strdup(name);
|
||||
ecs_size_t i, len = ecs_os_strlen(sym);
|
||||
ptr = sym;
|
||||
for (i = 0, ptr = sym; i < len && *ptr; i ++, ptr ++) {
|
||||
if (*ptr == ':') {
|
||||
sym[i] = '.';
|
||||
ptr ++;
|
||||
} else {
|
||||
sym[i] = *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
sym[i] = '\0';
|
||||
|
||||
return sym;
|
||||
}
|
||||
};
|
||||
|
||||
// The following functions are lifecycle callbacks that are automatically
|
||||
// registered with flecs to ensure component lifecycle is handled correctly. Not
|
||||
// all types require this, yet callbacks are registered by default, which
|
||||
|
@ -10970,7 +11082,7 @@ void component_ctor(
|
|||
T *t_ptr = static_cast<T*>(ptr);
|
||||
|
||||
for (int i = 0; i < count; i ++) {
|
||||
new(&t_ptr[i]) T;
|
||||
FLECS_PLACEMENT_NEW(&t_ptr[i], T);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11146,14 +11258,7 @@ public:
|
|||
ecs_assert(s_id == entity, ECS_INCONSISTENT_COMPONENT_ID,
|
||||
_::name_helper<T>::name());
|
||||
|
||||
// Ensure the entity has the same name as what was registered.
|
||||
if (s_id >= EcsFirstUserComponentId) {
|
||||
char *path = ecs_get_fullpath(world, entity);
|
||||
ecs_assert(!strcmp(path, s_name.c_str()),
|
||||
ECS_INCONSISTENT_COMPONENT_NAME,
|
||||
_::name_helper<T>::name());
|
||||
ecs_os_free(path);
|
||||
}
|
||||
ecs_assert(allow_tag == s_allow_tag, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
// Component was already registered and data is consistent with new
|
||||
// identifier, so nothing else to be done.
|
||||
|
@ -11177,10 +11282,12 @@ public:
|
|||
{
|
||||
// If no id has been registered yet, do it now.
|
||||
if (!s_id) {
|
||||
const char *n = _::name_helper<T>::name();
|
||||
|
||||
if (!name) {
|
||||
// If no name was provided, retrieve the name implicitly from
|
||||
// the name_helper class.
|
||||
name = _::name_helper<T>::name();
|
||||
name = n;
|
||||
}
|
||||
|
||||
s_allow_tag = allow_tag;
|
||||
|
@ -11210,6 +11317,9 @@ public:
|
|||
flecs::world w(world);
|
||||
flecs::entity result = entity(w, name, true);
|
||||
|
||||
// Init the component_info instance with the identiifer.
|
||||
init(world, result.id(), allow_tag);
|
||||
|
||||
// Now use the resulting identifier to register the component. Note
|
||||
// that the name is not passed into this function, as the entity was
|
||||
// already created with the correct name.
|
||||
|
@ -11218,12 +11328,48 @@ public:
|
|||
size(),
|
||||
alignment());
|
||||
|
||||
ecs_assert(entity != 0, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
// Set the symbol in the Name component to the actual C++ name.
|
||||
// Comparing symbols allows for verifying whether a different
|
||||
// component is being registered under the same name. We can't use
|
||||
// the name used for registration, because it is possible that a
|
||||
// user (erroneously) attempts to register the same datatype with
|
||||
// the same name. Without verifying that the actual C++ type name
|
||||
// matches, that scenario would go undetected.
|
||||
EcsName *name_comp = ecs_get_mut(world, entity, EcsName, NULL);
|
||||
char *symbol = symbol_helper<T>::symbol();
|
||||
|
||||
if (name_comp->symbol) {
|
||||
ecs_assert( !strcmp(name_comp->symbol, symbol),
|
||||
ECS_COMPONENT_NAME_IN_USE, name);
|
||||
} else {
|
||||
name_comp->symbol = symbol;
|
||||
}
|
||||
|
||||
// The identifier returned by the function should be the same as the
|
||||
// identifier that was passed in.
|
||||
ecs_assert(entity == result.id(), ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
// Init the component_info instance with the identiifer.
|
||||
init(world, entity);
|
||||
} else if (world && !ecs_exists(world, s_id)) {
|
||||
const char *n = _::name_helper<T>::name();
|
||||
|
||||
if (!name) {
|
||||
// If no name was provided, retrieve the name implicitly from
|
||||
// the name_helper class.
|
||||
name = n;
|
||||
}
|
||||
|
||||
ecs_entity_t entity = ecs_new_component(
|
||||
world, s_id, name,
|
||||
size(),
|
||||
alignment());
|
||||
|
||||
(void)entity;
|
||||
|
||||
ecs_assert(entity == s_id, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
init(world, s_id, allow_tag);
|
||||
}
|
||||
|
||||
// By now we should have a valid identifier
|
||||
|
@ -11238,7 +11384,7 @@ public:
|
|||
bool allow_tag = true)
|
||||
{
|
||||
// If no id has been registered yet, do it now.
|
||||
if (!s_id) {
|
||||
if (!s_id || (world && !ecs_exists(world, s_id))) {
|
||||
// This will register a component id, but will not register
|
||||
// lifecycle callbacks.
|
||||
id_no_lifecycle(world, name, allow_tag);
|
||||
|
@ -11315,6 +11461,8 @@ public:
|
|||
|
||||
// Return the size of a component.
|
||||
static size_t size() {
|
||||
ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
// C++ types that have no members still have a size. Use std::is_empty
|
||||
// to check if the type is empty. If so, use 0 for the component size.
|
||||
//
|
||||
|
@ -11330,6 +11478,8 @@ public:
|
|||
|
||||
// Return the alignment of a component.
|
||||
static size_t alignment() {
|
||||
ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
if (size() == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -11354,6 +11504,7 @@ private:
|
|||
static entity_t s_id;
|
||||
static type_t s_type;
|
||||
static std::string s_name;
|
||||
static std::string s_symbol;
|
||||
static bool s_allow_tag;
|
||||
};
|
||||
|
||||
|
@ -11381,14 +11532,15 @@ flecs::entity pod_component(const flecs::world& world, const char *name = nullpt
|
|||
entity_t id = 0;
|
||||
|
||||
if (_::component_info<T>::registered()) {
|
||||
/* To support components across multiple worlds, ensure that the
|
||||
* component ids are the same. */
|
||||
/* Obtain component id. Because the component is already registered,
|
||||
* this operation does nothing besides returning the existing id */
|
||||
id = _::component_info<T>::id_no_lifecycle(world_ptr, name, allow_tag);
|
||||
|
||||
/* If entity is not empty check if the name matches */
|
||||
if (ecs_get_type(world_ptr, id) != nullptr) {
|
||||
if (id >= EcsFirstUserComponentId) {
|
||||
char *path = ecs_get_fullpath(world_ptr, id);
|
||||
char *path = ecs_get_path_w_sep(
|
||||
world_ptr, 0, id, 0, "::", nullptr);
|
||||
ecs_assert(!strcmp(path, name),
|
||||
ECS_INCONSISTENT_COMPONENT_NAME, name);
|
||||
ecs_os_free(path);
|
||||
|
@ -11426,10 +11578,23 @@ flecs::entity pod_component(const flecs::world& world, const char *name = nullpt
|
|||
* or entity has been registered with this name */
|
||||
ecs_entity_t entity = ecs_lookup_fullpath(world_ptr, name);
|
||||
|
||||
(void)entity;
|
||||
/* If entity exists, compare symbol name to ensure that the component
|
||||
* we are trying to register under this name is the same */
|
||||
if (entity) {
|
||||
const EcsName *name_comp = ecs_get_mut(world.c_ptr(), entity, EcsName, NULL);
|
||||
ecs_assert(name_comp != NULL, ECS_INTERNAL_ERROR, NULL);
|
||||
ecs_assert(name_comp->symbol != NULL, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
ecs_assert(entity == 0, ECS_COMPONENT_NAME_IN_USE, name);
|
||||
const char *symbol = _::name_helper<T>::name();
|
||||
|
||||
ecs_assert(!strcmp(name_comp->symbol, symbol),
|
||||
ECS_COMPONENT_NAME_IN_USE, name);
|
||||
|
||||
(void)name_comp;
|
||||
(void)symbol;
|
||||
}
|
||||
|
||||
/* Register id as usual */
|
||||
id = _::component_info<T>::id_no_lifecycle(world_ptr, name, allow_tag);
|
||||
}
|
||||
|
||||
|
@ -11489,23 +11654,32 @@ flecs::entity module(const flecs::world& world, const char *name = nullptr) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
flecs::entity import(world& world) {
|
||||
if (!_::component_info<T>::registered()) {
|
||||
ecs_entity_t do_import(world& world) {
|
||||
ecs_trace_1("import %s", _::name_helper<T>::name());
|
||||
ecs_log_push();
|
||||
|
||||
ecs_entity_t scope = ecs_get_scope(world.c_ptr());
|
||||
|
||||
// Allocate module, so the this ptr will remain stable
|
||||
T *module_data = new T(world);
|
||||
// TODO: make sure memory is cleaned up with world
|
||||
T *module_data = FLECS_NEW(T)(world);
|
||||
|
||||
ecs_set_scope(world.c_ptr(), scope);
|
||||
|
||||
flecs::entity m = world.lookup(_::component_info<T>::name_no_lifecycle(world.c_ptr()));
|
||||
// It should now be possible to lookup the module
|
||||
char *symbol = _::symbol_helper<T>::symbol();
|
||||
ecs_entity_t m = ecs_lookup_symbol(world.c_ptr(), symbol);
|
||||
ecs_assert(m != 0, ECS_MODULE_UNDEFINED, symbol);
|
||||
ecs_os_free(symbol);
|
||||
|
||||
_::component_info<T>::init(world.c_ptr(), m, false);
|
||||
|
||||
ecs_assert(_::component_info<T>::size() != 0, ECS_INTERNAL_ERROR, NULL);
|
||||
|
||||
// Set module singleton component
|
||||
|
||||
ecs_set_ptr_w_entity(
|
||||
world.c_ptr(),
|
||||
m.id(),
|
||||
world.c_ptr(), m,
|
||||
_::component_info<T>::id_no_lifecycle(world.c_ptr()),
|
||||
_::component_info<T>::size(),
|
||||
module_data);
|
||||
|
@ -11513,10 +11687,32 @@ flecs::entity import(world& world) {
|
|||
ecs_log_pop();
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
flecs::entity import(world& world) {
|
||||
const char *symbol = _::name_helper<T>::name();
|
||||
|
||||
ecs_entity_t m = ecs_lookup_symbol(world.c_ptr(), symbol);
|
||||
|
||||
if (!_::component_info<T>::registered()) {
|
||||
|
||||
/* Module is registered with world, initialize static data */
|
||||
if (m) {
|
||||
_::component_info<T>::init(world.c_ptr(), m, false);
|
||||
|
||||
/* Module is not yet registered, register it now */
|
||||
} else {
|
||||
return flecs::entity(world,
|
||||
_::component_info<T>::id_no_lifecycle(world.c_ptr()));
|
||||
m = do_import<T>(world);
|
||||
}
|
||||
|
||||
/* Module has been registered, but could have been for another world. Import
|
||||
* if module hasn't been registered for this world. */
|
||||
} else if (!m) {
|
||||
m = do_import<T>(world);
|
||||
}
|
||||
|
||||
return flecs::entity(world, m);
|
||||
}
|
||||
|
||||
|
||||
|
@ -11647,12 +11843,13 @@ class each_invoker {
|
|||
using Columns = typename column_args<Components ...>::Columns;
|
||||
|
||||
public:
|
||||
explicit each_invoker(Func func) : m_func(func) { }
|
||||
explicit each_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
|
||||
explicit each_invoker(const Func& func) noexcept : m_func(func) { }
|
||||
|
||||
// Invoke system
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, size_t index, Columns& columns, Targs... comps) {
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
|
||||
flecs::iter iter_wrapper(iter);
|
||||
(void)index;
|
||||
(void)columns;
|
||||
|
@ -11668,17 +11865,16 @@ public:
|
|||
// Add components one by one to parameter pack
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, size_t index, Columns& columns, Targs... comps) {
|
||||
call_system(iter, func, index + 1, columns, comps..., columns[index]);
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
|
||||
each_invoker::call_system(iter, func, index + 1, columns, comps..., columns[index]);
|
||||
}
|
||||
|
||||
// Callback provided to flecs system
|
||||
static void run(ecs_iter_t *iter) {
|
||||
const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
|
||||
each_invoker *self = (each_invoker*)ctx->ctx;
|
||||
Func func = self->m_func;
|
||||
column_args<Components...> columns(iter);
|
||||
call_system(iter, func, 0, columns.m_columns);
|
||||
call_system(iter, self->m_func, 0, columns.m_columns);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -11695,13 +11891,13 @@ class action_invoker {
|
|||
using Columns = typename column_args<Components ...>::Columns;
|
||||
|
||||
public:
|
||||
explicit action_invoker(Func func)
|
||||
: m_func(func) { }
|
||||
explicit action_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
|
||||
explicit action_invoker(const Func& func) noexcept : m_func(func) { }
|
||||
|
||||
/* Invoke system */
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, int index, Columns& columns, Targs... comps) {
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, int index, Columns& columns, Targs... comps) {
|
||||
(void)index;
|
||||
(void)columns;
|
||||
|
||||
|
@ -11714,7 +11910,7 @@ public:
|
|||
/** Add components one by one to parameter pack */
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, int index, Columns& columns, Targs... comps) {
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, int index, Columns& columns, Targs... comps) {
|
||||
call_system(iter, func, index + 1, columns, comps..., columns[index]);
|
||||
}
|
||||
|
||||
|
@ -11722,9 +11918,8 @@ public:
|
|||
static void run(ecs_iter_t *iter) {
|
||||
const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
|
||||
action_invoker *self = (action_invoker*)ctx->ctx;
|
||||
Func func = self->m_func;
|
||||
column_args<Components...> columns(iter);
|
||||
call_system(iter, func, 0, columns.m_columns);
|
||||
call_system(iter, self->m_func, 0, columns.m_columns);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -11740,13 +11935,13 @@ class iter_invoker {
|
|||
using Columns = typename column_args<Components ...>::Columns;
|
||||
|
||||
public:
|
||||
explicit iter_invoker(Func func)
|
||||
: m_func(func) { }
|
||||
explicit iter_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
|
||||
explicit iter_invoker(const Func& func) noexcept : m_func(func) { }
|
||||
|
||||
/* Invoke system */
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, size_t index, Columns& columns, Targs... comps) {
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
|
||||
(void)index;
|
||||
(void)columns;
|
||||
flecs::iter iter_wrapper(iter);
|
||||
|
@ -11756,7 +11951,7 @@ public:
|
|||
/** Add components one by one to parameter pack */
|
||||
template <typename... Targs,
|
||||
typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
|
||||
static void call_system(ecs_iter_t *iter, Func func, size_t index, Columns& columns, Targs... comps) {
|
||||
static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
|
||||
call_system(iter, func, index + 1, columns, comps..., columns[index]);
|
||||
}
|
||||
|
||||
|
@ -11764,9 +11959,8 @@ public:
|
|||
static void run(ecs_iter_t *iter) {
|
||||
const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
|
||||
iter_invoker *self = (iter_invoker*)ctx->ctx;
|
||||
Func func = self->m_func;
|
||||
column_args<Components...> columns(iter);
|
||||
call_system(iter, func, 0, columns.m_columns);
|
||||
call_system(iter, self->m_func, 0, columns.m_columns);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -11950,36 +12144,33 @@ public:
|
|||
query_iterator<Components...> end() const;
|
||||
|
||||
template <typename Func>
|
||||
void each(Func func) const {
|
||||
void each(Func&& func) const {
|
||||
ecs_iter_t it = ecs_query_iter(m_query);
|
||||
|
||||
while (ecs_query_next(&it)) {
|
||||
_::column_args<Components...> columns(&it);
|
||||
_::each_invoker<Func, Components...> ctx(func);
|
||||
ctx.call_system(&it, func, 0, columns.m_columns);
|
||||
_::each_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
|
||||
}
|
||||
}
|
||||
|
||||
/* DEPRECATED */
|
||||
template <typename Func>
|
||||
void action(Func func) const {
|
||||
void action(Func&& func) const {
|
||||
ecs_iter_t it = ecs_query_iter(m_query);
|
||||
|
||||
while (ecs_query_next(&it)) {
|
||||
_::column_args<Components...> columns(&it);
|
||||
_::action_invoker<Func, Components...> ctx(func);
|
||||
ctx.call_system(&it, func, 0, columns.m_columns);
|
||||
_::action_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void iter(Func func) const {
|
||||
void iter(Func&& func) const {
|
||||
ecs_iter_t it = ecs_query_iter(m_query);
|
||||
|
||||
while (ecs_query_next(&it)) {
|
||||
_::column_args<Components...> columns(&it);
|
||||
_::iter_invoker<Func, Components...> ctx(func);
|
||||
ctx.call_system(&it, func, 0, columns.m_columns);
|
||||
_::iter_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -12211,11 +12402,12 @@ public:
|
|||
|
||||
/* DEPRECATED. Use iter instead. */
|
||||
template <typename Func>
|
||||
system& action(Func func) {
|
||||
system& action(Func&& func) {
|
||||
ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
|
||||
auto ctx = new _::action_invoker<Func, Components...>(func);
|
||||
using invoker_t = typename _::action_invoker<typename std::decay<Func>::type, Components...>;
|
||||
auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));
|
||||
|
||||
create_system(_::action_invoker<Func, Components...>::run, false);
|
||||
create_system(invoker_t::run, false);
|
||||
|
||||
EcsContext ctx_value = {ctx};
|
||||
ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
|
||||
|
@ -12227,11 +12419,12 @@ public:
|
|||
* is added in the fluent method chain. Create system signature from both
|
||||
* template parameters and anything provided by the signature method. */
|
||||
template <typename Func>
|
||||
system& iter(Func func) {
|
||||
system& iter(Func&& func) {
|
||||
ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
|
||||
auto ctx = new _::iter_invoker<Func, Components...>(func);
|
||||
using invoker_t = typename _::iter_invoker<typename std::decay<Func>::type, Components...>;
|
||||
auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));
|
||||
|
||||
create_system(_::iter_invoker<Func, Components...>::run, false);
|
||||
create_system(invoker_t::run, false);
|
||||
|
||||
EcsContext ctx_value = {ctx};
|
||||
ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
|
||||
|
@ -12242,10 +12435,11 @@ public:
|
|||
/* Each is similar to action, but accepts a function that operates on a
|
||||
* single entity */
|
||||
template <typename Func>
|
||||
system& each(Func func) {
|
||||
auto ctx = new _::each_invoker<Func, Components...>(func);
|
||||
system& each(Func&& func) {
|
||||
using invoker_t = typename _::each_invoker<typename std::decay<Func>::type, Components...>;
|
||||
auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));
|
||||
|
||||
create_system(_::each_invoker<Func, Components...>::run, true);
|
||||
create_system(invoker_t::run, true);
|
||||
|
||||
EcsContext ctx_value = {ctx};
|
||||
ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
|
||||
|
|
Loading…
Reference in New Issue