Properly link flecs library

This commit is contained in:
2023-11-09 11:38:29 +01:00
parent dc585396c3
commit 8edcf9305c
1392 changed files with 390081 additions and 164 deletions

View File

@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.5)
cmake_policy(SET CMP0063 NEW)
project(flecs_cpp_examples LANGUAGES CXX)
set(FLECS_DIR ../..)
set(CUR_DIR ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(${FLECS_DIR} ${CMAKE_CURRENT_BINARY_DIR}/flecs)
include(../../cmake/target_default_compile_options.cmake)
include(../../cmake/target_default_compile_warnings.cmake)
include(../../cmake/target_default_compile_functions.cmake)
list_targets(EXAMPLES)
foreach (EXAMPLE ${EXAMPLES})
create_target_cxx(${EXAMPLE} "")
create_target_cxx(${EXAMPLE} "static")
endforeach ()

View File

@@ -0,0 +1,5 @@
.bake_cache
.DS_Store
.vscode
gcov
bin

View File

@@ -0,0 +1,16 @@
#ifndef BASICS_H
#define BASICS_H
/* This generated file contains includes for project dependencies */
#include "basics/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 BASICS_BAKE_CONFIG_H
#define BASICS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,12 @@
{
"id": "basics",
"type": "application",
"value": {
"author": "Jane Doe",
"description": "A simple hello world flecs application",
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,53 @@
#include <basics.h>
#include <iostream>
struct Position {
double x, y;
};
struct Walking { };
int main(int, char *[]) {
flecs::world ecs;
// Create an entity with name Bob
flecs::entity bob = ecs.entity("Bob")
// The set operation finds or creates a component, and sets it.
// Components are automatically registered with the world.
.set<Position>({10, 20})
// The add operation adds a component without setting a value. This is
// useful for tags, or when adding a component with its default value.
.add<Walking>();
// Get the value for the Position component
const Position* ptr = bob.get<Position>();
std::cout << "{" << ptr->x << ", " << ptr->y << "}" << "\n";
// Overwrite the value of the Position component
bob.set<Position>({20, 30});
// Create another named entity
flecs::entity alice = ecs.entity("Alice")
.set<Position>({10, 20});
// Add a tag after entity is created
alice.add<Walking>();
// Print all of the components the entity has. This will output:
// Position, Walking, (Identifier,Name)
std::cout << "[" << alice.type().str() << "]" << "\n";
// Remove tag
alice.remove<Walking>();
// Iterate all entities with Position
ecs.each([](flecs::entity e, Position& p) {
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}" << "\n";
});
// Output
// {10, 20}
// [Position, Walking, (Identifier,Name)]
// Alice: {10, 20}
// Bob: {20, 30}
}

View File

@@ -0,0 +1,16 @@
#ifndef EMPLACE_H
#define EMPLACE_H
/* This generated file contains includes for project dependencies */
#include "emplace/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 EMPLACE_BAKE_CONFIG_H
#define EMPLACE_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "emplace",
"type": "application",
"value": {
"use": [
"flecs"
],
"public": false,
"language": "c++"
}
}

View File

@@ -0,0 +1,28 @@
#include <emplace.h>
#include <iostream>
// The emplace method constructs a component directly in the storage vs. a
// regular set, which moves the value into an already constructed value in the
// storage. This reduces the overhead of creating a new component.
//
// Components that do not have a default constructor need to be created with
// emplace, as they can't be constructed automatically by flecs.
struct NoDefaultCtor {
NoDefaultCtor(double x_, double y_) : x(x_), y(y_) { }
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
flecs::entity e = ecs.entity()
.emplace<NoDefaultCtor>(10.0, 20.0);
const NoDefaultCtor *ptr = e.get<NoDefaultCtor>();
std::cout << "{" << ptr->x << ", " << ptr->y << "}" << "\n";
// Output
// {10, 20}
}

View File

@@ -0,0 +1,5 @@
.bake_cache
.DS_Store
.vscode
gcov
bin

View File

@@ -0,0 +1,16 @@
#ifndef HIERARCHY_H
#define HIERARCHY_H
/* This generated file contains includes for project dependencies */
#include "hierarchy/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 HIERARCHY_BAKE_CONFIG_H
#define HIERARCHY_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,12 @@
{
"id": "hierarchy",
"type": "application",
"value": {
"author": "Jane Doe",
"description": "A simple hello world flecs application",
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,65 @@
#include <hierarchy.h>
#include <iostream>
struct Position {
double x, y;
};
struct Star { };
struct Planet { };
struct Moon { };
void iterate_tree(flecs::entity e, Position p_parent = {0, 0}) {
// Print hierarchical name of entity & the entity type
std::cout << e.path() << " [" << e.type().str() << "]\n";
// Get entity position
const Position *p = e.get<Position>();
// Calculate actual position
Position p_actual = {p->x + p_parent.x, p->y + p_parent.y};
std::cout << "{" << p_actual.x << ", " << p_actual.y << "}\n\n";
// Iterate children recursively
e.children([&](flecs::entity child) {
iterate_tree(child, p_actual);
});
}
int main(int, char *[]) {
flecs::world ecs;
// Create a simple hierarchy.
// Hierarchies use ECS relationships and the builtin flecs::ChildOf relationship to
// create entities as children of other entities.
flecs::entity sun = ecs.entity("Sun")
.add<Star>()
.set<Position>({1, 1});
ecs.entity("Mercury")
.child_of(sun) // Shortcut for add(flecs::ChildOf, sun)
.add<Planet>()
.set<Position>({1, 1});
ecs.entity("Venus")
.child_of(sun)
.add<Planet>()
.set<Position>({2, 2});
flecs::entity earth = ecs.entity("Earth")
.child_of(sun)
.add<Planet>()
.set<Position>({3, 3});
flecs::entity moon = ecs.entity("Moon")
.child_of(earth)
.add<Moon>()
.set<Position>({0.1, 0.1});
// Is the Moon a child of Earth?
std::cout << "Child of Earth? " << moon.has(flecs::ChildOf, earth) << "\n\n";
// Do a depth-first walk of the tree
iterate_tree(sun);
}

View File

@@ -0,0 +1,5 @@
.bake_cache
.DS_Store
.vscode
gcov
bin

View File

@@ -0,0 +1,16 @@
#ifndef HOOKS_H
#define HOOKS_H
/* This generated file contains includes for project dependencies */
#include "hooks/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 HOOKS_BAKE_CONFIG_H
#define HOOKS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,10 @@
{
"id": "hooks",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,108 @@
#include <hooks.h>
#include <iostream>
// Component hooks are callbacks that can be registered for a type that are
// invoked during different parts of the component lifecycle.
//
// In the C++ API the ctor, dtor, copy and move methods of a type are
// automatically registered as component hooks.
struct String {
String(const char *v = nullptr) {
flecs::log::trace("Ctor(const char*)");
value = ecs_os_strdup(v);
}
~String() {
flecs::log::trace("Dtor");
ecs_os_free(value);
}
String(const String& obj) {
flecs::log::trace("Copy");
value = ecs_os_strdup(obj.value);
}
String(String&& obj) {
flecs::log::trace("Move");
value = obj.value;
obj.value = nullptr;
}
String& operator=(const String& obj) {
flecs::log::trace("Copy assign");
ecs_os_free(value);
value = ecs_os_strdup(obj.value);
return *this;
}
String& operator=(String&& obj) {
flecs::log::trace("Move assign");
ecs_os_free(value);
value = obj.value;
obj.value = nullptr;
return *this;
}
char *value;
};
struct Tag { };
int main(int, char *[]) {
flecs::world ecs;
// Register additional add, remove and set hooks for type
ecs.component<String>()
.on_add([](flecs::entity e, String&) {
flecs::log::trace("OnAdd: %s", e.name().c_str());
})
.on_remove([](flecs::entity e, String&) {
flecs::log::trace("OnRemove: %s", e.name().c_str());
})
.on_set([](flecs::entity e, String&) {
flecs::log::trace("OnSet: %s", e.name().c_str());
});
// Register in advance to keep output trace clean
ecs.component<Tag>();
flecs::log::set_level(0);
flecs::entity e = ecs.entity("Entity");
flecs::log::push("e.add<String>()");
e.add<String>();
flecs::log::pop();
flecs::log::push("e.set<String>({\"Hello World\"})");
e.set<String>({"Hello World"});
flecs::log::pop();
// This operation changes the entity's archetype, which invokes a move
flecs::log::push("e.add<Tag>()");
e.add<Tag>();
flecs::log::pop();
flecs::log::push("e.destruct()");
e.destruct();
flecs::log::pop();
flecs::log::set_level(-1);
// Output:
// info: e.add<String>()
// info: | Ctor
// info: | OnAdd: Entity
// info: e.set<String>({"Hello World"})
// info: | Ctor
// info: | Move assign
// info: | OnSet: Entity
// info: | Dtor
// info: e.add<Tag>()
// info: | Move
// info: | Dtor
// info: e.destruct()
// info: | OnRemove: Entity
// info: | Dtor
}

View File

@@ -0,0 +1,16 @@
#ifndef ITERATE_COMPONENTS_H
#define ITERATE_COMPONENTS_H
/* This generated file contains includes for project dependencies */
#include "iterate_components/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 ITERATE_COMPONENTS_BAKE_CONFIG_H
#define ITERATE_COMPONENTS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,13 @@
{
"id": "iterate_components",
"type": "application",
"value": {
"author": "Jane Doe",
"description": "A simple hello world flecs application",
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,99 @@
#include <iterate_components.h>
#include <iostream>
// Ordinary components
struct Position {
double x, y;
};
struct Velocity {
double x, y;
};
// Tag
struct Human { };
// Two tags used to create a pair
struct Eats { };
struct Apples { };
void iterate_components(flecs::entity e) {
// 1. The easiest way to print the components is to use type::str
std::cout << e.type().str() << "\n\n";
// 2. To get individual component ids, use entity::each
int32_t i = 0;
e.each([&](flecs::id id) {
std::cout << i++ << ": " << id.str() << "\n";
});
std::cout << "\n";
// 3. we can also inspect and print the ids in our own way. This is a
// bit more complicated as we need to handle the edge cases of what can be
// encoded in an id, but provides the most flexibility.
i = 0;
e.each([&](flecs::id id) {
std::cout << i++ << ": ";
if (id.is_pair()) {
// If id is a pair, extract & print both parts of the pair
flecs::entity rel = id.first();
flecs::entity tgt = id.second();
std::cout << "rel: " << rel.name() << ", " << "tgt: " << tgt.name();
} else {
// Id contains a regular entity. Strip role before printing.
flecs::entity comp = id.entity();
std::cout << "entity: " << comp.name();
}
std::cout << "\n";
});
std::cout << "\n\n";
}
int main(int, char *[]) {
flecs::world ecs;
flecs::entity bob = ecs.entity()
.set<Position>({10, 20})
.set<Velocity>({1, 1})
.add<Human>()
.add<Eats, Apples>();
std::cout << "Bob's components:\n";
iterate_components(bob);
// We can use the same function to iterate the components of a component
std::cout << "Position's components:\n";
iterate_components(ecs.component<Position>());
}
// Output:
// Bob's components:
// Position, Velocity, Human, (Eats,Apples)
//
// 0: Position
// 1: Velocity
// 2: Human
// 3: (Eats,Apples)
//
// 0: entity: Position
// 1: entity: Velocity
// 2: entity: Human
// 3: rel: Eats, tgt: Apples
//
//
// Position's components:
// Component, (Identifier,Name), (Identifier,Symbol), (OnDelete,Panic)
//
// 0: Component
// 1: (Identifier,Name)
// 2: (Identifier,Symbol)
// 3: (OnDelete,Panic)
//
// 0: entity: Component
// 1: rel: Identifier, tgt: Name
// 2: rel: Identifier, tgt: Symbol
// 3: rel: OnDelete, tgt: Panic

View File

@@ -0,0 +1,16 @@
#ifndef MULTI_SET_GET_H
#define MULTI_SET_GET_H
/* This generated file contains includes for project dependencies */
#include "multi_set_get/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 MULTI_SET_GET_BAKE_CONFIG_H
#define MULTI_SET_GET_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "multi_set_get",
"type": "application",
"value": {
"use": [
"flecs"
],
"public": false,
"language": "c++"
}
}

View File

@@ -0,0 +1,39 @@
#include <multi_set_get.h>
#include <iostream>
/* This code shows how to get & set multiple components in a single command */
struct Position {
double x, y;
};
struct Mass {
double value;
};
int main(int, char *[]) {
flecs::world ecs;
// Create new entity, set Position and Mass component
flecs::entity e = ecs.entity()
.set([](Position& p, Mass& m) {
p.x = 10;
p.y = 20;
m.value = 100;
});
// Print values of Position and Mass component
bool found = e.get([](const Position& p, const Mass& m) {
std::cout << "Position: {" << p.x << ", " << p.y << "}\n"
<< "Mass: {" << m.value << "}\n";
});
std::cout << "Components found: " << (found ? "true" : "false") << "\n";
// Output:
// Position: {10, 20}
// Mass: {100}
// Components found: true
return 0;
}

View File

@@ -0,0 +1,5 @@
.bake_cache
.DS_Store
.vscode
gcov
bin

View File

@@ -0,0 +1,16 @@
#ifndef PREFAB_H
#define PREFAB_H
/* This generated file contains includes for project dependencies */
#include "prefab/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 PREFAB_BAKE_CONFIG_H
#define PREFAB_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,12 @@
{
"id": "prefab",
"type": "application",
"value": {
"author": "Jane Doe",
"description": "A simple hello world flecs application",
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,70 @@
#include <prefab.h>
#include <iostream>
// Prefabs are entities that can be used as templates for other entities. They
// are created with a builtin Prefab tag, which by default excludes them from
// queries and systems.
struct Attack { double value; };
struct Defense { double value; };
struct FreightCapacity { double value; };
struct ImpulseSpeed { double value; };
struct HasFTL { };
struct Position { double x = 0; double y = 0; };
int main(int, char *[]) {
flecs::world ecs;
// Create a prefab hierarchy.
flecs::entity spaceship = ecs.prefab("Spaceship")
// Add components to prefab entity as usual
.set<ImpulseSpeed>({50})
.set<Defense>({50})
// By default components in an inheritance hierarchy are shared between
// entities. The override function ensures that instances have a private
// copy of the component.
.override<Position>();
flecs::entity freighter = ecs.prefab("Freighter")
// Short for .add(flecs::IsA, spaceship). This ensures the entity
// inherits all components from spaceship.
.is_a(spaceship)
.add<HasFTL>()
.set<FreightCapacity>({100})
.set<Defense>({100});
flecs::entity mammoth_freighter = ecs.prefab("MammothFreighter")
.is_a(freighter)
.set<FreightCapacity>({500})
.set<Defense>({300});
ecs.prefab("Frigate")
.is_a(spaceship)
.add<HasFTL>()
.set<Attack>({100})
.set<Defense>({75})
.set<ImpulseSpeed>({125});
// Create a regular entity from a prefab.
// The instance will have a private copy of the Position component, because
// of the override in the spaceship entity. All other components are shared.
flecs::entity inst = ecs.entity("my_mammoth_freighter")
.is_a(mammoth_freighter);
// Inspect the type of the entity. This outputs:
// Position,(Identifier,Name),(IsA,MammothFreighter)
std::cout << "Instance type: [" << inst.type().str() << "]\n";
// Even though the instance doesn't have a private copy of ImpulseSpeed, we
// can still get it using the regular API (outputs 50)
const ImpulseSpeed *ptr = inst.get<ImpulseSpeed>();
std::cout << "Impulse speed: " << ptr->value << "\n";
// Prefab components can be iterated just like regular components:
ecs.each([](flecs::entity e, ImpulseSpeed& is, Position& p) {
p.x += is.value;
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
});
}

View File

@@ -0,0 +1,16 @@
#ifndef EXPLORER_H
#define EXPLORER_H
/* This generated file contains includes for project dependencies */
#include "explorer/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 EXPLORER_BAKE_CONFIG_H
#define EXPLORER_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "explorer",
"type": "application",
"value": {
"public": false,
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,37 @@
#include <explorer.h>
#include <iostream>
using mass = flecs::units::mass;
struct Mass {
double value;
};
int main(int argc, char *argv[]) {
// Passing in the command line arguments will allow the explorer to display
// the application name.
flecs::world world(argc, argv);
world.import<flecs::units>();
world.import<flecs::monitor>(); // Collect statistics periodically
// Mass component
world.component<Mass>()
.member<double, mass::KiloGrams>("value");
// Simple hierarchy
flecs::entity Sun = world.entity("Sun")
.set<Mass>({1.988500e31});
flecs::entity Earth = world.scope(Sun).entity("Earth")
.set<Mass>({5.9722e24});
world.scope(Earth).entity("Moon")
.set<Mass>({7.34767309e22});
// Run application with REST interface. When the application is running,
// navigate to https://flecs.dev/explorer to inspect it!
//
// See docs/RestApi.md#explorer for more information.
return world.app().enable_rest().run();
}

View File

@@ -0,0 +1,16 @@
#ifndef FACTORY_H
#define FACTORY_H
/* This generated file contains includes for project dependencies */
#include "factory/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 FACTORY_BAKE_CONFIG_H
#define FACTORY_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,10 @@
{
"id": "factory",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,53 @@
using factories
resources {
// Ore stacks can contain 50 items
with StackCount{50} {
// Raw materials can't be produced
Copper
Iron
Aluminium
Steel {
- Requires[{Iron, 1}]
- TimeToProduce{2}
- StackCount{50}
}
}
Gear {
- Requires[{Iron, 1}]
- TimeToProduce{1}
- StackCount{100}
}
Circuit {
- Requires[{Iron, 1}, {Copper, 3}]
- TimeToProduce{2}
- StackCount{100}
}
SolarPanel {
- Requires[{Copper, 5}, {Circuit, 15}, {Steel, 5}]
- TimeToProduce{10}
- StackCount{20}
}
HullMaterial {
- Requires[{Aluminium, 10}, {Copper, 5}, {Steel, 20}]
- TimeToProduce{10}
- StackCount{20}
}
Radar {
- Requires[{Gear, 5}, {Circuit, 5}, {Iron, 10}]
- TimeToProduce{20}
- StackCount{1}
}
Satellite {
- Requires[{HullMaterial, 10}, {SolarPanel, 5}, {Radar, 1}]
- TimeToProduce{30}
- StackCount{1}
}
}

View File

@@ -0,0 +1,79 @@
using factories
using resources
// Resource depots
depot {
iron {
- (Stores, Iron){amount: 5000}
}
copper {
- (Stores, Copper){amount: 5000}
}
aluminium {
- (Stores, Aluminium){amount: 5000}
}
gear {
- (Stores, Gear){amount: 0}
}
steel {
- (Stores, Steel){amount: 0}
}
circuit {
- (Stores, Circuit){amount: 0}
}
}
// Factories
factory {
with Factory{ recipe: Gear, inputs: [depot.iron], output: depot.gear } {
gear_1
gear_2
}
with Factory{recipe: Steel, inputs: [depot.iron], output: depot.steel} {
steel_1
steel_2
steel_3
steel_4
steel_5
steel_6
}
with Factory{recipe: Circuit, inputs: [depot.iron, depot.copper], output: depot.circuit } {
circuit_1
circuit_2
}
radar {
- Factory{
recipe: Radar,
inputs: [depot.gear, depot.circuit, depot.iron]
}
}
solar_panel {
- Factory{
recipe: SolarPanel,
inputs: [depot.copper, depot.circuit, depot.steel]
}
}
hull {
- Factory{
recipe: HullMaterial,
inputs: [depot.aluminium, depot.copper, depot.steel]
}
}
satellite {
- Factory{
recipe: Satellite,
inputs: [hull, solar_panel, radar]
}
}
}

View File

@@ -0,0 +1,343 @@
#include <factory.h>
#include <iostream>
// This example shows how a simple production hierarchy can be simulated in ECS.
// The example has the following concepts:
//
// - A recipe describes the requirements and time required to produce a resource
// - Factories produce resources based on an assigned recipe
// - Depots store resources
//
// A factory needs to be connected to inputs that provide the resource. Once the
// inputs are connected correctly, the factory will start producing the resource
// once it has collected all of the required resources from the inputs.
//
// Factories can act as inputs for other factories. Depots can be used to
// combine the output of multiple factories.
//
// The resource definitions and scene are loaded at runtime from resource.flecs
// and scene.flecs.
//
// Few notes:
// - The demo doesn't have graphics, but can be viewed with the explorer.
// - Components store references to entities as entity_t's. They could also
// flecs::entity's, but this requires a bit less memory.
// - Some data is duplicated between resource and factory components so that
// systems can mostly operate on local data
//
using namespace flecs;
// Factory module
struct factories {
// Maximum number of resources a recipe can depend on
static constexpr int MaxInputs = 3;
// -- Recipe components
// Single resource requirement for a recipe
struct Requirement {
entity_t resource;
int32_t amount;
};
// All resource requirements for a recipe
struct Requires {
Requirement items[MaxInputs];
};
// Time it takes to produce a resource
struct TimeToProduce {
float value;
};
// Limit how many items can be stacked for a specific resource
struct StackCount {
int32_t amount;
};
// -- Depot & Factory components
// Resource storage
struct Stores {
int32_t amount;
};
// Factory configuration
struct Factory {
// Recipe for the resource to produce
entity_t recipe;
// Must provide resources as specified by recipe
entity_t inputs[MaxInputs];
// Optional output which allows a factory to forward items to a depot
entity_t output;
};
// Factory state
enum class FactoryState {
// Factory isn't connected to (correct) inputs yet
Idle,
// Factory is connected, but doesn't have the required resources yet
WaitingForResources,
// Factory is producing resource
Producing,
// Factory is done producing
TransferResource
};
// Tracks which resources have been supplied to factory
struct FactorySupply {
int32_t required[MaxInputs];
int32_t collected[MaxInputs];
flecs::ref<Stores> inputs[MaxInputs];
flecs::ref<Stores> output;
};
// Track production progress
struct FactoryProduction {
float value;
float duration;
int32_t max_stack;
};
// Module import function
factories(world& world) {
// Units improve visualization of component values in the explorer.
world.import<flecs::units>();
// -- Component registration
// Reflection data is registered so we can view the components from the
// explorer and assign them from .flecs files.
world.component<Stores>()
.member<int32_t>("amount");
world.component<Requirement>()
.member(flecs::Entity, "resource")
.member<int32_t>("amount");
world.component<Requires>()
.array<Requirement>(3);
world.component<FactorySupply>()
.member<int32_t>("required", 3)
.member<int32_t>("collected", 3);
world.component<TimeToProduce>()
.member<float, units::duration::Seconds>("value");
world.component<StackCount>()
.member<int32_t>("amount");
world.component<FactoryProduction>()
.member<float, units::Percentage>("value")
.member<float, units::duration::Seconds>("duration")
.member<int32_t>("max_stack");
world.component<Factory>()
// Factories start out idle
.on_add([](entity factory, Factory) {
factory.add(FactoryState::Idle);
})
// Check if factory is properly setup when value is assigned to component
.on_set(factory_init)
.member(flecs::Entity, "recipe")
.member(flecs::Entity, "inputs", 3)
.member(flecs::Entity, "output");
// System that collects resources from inputs
world.system<FactorySupply>("Collect")
.with(FactoryState::WaitingForResources)
.interval(1.0f)
.each([](entity factory, FactorySupply& s) {
bool satisfied = true;
for (int i = 0; i < MaxInputs; i ++) {
int32_t needed = s.required[i] - s.collected[i];
if (needed) {
Stores *p = s.inputs[i].get();
if (p->amount >= needed) {
s.collected[i] += needed;
p->amount -= needed;
} else {
s.collected[i] += p->amount;
p->amount = 0;
satisfied = false;
}
}
}
// If all resources are satisfied, change state of factory to producing
if (satisfied) {
// Consume collected resources
for (int i = 0; i < MaxInputs; i ++) {
s.collected[i] = 0;
}
factory.add(FactoryState::Producing);
}
});
// System that produces a resource once all input requirements are met
world.system<FactoryProduction>("Produce")
.with(FactoryState::Producing)
.interval(0.1f)
.each([](flecs::iter& it, size_t i, FactoryProduction& p) {
p.value += it.delta_system_time() / p.duration;
if (p.value >= 1) {
p.value = 1;
it.entity(i).add(FactoryState::TransferResource);
}
});
// System that transfers resource and resets factory for next item
world.system<FactorySupply, FactoryProduction, Stores>("Transfer")
.term_at(3).second(Wildcard)
.with(FactoryState::TransferResource)
.interval(1.0f)
.each([](entity factory, FactorySupply& s, FactoryProduction& p, Stores& out) {
// Reset production progress
p.value = 0;
// If depot is configured, transfer local resources first
Stores *depot = s.output.try_get();
if (depot) {
int32_t available_space = p.max_stack - depot->amount;
if (out.amount > available_space) {
depot->amount += available_space;
out.amount -= available_space;
} else {
depot->amount += out.amount;
out.amount = 0;
}
}
// Now check which storage to output the new resource item to. If a
// depot is configured, attempt to store it there, otherwise store it
// in factory.
Stores *store = &out;
if (depot) {
if (!p.max_stack || (depot->amount < p.max_stack)) {
store = depot;
}
}
if (store->amount < p.max_stack) {
// Add resource to storage and go back to collecting resources
store->amount ++;
factory.add(FactoryState::WaitingForResources);
} else {
// No space in output, do nothing
}
});
}
private:
// on_set hook for Factory component. When Factory component value is written,
// check if the factory has a recipe and whether the factory inputs satisfy
// the recipe requirements.
static void factory_init(entity factory, Factory& config) {
world world = factory.world();
entity recipe = world.entity(config.recipe);
recipe.get([&](const Requires& r) {
entity output = world.entity(config.output);
if (output) {
if (!output.has<Stores>(recipe)) {
std::cout << factory.path() << ": output doesn't provide resource "
<< recipe.path() << "\n";
return;
}
}
// For each recipe requirement, make sure a correct input is connected
bool satisfied = true;
for (int i = 0; i < MaxInputs; i ++) {
entity resource = world.entity(r.items[i].resource);
entity input = world.entity(config.inputs[i]);
if (!resource) {
if (input) {
std::cout << factory.path() <<
": input connected to empty input slot\n";
}
continue;
}
if (resource && !input) {
satisfied = false;
break;
}
if (!input.has<Stores>(resource)) {
std::cout << factory.path() << ": input doesn't provide resource "
<< recipe.path() << "\n";
satisfied = false;
break;
}
}
// If we got through all requirements without issues, factory is ready
// to start collecting resources
if (satisfied) {
factory.add(FactoryState::WaitingForResources);
// Initialize supply component
factory.set([&](FactorySupply& s) {
for (int i = 0; i < MaxInputs; i ++) {
entity resource = world.entity(r.items[i].resource);
entity input = world.entity(config.inputs[i]);
int32_t amount = r.items[i].amount;
s.required[i] = amount;
s.collected[i] = 0;
if (!resource) {
continue;
}
// Take a ref to the resource provider for the factory input. Refs
// provide quick and convenient access for repeatedly accessing a
// component from the same entity.
s.inputs[i] = input.get_ref<Stores>(resource);
}
if (output) {
// If the factory has an output configured, also take a ref to it so
// we can quickly add the produced resources to it.
s.output = output.get_ref<Stores>(recipe);
}
});
// Add component that tracks how much time is left to produce a resource
recipe.get([&](const TimeToProduce& ttp, const StackCount& sc) {
factory.set<FactoryProduction>({ 0, ttp.value, sc.amount });
});
// Set output resource for factory
factory.add<Stores>(recipe);
}
});
}
};
int main(int argc, char *argv[]) {
flecs::world world(argc, argv);
world.import<factories>();
ecs_plecs_from_file(world, "resources.flecs");
ecs_plecs_from_file(world, "scene.flecs");
return world.app()
.enable_rest()
.target_fps(60)
.delta_time(1.0f / 60.0f) // Run at fixed time step
.run();
}

View File

@@ -0,0 +1,16 @@
#ifndef INVENTORY_SYSTEM_H
#define INVENTORY_SYSTEM_H
/* This generated file contains includes for project dependencies */
#include "inventory_system/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 INVENTORY_SYSTEM_BAKE_CONFIG_H
#define INVENTORY_SYSTEM_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "inventory_system",
"type": "application",
"value": {
"use": [
"flecs"
],
"public": false,
"language": "c++"
}
}

View File

@@ -0,0 +1,371 @@
#include <inventory_system.h>
#include <iostream>
// This example shows one possible way to implement an inventory system using
// ECS relationships.
// Inventory tags/relationships
struct Item { }; // Base item type
struct Container { }; // Container tag
struct Inventory { }; // Inventory tag
struct ContainedBy { }; // ContainedBy relationship
// Item / unit properties
struct Active { }; // Item is active/worn
struct Amount {
int value; // Number of items the instance represents
};
struct Health {
int value; // Health of the item
};
struct Attack {
int value; // Amount of damage an item deals per use
};
// Items
struct Sword : Item { };
struct Armor : Item { };
struct Coin : Item { };
// Item prefab types
struct WoodenSword { };
struct IronSword { };
struct WoodenArmor { };
struct IronArmor { };
// Find Item kind of entity
flecs::entity item_kind(flecs::entity item) {
flecs::world world = item.world();
flecs::entity result;
item.each([&](flecs::id id) {
if (id.is_entity()) {
// If id is a plain entity (component), check if component inherits
// from Item
if (id.entity().has(flecs::IsA, world.id<Item>())) {
result = id.entity();
}
} else if (id.is_pair()) {
// If item has a base entity, check if the base has an attribute
// that is an Item.
if (id.first() == flecs::IsA) {
flecs::entity base_kind = item_kind(id.second());
if (base_kind) {
result = base_kind;
}
}
}
});
return result;
}
// Almost the same as item_kind, but return name of prefab vs item kind. This
// returns a more user-friendly name, like "WoodenSword" vs. just "Sword"
const char* item_name(flecs::entity item) {
flecs::world world = item.world();
const char *result = NULL;
item.each([&](flecs::id id) {
if (id.is_entity()) {
if (id.entity().has(flecs::IsA, world.id<Item>())) {
result = id.entity().name();
}
} else if (id.is_pair()) {
if (id.first() == flecs::IsA) {
flecs::entity base_kind = item_kind(id.second());
if (base_kind) {
result = id.second().name();
}
}
}
});
return result;
}
// If entity is not a container, get its inventory
flecs::entity get_container(flecs::entity container) {
if (container.has<Container>()) {
return container;
}
return container.target<Inventory>();
}
// Iterate all items in an inventory
template <typename Func>
void for_each_item(flecs::entity container, const Func& func) {
container.world().filter_builder()
.with<ContainedBy>(container)
.build()
.each(func);
}
// Find item in inventory of specified kind
flecs::entity find_item_w_kind(
flecs::entity container, flecs::entity kind, bool active_required = false)
{
flecs::entity result;
container = get_container(container);
for_each_item(container, [&](flecs::entity item) {
// Check if we should only return active items. This is useful when
// searching for an item that needs to be equipped.
if (active_required) {
if (!item.has<Active>()) {
return;
}
}
flecs::entity ik = item_kind(item);
if (ik == kind) {
result = item;
}
});
return result;
}
// Transfer item to container
void transfer_item(flecs::entity container, flecs::entity item) {
const Amount *amt = item.get<Amount>();
if (amt) {
// If item has amount we need to check if the container already has an
// item of this kind, and increase the value.
flecs::world ecs = container.world();
flecs::entity ik = item_kind(item);
flecs::entity dst_item = find_item_w_kind(container, ik);
if (dst_item) {
// If a matching item was found, increase its amount
Amount *dst_amt = dst_item.get_mut<Amount>();
dst_amt->value += amt->value;
item.destruct(); // Remove the src item
return;
} else {
// If no matching item was found, fallthrough which will move the
// item from the src container to the dst container
}
}
// Move item to target container (replaces previous ContainedBy, if any)
item.add<ContainedBy>(container);
}
// Move items from one container to another
void transfer_items(flecs::entity dst, flecs::entity src) {
std::cout << ">> Transfer items from "
<< src.name() << " to " << dst.name() << "\n\n";
// Defer, because we're adding/removing components while we're iterating
dst.world().defer([&] {
dst = get_container(dst); // Make sure to replace players with container
src = get_container(src);
for_each_item(src, [&](flecs::entity item) {
transfer_item(dst, item);
});
});
}
// Attack player
void attack(flecs::entity player, flecs::entity weapon) {
flecs::world ecs = player.world();
std::cout << ">> " << player.name() << " is attacked with a "
<< item_name(weapon) << "!\n";
const Attack *att = weapon.get<Attack>();
if (!att) {
// A weapon without Attack power? Odd.
std::cout << " - the weapon is a dud\n";
return;
}
int att_value = att->value;
// Get armor item, if player has equipped any
flecs::entity armor = find_item_w_kind(player, ecs.entity<Armor>(), true);
if (armor) {
Health *armor_health = armor.get_mut<Health>();
if (!armor_health) {
// Armor without Defense power? Odd.
std::cout << " - the " << item_name(armor) << " armor is a dud\n";
} else {
std::cout << " - " << player.name() << " defends with "
<< item_name(armor) << "\n";
// Subtract attack from armor health. If armor health goes below
// zero, delete the armor and carry over remaining attack points.
armor_health->value -= att_value;
if (armor_health->value <= 0) {
att_value += armor_health->value;
armor.destruct();
std::cout << " - " << item_name(armor) << " is destroyed!\n";
} else {
std::cout << " - " << item_name(armor) << " has "
<< armor_health->value << " health left after taking "
<< att_value << " damage\n";
att_value = 0;
}
}
} else {
// Brave but stupid
std::cout << " - " << player.name() << " fights without armor!\n";
}
// For each usage of the weapon, subtract one from its health
Health *weapon_health = weapon.get_mut<Health>();
if (!--weapon_health->value) {
std::cout << " - " << item_name(weapon) << " is destroyed!\n";
weapon.destruct();
} else {
std::cout << " - " << item_name(weapon) << " has "
<< weapon_health->value << " uses left";
}
// If armor didn't counter the whole attack, subtract from the player health
if (att_value) {
Health *player_health = player.get_mut<Health>();
if (!(player_health->value -= att_value)) {
std::cout << " - " << player.name() << " died!\n";
player.destruct();
} else {
std::cout << " - " << player.name() << " has "
<< player_health->value << " health left after taking "
<< att_value << " damage\n";
}
}
std::cout << "\n";
}
// Print items in inventory
void print_items(flecs::entity container) {
std::cout << "-- " << container.name() << "'s inventory:\n";
// In case the player entity was provided, make sure we're working with its
// inventory entity.
container = get_container(container);
int32_t count = 0;
for_each_item(container, [&](flecs::entity item) {
// Items with an Amount component fill up a single inventory slot but
// represent multiple instances, like coins.
int32_t amount = 1;
item.get([&](const Amount& amt) {
amount = amt.value;
});
std::cout << " - " << amount << " " << item_name(item);
if (amount > 1) std::cout << "s";
std::cout << " (" << item_kind(item).name() << ")\n";
count ++;
});
if (!count) {
std::cout << " - << empty >>\n";
}
std::cout << "\n";
}
int main(int, char *[]) {
flecs::world ecs;
// Register ContainedBy relationship
ecs.component<ContainedBy>()
.add(flecs::Exclusive); // Item can only be contained by one container
// Register item kinds
ecs.component<Sword>().is_a<Item>();
ecs.component<Armor>().is_a<Item>();
ecs.component<Coin>().is_a<Item>();
// Register item prefabs
ecs.prefab<WoodenSword>().add<Sword>()
.set<Attack>({ 1 })
.set_override<Health>({ 5 }); // copy to instance, don't share
ecs.prefab<IronSword>().add<Sword>()
.set<Attack>({ 2 })
.set_override<Health>({ 10 });
ecs.prefab<WoodenArmor>().add<Armor>()
.set_override<Health>({ 10 });
ecs.prefab<IronArmor>().add<Armor>()
.set_override<Health>({ 20 });
// Create a loot box with items
flecs::entity loot_box = ecs.entity("Chest").add<Container>().with<ContainedBy>([&]{
ecs.entity().is_a<IronSword>();
ecs.entity().is_a<WoodenArmor>();
ecs.entity().add<Coin>().set<Amount>({ 30 });
});
// Create a player entity with an inventory
flecs::entity player = ecs.entity("Player").set<Health>({10}).add<Inventory>(
ecs.entity().add<Container>().with<ContainedBy>([&]{
ecs.entity().add<Coin>().set<Amount>({ 20 });
})
);
// Print items in loot box
print_items(loot_box);
// Print items in player inventory
print_items(player);
// Copy items from loot box to player inventory
transfer_items(player, loot_box);
// Print items in player inventory after transfer
print_items(player);
// Print items in loot box after transfer
print_items(loot_box);
// Find armor entity & equip it
flecs::entity armor = find_item_w_kind(player, ecs.entity<Armor>());
if (armor) {
armor.add<Active>();
}
// Create a weapon to attack the player with
flecs::entity my_sword = ecs.entity()
.is_a<IronSword>();
// Attack player
attack(player, my_sword);
std::cout << "\n";
// Output
// -- Chest's inventory:
// - 1 IronSword (Sword)
// - 1 WoodenArmor (Armor)
// - 30 Coins (Coin)
// -- Player's inventory:
// - 20 Coins (Coin)
// >> Transfer items from Chest to Player
// -- Player's inventory:
// - 50 Coins (Coin)
// - 1 IronSword (Sword)
// - 1 WoodenArmor (Armor)
// -- Chest's inventory:
// - << empty >>
// >> Player is attacked with a IronSword!
// - Player defends with WoodenArmor
// - WoodenArmor has 8 health left after taking 2 damage
// - IronSword has 9 health left
}

View File

@@ -0,0 +1,16 @@
#ifndef SCENE_MANAGEMENT_H
#define SCENE_MANAGEMENT_H
/* This generated file contains includes for project dependencies */
#include "scene_management/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 SCENE_MANAGEMENT_BAKE_CONFIG_H
#define SCENE_MANAGEMENT_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "scene_management",
"type": "application",
"value": {
"use": [
"flecs"
],
"public": false,
"language": "c++"
}
}

View File

@@ -0,0 +1,190 @@
#include <scene_management.h>
#include <iostream>
#include <string>
// This example shows one possible way to implement scene management
// using pipelines.
// Scene relationships/tags
struct ActiveScene { }; // Represents the current scene
struct SceneRoot { }; // Parent for all entities unique to the scene
// Scenes
using Pipeline = flecs::entity;
struct MenuScene { Pipeline pip; };
struct GameScene { Pipeline pip; };
// Components for Example
struct Position { float x, y; };
struct Button { std::string text; };
struct Character { bool alive; };
struct Health { int amount; };
// Removes all entities who are children of
// the current scene root.
// (NOTE: should use defer_begin() / defer_end())
void reset_scene(flecs::world& ecs) {
ecs.delete_with(flecs::ChildOf, ecs.entity<SceneRoot>());
}
void menu_scene(flecs::iter& it, size_t, ActiveScene) {
std::cout << "\n>> ActiveScene has changed to `MenuScene`\n\n";
flecs::world ecs = it.world();
flecs::entity scene = ecs.component<SceneRoot>();
reset_scene(ecs);
// Creates a start menu button
// when we enter the menu scene.
ecs.entity("Start Button")
.set(Button{ "Play the Game!" })
.set(Position{ 50, 50 })
.child_of(scene);
ecs.set_pipeline(ecs.get<MenuScene>()->pip);
}
void game_scene(flecs::iter& it, size_t, ActiveScene) {
std::cout << "\n>> ActiveScene has changed to `GameScene`\n\n";
flecs::world ecs = it.world();
flecs::entity scene = ecs.component<SceneRoot>();
reset_scene(ecs);
// Creates a player character
// when we enter the game scene.
ecs.entity("Player")
.set(Character{ })
.set(Health{ 2 })
.set(Position{ 0, 0 })
.child_of(scene);
ecs.set_pipeline(ecs.get<GameScene>()->pip);
}
void init_scenes(flecs::world& ecs) {
// Can only have one active scene
// in a game at a time.
ecs.component<ActiveScene>()
.add(flecs::Exclusive);
// Each scene gets a pipeline that
// runs the associated systems plus
// all other scene-agnostic systems.
flecs::entity menu = ecs.pipeline()
.with(flecs::System)
.without<GameScene>() // Use "without()" of the other scenes
// so that we can run every system that
// doesn't have a scene attached to it.
.build();
flecs::entity game = ecs.pipeline()
.with(flecs::System)
.without<MenuScene>()
.build();
// Set pipeline entities on the scenes
// to easily find them later with get().
ecs.set<MenuScene>({ menu });
ecs.set<GameScene>({ game });
// Observer to call scene change logic for
// MenuScene when added to the ActiveScene.
ecs.observer<ActiveScene>("Scene Change to Menu")
.event(flecs::OnAdd)
.second<MenuScene>()
.each(menu_scene);
// Observer to call scene change logic for
// GameScene when added to the ActiveScene.
ecs.observer<ActiveScene>("Scene Change to Game")
.event(flecs::OnAdd)
.second<GameScene>()
.each(game_scene);
}
void init_systems(flecs::world& ecs) {
// Will run every time regardless of the
// current scene we're in.
ecs.system<const Position>("Print Position")
.each([](flecs::entity e, const Position& p) {
// Prints out the position of the
// entity.
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
});
// Will only run when the game scene is
// currently active.
ecs.system<Health>("Characters Lose Health")
.kind<GameScene>()
.each([](Health& h) {
// Prints out the character's health
// and then decrements it by one.
std::cout << h.amount << " health remaining\n";
h.amount--;
});
// Will only run when the menu scene is
// currently active.
ecs.system<const Button>("Print Menu Button Text")
.kind<MenuScene>()
.each([](const Button& b) {
// Prints out the text of the menu
// button.
std::cout << "Button says \"" << b.text << "\"\n";
});
}
int main(int, char *[]) {
flecs::world ecs;
init_scenes(ecs);
init_systems(ecs);
ecs.add<ActiveScene, MenuScene>();
ecs.progress();
ecs.add<ActiveScene, GameScene>();
ecs.progress();
ecs.progress();
ecs.progress();
ecs.add<ActiveScene, MenuScene>();
ecs.progress();
ecs.add<ActiveScene, GameScene>();
ecs.progress();
ecs.progress();
ecs.progress();
// Output
// >> ActiveScene has changed to `MenuScene`
// Start Button: {50, 50}
// Button says "Play the Game!"
// >> ActiveScene has changed to `GameScene`
// Player: {0, 0}
// 2 health remaining
// Player: {0, 0}
// 1 health remaining
// Player: {0, 0}
// 0 health remaining
// >> ActiveScene has changed to `MenuScene`
// Start Button: {50, 50}
// Button says "Play the Game!"
// >> ActiveScene has changed to `GameScene`
// Player: {0, 0}
// 2 health remaining
// Player: {0, 0}
// 1 health remaining
// Player: {0, 0}
// 0 health remaining
}

View File

@@ -0,0 +1,5 @@
.bake_cache
.DS_Store
.vscode
gcov
bin

View File

@@ -0,0 +1,16 @@
#ifndef HELLO_WORLD_H
#define HELLO_WORLD_H
/* This generated file contains includes for project dependencies */
#include "hello_world/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 HELLO_WORLD_BAKE_CONFIG_H
#define HELLO_WORLD_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,12 @@
{
"id": "hello_world",
"type": "application",
"value": {
"author": "Jane Doe",
"description": "A simple hello world flecs application",
"use": [
"flecs"
],
"language": "c++"
}
}

View File

@@ -0,0 +1,50 @@
#include <hello_world.h>
#include <iostream>
// Component types
struct Position {
double x;
double y;
};
struct Velocity {
double x;
double y;
};
// Tag types
struct Eats { };
struct Apples { };
int main(int, char *[]) {
// Create the world
flecs::world ecs;
// Register system
ecs.system<Position, Velocity>()
.each([](Position& p, Velocity& v) {
p.x += v.x;
p.y += v.y;
});
// Create an entity with name Bob, add Position and food preference
flecs::entity Bob = ecs.entity("Bob")
.set(Position{0, 0})
.set(Velocity{1, 2})
.add<Eats, Apples>();
// Show us what you got
std::cout << Bob.name() << "'s got [" << Bob.type().str() << "]\n";
// Run systems twice. Usually this function is called once per frame
ecs.progress();
ecs.progress();
// See if Bob has moved (he has)
const Position *p = Bob.get<Position>();
std::cout << Bob.name() << "'s position is {" << p->x << ", " << p->y << "}\n";
// Output
// Bob's got [Position, Velocity, (Identifier,Name), (Eats,Apples)]
// Bob's position is {2, 4}
}

View File

@@ -0,0 +1,32 @@
#ifndef SIMPLE_MODULE_H
#define SIMPLE_MODULE_H
/* This generated file contains includes for project dependencies */
#include "simple_module/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
namespace simple {
struct Position {
double x, y;
};
struct Velocity {
double x, y;
};
struct module {
module(flecs::world& world); // Ctor that loads the module
};
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 SIMPLE_MODULE_BAKE_CONFIG_H
#define SIMPLE_MODULE_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "simple_module",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,31 @@
#include <simple_module.h>
#include <iostream>
int main(int, char *[]) {
flecs::world ecs;
ecs.import<simple::module>();
// Create system that uses component from module
ecs.system<const simple::Position>("PrintPosition")
.each([](const simple::Position& p) {
std::cout << "p = {" << p.x << ", " << p.y << "} (system)\n";
});
// Create entity with imported components
flecs::entity e = ecs.entity()
.set<simple::Position>({10, 20})
.set<simple::Velocity>({1, 1});
// Call progress which runs imported Move system
ecs.progress();
// Use component from module in operation
e.get([](const simple::Position& p) {
std::cout << "p = {" << p.x << ", " << p.y << "} (get)\n";
});
// Output:
// p = {11.000000, 22.000000} (system)
// p = {11.000000, 22.000000} (get)
}

View File

@@ -0,0 +1,26 @@
#include <simple_module.h>
namespace simple {
module::module(flecs::world& ecs) {
// Register module with world. The module entity will be created with the
// same hierarchy as the C++ namespaces (e.g. simple.module)
ecs.module<module>();
// All contents of the module are created inside the module's namespace, so
// the Position component will be created as simple.module.Position
// Component registration is optional, however by registering components
// inside the module constructor, they will be created inside the scope
// of the module.
ecs.component<Position>();
ecs.component<Velocity>();
ecs.system<Position, const Velocity>("Move")
.each([](Position& p, const Velocity& v) {
p.x += v.x;
p.y += v.y;
});
}
}

View File

@@ -0,0 +1,16 @@
#ifndef BASICS_H
#define BASICS_H
/* This generated file contains includes for project dependencies */
#include "basics/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 BASICS_BAKE_CONFIG_H
#define BASICS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "basics",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,68 @@
#include <basics.h>
#include <iostream>
// Observers provide a mechanism for responding to builtin and user defined
// events. They are similar to systems, in that they have the same callback
// signature and use the same query interface to match with entities, but
// instead of a phase they have an event kind.
//
// The most commonly used builtin events are:
// - flecs::OnAdd: a component was added
// - flecs::OnRemove: a component was removed
// - flecs::OnSet: a component's value was changed
//
// The OnAdd and OnRemove events are only thrown when a component is
// actually added or removed. If an application invokes add and the entity
// already has the component, no event is emitted. Similarly, if an application
// invokes remove for a component the entity doesn't have, no event is
// emitted. That is in contrast to OnSet, which is invoked each time set
// or modified is invoked.
//
// Observers are different from component hooks in a number of ways:
// - A component can only have one hook, whereas it can match many observers
// - A hook matches one component, whereas observers can match complex queries
// - Hooks are for add/set/remove events, observers can match custom events.
struct Position {
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
// Create an observer for three events
ecs.observer<Position>()
.event(flecs::OnAdd)
.event(flecs::OnRemove)
.event(flecs::OnSet)
.each([](flecs::iter& it, size_t i, Position& p) {
if (it.event() == flecs::OnAdd) {
// No assumptions about the component value should be made here. If
// a ctor for the component was registered it will be called before
// the EcsOnAdd event, but a value assigned by set won't be visible.
std::cout << " - OnAdd: " << it.event_id().str() << ": "
<< it.entity(i).name() << "\n";
} else {
// EcsOnSet or EcsOnRemove event
std::cout << " - " << it.event().name() << ": "
<< it.event_id().str() << ": "
<< it.entity(i).name()
<< ": {" << p.x << ", " << p.y << "}\n";
}
});
// Create entity, set Position (emits EcsOnAdd and EcsOnSet)
flecs::entity e = ecs.entity("e")
.set<Position>({10, 20});
// Remove component (emits EcsOnRemove)
e.remove<Position>();
// Remove component again (no event is emitted)
e.remove<Position>();
// Output
// - OnAdd: Position: e
// - OnSet: Position: e: {10, 20}
// - OnRemove: Position: e: {10, 20}
}

View File

@@ -0,0 +1,16 @@
#ifndef CUSTOM_EVENT_H
#define CUSTOM_EVENT_H
/* This generated file contains includes for project dependencies */
#include "custom_event/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 CUSTOM_EVENT_BAKE_CONFIG_H
#define CUSTOM_EVENT_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "custom_event",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,46 @@
#include <custom_event.h>
#include <iostream>
// Observers can be used to match custom events. Custom events can be emitted
// using the ecs_emit function. This function is also used by builtin events,
// so builtin and custom events use the same rules for matching with observers.
//
// An event consists out of three pieces of data used to match with observers:
// - An single event kind (EcsOnAdd, EcsOnRemove, ...)
// - One or more event ids (Position, Velocity, ...)
// - A source (either an entity or a table)
struct Position {
double x, y;
};
// Create tag type to use as event (could also use entity)
struct MyEvent { };
int main(int, char *[]) {
flecs::world ecs;
// Create observer for custom event
ecs.observer<Position>()
.event<MyEvent>()
.each([](flecs::iter& it, size_t i, Position&) {
std::cout << " - " << it.event().name() << ": "
<< it.event_id().str() << ": "
<< it.entity(i).name() << "\n";
});
// The observer filter can be matched against the entity, so make sure it
// has the Position component before emitting the event. This does not
// trigger the observer yet.
flecs::entity e = ecs.entity("e")
.set<Position>({10, 20});
// Emit the custom event
ecs.event<MyEvent>()
.id<Position>()
.entity(e)
.emit();
// Output
// - MyEvent: Position: e
}

View File

@@ -0,0 +1,16 @@
#ifndef ENTITY_EVENT_H
#define ENTITY_EVENT_H
/* This generated file contains includes for project dependencies */
#include "entity_event/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 ENTITY_EVENT_BAKE_CONFIG_H
#define ENTITY_EVENT_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "entity_event",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,55 @@
#include <iostream>
#include <entity_event.h>
// Entity events are events that are emitted and observed for a specific entity.
// They are a thin wrapper around regular observers, which match against queries
// instead of single entities. While they work similarly under the hood, entity
// events provide a much simpler API.
//
// An entity event only needs two pieces of data:
// - The entity on which to emit the event
// - The event to emit
// An event without payload
struct Click { };
// An event with payload
struct Resize {
double width, height;
};
int main(int, char *[]) {
flecs::world ecs;
// Create a widget entity
flecs::entity widget = ecs.entity("MyWidget");
// Observe the Click event on the widget entity.
widget.observe<Click>([]() {
std::cout << "clicked!\n";
});
// Observers can have an entity argument that holds the event source.
// This allows the same function to be reused for different entities.
widget.observe<Click>([](flecs::entity src) {
std::cout << "clicked on " << src.path() << "!\n";
});
// Observe the Resize event. Events with payload are passed as arguments
// to the observer callback.
widget.observe([](Resize& p) {
std::cout << "resized to {"
<< p.width << ", " << p.height << "}!\n";
});
// Emit the Click event
widget.emit<Click>();
// Emit the Resize event
widget.emit<Resize>({100, 200});
// Output
// clicked!
// clicked on ::MyWidget!
// resized to {100, 200}!
}

View File

@@ -0,0 +1,16 @@
#ifndef MONITOR_H
#define MONITOR_H
/* This generated file contains includes for project dependencies */
#include "monitor/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 MONITOR_BAKE_CONFIG_H
#define MONITOR_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "monitor",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,54 @@
#include <monitor.h>
#include <iostream>
// A monitor observer triggers when an entity starts/stop matching the observer
// filter. The observer communicates whether an entity is "entering/leaving" the
// monitor by setting ecs_iter_t::event to EcsOnAdd (for entering) or
// EcsOnRemove (for leaving).
//
// To specify that an observer is a monitor observer, the EcsMonitor tag must be
// provided as event. No additional event kinds should be provided for a monitor
// observer.
struct Position {
double x, y;
};
struct Velocity {
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
// Create observer for custom event
ecs.observer<Position, Velocity>()
.event(flecs::Monitor) // Monitor entities entering/leaving the query
.each([](flecs::iter& it, size_t i, Position&, Velocity&) {
if (it.event() == flecs::OnAdd) {
std::cout << " - Enter: "
<< it.event_id().str() << ": "
<< it.entity(i).name() << "\n";
} else if (it.event() == flecs::OnRemove) {
std::cout << " - Leave: "
<< it.event_id().str() << ": "
<< it.entity(i).name() << "\n";
}
});
// Create entity
flecs::entity e = ecs.entity("e");
// This does not yet trigger the monitor, as the entity does not yet match.
e.set<Position>({10, 20});
// This triggers the monitor with EcsOnAdd, as the entity now matches.
e.set<Velocity>({1, 2});
// This triggers the monitor with EcsOnRemove, as the entity no longer matches.
e.remove<Position>();
// Output
// - Enter: Velocity: e
// - Leave: Position: e
}

View File

@@ -0,0 +1,16 @@
#ifndef PROPAGATE_H
#define PROPAGATE_H
/* This generated file contains includes for project dependencies */
#include "propagate/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 PROPAGATE_BAKE_CONFIG_H
#define PROPAGATE_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "propagate",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,48 @@
#include <propagate.h>
#include <iostream>
// Events are propagated along relationship edges. This means that observers can
// listen for events from a parent or prefab, like triggering when a component
// inherited from a prefab was set.
//
// Event propagation happens automatically when an observer contains a filter
// with the EcsUp flag set (indicating upwards traversal). Observers use the
// same matching logic as queries: if a query with upwards traversal matches an
// entity, so will an observer.
//
// Events are only propagated along traversable relationship edges.
struct Position {
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
// Create observer that listens for events from both self and parent
ecs.observer<Position, Position>()
.term_at(2).parent() // select 2nd Position from parent
.event(flecs::OnSet)
.each([](flecs::iter& it, size_t i, Position& p_self, Position& p_parent) {
std::cout << " - " << it.event().name() << ": "
<< it.event_id().str() << ": "
<< it.entity(i).name() << ": "
<< "self: {" << p_self.x << ", " << p_self.y << "}, "
<< "parent: {" << p_parent.x << ", " << p_parent.y << "}\n";
});
// Create entity and parent
flecs::entity p = ecs.entity("p");
flecs::entity e = ecs.entity("e").child_of(p);
// Set Position on entity. This doesn't trigger the observer yet, since the
// parent doesn't have Position yet.
e.set<Position>({10, 20});
// Set Position on parent. This event will be propagated and trigger the
// observer, as the observer query now matches.
p.set<Position>({1, 2});
// Output
// - OnSet: Position: e: self: {10, 20}, parent: {1, 2}
}

View File

@@ -0,0 +1,16 @@
#ifndef TWO_COMPONENTS_H
#define TWO_COMPONENTS_H
/* This generated file contains includes for project dependencies */
#include "two_components/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 TWO_COMPONENTS_BAKE_CONFIG_H
#define TWO_COMPONENTS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "two_components",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,39 @@
#include <two_components.h>
#include <iostream>
// An observer can match multiple components/tags. Only entities that match the
// entire observer filter will be forwarded to the callback. For example, an
// observer for Position,Velocity won't match an entity that only has Position.
struct Position {
double x, y;
};
struct Velocity {
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
// Create observer for custom event
ecs.observer<Position, Velocity>()
.event(flecs::OnSet)
.each([](flecs::iter& it, size_t i, Position& p, Velocity& v) {
std::cout << " - " << it.event().name() << ": "
<< it.event_id().str() << ": "
<< it.entity(i).name() << ": "
<< "p: {" << p.x << ", " << p.y << "} "
<< "v: {" << v.x << ", " << v.y << "}\n";
});
// Create entity, set Position (emits EcsOnSet, does not yet match observer)
flecs::entity e = ecs.entity("e")
.set<Position>({10, 20});
// Set Velocity (emits EcsOnSet, matches observer)
e.set<Velocity>({1, 2});
// Output
// - OnSet: Velocity: e: p: {10, 20} v: {1, 2}
}

View File

@@ -0,0 +1,16 @@
#ifndef YIELD_EXISTING_H
#define YIELD_EXISTING_H
/* This generated file contains includes for project dependencies */
#include "yield_existing/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 YIELD_EXISTING_BAKE_CONFIG_H
#define YIELD_EXISTING_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "yield_existing",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,36 @@
#include <yield_existing.h>
#include <iostream>
// Observers can enable a "yield_existing" feature that upon creation of the
// observer produces events for all entities that match the observer query. The
// feature is only implemented for the builtin EcsOnAdd and EcsOnSet events.
//
// Custom events can also implement behavior for yield_existing by adding the
// Iterable component to the event (see EcsIterable for more details).
struct Position {
double x, y;
};
int main(int, char *[]) {
flecs::world ecs;
// Create existing entities with Position component
ecs.entity("e1").set<Position>({10, 20});
ecs.entity("e2").set<Position>({20, 30});
// Create an observer for three events
ecs.observer<Position>()
.event(flecs::OnSet)
.yield_existing() // Trigger for existing matching entities
.each([](flecs::iter& it, size_t i, Position& p) {
std::cout << " - " << it.event().name() << ": "
<< it.event_id().str() << ": "
<< it.entity(i).name()
<< ": {" << p.x << ", " << p.y << "}\n";
});
// Output
// - OnSet: Position: e1: {10, 20}
// - OnSet: Position: e2: {20, 30}
}

View File

@@ -0,0 +1,16 @@
#ifndef BASICS_H
#define BASICS_H
/* This generated file contains includes for project dependencies */
#include "basics/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 BASICS_BAKE_CONFIG_H
#define BASICS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "basics",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,56 @@
#include <basics.h>
#include <iostream>
// Prefabs are entities that can be used as templates for other entities. They
// are created with a builtin Prefab tag, which by default excludes them from
// queries and systems.
//
// Prefab instances are entities that have an IsA relationship to the prefab.
// The IsA relationship causes instances to inherit the components from the
// prefab. By default all instances for a prefab share its components.
//
// Inherited components save memory as they only need to be stored once for all
// prefab instances. They also speed up the creation of prefabs, as inherited
// components don't need to be copied to the instances.
//
// To get a private copy of a component, an instance can add it which is called
// an override. Overrides can be manual (by using add) or automatic (see the
// auto_override example).
//
// If a prefab has children, adding the IsA relationship instantiates the prefab
// children for the instance (see hierarchy example).
struct Defense {
double value;
};
int main() {
flecs::world ecs;
// Create a SpaceShip prefab with a Defense component.
flecs::entity SpaceShip = ecs.prefab("SpaceShip")
.set<Defense>({ 50 });
// Create a prefab instance
flecs::entity inst = ecs.entity("my_spaceship").is_a(SpaceShip);
// Because of the IsA relationship, the instance now shares the Defense
// component with the prefab, and can be retrieved as a regular component:
const Defense *d_inst = inst.get<Defense>();
std::cout << "defense: " << d_inst->value << "\n";
// Because the component is shared, changing the value on the prefab will
// also change the value for the instance:
SpaceShip.set<Defense>({ 100 });
std::cout << "defense after set: " << d_inst->value << "\n";
// Prefab components can be iterated like regular components:
ecs.each([](flecs::entity e, Defense& d) {
std::cout << e.path() << ": " << d.value << "\n";
});
// Output:
// defense: 50
// defense after set: 100
// ::my_spaceship: 100
}

View File

@@ -0,0 +1,16 @@
#ifndef HIERARCHY_H
#define HIERARCHY_H
/* This generated file contains includes for project dependencies */
#include "hierarchy/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 HIERARCHY_BAKE_CONFIG_H
#define HIERARCHY_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "hierarchy",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

View File

@@ -0,0 +1,27 @@
#include <hierarchy.h>
#include <iostream>
// When a prefab has children, they are instantiated for an instance when the
// IsA relationship to the prefab is added.
int main() {
flecs::world ecs;
// Create a prefab hierarchy.
flecs::entity SpaceShip = ecs.prefab("SpaceShip");
ecs.prefab("Engine").child_of(SpaceShip);
ecs.prefab("Cockpit").child_of(SpaceShip);
// Instantiate the prefab. This also creates an Engine and Cockpit child
// for the instance.
flecs::entity inst = ecs.entity("my_spaceship").is_a(SpaceShip);
flecs::entity inst_engine = inst.lookup("Engine");
flecs::entity inst_cockpit = inst.lookup("Cockpit");
std::cout << "instance engine: " << inst_engine.path() << "\n";
std::cout << "instance cockpit: " << inst_cockpit.path() << "\n";
// Output:
// instance engine: ::my_spaceship::Engine
// instance cockpit: ::my_spaceship::Cockpit
}

View File

@@ -0,0 +1,16 @@
#ifndef NESTED_PREFABS_H
#define NESTED_PREFABS_H
/* This generated file contains includes for project dependencies */
#include "nested_prefabs/bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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 NESTED_PREFABS_BAKE_CONFIG_H
#define NESTED_PREFABS_BAKE_CONFIG_H
/* Headers of public dependencies */
#include <flecs.h>
#endif

View File

@@ -0,0 +1,11 @@
{
"id": "nested_prefabs",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}

Some files were not shown because too many files have changed in this diff Show More