Properly link flecs library
This commit is contained in:
19
engine/libs/flecs/examples/cpp/CMakeLists.txt
Normal file
19
engine/libs/flecs/examples/cpp/CMakeLists.txt
Normal 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 ()
|
||||
5
engine/libs/flecs/examples/cpp/entities/basics/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/entities/basics/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
12
engine/libs/flecs/examples/cpp/entities/basics/project.json
Normal file
12
engine/libs/flecs/examples/cpp/entities/basics/project.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "basics",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
53
engine/libs/flecs/examples/cpp/entities/basics/src/main.cpp
Normal file
53
engine/libs/flecs/examples/cpp/entities/basics/src/main.cpp
Normal 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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
engine/libs/flecs/examples/cpp/entities/emplace/project.json
Normal file
11
engine/libs/flecs/examples/cpp/entities/emplace/project.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "emplace",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
28
engine/libs/flecs/examples/cpp/entities/emplace/src/main.cpp
Normal file
28
engine/libs/flecs/examples/cpp/entities/emplace/src/main.cpp
Normal 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}
|
||||
}
|
||||
5
engine/libs/flecs/examples/cpp/entities/hierarchy/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/entities/hierarchy/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "hierarchy",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
5
engine/libs/flecs/examples/cpp/entities/hooks/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/entities/hooks/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
10
engine/libs/flecs/examples/cpp/entities/hooks/project.json
Normal file
10
engine/libs/flecs/examples/cpp/entities/hooks/project.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "hooks",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
108
engine/libs/flecs/examples/cpp/entities/hooks/src/main.cpp
Normal file
108
engine/libs/flecs/examples/cpp/entities/hooks/src/main.cpp
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "multi_set_get",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
5
engine/libs/flecs/examples/cpp/entities/prefab/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/entities/prefab/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
12
engine/libs/flecs/examples/cpp/entities/prefab/project.json
Normal file
12
engine/libs/flecs/examples/cpp/entities/prefab/project.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "prefab",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"author": "Jane Doe",
|
||||
"description": "A simple hello world flecs application",
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
70
engine/libs/flecs/examples/cpp/entities/prefab/src/main.cpp
Normal file
70
engine/libs/flecs/examples/cpp/entities/prefab/src/main.cpp
Normal 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";
|
||||
});
|
||||
}
|
||||
16
engine/libs/flecs/examples/cpp/explorer/include/explorer.h
Normal file
16
engine/libs/flecs/examples/cpp/explorer/include/explorer.h
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
engine/libs/flecs/examples/cpp/explorer/project.json
Normal file
11
engine/libs/flecs/examples/cpp/explorer/project.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "explorer",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"public": false,
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
37
engine/libs/flecs/examples/cpp/explorer/src/main.cpp
Normal file
37
engine/libs/flecs/examples/cpp/explorer/src/main.cpp
Normal 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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "factory",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "inventory_system",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "scene_management",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"public": false,
|
||||
"language": "c++"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
5
engine/libs/flecs/examples/cpp/hello_world/.gitignore
vendored
Normal file
5
engine/libs/flecs/examples/cpp/hello_world/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.bake_cache
|
||||
.DS_Store
|
||||
.vscode
|
||||
gcov
|
||||
bin
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
12
engine/libs/flecs/examples/cpp/hello_world/project.json
Normal file
12
engine/libs/flecs/examples/cpp/hello_world/project.json
Normal 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++"
|
||||
}
|
||||
}
|
||||
50
engine/libs/flecs/examples/cpp/hello_world/src/main.cpp
Normal file
50
engine/libs/flecs/examples/cpp/hello_world/src/main.cpp
Normal 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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "simple_module",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
engine/libs/flecs/examples/cpp/observers/basics/project.json
Normal file
11
engine/libs/flecs/examples/cpp/observers/basics/project.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "basics",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
68
engine/libs/flecs/examples/cpp/observers/basics/src/main.cpp
Normal file
68
engine/libs/flecs/examples/cpp/observers/basics/src/main.cpp
Normal 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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "custom_event",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "entity_event",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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}!
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "monitor",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "propagate",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "two_components",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "yield_existing",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
engine/libs/flecs/examples/cpp/prefabs/basics/project.json
Normal file
11
engine/libs/flecs/examples/cpp/prefabs/basics/project.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "basics",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
56
engine/libs/flecs/examples/cpp/prefabs/basics/src/main.cpp
Normal file
56
engine/libs/flecs/examples/cpp/prefabs/basics/src/main.cpp
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"id": "hierarchy",
|
||||
"type": "application",
|
||||
"value": {
|
||||
"use": [
|
||||
"flecs"
|
||||
],
|
||||
"language": "c++",
|
||||
"public": false
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user