Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,586 changes: 802 additions & 1,784 deletions distr/flecs.c

Large diffs are not rendered by default.

1,577 changes: 405 additions & 1,172 deletions distr/flecs.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/c/queries/component_inheritance/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
],
"public": false
}
}
}
90 changes: 47 additions & 43 deletions examples/c/queries/component_inheritance/src/main.c
Original file line number Diff line number Diff line change
@@ -1,70 +1,74 @@
#include <component_inheritance.h>
#include <stdio.h>

// This example shows how queries can be used to match simple inheritance trees.
// This example shows how queries can match components that derive from a base
// component through the IsA relationship. A query for the base component
// matches all entities that have a derived component, and can read the members
// that are inherited from the base. See the tag_inheritance example for
// inheritance trees built from tags instead of components.

int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init_w_args(argc, argv);
// Buf is the base component. HealthBuf and ManaBuf derive from it, so they
// start with the same members as Buf (the base layout is a prefix of the
// derived layout).
typedef struct {
float value;
} Buf;

typedef struct {
float value;
} HealthBuf;

// Use convenience macros to create simple hierarchy of unit types.
// This macro call:
// ECS_ENTITY(ecs, CombatUnit, (IsA, Unit))
//
// is the same as these C statements:
// ecs_entity_t CombatUnit = ecs_new_entity("CombatUnit");
// ecs_add_pair(ecs, CombatUnit, EcsIsA, Unit);
typedef struct {
float value;
} ManaBuf;

ECS_TAG(ecs, Unit);
ECS_ENTITY(ecs, CombatUnit, (IsA, Unit));
ECS_ENTITY(ecs, MeleeUnit, (IsA, CombatUnit));
ECS_ENTITY(ecs, RangedUnit, (IsA, CombatUnit));
int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init_w_args(argc, argv);

ECS_ENTITY(ecs, Warrior, (IsA, MeleeUnit));
ECS_ENTITY(ecs, Wizard, (IsA, RangedUnit));
ECS_ENTITY(ecs, Marksman, (IsA, RangedUnit));
ECS_ENTITY(ecs, Builder, (IsA, Unit));
ECS_COMPONENT(ecs, Buf);
ECS_COMPONENT(ecs, HealthBuf);
ECS_COMPONENT(ecs, ManaBuf);

// Create a few units
ecs_entity_t warrior_1 = ecs_entity(ecs, { .name = "warrior_1" });
ecs_add(ecs, warrior_1, Warrior);
ecs_entity_t warrior_2 = ecs_entity(ecs, { .name = "warrior_2" });
ecs_add(ecs, warrior_2, Warrior);
// Make the ECS aware of the inheritance relationships.
ecs_add_pair(ecs, ecs_id(HealthBuf), EcsIsA, ecs_id(Buf));
ecs_add_pair(ecs, ecs_id(ManaBuf), EcsIsA, ecs_id(Buf));

ecs_entity_t marksman_1 = ecs_entity(ecs, { .name = "marksman_1" });
ecs_add(ecs, marksman_1, Marksman);
ecs_entity_t marksman_2 = ecs_entity(ecs, { .name = "marksman_2" });
ecs_add(ecs, marksman_2, Marksman);
// Create a few entities with derived buf components
ecs_entity_t warrior = ecs_entity(ecs, { .name = "warrior" });
ecs_set(ecs, warrior, HealthBuf, { .value = 10 });

ecs_entity_t wizard_1 = ecs_entity(ecs, { .name = "wizard_1" });
ecs_add(ecs, wizard_1, Wizard);
ecs_entity_t wizard_2 = ecs_entity(ecs, { .name = "wizard_2" });
ecs_add(ecs, wizard_2, Wizard);
ecs_entity_t wizard = ecs_entity(ecs, { .name = "wizard" });
ecs_set(ecs, wizard, ManaBuf, { .value = 25 });

ecs_entity_t builder_1 = ecs_entity(ecs, { .name = "builder_1" });
ecs_add(ecs, builder_1, Builder);
ecs_entity_t builder_2 = ecs_entity(ecs, { .name = "builder_2" });
ecs_add(ecs, builder_2, Builder);
ecs_entity_t paladin = ecs_entity(ecs, { .name = "paladin" });
ecs_set(ecs, paladin, HealthBuf, { .value = 5 });

// Create a query to find all ranged units
// Create a query for the base component. This matches all entities with a
// component that derives from Buf.
ecs_query_t *q = ecs_query(ecs, {
.terms = {{ .id = RangedUnit }}
.terms = {{ .id = ecs_id(Buf) }}
});

