Skip to content
Flecs v4.1
impl.hpp
Go to the documentation of this file.
1/**
2 * @file addons/cpp/mixins/module/impl.hpp
3 * @brief Module implementation.
4 */
5
6#pragma once
7
8namespace flecs {
9
10namespace _ {
11
12template <typename T>
13ecs_entity_t do_import(world& world, const char *symbol) {
14 ecs_trace("#[magenta]import#[reset] %s", _::type_name<T>());
16
17 ecs_entity_t scope = ecs_set_scope(world, 0);
18
19 // Initialize module component type and don't allow it to be registered as a
20 // tag, as this would prevent calling emplace().
21 auto c_ = component<T>(world, nullptr, false);
22
23 // Make module component sparse so that it'll never move in memory. This
24 // guarantees that a module destructor can be reliably used to clean up
25 // module resources.
26 c_.add(flecs::Sparse);
27
28#ifdef FLECS_CONSTRAINT_TRAITS
29 c_.add(flecs::Singleton);
30#endif
31
32 ecs_add_id(world, c_, EcsModule);
33
34 ecs_set_scope(world, c_);
35 world.emplace<T>(world);
36 ecs_set_scope(world, scope);
37
38 // It should now be possible to look up the module.
39 ecs_entity_t m = ecs_lookup_symbol(world, symbol, false, false);
40 ecs_assert(m != 0, ECS_MODULE_UNDEFINED, "%s", symbol);
41 ecs_assert(m == c_, ECS_INTERNAL_ERROR, nullptr);
42
44
45 return m;
46}
47
48template <typename T>
49flecs::entity import(world& world) {
50 char *symbol = ecs_cpp_get_symbol_name(nullptr, type_name<T>(), 0);
51
52 ecs_entity_t m = ecs_lookup_symbol(world, symbol, true, false);
53
54 if (!_::type<T>::registered(world)) {
55 // Module is registered with world, initialize static data.
56 if (m) {
57 _::type<T>::init_builtin(world, m, false);
58
59 // Module is not yet registered, register it now.
60 } else {
61 m = _::do_import<T>(world, symbol);
62 }
63
64 // Module has been registered, but could have been for another world.
65 // Import if module hasn't been registered for this world.
66 } else if (!m) {
67 m = _::do_import<T>(world, symbol);
68 }
69
70 ecs_os_free(symbol);
71 return flecs::entity(world, m);
72}
73
74}
75
76/**
77 * @defgroup cpp_addons_modules Modules
78 * @ingroup cpp_addons
79 * Modules organize components, systems, and more in reusable units of code.
80 *
81 * @{
82 */
83
84template <typename Module>
85inline flecs::entity world::module(const char *name) const {
86 flecs::entity result = this->entity(
87 _::type<Module>::register_id(world_, nullptr, false));
88
89 if (name) {
90 flecs::entity prev_parent = result.parent();
91 ecs_add_path_w_sep(world_, result, 0, name, "::", "::");
92 flecs::entity parent = result.parent();
93 if (prev_parent != parent) {
94 if (parent && result.has(flecs::Module)) {
95 parent.add(flecs::Module);
96 }
97
98 // Module was reparented, clean up old parent(s).
99 flecs::entity cur = prev_parent, next;
100 while (cur) {
101 // Stop if the old parent is an ancestor of the new parent.
102 flecs::entity p = parent;
103 while (p && p != cur) {
104 p = p.parent();
105 }
106 if (p == cur) {
107 break;
108 }
109
110 next = cur.parent();
111
112 // Move entities that were created in the old parent to the
113 // renamed module.
114 bool has_modules = false;
116 ecs_iter_t it = ecs_children(world_, cur);
117 while (ecs_children_next(&it)) {
118 for (int32_t i = 0; i < it.count; i ++) {
119 flecs::entity_t child = it.entities[i];
120 if (ecs_has_id(world_, child, EcsModule)) {
121 has_modules = true;
122 continue;
123 }
124 if (ecs_has_pair(world_, child, ecs_id(EcsPoly),
126 {
127 continue;
128 }
129 ecs_add_pair(world_, child, EcsChildOf, result);
130 }
131 }
133
134 if (has_modules) {
135 break;
136 }
137
138 cur.destruct();
139 this->set_version(cur);
140 cur = next;
141 }
142 }
143 }
144
145 return result;
146}
147
148template <typename Module>
150 return flecs::_::import<Module>(*this);
151}
152
153/** @} */
154
155}
FLECS_API char * ecs_cpp_get_symbol_name(char *symbol_name, const char *type_name, size_t len)
Get symbol name from type name.
void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Add a (component) ID to an entity.
const ecs_entity_t EcsWildcard
Wildcard entity ("*").
const ecs_entity_t EcsChildOf
Used to express parent-child relationships.
const ecs_entity_t EcsModule
Tag added to module entities.
FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
Component ID for EcsDocDescription.
#define ECS_MODULE_UNDEFINED
Module undefined error code.
Definition log.h:712
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:473
#define ecs_log_push()
Push log indentation at the default level.
Definition log.h:458
#define ECS_INTERNAL_ERROR
Internal error code.
Definition log.h:681
#define ecs_trace(...)
Tracing macro.
Definition log.h:309
#define ecs_log_pop()
Pop log indentation at the default level.
Definition log.h:460
bool ecs_defer_end(ecs_world_t *world)
End a block of operations to defer.
bool ecs_defer_begin(ecs_world_t *world)
Defer operations until the end of the frame.
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:395
flecs::entity import()
Import a module.
Definition impl.hpp:149
flecs::entity module(const char *name=nullptr) const
Define a module.
Definition impl.hpp:85
ecs_entity_t entity_t
Entity type.
Definition c_types.hpp:21
bool ecs_children_next(ecs_iter_t *it)
Progress an iterator created with ecs_children().
ecs_iter_t ecs_children(const ecs_world_t *world, ecs_entity_t parent)
Iterate children of a parent.
bool ecs_has_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Test if an entity has a component.
#define ecs_add_pair(world, subject, first, second)
Add a pair to an entity.
Definition flecs_c.h:275
#define ecs_has_pair(world, entity, first, second)
Test if an entity has a pair.
Definition flecs_c.h:527
ecs_entity_t ecs_lookup_symbol(const ecs_world_t *world, const char *symbol, bool lookup_as_path, bool recursive)
Look up an entity by its symbol name.
ecs_entity_t ecs_add_path_w_sep(ecs_world_t *world, ecs_entity_t entity, ecs_entity_t parent, const char *path, const char *sep, const char *prefix)
Add a specified path to an entity.
ecs_entity_t ecs_set_scope(ecs_world_t *world, ecs_entity_t scope)
Set the current scope.
Int to enum.
Definition component.hpp:18
Component for storing a poly object.
Definition flecs.h:1626
Iterator.
Definition flecs.h:1192
int32_t count
Number of entities to iterate.
Definition flecs.h:1199
const ecs_entity_t * entities
Entity identifiers.
Definition flecs.h:1200
component(flecs::world_t *world, const char *name=nullptr, bool allow_tag=true, flecs::id_t id=0)
Register a component.
flecs::entity parent() const
Get parent of entity.
Definition impl.hpp:68
Entity.
Definition entity.hpp:30
void destruct() const
Delete an entity.
Definition entity.hpp:208
entity()
Default constructor.
Definition entity.hpp:32
world_t * world_
Pointer to the underlying C world.
Definition world.hpp:1009
void set_version(flecs::entity_t e) const
Set the version of an entity to the provided value.
Definition world.hpp:884
flecs::entity entity(Args &&... args) const
Create an entity.