Properly link flecs library
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
#ifndef SYSTEMS_H
|
||||
#define SYSTEMS_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "systems/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 SYSTEMS_BAKE_CONFIG_H
|
||||
#define SYSTEMS_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
12
engine/libs/flecs/examples/cpp/systems/basics/project.json
Normal file
12
engine/libs/flecs/examples/cpp/systems/basics/project.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "systems",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
39
engine/libs/flecs/examples/cpp/systems/basics/src/main.cpp
Normal file
39
engine/libs/flecs/examples/cpp/systems/basics/src/main.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <systems.h>
|
||||
#include <iostream>
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Create a system for Position, Velocity. Systems are like queries (see
|
||||
// queries) with a function that can be ran or scheduled (see pipeline).
|
||||
flecs::system s = ecs.system<Position, const Velocity>()
|
||||
.each([](flecs::entity e, Position& p, const Velocity& v) {
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
|
||||
});
|
||||
|
||||
// Create a few test entities for a Position, Velocity query
|
||||
ecs.entity("e1")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
ecs.entity("e2")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({3, 4});
|
||||
|
||||
// This entity will not match as it does not have Position, Velocity
|
||||
ecs.entity("e3")
|
||||
.set<Position>({10, 20});
|
||||
|
||||
// Run the system
|
||||
s.run();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CUSTOM_PHASES_H
|
||||
#define CUSTOM_PHASES_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "custom_phases/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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_PHASES_BAKE_CONFIG_H
|
||||
#define CUSTOM_PHASES_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "custom_phases",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <custom_phases.h>
|
||||
#include <iostream>
|
||||
|
||||
// This application demonstrates how to use custom phases for systems. The
|
||||
// default pipeline will automatically run systems for custom phases as long as
|
||||
// they have the flecs::Phase tag.
|
||||
|
||||
// Dummy system
|
||||
void Sys(flecs::iter& it) {
|
||||
std::cout << "system " << it.system().name() << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
flecs::world ecs(argc, argv);
|
||||
|
||||
// Create two custom phases that branch off of EcsOnUpdate. Note that the
|
||||
// phases have the Phase tag, which is necessary for the builtin pipeline
|
||||
// to discover which systems it should run.
|
||||
flecs::entity Physics = ecs.entity()
|
||||
.add(flecs::Phase)
|
||||
.depends_on(flecs::OnUpdate);
|
||||
|
||||
flecs::entity Collisions = ecs.entity()
|
||||
.add(flecs::Phase)
|
||||
.depends_on(Physics);
|
||||
|
||||
// Create 3 dummy systems.
|
||||
ecs.system("CollisionSystem")
|
||||
.kind(Collisions)
|
||||
.iter(Sys);
|
||||
|
||||
ecs.system("PhysicsSystem")
|
||||
.kind(Physics)
|
||||
.iter(Sys);
|
||||
|
||||
ecs.system("GameSystem")
|
||||
.kind(flecs::OnUpdate)
|
||||
.iter(Sys);
|
||||
|
||||
// Run pipeline
|
||||
ecs.progress();
|
||||
|
||||
// Output
|
||||
// system GameSystem
|
||||
// system PhysicsSystem
|
||||
// system CollisionSystem
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CUSTOM_PHASES_NO_BUILTIN_H
|
||||
#define CUSTOM_PHASES_NO_BUILTIN_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "custom_phases_no_builtin/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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_PHASES_NO_BUILTIN_BAKE_CONFIG_H
|
||||
#define CUSTOM_PHASES_NO_BUILTIN_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "custom_phases_no_builtin",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <custom_phases_no_builtin.h>
|
||||
#include <iostream>
|
||||
|
||||
// This application demonstrates how to use custom phases for systems. The
|
||||
// default pipeline will automatically run systems for custom phases as long as
|
||||
// they have the flecs::Phase tag.
|
||||
|
||||
// Dummy system
|
||||
void Sys(flecs::iter& it) {
|
||||
std::cout << "system " << it.system().name() << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
flecs::world ecs(argc, argv);
|
||||
|
||||
// Create three custom phases. Note that the phases have the Phase tag,
|
||||
// which is necessary for the builtin pipeline to discover which systems it
|
||||
// should run.
|
||||
flecs::entity Update = ecs.entity()
|
||||
.add(flecs::Phase);
|
||||
|
||||
flecs::entity Physics = ecs.entity()
|
||||
.add(flecs::Phase)
|
||||
.depends_on(Update);
|
||||
|
||||
flecs::entity Collisions = ecs.entity()
|
||||
.add(flecs::Phase)
|
||||
.depends_on(Physics);
|
||||
|
||||
// Create 3 dummy systems.
|
||||
ecs.system("CollisionSystem")
|
||||
.kind(Collisions)
|
||||
.iter(Sys);
|
||||
|
||||
ecs.system("PhysicsSystem")
|
||||
.kind(Physics)
|
||||
.iter(Sys);
|
||||
|
||||
ecs.system("GameSystem")
|
||||
.kind(Update)
|
||||
.iter(Sys);
|
||||
|
||||
// Run pipeline
|
||||
ecs.progress();
|
||||
|
||||
// Output
|
||||
// system GameSystem
|
||||
// system PhysicsSystem
|
||||
// system CollisionSystem
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CUSTOM_PIPELINE_H
|
||||
#define CUSTOM_PIPELINE_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "custom_pipeline/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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_PIPELINE_BAKE_CONFIG_H
|
||||
#define CUSTOM_PIPELINE_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "custom_pipeline",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <custom_pipeline.h>
|
||||
#include <iostream>
|
||||
|
||||
// Custom pipelines make it possible for applications to override which systems
|
||||
// are ran by a pipeline and how they are ordered. Pipelines are queries under
|
||||
// the hood, and custom pipelines override the query used for system matching.
|
||||
|
||||
// If you only want to use custom phases in addition or in place of the builtin
|
||||
// phases see the custom_phases and custom_phases_no_builtin examples, as this
|
||||
// does not require using a custom pipeline.
|
||||
|
||||
struct Physics {};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
flecs::world ecs(argc, argv);
|
||||
|
||||
// Create a pipeline that matches systems with Physics. Note that this
|
||||
// pipeline does not require the use of phases (see custom_phases) or of the
|
||||
// DependsOn relationship.
|
||||
flecs::entity pipeline = ecs.pipeline()
|
||||
.with(flecs::System) // Mandatory, must always match systems
|
||||
.with<Physics>()
|
||||
.build();
|
||||
|
||||
// Configure the world to use the custom pipeline
|
||||
ecs.set_pipeline(pipeline);
|
||||
|
||||
// Create system with Physics tag
|
||||
ecs.system()
|
||||
.kind<Physics>()
|
||||
.iter([](flecs::iter&) {
|
||||
std::cout << "System ran!\n";
|
||||
});
|
||||
|
||||
// Runs the pipeline & system
|
||||
ecs.progress();
|
||||
|
||||
// Output:
|
||||
// System ran!
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CUSTOM_RUNNER_H
|
||||
#define CUSTOM_RUNNER_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "custom_runner/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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_RUNNER_BAKE_CONFIG_H
|
||||
#define CUSTOM_RUNNER_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "custom_runner",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <custom_runner.h>
|
||||
#include <iostream>
|
||||
|
||||
// Systems can be created with a custom run function that takes control over the
|
||||
// entire iteration. By default, a system is invoked once per matched table,
|
||||
// which means the function can be called multiple times per frame. In some
|
||||
// cases that's inconvenient, like when a system has things it needs to do only
|
||||
// once per frame. For these use cases, the run callback can be used which is
|
||||
// called once per frame per system.
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
flecs::system s = ecs.system<Position, const Velocity>()
|
||||
// The run function has a signature that accepts a C iterator. By
|
||||
// forwarding the iterator to it->callback, the each function of the
|
||||
// system is invoked.
|
||||
.run([](flecs::iter_t *it) {
|
||||
std::cout << "Move begin\n";
|
||||
|
||||
// Walk over the iterator, forward to the system callback
|
||||
while (ecs_iter_next(it)) {
|
||||
it->callback(it);
|
||||
}
|
||||
|
||||
std::cout << "Move end\n";
|
||||
})
|
||||
.each([](flecs::entity e, Position& p, const Velocity& v) {
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
|
||||
});
|
||||
|
||||
// Create a few test entities for a Position, Velocity query
|
||||
ecs.entity("e1")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
ecs.entity("e2")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({3, 4});
|
||||
|
||||
// This entity will not match as it does not have Position, Velocity
|
||||
ecs.entity("e3")
|
||||
.set<Position>({10, 20});
|
||||
|
||||
// Run the system
|
||||
s.run();
|
||||
|
||||
// Output
|
||||
// Move begin
|
||||
// e1: {11, 22}
|
||||
// e2: {13, 24}
|
||||
// Move end
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef DELTA_TIME_H
|
||||
#define DELTA_TIME_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "delta_time/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 DELTA_TIME_BAKE_CONFIG_H
|
||||
#define DELTA_TIME_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "delta_time",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <delta_time.h>
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Create system that prints delta_time. This system doesn't query for any
|
||||
// components which means it won't match any entities, but will still be ran
|
||||
// once for each call to ecs_progress.
|
||||
ecs.system()
|
||||
.iter([](flecs::iter& it) {
|
||||
std::cout << "delta_time: " << it.delta_time() << std::endl;
|
||||
});
|
||||
|
||||
// Call progress with 0.0f for the delta_time parameter. This will cause
|
||||
// ecs_progress to measure the time passed since the last frame. The
|
||||
// delta_time of the first frame is a best guess (16ms).
|
||||
ecs.progress();
|
||||
|
||||
// The following calls should print a delta_time of approximately 100ms
|
||||
|
||||
ecs_os_sleep(0, 100 * 1000 * 1000);
|
||||
ecs.progress();
|
||||
|
||||
ecs_os_sleep(0, 100 * 1000 * 1000);
|
||||
ecs.progress();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef MUTATE_ENTITY_H
|
||||
#define MUTATE_ENTITY_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "mutate_entity/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 MUTATE_ENTITY_BAKE_CONFIG_H
|
||||
#define MUTATE_ENTITY_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "mutate_entity",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <mutate_entity.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
struct Timeout {
|
||||
double value;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// System that deletes an entity after a timeout expires
|
||||
ecs.system<Timeout>()
|
||||
.each([](flecs::iter& it, size_t index, Timeout& t) {
|
||||
t.value -= static_cast<double>(it.delta_time());
|
||||
if (t.value <= 0) {
|
||||
// Delete the entity
|
||||
|
||||
// To make sure that the storage doesn't change while a system
|
||||
// is iterating entities, and multiple threads can safely access
|
||||
// the data, mutations (like a delete) are added to a command
|
||||
// queue and executed when it's safe to do so.
|
||||
|
||||
// When the entity to be mutated is not the same as the entity
|
||||
// provided by the system, an additional mut() call is required.
|
||||
// See the mutate_entity_handle example.
|
||||
flecs::entity e = it.entity(index);
|
||||
e.destruct();
|
||||
std::cout << "Expire: " << e.name() << "deleted!\n";
|
||||
}
|
||||
});
|
||||
|
||||
// System that prints remaining expiry time
|
||||
ecs.system<const Timeout>()
|
||||
.each([](flecs::entity e, const Timeout& t) {
|
||||
std::cout << "PrintExpire: " << e.name() << " has " << std::fixed
|
||||
<< std::setprecision(2) << t.value << " seconds left\n";
|
||||
});
|
||||
|
||||
// Observer that triggers when entity is actually deleted
|
||||
ecs.observer<Timeout>()
|
||||
.event(flecs::OnRemove)
|
||||
.each([](flecs::entity e, Timeout&) {
|
||||
std::cout << "Expired: " << e.name() << " actually deleted\n";
|
||||
});
|
||||
|
||||
|
||||
flecs::entity e = ecs.entity("MyEntity")
|
||||
.set<Timeout>({3.0});
|
||||
|
||||
ecs.set_target_fps(1);
|
||||
|
||||
while (ecs.progress()) {
|
||||
// If entity is no longer alive, exit
|
||||
if (!e.is_alive()) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "Tick...\n";
|
||||
}
|
||||
|
||||
// Output
|
||||
// PrintExpire: MyEntity has 2.00 seconds left
|
||||
// Tick...
|
||||
// PrintExpire: MyEntity has 0.99 seconds left
|
||||
// Tick...
|
||||
// Expire: MyEntitydeleted!
|
||||
// PrintExpire: MyEntity has -0.02 seconds left
|
||||
// Expired: MyEntity actually deleted
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef MUTATE_ENTITY_HANDLE_H
|
||||
#define MUTATE_ENTITY_HANDLE_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "mutate_entity_handle/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 MUTATE_ENTITY_HANDLE_BAKE_CONFIG_H
|
||||
#define MUTATE_ENTITY_HANDLE_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "mutate_entity_handle",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <mutate_entity_handle.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
// This example is the same as the mutate_entity example, but instead stores the
|
||||
// handle of the to be deleted entity in a component.
|
||||
|
||||
struct Timeout {
|
||||
flecs::entity to_delete;
|
||||
double value;
|
||||
};
|
||||
|
||||
struct Tag { };
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
ecs.system<Timeout>()
|
||||
.each([](flecs::iter& it, size_t, Timeout& t) {
|
||||
t.value -= static_cast<double>(it.delta_time());
|
||||
if (t.value <= 0) {
|
||||
// Delete the entity
|
||||
|
||||
// To make sure the delete operation is enqueued (see
|
||||
// mutate_entity example for more details) we need to provide it
|
||||
// with a mutable context (stage) using the mut() function. If
|
||||
// we don't provide a mutable context, the operation will be
|
||||
// attempted on the context stored in the flecs::entity object,
|
||||
// which would throw a readonly error.
|
||||
|
||||
// To catch these errors at compile time, replace the type of
|
||||
// to_delete with flecs::entity_view. This class does not have
|
||||
// any methods for mutating the entity, which forces the code to
|
||||
// first call mut().
|
||||
|
||||
// The it.world() function can be used to provide the context:
|
||||
// t.to_delete.mut(it.world()).destruct();
|
||||
//
|
||||
// The current entity can also be used to provide context. This
|
||||
// is useful for functions that accept a flecs::entity:
|
||||
// t.to_delete.mut(it.entity(index)).destruct();
|
||||
//
|
||||
// A shortcut is to use the iterator directly:
|
||||
t.to_delete.mut(it).destruct();
|
||||
std::cout << "Expire: " << t.to_delete.name() << " deleted!\n";
|
||||
}
|
||||
});
|
||||
|
||||
ecs.system<const Timeout>()
|
||||
.each([](const Timeout& t) {
|
||||
std::cout << "PrintExpire: " << t.to_delete.name() << " has "
|
||||
<< std::fixed << std::setprecision(2) << t.value
|
||||
<< " seconds left\n";
|
||||
});
|
||||
|
||||
ecs.observer<Tag>()
|
||||
.event(flecs::OnRemove)
|
||||
.each([](flecs::entity e, Tag) {
|
||||
std::cout << "Expired: " << e.name() << " actually deleted\n";
|
||||
});
|
||||
|
||||
// Add Tag so we can get notified when entity is actually deleted
|
||||
flecs::entity to_delete = ecs.entity("ToDelete")
|
||||
.add<Tag>();
|
||||
|
||||
ecs.entity("MyEntity")
|
||||
.set<Timeout>({to_delete, 3.0});
|
||||
|
||||
ecs.set_target_fps(1);
|
||||
|
||||
while (ecs.progress()) {
|
||||
// If entity is no longer alive, exit
|
||||
if (!to_delete.is_alive()) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "Tick...\n";
|
||||
}
|
||||
|
||||
// Output
|
||||
// PrintExpire: ToDelete has 2.00 seconds left
|
||||
// Tick...
|
||||
// PrintExpire: ToDelete has 0.98 seconds left
|
||||
// Tick...
|
||||
// Expire: ToDelete deleted!
|
||||
// PrintExpire: ToDelete has -0.03 seconds left
|
||||
// Expired: ToDelete actually deleted
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef NO_READONLY_H
|
||||
#define NO_READONLY_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "no_readonly/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 NO_READONLY_BAKE_CONFIG_H
|
||||
#define NO_READONLY_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "no_readonly",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include <no_readonly.h>
|
||||
#include <iostream>
|
||||
|
||||
// When an application calls world.progress(), the world is put in readonly mode.
|
||||
// This ensures that systems (on multiple threads) can safely iterate
|
||||
// components, without having to worry about components moving around while
|
||||
// they're being read. This has as side effect that any operations (like adding
|
||||
// or removing components) are not visible until the end of the frame (see the
|
||||
// sync_point example for more details).
|
||||
// Sometimes this is not what you want, and you need a change to be visible
|
||||
// immediately. For these use cases, applications can use a no_readonly system.
|
||||
// This temporarily takes the world out of readonly mode, so a system can make
|
||||
// changes that are directly visible.
|
||||
// Because they mutate the world directly, no_readonly systems are never ran on
|
||||
// more than one thread, and no other systems are ran at the same time.
|
||||
|
||||
struct Waiter { };
|
||||
struct Plate { };
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Create query to find all waiters without a plate
|
||||
flecs::query<> q_waiter = ecs.query_builder()
|
||||
.with<Waiter>()
|
||||
.without<Plate>(flecs::Wildcard)
|
||||
.build();
|
||||
|
||||
// System that assigns plates to waiter. By making this system no_readonly
|
||||
// plate assignments are assigned directly (not deferred) to waiters, which
|
||||
// ensures that we won't assign plates to the same waiter more than once.
|
||||
ecs.system("AssignPlate")
|
||||
.with<Plate>()
|
||||
.without<Waiter>(flecs::Wildcard)
|
||||
.no_readonly()
|
||||
.iter([&](flecs::iter& it) {
|
||||
for (auto i : it) {
|
||||
flecs::entity plate = it.entity(i);
|
||||
|
||||
// Find an available waiter
|
||||
flecs::entity waiter = q_waiter.first();
|
||||
if (waiter) {
|
||||
// An available waiter was found, assign a plate to it so
|
||||
// that the next plate will no longer find it.
|
||||
// The defer_suspend function temporarily suspends deferring
|
||||
// operations, which ensures that our plate is assigned
|
||||
// immediately. Even though this is a no_readonly system,
|
||||
// defering is still enabled by default, as adding/removing
|
||||
// components to the entities being iterated would intefere
|
||||
// with the system iterator.
|
||||
it.world().defer_suspend();
|
||||
waiter.add<Plate>(plate);
|
||||
it.world().defer_resume();
|
||||
|
||||
// Now that defering is resumed, we can safely also add the
|
||||
// waiter to the plate. We can't do this while defering is
|
||||
// suspended, because the plate is the entity we're
|
||||
// currently iterating, and we don't want to move it to a
|
||||
// different table while we're iterating it.
|
||||
plate.add<Waiter>(waiter);
|
||||
|
||||
std::cout << "Assigned "
|
||||
<< waiter.name() << " to "
|
||||
<< plate.name() << "!\n";
|
||||
} else {
|
||||
// No available waiters, can't assign the plate
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create a few plates and waiters
|
||||
flecs::entity waiter_1 = ecs.entity("waiter_1").add<Waiter>();
|
||||
ecs.entity("waiter_2").add<Waiter>();
|
||||
ecs.entity("waiter_3").add<Waiter>();
|
||||
|
||||
ecs.entity("plate_1").add<Plate>();
|
||||
flecs::entity plate_2 = ecs.entity("plate_2").add<Plate>();
|
||||
ecs.entity("plate_3").add<Plate>();
|
||||
|
||||
waiter_1.add<Plate>(plate_2);
|
||||
plate_2.add<Waiter>(waiter_1);
|
||||
|
||||
// run systems
|
||||
ecs.progress();
|
||||
|
||||
// Output:
|
||||
// Assigned waiter_3 to plate_1!
|
||||
// Assigned waiter_2 to plate_3!
|
||||
}
|
||||
5
engine/libs/flecs/examples/cpp/systems/pipeline/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/systems/pipeline/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef PIPELINE_H
|
||||
#define PIPELINE_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "pipeline/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 PIPELINE_BAKE_CONFIG_H
|
||||
#define PIPELINE_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
12
engine/libs/flecs/examples/cpp/systems/pipeline/project.json
Normal file
12
engine/libs/flecs/examples/cpp/systems/pipeline/project.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "pipeline",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
43
engine/libs/flecs/examples/cpp/systems/pipeline/src/main.cpp
Normal file
43
engine/libs/flecs/examples/cpp/systems/pipeline/src/main.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <pipeline.h>
|
||||
#include <iostream>
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Create a system for moving an entity
|
||||
ecs.system<Position, const Velocity>()
|
||||
.kind(flecs::OnUpdate) // A phase orders a system in a pipeline
|
||||
.each([](Position& p, const Velocity& v) {
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
});
|
||||
|
||||
// Create a system for printing the entity position
|
||||
ecs.system<const Position>()
|
||||
.kind(flecs::PostUpdate)
|
||||
.each([](flecs::entity e, const Position& p) {
|
||||
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
|
||||
});
|
||||
|
||||
// Create a few test entities for a Position, Velocity query
|
||||
ecs.entity("e1")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
ecs.entity("e2")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({3, 4});
|
||||
|
||||
// Run the default pipeline. This will run all systems ordered by their
|
||||
// phase. Systems within the same phase are ran in declaration order. This
|
||||
// function is usually called in a loop.
|
||||
ecs.progress();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef STARTUP_SYSTEM_H
|
||||
#define STARTUP_SYSTEM_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "startup_system/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 STARTUP_SYSTEM_BAKE_CONFIG_H
|
||||
#define STARTUP_SYSTEM_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "startup_system",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <startup_system.h>
|
||||
#include <iostream>
|
||||
|
||||
// Startup systems are systems registered with the EcsOnStart phase, and are
|
||||
// only ran during the first frame. Just like with regular phases, custom phases
|
||||
// can depend on the EcsOnStart phase (see custom_phases example). Phases that
|
||||
// depend on EcsOnStart are also only ran during the first frame.
|
||||
//
|
||||
// Other than that, startup systems behave just like regular systems (they can
|
||||
// match components, can introduce merge points), with as only exception that
|
||||
// they are guaranteed to always run on the main thread.
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Startup system
|
||||
ecs.system("Startup")
|
||||
.kind(flecs::OnStart)
|
||||
.iter([](flecs::iter& it) {
|
||||
std::cout << it.system().name() << "\n";
|
||||
});
|
||||
|
||||
// Regular system
|
||||
ecs.system("Update")
|
||||
.iter([](flecs::iter& it) {
|
||||
std::cout << it.system().name() << "\n";
|
||||
});
|
||||
|
||||
// First frame. This runs both the Startup and Update systems
|
||||
ecs.progress();
|
||||
|
||||
// Second frame. This runs only the Update system
|
||||
ecs.progress();
|
||||
|
||||
// Output
|
||||
// Startup
|
||||
// Update
|
||||
// Update
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef SYNC_POINT_H
|
||||
#define SYNC_POINT_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "sync_point/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 SYNC_POINT_BAKE_CONFIG_H
|
||||
#define SYNC_POINT_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "sync_point",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <sync_point.h>
|
||||
#include <iostream>
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// System that sets velocity using ecs_set for entities with Position.
|
||||
// While systems are progressing, operations like ecs_set are deferred until
|
||||
// it is safe to merge. By default this merge happens at the end of the
|
||||
// frame, but we can annotate systems to give the scheduler more information
|
||||
// about what it's doing, which allows it to insert sync points earlier.
|
||||
//
|
||||
// Note that sync points are never necessary/inserted for systems that write
|
||||
// components provided by their signature, as these writes directly happen
|
||||
// in the ECS storage and are never deferred.
|
||||
//
|
||||
// .inout_none() for Position tells the scheduler that while we
|
||||
// want to match entities with Position, we're not interested in reading or
|
||||
// writing the component value.
|
||||
ecs.system("SetVelocity")
|
||||
.with<Position>().inout_none()
|
||||
.write<Velocity>() // Velocity is written, but shouldn't be matched
|
||||
.each([](flecs::entity e) {
|
||||
e.set<Velocity>({1, 2});
|
||||
});
|
||||
|
||||
// This system reads Velocity, which causes the insertion of a sync point.
|
||||
ecs.system<Position, const Velocity>("Move")
|
||||
.each([](Position& p, const Velocity& v) {
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
});
|
||||
|
||||
// Print resulting Position
|
||||
ecs.system<const Position>("PrintPosition")
|
||||
.each([](flecs::entity e, const Position& p) {
|
||||
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
|
||||
});
|
||||
|
||||
// Create a few test entities for a Position, Velocity query
|
||||
ecs.entity("e1")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
ecs.entity("e2")
|
||||
.set<Position>({10, 20})
|
||||
.set<Velocity>({3, 4});
|
||||
|
||||
// Run systems. Debug logging enables us to see the generated schedule
|
||||
flecs::log::set_level(1);
|
||||
ecs.progress();
|
||||
flecs::log::set_level(-1); // Restore so we don't get world cleanup logs
|
||||
|
||||
// Output:
|
||||
// info: pipeline rebuild:
|
||||
// info: | schedule: threading: 0, staging: 1:
|
||||
// info: | | system SetVelocity
|
||||
// info: | | merge
|
||||
// info: | schedule: threading: 0, staging: 1:
|
||||
// info: | | system Move
|
||||
// info: | | system PrintPosition
|
||||
// info: | | merge
|
||||
// e1: {11.000000, 22.000000}
|
||||
// e2: {11.000000, 22.000000}
|
||||
//
|
||||
// The "merge" lines indicate sync points.
|
||||
//
|
||||
// Removing '.write<Velocity>()' from the system will remove the first
|
||||
// sync point from the schedule.
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef SYNC_POINT_DELETE_H
|
||||
#define SYNC_POINT_DELETE_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "sync_point_delete/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 SYNC_POINT_DELETE_BAKE_CONFIG_H
|
||||
#define SYNC_POINT_DELETE_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "sync_point_delete",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include <sync_point_delete.h>
|
||||
#include <iostream>
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// This example shows how to annotate systems that delete entities, in a way
|
||||
// that allows the scheduler to correctly insert sync points. See the
|
||||
// sync_point example for more details on sync points.
|
||||
//
|
||||
// While annotating a system for a delete operation follows the same
|
||||
// design as other operations, one key difference is that a system often
|
||||
// does not know which components a to be deleted entity has. This makes it
|
||||
// impossible to annotate the system in advance for specific components.
|
||||
//
|
||||
// To ensure the scheduler is still able to insert the correct sync points,
|
||||
// a system can use a wildcard to indicate that any component could be
|
||||
// modified by the system, which forces the scheduler to insert a sync.
|
||||
|
||||
// Basic move system.
|
||||
ecs.system<Position, const Velocity>("Move")
|
||||
.each([](Position& p, const Velocity& v) {
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
});
|
||||
|
||||
// Delete entities when p.x >= 3. Add wildcard annotation to indicate any
|
||||
// component could be written by the system. Position itself is added as
|
||||
// const, since inside the system we're only reading it.
|
||||
ecs.system<const Position>("DeleteEntity")
|
||||
.write(flecs::Wildcard)
|
||||
.each([](flecs::entity e, const Position& p) {
|
||||
if (p.x >= 3) {
|
||||
std::cout << "Delete entity " << e.name() << "\n";
|
||||
e.destruct();
|
||||
}
|
||||
});
|
||||
|
||||
// Print resulting Position. Note that this system will never print entities
|
||||
// that have been deleted by the previous system.
|
||||
ecs.system<const Position>("PrintPosition")
|
||||
.each([](flecs::entity e, const Position& p) {
|
||||
std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
|
||||
});
|
||||
|
||||
// Create a few test entities for a Position, Velocity query
|
||||
ecs.entity("e1")
|
||||
.set<Position>({0, 0})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
ecs.entity("e2")
|
||||
.set<Position>({1, 2})
|
||||
.set<Velocity>({1, 2});
|
||||
|
||||
// Run systems. Debug logging enables us to see the generated schedule
|
||||
flecs::log::set_level(1);
|
||||
while (ecs.progress()) {
|
||||
if (!ecs.count<Position>()) {
|
||||
break; // No more entities left with Position
|
||||
}
|
||||
}
|
||||
flecs::log::set_level(-1); // Restore so we don't get world cleanup logs
|
||||
|
||||
// Output:
|
||||
// info: pipeline rebuild:
|
||||
// info: | schedule: threading: 0, staging: 1:
|
||||
// info: | | system Move
|
||||
// info: | | system DeleteEntity
|
||||
// info: | | merge
|
||||
// info: | schedule: threading: 0, staging: 1:
|
||||
// info: | | system PrintPosition
|
||||
// info: | | merge
|
||||
// e1: {1, 2}
|
||||
// e2: {2, 4}
|
||||
// Delete entity e2
|
||||
// e1: {2, 4}
|
||||
// Delete entity e1
|
||||
// info: system Move deactivated
|
||||
// info: system DeleteEntity deactivated
|
||||
// info: system PrintPosition deactivated
|
||||
//
|
||||
// Removing the wildcard annotation from the DeleteEntity system will
|
||||
// remove the first sync point.
|
||||
//
|
||||
// Note how after both entities are deleted, all three systems are
|
||||
// deactivated. This happens when there are no matching entities for a
|
||||
// system. A deactivated system is not ran by the scheduler, which reduces
|
||||
// overhead.
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef SYSTEM_CTX_H
|
||||
#define SYSTEM_CTX_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "system_ctx/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 SYSTEM_CTX_BAKE_CONFIG_H
|
||||
#define SYSTEM_CTX_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "system_ctx",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <system_ctx.h>
|
||||
#include <iostream>
|
||||
|
||||
// Applications can pass context data to a system. A common use case where this
|
||||
// comes in handy is when a system needs to iterate more than one query. The
|
||||
// following example shows how to pass a custom query into a system for a simple
|
||||
// collision detection example.
|
||||
|
||||
struct Position {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Radius {
|
||||
double value;
|
||||
};
|
||||
|
||||
double sqr(double value) {
|
||||
return value * value;
|
||||
}
|
||||
|
||||
double distance_sqr(const Position& p1, const Position& p2) {
|
||||
return sqr(p2.x - p1.x) + sqr(p2.y - p1.y);
|
||||
}
|
||||
|
||||
double randd(int max) {
|
||||
return static_cast<double>((rand() % max));
|
||||
}
|
||||
|
||||
using CollisionQuery = flecs::query<const Position, const Radius>;
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
CollisionQuery q_collide = ecs.query<const Position, const Radius>();
|
||||
|
||||
flecs::system sys = ecs.system<const Position, const Radius>("Collide")
|
||||
.ctx(&q_collide)
|
||||
.each([](flecs::iter& it, size_t i, const Position& p1, const Radius& r1) {
|
||||
CollisionQuery *q = it.ctx<CollisionQuery>();
|
||||
flecs::entity e1 = it.entity(i);
|
||||
|
||||
q->each([&](flecs::entity e2, const Position& p2, const Radius& r2) {
|
||||
if (e1 == e2) {
|
||||
// don't collide with self
|
||||
return;
|
||||
}
|
||||
|
||||
if (e1 > e2) {
|
||||
// Simple trick to prevent collisions from being detected
|
||||
// twice with the entities reversed.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for collision
|
||||
double d_sqr = distance_sqr(p1, p2);
|
||||
double r_sqr = sqr(r1.value + r2.value);
|
||||
if (r_sqr > d_sqr) {
|
||||
std::cout << e1 << " and " << e2 << " collided!\n";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Create a few test entities
|
||||
for (int i = 0; i < 10; i ++) {
|
||||
ecs.entity()
|
||||
.set<Position>({ randd(100), randd(100) })
|
||||
.set<Radius>({ randd(10) + 1 });
|
||||
}
|
||||
|
||||
// Run the system
|
||||
sys.run();
|
||||
|
||||
// Output
|
||||
// 526 and 529 collided!
|
||||
// 527 and 534 collided!
|
||||
// 529 and 531 collided!
|
||||
// 533 and 535 collided!
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef TARGET_FPS_H
|
||||
#define TARGET_FPS_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "target_fps/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 TARGET_FPS_BAKE_CONFIG_H
|
||||
#define TARGET_FPS_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "target_fps",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <target_fps.h>
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
// Create system that prints delta_time. This system doesn't query for any
|
||||
// components which means it won't match any entities, but will still be ran
|
||||
// once for each call to ecs_progress.
|
||||
ecs.system()
|
||||
.iter([](flecs::iter& it) {
|
||||
std::cout << "delta_time: " << it.delta_time() << std::endl;
|
||||
});
|
||||
|
||||
// Set target FPS to 1 frame per second
|
||||
ecs.set_target_fps(1);
|
||||
|
||||
// Run 5 frames
|
||||
for (int i = 0; i < 5; i ++) {
|
||||
// To make sure the frame doesn't run faster than the specified target
|
||||
// FPS ecs_progress will insert a sleep if the measured delta_time is
|
||||
// smaller than 1 / target_fps.
|
||||
//
|
||||
// By default ecs_progress uses the sleep function provided by the OS
|
||||
// which is not always very accurate. If more accuracy is required the
|
||||
// sleep function of the OS API can be overridden with a custom one.
|
||||
//
|
||||
// If a value other than 0 is provided to the delta_time argument of
|
||||
// ecs_progress, this value will be used to calculate the length of
|
||||
// the sleep to insert.
|
||||
ecs.progress();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef TIME_INTERVAL_H
|
||||
#define TIME_INTERVAL_H
|
||||
|
||||
/* This generated file contains includes for project dependencies */
|
||||
#include "time_interval/bake_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 TIME_INTERVAL_BAKE_CONFIG_H
|
||||
#define TIME_INTERVAL_BAKE_CONFIG_H
|
||||
|
||||
/* Headers of public dependencies */
|
||||
#include <flecs.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "time_interval",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <time_interval.h>
|
||||
#include <iostream>
|
||||
|
||||
// This example shows how to run a system at a specified time interval.
|
||||
|
||||
void Tick(flecs::iter& it) {
|
||||
std::cout << it.system().name() << "\n";
|
||||
}
|
||||
|
||||
int main(int, char *[]) {
|
||||
flecs::world ecs;
|
||||
|
||||
ecs.system("Tick")
|
||||
.interval(1.0) // time in seconds
|
||||
.iter(Tick);
|
||||
|
||||
ecs.system("FastTick")
|
||||
.interval(0.5)
|
||||
.iter(Tick);
|
||||
|
||||
// Run the main loop at 60 FPS
|
||||
ecs.set_target_fps(60);
|
||||
|
||||
while (ecs.progress()) { }
|
||||
|
||||
// Output
|
||||
// FastTick
|
||||
// Tick
|
||||
// FastTick
|
||||
// FastTick
|
||||
// Tick
|
||||
// FastTick
|
||||
// FastTick
|
||||
// Tick
|
||||
// FastTick
|
||||
// FastTick
|
||||
// ...
|
||||
}
|
||||
Reference in New Issue
Block a user