// Iterate the query
// Iterate the query. Because the matched component can be a derived type
// that is larger than Buf, use ecs_base_field to get the field pointer and
// ecs_field_stride to advance from one element to the next.
ecs_iter_t it = ecs_query_iter(ecs, q);
while (ecs_query_next(&it)) {
void *bufs = ecs_base_field(&it, Buf, 0);
size_t stride = ecs_field_stride(&it, 0);
for (int i = 0; i < it.count; i ++) {
printf("Unit %s found\n", ecs_get_name(ecs, it.entities[i]));
Buf *buf = ECS_OFFSET(bufs, stride * (size_t)i);
printf("%s has buf value %.0f\n",
ecs_get_name(ecs, it.entities[i]), (double)buf->value);
}
}

ecs_query_fini(q);

// Output
// Unit wizard_1 found
// Unit wizard_2 found
// Unit marksman_1 found
// Unit marksman_2 found
// warrior has buf value 10
// paladin has buf value 5
// wizard has buf value 25

return ecs_fini(ecs);
}
4 changes: 2 additions & 2 deletions examples/c/queries/setting_variables/src/main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <setting_variables.h>
#include <stdio.h>

// This example extends the component_inheritance example, and shows how
// This example extends the tag_inheritance example, and shows how
// we can use a single query to match units from different players and platoons
// by setting query variables before we iterate.
//
Expand All @@ -14,7 +14,7 @@ static const int PlatoonsPerPlayer = 3;
int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init_w_args(argc, argv);

// Unit datamodel - see component_inheritance example
// Unit datamodel - see tag_inheritance example
ECS_TAG(ecs, Unit);
ECS_ENTITY(ecs, CombatUnit, (IsA, Unit));
ECS_ENTITY(ecs, MeleeUnit, (IsA, CombatUnit));
Expand Down
11 changes: 11 additions & 0 deletions examples/c/queries/tag_inheritance/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cc_binary(
name = "tag_inheritance",
srcs = glob([
"src/*.c",
"include/**/*.h",
]),
includes = ["include"],
deps = [
"//:flecs",
],
)
16 changes: 16 additions & 0 deletions examples/c/queries/tag_inheritance/include/tag_inheritance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef TAG_INHERITANCE_H
#define TAG_INHERITANCE_H

/* This generated file contains includes for project dependencies */
#include "tag_inheritance/bake_config.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif

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 TAG_INHERITANCE_BAKE_CONFIG_H
#define TAG_INHERITANCE_BAKE_CONFIG_H

/* Headers of public dependencies */
#include <flecs.h>

#endif

10 changes: 10 additions & 0 deletions examples/c/queries/tag_inheritance/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "tag_inheritance",
"type": "application",
"value": {
"use": [
"flecs"
],
"public": false
}
}
72 changes: 72 additions & 0 deletions examples/c/queries/tag_inheritance/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <tag_inheritance.h>
#include <stdio.h>

// This example shows how queries can be used to match simple inheritance trees
// built from tags. See the component_inheritance example for inheritance trees
// built from components with data.

int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init_w_args(argc, argv);

// Use convenience macros to create simple hierarchy of unit types.
// This macro call:
// ECS_ENTITY(ecs, CombatUnit, (IsA, Unit))
//
// is the same as these C statements:
// ecs_entity_t CombatUnit = ecs_new_entity("CombatUnit");
// ecs_add_pair(ecs, CombatUnit, EcsIsA, Unit);

ECS_TAG(ecs, Unit);
ECS_ENTITY(ecs, CombatUnit, (IsA, Unit));
ECS_ENTITY(ecs, MeleeUnit, (IsA, CombatUnit));
ECS_ENTITY(ecs, RangedUnit, (IsA, CombatUnit));

ECS_ENTITY(ecs, Warrior, (IsA, MeleeUnit));
ECS_ENTITY(ecs, Wizard, (IsA, RangedUnit));
ECS_ENTITY(ecs, Marksman, (IsA, RangedUnit));
ECS_ENTITY(ecs, Builder, (IsA, Unit));

// Create a few units
ecs_entity_t warrior_1 = ecs_entity(ecs, { .name = "warrior_1" });
ecs_add(ecs, warrior_1, Warrior);
ecs_entity_t warrior_2 = ecs_entity(ecs, { .name = "warrior_2" });
ecs_add(ecs, warrior_2, Warrior);

ecs_entity_t marksman_1 = ecs_entity(ecs, { .name = "marksman_1" });
ecs_add(ecs, marksman_1, Marksman);
ecs_entity_t marksman_2 = ecs_entity(ecs, { .name = "marksman_2" });
ecs_add(ecs, marksman_2, Marksman);

ecs_entity_t wizard_1 = ecs_entity(ecs, { .name = "wizard_1" });
ecs_add(ecs, wizard_1, Wizard);
ecs_entity_t wizard_2 = ecs_entity(ecs, { .name = "wizard_2" });
ecs_add(ecs, wizard_2, Wizard);

