registry/dispatcher/emitter: removed ::discard, updated test and doc
This commit is contained in:
@@ -32,10 +32,12 @@ erased on the other side of a boundary.<br/>
|
||||
The `type_info` class template is how identifiers are generated and thus made
|
||||
available to the rest of the library.
|
||||
|
||||
The only case in which this may arouse some interest is in case of conflicts
|
||||
between identifiers (definitely uncommon though) or where the default solution
|
||||
proposed by `EnTT` is not suitable for the user's purposes.<br/>
|
||||
Please refer to the dedicated section for more details.
|
||||
In general, this class doesn't arouse much interest. The only exception is in
|
||||
case of conflicts between identifiers (definitely uncommon though) or where the
|
||||
default solution proposed by `EnTT` isn't suitable for the user's purposes.<br/>
|
||||
The section dedicated to this core class contains all the details to get around
|
||||
the problem in a concise and elegant way. Please refer to the specific
|
||||
documentation.
|
||||
|
||||
# Meta context
|
||||
|
||||
@@ -80,29 +82,22 @@ available.
|
||||
|
||||
There is another subtle problem due to memory management that can lead to
|
||||
headaches.<br/>
|
||||
This can occur where there are pools of objects (such as components or events)
|
||||
dynamically created on demand.
|
||||
It can occur where there are pools of objects (such as components or events)
|
||||
dynamically created on demand. This is usually not a problem when working with
|
||||
linked libraries that rely on the same dynamic runtime. However, it can occur in
|
||||
the case of plugins or statically linked runtimes.
|
||||
|
||||
As an example, imagine creating an instance of `registry` in the main executable
|
||||
and share it with a plugin. If the latter starts working with a component that
|
||||
and sharing it with a plugin. If the latter starts working with a component that
|
||||
is unknown to the former, a dedicated pool is created within the registry on
|
||||
first use.<br/>
|
||||
As one can guess, this pool is instantiated on a different side of the boundary
|
||||
from the `registry`. Therefore, the instance is now managing memory from
|
||||
different spaces and this can quickly lead to crashes if not properly addressed.
|
||||
|
||||
Fortunately, all classes that could potentially suffer from this problem offer
|
||||
also a `discard` member function to get rid of these pools:
|
||||
|
||||
```cpp
|
||||
registry.discard<local_type>();
|
||||
```
|
||||
|
||||
This is all there is to do to get around this. Again, `discard` is only to be
|
||||
invoked if it's certain that the container and pools are instantiated on
|
||||
different sides of the boundary.
|
||||
|
||||
If in doubts or to avoid risks, simply invoke the `prepare` member function or
|
||||
any of the other functions that refer to the desired type to force the
|
||||
generation of the pools that are used on both sides of the boundary.<br/>
|
||||
This is something to be done usually in the main context when needed.
|
||||
To overcome the risk, it's recommended to use well-defined interfaces that make
|
||||
fundamental types pass through the boundaries, isolating the instances of the
|
||||
`EnTT` classes from time to time and as appropriate.<br/>
|
||||
Refer to the test suite for some examples, read the documentation available
|
||||
online about this type of issues or consult someone who has already had such
|
||||
experiences to avoid problems.
|
||||
|
||||
@@ -155,7 +155,7 @@ class basic_registry {
|
||||
template<typename Component>
|
||||
void maybe_valid_if(const Entity entt, basic_registry &owner) {
|
||||
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
|
||||
const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
|
||||
[[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
|
||||
|
||||
const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<pool_type<Owned> &>(cpools).has(entt)) && ...)
|
||||
&& ((std::is_same_v<Component, Get> || owner.assure<Get>().has(entt)) && ...)
|
||||
@@ -302,17 +302,6 @@ public:
|
||||
assure<Component>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discards the pools for the given components.
|
||||
* @tparam Component Types of components for which to discard the pools.
|
||||
*/
|
||||
template<typename... Component>
|
||||
void discard() {
|
||||
pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&pdata) {
|
||||
return ((pdata.type_id == type_info<Component>::id()) || ...);
|
||||
}), pools.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of existing components of the given type.
|
||||
* @tparam Component Type of component of which to return the size.
|
||||
|
||||
@@ -98,17 +98,6 @@ class dispatcher {
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Discards the pools for the given events.
|
||||
* @tparam Event Types of events for which to discard the pools.
|
||||
*/
|
||||
template<typename... Event>
|
||||
void discard() {
|
||||
pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&cpool) {
|
||||
return ((cpool->type_id() == type_info<Event>::id()) || ...);
|
||||
}), pools.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a sink object for the given event.
|
||||
*
|
||||
|
||||
@@ -186,17 +186,6 @@ public:
|
||||
/*! @brief Default move assignment operator. @return This emitter. */
|
||||
emitter & operator=(emitter &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Discards the pools for the given events.
|
||||
* @tparam Event Types of events for which to discard the pools.
|
||||
*/
|
||||
template<typename... Event>
|
||||
void discard() {
|
||||
pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&cpool) {
|
||||
return ((cpool->type_id() == type_info<Event>::id()) || ...);
|
||||
}), pools.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Emits the given event.
|
||||
*
|
||||
|
||||
@@ -2,10 +2,22 @@
|
||||
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/utility.hpp>
|
||||
#include <entt/signal/dispatcher.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(entt::dispatcher &ref)
|
||||
: dispatcher{&ref}
|
||||
{}
|
||||
|
||||
void proxy::trigger(message msg) {
|
||||
dispatcher->trigger(msg);
|
||||
}
|
||||
|
||||
void proxy::trigger(event ev) {
|
||||
dispatcher->trigger(ev);
|
||||
}
|
||||
|
||||
struct listener {
|
||||
void on(message msg) { value = msg.payload; }
|
||||
int value{};
|
||||
@@ -13,14 +25,15 @@ struct listener {
|
||||
|
||||
TEST(Lib, Dispatcher) {
|
||||
entt::dispatcher dispatcher;
|
||||
proxy handler{dispatcher};
|
||||
listener listener;
|
||||
|
||||
ASSERT_EQ(listener.value, 0);
|
||||
|
||||
dispatcher.sink<message>().connect<entt::overload<void(message)>(&listener::on)>(listener);
|
||||
dispatcher.sink<message>().connect<&listener::on>(listener);
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = &dispatcher;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
#include <cr.h>
|
||||
#include <entt/signal/dispatcher.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
|
||||
static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(event{});
|
||||
static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(message{42});
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->discard<event>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
16
test/lib/dispatcher_plugin/proxy.h
Normal file
16
test/lib/dispatcher_plugin/proxy.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENTT_LIB_DISPATCHER_PLUGIN_PROXY_H
|
||||
#define ENTT_LIB_DISPATCHER_PLUGIN_PROXY_H
|
||||
|
||||
#include <entt/signal/fwd.hpp>
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: dispatcher_proxy {
|
||||
proxy(entt::dispatcher &);
|
||||
void trigger(message) override;
|
||||
void trigger(event) override;
|
||||
|
||||
private:
|
||||
entt::dispatcher *dispatcher;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,4 +7,10 @@ struct message {
|
||||
|
||||
struct event {};
|
||||
|
||||
struct dispatcher_proxy {
|
||||
virtual ~dispatcher_proxy() = default;
|
||||
virtual void trigger(message) = 0;
|
||||
virtual void trigger(event) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,10 +2,22 @@
|
||||
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/utility.hpp>
|
||||
#include <entt/signal/dispatcher.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(entt::dispatcher &ref)
|
||||
: dispatcher{&ref}
|
||||
{}
|
||||
|
||||
void proxy::trigger(message msg) {
|
||||
dispatcher->trigger(msg);
|
||||
}
|
||||
|
||||
void proxy::trigger(event ev) {
|
||||
dispatcher->trigger(ev);
|
||||
}
|
||||
|
||||
struct listener {
|
||||
void on(message msg) { value = msg.payload; }
|
||||
int value{};
|
||||
@@ -13,14 +25,15 @@ struct listener {
|
||||
|
||||
TEST(Lib, Dispatcher) {
|
||||
entt::dispatcher dispatcher;
|
||||
proxy handler{dispatcher};
|
||||
listener listener;
|
||||
|
||||
ASSERT_EQ(listener.value, 0);
|
||||
|
||||
dispatcher.sink<message>().connect<entt::overload<void(message)>(&listener::on)>(listener);
|
||||
dispatcher.sink<message>().connect<&listener::on>(listener);
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = &dispatcher;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
#include <cr.h>
|
||||
#include <entt/signal/dispatcher.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
|
||||
static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(event{});
|
||||
static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(message{42});
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<entt::dispatcher *>(ctx->userdata)->discard<event>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
16
test/lib/dispatcher_plugin_std/proxy.h
Normal file
16
test/lib/dispatcher_plugin_std/proxy.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENTT_LIB_DISPATCHER_PLUGIN_STD_PROXY_H
|
||||
#define ENTT_LIB_DISPATCHER_PLUGIN_STD_PROXY_H
|
||||
|
||||
#include <entt/signal/fwd.hpp>
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: dispatcher_proxy {
|
||||
proxy(entt::dispatcher &);
|
||||
void trigger(message) override;
|
||||
void trigger(event) override;
|
||||
|
||||
private:
|
||||
entt::dispatcher *dispatcher;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,33 +1,16 @@
|
||||
#ifndef ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
|
||||
#define ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/type_info.hpp>
|
||||
|
||||
template<typename>
|
||||
struct event_id;
|
||||
|
||||
#define ASSIGN_TYPE_ID(clazz)\
|
||||
template<>\
|
||||
struct event_id<clazz>\
|
||||
: std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
|
||||
{}
|
||||
|
||||
template<typename Type>
|
||||
struct entt::type_info<Type> {
|
||||
static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
|
||||
return event_id<Type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
struct message {
|
||||
int payload;
|
||||
};
|
||||
|
||||
struct event {};
|
||||
|
||||
ASSIGN_TYPE_ID(message);
|
||||
ASSIGN_TYPE_ID(event);
|
||||
struct dispatcher_proxy {
|
||||
virtual ~dispatcher_proxy() = default;
|
||||
virtual void trigger(message) = 0;
|
||||
virtual void trigger(event) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,24 @@
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(test_emitter &ref)
|
||||
: emitter{&ref}
|
||||
{}
|
||||
|
||||
void proxy::publish(message msg) {
|
||||
emitter->publish<message>(msg);
|
||||
}
|
||||
|
||||
void proxy::publish(event ev) {
|
||||
emitter->publish<event>(ev);
|
||||
}
|
||||
|
||||
TEST(Lib, Emitter) {
|
||||
test_emitter emitter;
|
||||
proxy handler{emitter};
|
||||
int value{};
|
||||
|
||||
ASSERT_EQ(value, 0);
|
||||
@@ -14,7 +28,7 @@ TEST(Lib, Emitter) {
|
||||
emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = &emitter;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#include <cr.h>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<event>();
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<message>(42);
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<message>(3);
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(event{});
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(message{42});
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(message{3});
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<test_emitter *>(ctx->userdata)->discard<event>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
15
test/lib/emitter_plugin/proxy.h
Normal file
15
test/lib/emitter_plugin/proxy.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ENTT_LIB_EMITTER_PLUGIN_PROXY_H
|
||||
#define ENTT_LIB_EMITTER_PLUGIN_PROXY_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: emitter_proxy {
|
||||
proxy(test_emitter &);
|
||||
void publish(message) override;
|
||||
void publish(event) override;
|
||||
|
||||
private:
|
||||
test_emitter *emitter;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -13,4 +13,10 @@ struct message {
|
||||
|
||||
struct event {};
|
||||
|
||||
struct emitter_proxy {
|
||||
virtual ~emitter_proxy() = default;
|
||||
virtual void publish(message) = 0;
|
||||
virtual void publish(event) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,24 @@
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(test_emitter &ref)
|
||||
: emitter{&ref}
|
||||
{}
|
||||
|
||||
void proxy::publish(message msg) {
|
||||
emitter->publish<message>(msg);
|
||||
}
|
||||
|
||||
void proxy::publish(event ev) {
|
||||
emitter->publish<event>(ev);
|
||||
}
|
||||
|
||||
TEST(Lib, Emitter) {
|
||||
test_emitter emitter;
|
||||
proxy handler{emitter};
|
||||
int value{};
|
||||
|
||||
ASSERT_EQ(value, 0);
|
||||
@@ -14,7 +28,7 @@ TEST(Lib, Emitter) {
|
||||
emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = &emitter;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#include <cr.h>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<event>();
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<message>(42);
|
||||
static_cast<test_emitter *>(ctx->userdata)->publish<message>(3);
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(event{});
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(message{42});
|
||||
static_cast<emitter_proxy *>(ctx->userdata)->publish(message{3});
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<test_emitter *>(ctx->userdata)->discard<event>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
15
test/lib/emitter_plugin_std/proxy.h
Normal file
15
test/lib/emitter_plugin_std/proxy.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ENTT_LIB_EMITTER_PLUGIN_STD_PROXY_H
|
||||
#define ENTT_LIB_EMITTER_PLUGIN_STD_PROXY_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: emitter_proxy {
|
||||
proxy(test_emitter &);
|
||||
void publish(message) override;
|
||||
void publish(event) override;
|
||||
|
||||
private:
|
||||
test_emitter *emitter;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,27 +1,8 @@
|
||||
#ifndef ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
|
||||
#define ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
|
||||
template<typename>
|
||||
struct event_id;
|
||||
|
||||
#define ASSIGN_TYPE_ID(clazz)\
|
||||
template<>\
|
||||
struct event_id<clazz>\
|
||||
: std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
|
||||
{}
|
||||
|
||||
template<typename Type>
|
||||
struct entt::type_info<Type> {
|
||||
static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
|
||||
return event_id<Type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
struct test_emitter
|
||||
: entt::emitter<test_emitter>
|
||||
{};
|
||||
@@ -32,7 +13,10 @@ struct message {
|
||||
|
||||
struct event {};
|
||||
|
||||
ASSIGN_TYPE_ID(message);
|
||||
ASSIGN_TYPE_ID(event);
|
||||
struct emitter_proxy {
|
||||
virtual ~emitter_proxy() = default;
|
||||
virtual void publish(message) = 0;
|
||||
virtual void publish(event) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,26 @@
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(entt::registry &ref)
|
||||
: registry{&ref}
|
||||
{}
|
||||
|
||||
void proxy::for_each(void(*cb)(position &, velocity &)) {
|
||||
registry->view<position, velocity>().each(cb);
|
||||
}
|
||||
|
||||
void proxy::assign(velocity vel) {
|
||||
for(auto entity: registry->view<position>()) {
|
||||
registry->assign<velocity>(entity, vel);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Lib, Registry) {
|
||||
entt::registry registry;
|
||||
proxy handler{registry};
|
||||
|
||||
for(auto i = 0; i < 3; ++i) {
|
||||
const auto entity = registry.create();
|
||||
@@ -14,7 +30,7 @@ TEST(Lib, Registry) {
|
||||
}
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = ®istry;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
#include <cr.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
[ctx]() {
|
||||
auto *registry = static_cast<entt::registry *>(ctx->userdata);
|
||||
// forces the creation of the pool for the velocity component
|
||||
registry->prepare<velocity>();
|
||||
auto *proxy = static_cast<registry_proxy *>(ctx->userdata);
|
||||
|
||||
for(auto entity: registry->view<position>()) {
|
||||
registry->assign<velocity>(entity, 1., 1.);
|
||||
}
|
||||
proxy->assign({1., 1.});
|
||||
|
||||
registry->view<position, velocity>().each([](auto &pos, auto &vel) {
|
||||
pos.x += 16 * vel.dx;
|
||||
pos.y += 16 * vel.dy;
|
||||
proxy->for_each([](auto &pos, auto &vel) {
|
||||
pos.x += static_cast<int>(16 * vel.dx);
|
||||
pos.y += static_cast<int>(16 * vel.dy);
|
||||
});
|
||||
}();
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<entt::registry *>(ctx->userdata)->discard<velocity>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
16
test/lib/registry_plugin/proxy.h
Normal file
16
test/lib/registry_plugin/proxy.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENTT_LIB_REGISTRY_PLUGIN_PROXY_H
|
||||
#define ENTT_LIB_REGISTRY_PLUGIN_PROXY_H
|
||||
|
||||
#include <entt/entity/fwd.hpp>
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: registry_proxy {
|
||||
proxy(entt::registry &);
|
||||
void for_each(void(*)(position &, velocity &)) override;
|
||||
void assign(velocity) override;
|
||||
|
||||
private:
|
||||
entt::registry *registry;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,4 +11,10 @@ struct velocity {
|
||||
double dy;
|
||||
};
|
||||
|
||||
struct registry_proxy {
|
||||
virtual ~registry_proxy() = default;
|
||||
virtual void for_each(void(*)(position &, velocity &)) = 0;
|
||||
virtual void assign(velocity) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,26 @@
|
||||
#include <cr.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "proxy.h"
|
||||
#include "types.h"
|
||||
|
||||
proxy::proxy(entt::registry &ref)
|
||||
: registry{&ref}
|
||||
{}
|
||||
|
||||
void proxy::for_each(void(*cb)(position &, velocity &)) {
|
||||
registry->view<position, velocity>().each(cb);
|
||||
}
|
||||
|
||||
void proxy::assign(velocity vel) {
|
||||
for(auto entity: registry->view<position>()) {
|
||||
registry->assign<velocity>(entity, vel);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Lib, Registry) {
|
||||
entt::registry registry;
|
||||
proxy handler{registry};
|
||||
|
||||
for(auto i = 0; i < 3; ++i) {
|
||||
const auto entity = registry.create();
|
||||
@@ -14,7 +30,7 @@ TEST(Lib, Registry) {
|
||||
}
|
||||
|
||||
cr_plugin ctx;
|
||||
ctx.userdata = ®istry;
|
||||
ctx.userdata = &handler;
|
||||
cr_plugin_load(ctx, PLUGIN);
|
||||
cr_plugin_update(ctx);
|
||||
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
#include <cr.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include "types.h"
|
||||
|
||||
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
|
||||
switch (operation) {
|
||||
case CR_STEP:
|
||||
[ctx]() {
|
||||
auto *registry = static_cast<entt::registry *>(ctx->userdata);
|
||||
// forces the creation of the pool for the velocity component
|
||||
registry->prepare<velocity>();
|
||||
auto *proxy = static_cast<registry_proxy *>(ctx->userdata);
|
||||
|
||||
for(auto entity: registry->view<position>()) {
|
||||
registry->assign<velocity>(entity, 1., 1.);
|
||||
}
|
||||
proxy->assign({1., 1.});
|
||||
|
||||
registry->view<position, velocity>().each([](auto &pos, auto &vel) {
|
||||
pos.x += 16 * vel.dx;
|
||||
pos.y += 16 * vel.dy;
|
||||
proxy->for_each([](auto &pos, auto &vel) {
|
||||
pos.x += static_cast<int>(16 * vel.dx);
|
||||
pos.y += static_cast<int>(16 * vel.dy);
|
||||
});
|
||||
}();
|
||||
break;
|
||||
case CR_CLOSE:
|
||||
static_cast<entt::registry *>(ctx->userdata)->discard<velocity>();
|
||||
break;
|
||||
case CR_LOAD:
|
||||
case CR_UNLOAD:
|
||||
// nothing to do here, this is only a test.
|
||||
|
||||
16
test/lib/registry_plugin_std/proxy.h
Normal file
16
test/lib/registry_plugin_std/proxy.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENTT_LIB_REGISTRY_PLUGIN_STD_PROXY_H
|
||||
#define ENTT_LIB_REGISTRY_PLUGIN_STD_PROXY_H
|
||||
|
||||
#include <entt/entity/fwd.hpp>
|
||||
#include "types.h"
|
||||
|
||||
struct proxy: registry_proxy {
|
||||
proxy(entt::registry &);
|
||||
void for_each(void(*)(position &, velocity &)) override;
|
||||
void assign(velocity) override;
|
||||
|
||||
private:
|
||||
entt::registry *registry;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,26 +1,6 @@
|
||||
#ifndef ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
|
||||
#define ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/type_info.hpp>
|
||||
|
||||
template<typename>
|
||||
struct component_id;
|
||||
|
||||
#define ASSIGN_TYPE_ID(clazz)\
|
||||
template<>\
|
||||
struct component_id<clazz>\
|
||||
: std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
|
||||
{}
|
||||
|
||||
template<typename Type>
|
||||
struct entt::type_info<Type> {
|
||||
static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
|
||||
return component_id<Type>::value;
|
||||
}
|
||||
};
|
||||
|
||||
struct position {
|
||||
int x;
|
||||
int y;
|
||||
@@ -31,7 +11,10 @@ struct velocity {
|
||||
double dy;
|
||||
};
|
||||
|
||||
ASSIGN_TYPE_ID(position);
|
||||
ASSIGN_TYPE_ID(velocity);
|
||||
struct registry_proxy {
|
||||
virtual ~registry_proxy() = default;
|
||||
virtual void for_each(void(*)(position &, velocity &)) = 0;
|
||||
virtual void assign(velocity) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user