Skip to content
Flecs v4.1
queries/group_by_custom

  • C

    View on GitHub

    1#include <group_by_custom.h>
    2#include <stdio.h>
    3
    4// This example does the same as the group_by example, but with a custom
    5// group_by function. A custom function makes it possible to customize how a
    6// group id is calculated for a table.
    7
    8typedef struct {
    9 double x, y;
    10} Position;
    11
    12uint64_t group_by_relation(ecs_world_t *ecs, ecs_table_t *table,
    13 ecs_entity_t id, void *ctx)
    14{
    15 (void)ctx; // marks ctx as unused, avoids compiler warnings
    16
    17 // Use ecs_search to find the target for the relationship in the table
    18 ecs_id_t match;
    19 if (ecs_search(ecs, table, ecs_pair(id, EcsWildcard), &match) != -1) {
    20 return ecs_pair_second(ecs, match); // First, Second or Third
    21 }
    22
    23 return 0;
    24}
    25
    26int main(int argc, char *argv[]) {
    27 ecs_world_t *ecs = ecs_init_w_args(argc, argv);
    28
    29 ECS_COMPONENT(ecs, Position);
    30 ECS_TAG(ecs, Tag); // Dummy tag to put entities in different tables
    31
    32 // Create a relationship to use for the group_by function. Tables will
    33 // be assigned the relationship target as group id
    34 ECS_TAG(ecs, Group);
    35
    36 // Targets for the relationship, which will be used as group ids.
    37 ECS_TAG(ecs, First);
    38 ECS_TAG(ecs, Second);
    39 ECS_TAG(ecs, Third);
    40
    41 // Grouped query
    42 ecs_query_t *q = ecs_query(ecs, {
    43 .terms = {
    44 { .id = ecs_id(Position) }
    45 },
    46 .group_by_callback = group_by_relation,
    47 .group_by = Group // Passed to id argument of group_by function
    48 });
    49
    50 // Create entities in 6 different tables with 3 group ids
    51 ecs_entity_t e1 = ecs_new_w_pair(ecs, Group, Third);
    52 ecs_set(ecs, e1, Position, {1, 1});
    53
    54 ecs_entity_t e2 = ecs_new_w_pair(ecs, Group, Second);
    55 ecs_set(ecs, e2, Position, {2, 2});
    56
    57 ecs_entity_t e3 = ecs_new_w_pair(ecs, Group, First);
    58 ecs_set(ecs, e3, Position, {3, 3});
    59
    60 ecs_entity_t e4 = ecs_new_w_pair(ecs, Group, Third);
    61 ecs_set(ecs, e4, Position, {4, 4});
    62 ecs_add(ecs, e4, Tag);
    63
    64 ecs_entity_t e5 = ecs_new_w_pair(ecs, Group, Second);
    65 ecs_set(ecs, e5, Position, {5, 5});
    66 ecs_add(ecs, e5, Tag);
    67
    68 ecs_entity_t e6 = ecs_new_w_pair(ecs, Group, First);
    69 ecs_set(ecs, e6, Position, {6, 6});
    70 ecs_add(ecs, e6, Tag);
    71
    72 // The query cache now looks like this:
    73 // - group First:
    74 // - table [Position, (Group, First)]
    75 // - table [Position, Tag, (Group, First)]
    76 //
    77 // - group Second:
    78 // - table [Position, (Group, Second)]
    79 // - table [Position, Tag, (Group, Second)]
    80 //
    81 // - group Third:
    82 // - table [Position, (Group, Third)]
    83 // - table [Position, Tag, (Group, Third)]
    84 //
    85
    86 // Iterate query, print position & table components
    87 ecs_iter_t it = ecs_query_iter(ecs, q);
    88 while (ecs_query_next(&it)) {
    89 Position *p = ecs_field(&it, Position, 0);
    90 char *table_str = ecs_table_str(ecs, it.table);
    91 char *group_str = ecs_get_path(ecs, ecs_iter_get_group(&it));
    92
    93 printf(" - group %s: table [%s]\n", group_str, table_str);
    94
    95 for (int i = 0; i < it.count; i ++) {
    96 printf(" {%f, %f}\n", p[i].x, p[i].y);
    97 }
    98
    99 ecs_os_free(group_str);
    100 ecs_os_free(table_str);
    101 printf("\n");
    102 }
    103
    104 // Output:
    105 // - group First: table [Position, (Group,First)]
    106 // {3.000000, 3.000000}
    107 //
    108 // - group First: table [Position, Tag, (Group,First)]
    109 // {6.000000, 6.000000}
    110 //
    111 // - group Second: table [Position, (Group,Second)]
    112 // {2.000000, 2.000000}
    113 //
    114 // - group Second: table [Position, Tag, (Group,Second)]
    115 // {5.000000, 5.000000}
    116 //
    117 // - group Third: table [Position, (Group,Third)]
    118 // {1.000000, 1.000000}
    119 //
    120 // - group Third: table [Position, Tag, (Group,Third)]
    121 // {4.000000, 4.000000}
    122
    123 return ecs_fini(ecs);
    124}
    const ecs_entity_t EcsWildcard
    Wildcard entity ("*").
    FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
    Component ID for EcsDocDescription.
    ecs_id_t ecs_entity_t
    An entity identifier.
    Definition flecs.h:395
    struct ecs_world_t ecs_world_t
    A world is the container for all ECS data and supporting features.
    Definition flecs.h:439
    uint64_t ecs_id_t
    IDs are the things that can be added to an entity.
    Definition flecs.h:388
    struct ecs_table_t ecs_table_t
    A table stores entities and components for a specific type.
    Definition flecs.h:445
    char * ecs_table_str(const ecs_world_t *world, const ecs_table_t *table)
    Convert a table to a string.
    #define ecs_add(world, entity, T)
    Add a component to an entity.
    Definition flecs_c.h:271
    #define ecs_new_w_pair(world, first, second)
    Create a new entity with a pair.
    Definition flecs_c.h:256
    #define ECS_COMPONENT(world, id)
    Declare and define a component.
    Definition flecs_c.h:98
    #define ECS_TAG(world, id)
    Declare and define a tag.
    Definition flecs_c.h:59
    #define ecs_query(world,...)
    Shorthand for creating a query with ecs_query_init().
    Definition flecs_c.h:215
    #define ecs_get_path(world, child)
    Get path from root.
    Definition flecs_c.h:594
    #define ecs_set(world, entity, component,...)
    Set a component value.
    Definition flecs_c.h:310
    #define ecs_field(it, T, index)
    Get field data for a component.
    Definition flecs_c.h:720
    uint64_t ecs_iter_get_group(const ecs_iter_t *it)
    Return the group ID for the currently iterated result.
    bool ecs_query_next(ecs_iter_t *it)
    Progress a query iterator.
    ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
    Create a query iterator.
    int32_t ecs_search(const ecs_world_t *world, const ecs_table_t *table, ecs_id_t component, ecs_id_t *component_out)
    Search for a component in a table type.
    int ecs_fini(ecs_world_t *world)
    Delete a world.
    ecs_world_t * ecs_init_w_args(int argc, char *argv[])
    Create a new world with arguments.
    Iterator.
    Definition flecs.h:1183
    ecs_table_t * table
    Current table.
    Definition flecs.h:1195
    int32_t count
    Number of entities to iterate.
    Definition flecs.h:1189
    Queries are lists of constraints (terms) that match entities.
    Definition flecs.h:858

  • C++

    View on GitHub

    1#include <group_by_custom.h>
    2#include <iostream>
    3
    4// This example does the same as the group_by example, but with a custom
    5// group_by function. A custom function makes it possible to customize how a
    6// group id is calculated for a table.
    7
    8struct Position {
    9 double x, y;
    10};
    11
    12// Dummy tag to put entities in different tables
    13struct Tag { };
    14
    15// Create a relationship to use for the group_by function. Tables will
    16// be assigned the relationship target as group id
    17struct Group { };
    18
    19// Targets for the relationship, which will be used as group ids.
    20struct First { };
    21struct Second { };
    22struct Third { };
    23
    24uint64_t group_by_relation(flecs::world_t *ecs, flecs::table_t *table,
    25 flecs::entity_t id, void *)
    26{
    27 // Use ecs_search to find the target for the relationship in the table
    28 flecs::id_t match;
    29 if (ecs_search(ecs, table, flecs::id(id, flecs::Wildcard), &match) != -1) {
    30 return flecs::id(ecs, match).second(); // First, Second or Third
    31 }
    32 return 0;
    33}
    34
    35int main() {
    36 flecs::world ecs;
    37
    38 // Register components in order so that id for First is lower than Third
    39 ecs.component<First>();
    40 ecs.component<Second>();
    41 ecs.component<Third>();
    42
    43 // Grouped query
    44 flecs::query<Position> q = ecs.query_builder<Position>()
    45 .group_by<Group>(group_by_relation)
    46 .build();
    47
    48 // Create entities in 6 different tables with 3 group ids
    49 ecs.entity().add<Group, Third>()
    50 .set<Position>({1, 1});
    51 ecs.entity().add<Group, Second>()
    52 .set<Position>({2, 2});
    53 ecs.entity().add<Group, First>()
    54 .set<Position>({3, 3});
    55
    56 ecs.entity().add<Group, Third>()
    57 .set<Position>({4, 4})
    58 .add<Tag>();
    59 ecs.entity().add<Group, Second>()
    60 .set<Position>({5, 5})
    61 .add<Tag>();
    62 ecs.entity().add<Group, First>()
    63 .set<Position>({6, 6})
    64 .add<Tag>();
    65
    66 // The query cache now looks like this:
    67 // - group First:
    68 // - table [Position, (Group, First)]
    69 // - table [Position, Tag, (Group, First)]
    70 //
    71 // - group Second:
    72 // - table [Position, (Group, Second)]
    73 // - table [Position, Tag, (Group, Second)]
    74 //
    75 // - group Third:
    76 // - table [Position, (Group, Third)]
    77 // - table [Position, Tag, (Group, Third)]
    78 //
    79
    80 q.run([&](flecs::iter& it) {
    81 while (it.next()) {
    82 auto p = it.field<Position>(0);
    83
    84 flecs::entity group = ecs.entity(it.group_id());
    85 std::cout << " - group " << group.path() << ": ["
    86 << "table [" << it.table().str() << "]\n";
    87
    88 for (auto i : it) {
    89 std::cout << " {" << p[i].x << ", " << p[i].y << "}\n";
    90 }
    91
    92 std::cout << "\n";
    93 }
    94 });
    95
    96 // Output:
    97 // - group ::First: table [Position, (Group,First)]
    98 // {3, 3}
    99 //
    100 // - group ::First: table [Position, Tag, (Group,First)]
    101 // {6, 6}
    102 //
    103 // - group ::Second: table [Position, (Group,Second)]
    104 // {2, 2}
    105 //
    106 // - group ::Second: table [Position, Tag, (Group,Second)]
    107 // {5, 5}
    108 //
    109 // - group ::Third: table [Position, (Group,Third)]
    110 // {1, 1}
    111 //
    112 // - group ::Third: table [Position, Tag, (Group,Third)]
    113 // {4, 4}
    114}
    flecs::component< T > component(Args &&... args) const
    Find or register a component.
    Definition impl.hpp:11
    flecs::query_builder< Comps... > query_builder(Args &&... args) const
    Create a query builder.
    Definition impl.hpp:342
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    ecs_table_t table_t
    Table type.
    Definition c_types.hpp:23
    ecs_id_t id_t
    ID type.
    Definition c_types.hpp:20
    ecs_entity_t entity_t
    Entity type.
    Definition c_types.hpp:21
    ecs_world_t world_t
    World type.
    Definition c_types.hpp:18
    flecs::string path(const char *sep="::", const char *init_sep="::") const
    Return the entity path.
    Entity.
    Definition entity.hpp:30
    Class that wraps around a flecs::id_t.
    Definition decl.hpp:27
    flecs::entity second() const
    Get second element from a pair.
    Definition impl.hpp:31
    Class for iterating over query results.
    Definition iter.hpp:68
    flecs::field< A > field(int8_t index) const
    Get read-only access to field data.
    Definition iter.hpp:84
    flecs::table table() const
    Get the table for the current iterator result.
    Definition iter.hpp:67
    uint64_t group_id() const
    Return the group ID for the current table (grouped queries only).
    Definition iter.hpp:434
    bool next()
    Progress iterator.
    Definition iter.hpp:465
    Typed query.
    Definition impl.hpp:271
    flecs::string str() const
    Convert the table type to a string.
    Definition table.hpp:40
    The world.
    Definition world.hpp:129