ecs_entity_t builder_1 = ecs_entity(ecs, { .name = "builder_1" });
ecs_add(ecs, builder_1, Builder);
ecs_entity_t builder_2 = ecs_entity(ecs, { .name = "builder_2" });
ecs_add(ecs, builder_2, Builder);

// Create a query to find all ranged units
ecs_query_t *q = ecs_query(ecs, {
.terms = {{ .id = RangedUnit }}
});

// Iterate the query
ecs_iter_t it = ecs_query_iter(ecs, q);
while (ecs_query_next(&it)) {
for (int i = 0; i < it.count; i ++) {
printf("Unit %s found\n", ecs_get_name(ecs, it.entities[i]));
}
}

ecs_query_fini(q);

// Output
// Unit wizard_1 found
// Unit wizard_2 found
// Unit marksman_1 found
// Unit marksman_2 found

return ecs_fini(ecs);
}
2 changes: 1 addition & 1 deletion examples/c/queries/transitive_queries/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// San Francisco is located in the United States
// Therefore Bob also lives in the United States.
//
// An example of transitivity can be seen in the component_inheritance example.
// An example of transitivity can be seen in the tag_inheritance example.
// This example uses the builtin IsA relationship, which is transitive. This
// example shows how to achieve similar behavior with a user-defined relationship.

Expand Down
2 changes: 1 addition & 1 deletion examples/cpp/queries/component_inheritance/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
"language": "c++",
"public": false
}
}
}
73 changes: 31 additions & 42 deletions examples/cpp/queries/component_inheritance/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,56 +1,45 @@
#include <component_inheritance.h>
#include <iostream>

// This example shows how queries can be used to match simple inheritance trees.

struct Unit { };
struct CombatUnit : Unit { };
struct MeleeUnit : CombatUnit { };
struct RangedUnit : CombatUnit { };

struct Warrior : MeleeUnit { };
struct Wizard : RangedUnit { };
struct Marksman : RangedUnit { };
struct Builder : Unit { };
// This example shows how queries can match components that derive from a base
// component through the IsA relationship. A query for the base component
// matches all entities that have a derived component, and can read the members
// that are inherited from the base. See the tag_inheritance example for
// inheritance trees built from tags instead of components.

// Buf is the base component. HealthBuf and ManaBuf derive from it, so they
// inherit the base members (the base subobject is stored at the start of the
// derived component).
struct Buf {
float value;
};

struct HealthBuf : Buf { };
struct ManaBuf : Buf { };

int main(int, char *[]) {
flecs::world ecs;

// Make the ECS aware of the inheritance relationships. Note that IsA
// relationship used here is the same as in the prefab example.
ecs.component<CombatUnit>().is_a<Unit>();
ecs.component<MeleeUnit>().is_a<CombatUnit>();
ecs.component<RangedUnit>().is_a<CombatUnit>();

ecs.component<Warrior>().is_a<MeleeUnit>();
ecs.component<Wizard>().is_a<RangedUnit>();
ecs.component<Marksman>().is_a<RangedUnit>();
ecs.component<Builder>().is_a<Unit>();

// Create a few units
ecs.entity("warrior_1").add<Warrior>();
ecs.entity("warrior_2").add<Warrior>();

ecs.entity("marksman_1").add<Marksman>();
ecs.entity("marksman_2").add<Marksman>();

ecs.entity("wizard_1").add<Wizard>();
ecs.entity("wizard_2").add<Wizard>();
// Make the ECS aware of the inheritance relationships.
ecs.component<HealthBuf>().is_a<Buf>();
ecs.component<ManaBuf>().is_a<Buf>();

ecs.entity("builder_1").add<Builder>();
ecs.entity("builder_2").add<Builder>();
// Create a few entities with derived buf components
ecs.entity("warrior").set<HealthBuf>({{ 10 }});
ecs.entity("wizard").set<ManaBuf>({{ 25 }});
ecs.entity("paladin").set<HealthBuf>({{ 5 }});

// Create a query to find all ranged units
flecs::query<RangedUnit> q = ecs.query<RangedUnit>();
// Create a query for the base component. This matches all entities with a
// component that derives from Buf.
flecs::query<Buf> q = ecs.query<Buf>();

// Iterate the query
q.each([](flecs::entity e, RangedUnit) {
std::cout << "Unit " << e.name() << " found\n";
// Iterate the query. The Buf members are accessible for derived components.
q.each([](flecs::entity e, Buf& b) {
std::cout << e.name() << " has buf value " << b.value << "\n";
});

// Output:
// Unit wizard_1 found
// Unit wizard_2 found
// Unit marksman_1 found
// Unit marksman_2 found
// warrior has buf value 10
// paladin has buf value 5
// wizard has buf value 25
}
Loading
Loading