Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
043f9a5025 | ||
|
|
822264a65e | ||
|
|
8e9a6a4f06 | ||
|
|
76f3909ec9 | ||
|
|
23e839b40e | ||
|
|
6a560fc7bf | ||
|
|
709d1c93a4 | ||
|
|
8d4b5f4bb7 | ||
|
|
9eb5a85e9e | ||
|
|
e7521445e9 | ||
|
|
bb050e2660 | ||
|
|
bc3b0eb491 | ||
|
|
7cea05d376 | ||
|
|
b8a3bdf6b5 | ||
|
|
638b6dba17 | ||
|
|
50ba8c6c39 | ||
|
|
94d15ebbef | ||
|
|
e150882231 | ||
|
|
80a659c90c | ||
|
|
17d96427ea | ||
|
|
7fdda788af | ||
|
|
182adbd9d9 | ||
|
|
4931c9cd9b | ||
|
|
a112409735 |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile tests
|
||||
working-directory: build
|
||||
env:
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile tests
|
||||
working-directory: build
|
||||
run: |
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
runs-on: macOS-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile tests
|
||||
working-directory: build
|
||||
run: |
|
||||
|
||||
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile tests
|
||||
working-directory: build
|
||||
env:
|
||||
|
||||
40
.github/workflows/deploy.yml
vendored
Normal file
40
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: deploy
|
||||
|
||||
on:
|
||||
release:
|
||||
types: published
|
||||
|
||||
jobs:
|
||||
|
||||
homebrew-entt:
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
GH_REPO: homebrew-entt
|
||||
FORMULA: entt.rb
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Clone repository
|
||||
working-directory: build
|
||||
env:
|
||||
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
run: |
|
||||
git clone https://$GITHUB_ACTOR:$PERSONAL_ACCESS_TOKEN@github.com/$GITHUB_ACTOR/$GH_REPO.git
|
||||
- name: Prepare formula
|
||||
working-directory: build
|
||||
run: |
|
||||
cd $GH_REPO
|
||||
curl "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" --location --fail --silent --show-error --output archive.tar.gz
|
||||
sed -i -e '/url/s/".*"/"'$(echo "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" | sed -e 's/[\/&]/\\&/g')'"/' $FORMULA
|
||||
sed -i -e '/sha256/s/".*"/"'$(openssl sha256 archive.tar.gz | cut -d " " -f 2)'"/' $FORMULA
|
||||
- name: Update remote
|
||||
working-directory: build
|
||||
run: |
|
||||
cd $GH_REPO
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "$GITHUB_ACTOR"
|
||||
git add $FORMULA
|
||||
git commit -m "Update to ${{ github.ref }}"
|
||||
git push --dry-run origin master
|
||||
15
BUILD.bazel
Normal file
15
BUILD.bazel
Normal file
@@ -0,0 +1,15 @@
|
||||
_msvc_copts = ["/std:c++17"]
|
||||
_gcc_copts = ["-std=c++17"]
|
||||
|
||||
cc_library(
|
||||
name = "entt",
|
||||
visibility = ["//visibility:public"],
|
||||
strip_include_prefix = "src",
|
||||
hdrs = glob(["src/**/*.h", "src/**/*.hpp"]),
|
||||
copts = select({
|
||||
"@bazel_tools//src/conditions:windows": _msvc_copts,
|
||||
"@bazel_tools//src/conditions:windows_msvc": _msvc_copts,
|
||||
"@bazel_tools//src/conditions:windows_msys": _msvc_copts,
|
||||
"//conditions:default": _gcc_copts,
|
||||
}),
|
||||
)
|
||||
@@ -81,17 +81,10 @@ add_library(EnTT::EnTT ALIAS EnTT)
|
||||
target_include_directories(
|
||||
EnTT
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
|
||||
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
EnTT
|
||||
INTERFACE
|
||||
$<$<AND:$<CONFIG:Debug>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:DEBUG>
|
||||
$<$<AND:$<CONFIG:Release>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:RELEASE>
|
||||
)
|
||||
|
||||
if(USE_ASAN)
|
||||
target_compile_options(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
|
||||
target_link_libraries(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
|
||||
@@ -107,16 +100,28 @@ target_compile_features(EnTT INTERFACE cxx_std_17)
|
||||
# Install EnTT
|
||||
#
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(CUSTOM_INSTALL_CONFIGDIR cmake)
|
||||
else()
|
||||
set(CUSTOM_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/entt)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(TARGETS EnTT EXPORT EnTTTargets)
|
||||
|
||||
export(EXPORT EnTTTargets FILE ${EnTT_BINARY_DIR}/EnTTTargets.cmake)
|
||||
configure_package_config_file(
|
||||
${EnTT_SOURCE_DIR}/cmake/in/EnTTConfig.cmake.in
|
||||
EnTTConfig.cmake
|
||||
INSTALL_DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
EnTTConfigVersion.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT EnTTTargets
|
||||
@@ -125,39 +130,14 @@ install(
|
||||
NAMESPACE EnTT::
|
||||
)
|
||||
|
||||
#
|
||||
# Build tree package config file
|
||||
#
|
||||
|
||||
configure_file(cmake/in/EnTTBuildConfig.cmake.in EnTTConfig.cmake @ONLY)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
#
|
||||
# Install tree package config file
|
||||
#
|
||||
|
||||
configure_package_config_file(
|
||||
cmake/in/EnTTConfig.cmake.in
|
||||
${CUSTOM_INSTALL_CONFIGDIR}/EnTTConfig.cmake
|
||||
INSTALL_DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
${EnTT_BINARY_DIR}/EnTTConfigVersion.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${EnTT_BINARY_DIR}/${CUSTOM_INSTALL_CONFIGDIR}/EnTTConfig.cmake
|
||||
${EnTT_BINARY_DIR}/EnTTConfigVersion.cmake
|
||||
${PROJECT_BINARY_DIR}/EnTTConfig.cmake
|
||||
${PROJECT_BINARY_DIR}/EnTTConfigVersion.cmake
|
||||
DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
|
||||
)
|
||||
|
||||
export(PACKAGE EnTT)
|
||||
install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
#
|
||||
# Tests
|
||||
@@ -193,16 +173,16 @@ endif()
|
||||
# AOB
|
||||
#
|
||||
|
||||
set(
|
||||
AOB_SOURCES
|
||||
.github/workflows/build.yml
|
||||
.github/workflows/coverage.yml
|
||||
.github/FUNDING.yml
|
||||
AUTHORS
|
||||
CONTRIBUTING.md
|
||||
LICENSE
|
||||
README.md
|
||||
TODO
|
||||
add_custom_target(
|
||||
aob
|
||||
SOURCES
|
||||
.github/workflows/build.yml
|
||||
.github/workflows/coverage.yml
|
||||
.github/workflows/deploy.yml
|
||||
.github/FUNDING.yml
|
||||
AUTHORS
|
||||
CONTRIBUTING.md
|
||||
LICENSE
|
||||
README.md
|
||||
TODO
|
||||
)
|
||||
|
||||
add_custom_target(aob SOURCES ${AOB_SOURCES})
|
||||
|
||||
@@ -222,6 +222,11 @@ documentation:
|
||||
* `CMake` version 3.7 or later.
|
||||
* `Doxygen` version 1.8 or later.
|
||||
|
||||
Alternatively, [Bazel](https://bazel.build) is also supported as a build system
|
||||
(credits to [zaucy](https://github.com/zaucy) who offered to maintain it).<br/>
|
||||
In the documentation below I'll still refer to `CMake`, this being the official
|
||||
build system of the library.
|
||||
|
||||
If you are looking for a C++14 version of `EnTT`, check out the git tag `cpp14`.
|
||||
|
||||
## Library
|
||||
|
||||
9
TODO
9
TODO
@@ -9,7 +9,6 @@
|
||||
* add examples (and credits) from @alanjfs :)
|
||||
* static reflection, hint: template<> meta_type_t<Type>: meta_descriptor<name, func..., props..., etc...> (see #342)
|
||||
* observer: user defined filters (eg .replace<T, &function> or .group<T, U, &func>)
|
||||
* use underlying_type as entity type within pools and registry? it would make different registries work together flawlessy
|
||||
* can we write a bool conv func for entt::entity that silently compares it to null?
|
||||
* reset... reset everywhere...
|
||||
* is it possible to make 0 the entity null?
|
||||
@@ -17,7 +16,13 @@
|
||||
* any-of rule for views/groups (eg entity has A and any of B/C/D)
|
||||
- get -> all, exclude -> none
|
||||
* review prepare after clone and the others have been removed
|
||||
* remove copy-ctor/op from sparse set and storage (it doesn't make much sense)
|
||||
* unlock deploy.yml
|
||||
|
||||
Next:
|
||||
* review pool<T>::remove, ::assign
|
||||
* replace observer class with observer functions
|
||||
* workflow to update the single include file automatically
|
||||
* workflow to update the doc automatically
|
||||
|
||||
* WIP:
|
||||
- deprecate snapshot, loader, ...
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
set(ENTT_VERSION "@PROJECT_VERSION@")
|
||||
set(ENTT_INCLUDE_DIRS "@CMAKE_CURRENT_SOURCE_DIR@/src")
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/EnTTTargets.cmake")
|
||||
endif()
|
||||
@@ -9,28 +9,24 @@ set(DOXY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
configure_file(doxy.in doxy.cfg @ONLY)
|
||||
|
||||
set(
|
||||
DOC_SOURCES
|
||||
dox/extra.dox
|
||||
md/core.md
|
||||
md/entity.md
|
||||
md/faq.md
|
||||
md/lib.md
|
||||
md/links.md
|
||||
md/locator.md
|
||||
md/meta.md
|
||||
md/process.md
|
||||
md/resource.md
|
||||
md/signal.md
|
||||
doxy.in
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
docs ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.cfg
|
||||
WORKING_DIRECTORY ${EnTT_SOURCE_DIR}
|
||||
VERBATIM
|
||||
SOURCES ${DOC_SOURCES}
|
||||
SOURCES
|
||||
dox/extra.dox
|
||||
md/core.md
|
||||
md/entity.md
|
||||
md/faq.md
|
||||
md/lib.md
|
||||
md/links.md
|
||||
md/locator.md
|
||||
md/meta.md
|
||||
md/process.md
|
||||
md/resource.md
|
||||
md/signal.md
|
||||
doxy.in
|
||||
)
|
||||
|
||||
install(
|
||||
|
||||
@@ -701,7 +701,11 @@ A general purpose cloning function could be defined as:
|
||||
```cpp
|
||||
template<typename Type>
|
||||
void clone(const entt::registry &from, entt::registry &to) {
|
||||
to.assign<Type>(from.data<Type>(), from.data<Type>() + from.size<Type>(), from.raw<Type>());
|
||||
if constexpr(ENTT_ENABLE_ETO(Type)) {
|
||||
to.assign<Type>(from.data<Type>(), from.data<Type>() + from.size<Type>());
|
||||
} else {
|
||||
to.assign<Type>(from.data<Type>(), from.data<Type>() + from.size<Type>(), from.raw<Type>());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -765,7 +769,7 @@ the type identifiers and their opaque functions for stamping. As an example:
|
||||
```
|
||||
template<typename Type>
|
||||
void stamp(const entt::registry &from, const entt::entity src, entt::registry &to, const entt::entity dst) {
|
||||
to.assign_or_replace<Type>(dst, from.get_or_assign<Type>(src));
|
||||
to.assign_or_replace<Type>(dst, from.get<Type>(src));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -989,9 +993,15 @@ In particular:
|
||||
void operator()(entt::entity);
|
||||
```
|
||||
|
||||
Where `entt::entity` is the type of the entities used by the registry. Note
|
||||
that all the member functions of the snapshot class make also an initial call
|
||||
to this endpoint to save the _size_ of the set they are going to store.<br/>
|
||||
Where `entt::entity` is the type of the entities used by the registry.<br/>
|
||||
Note that all member functions of the snapshot class make also an initial call
|
||||
to store aside the _size_ of the set they are going to store. In this case,
|
||||
the expected function type for the function call operator is:
|
||||
|
||||
```cpp
|
||||
void operator()(std::underlying_type_t<entt::entity>);
|
||||
```
|
||||
|
||||
In addition, an archive must accept a pair of entity and component for each
|
||||
type to be serialized. Therefore, given a type `T`, the archive must contain a
|
||||
function call operator with the following signature:
|
||||
@@ -1012,12 +1022,18 @@ In particular:
|
||||
|
||||
Where `entt::entity` is the type of the entities used by the registry. Each
|
||||
time the function is invoked, the archive must read the next element from the
|
||||
underlying storage and copy it in the given variable. Note that all the member
|
||||
functions of a loader class make also an initial call to this endpoint to read
|
||||
the _size_ of the set they are going to load.<br/>
|
||||
In addition, the archive must accept a pair of entity and component for each
|
||||
type to be restored. Therefore, given a type `T`, the archive must contain a
|
||||
function call operator with the following signature:
|
||||
underlying storage and copy it in the given variable.<br/>
|
||||
Note that all member functions of a loader class make also an initial call to
|
||||
read the _size_ of the set they are going to load. In this case, the expected
|
||||
function type for the function call operator is:
|
||||
|
||||
```cpp
|
||||
void operator()(std::underlying_type_t<entt::entity> &);
|
||||
```
|
||||
|
||||
In addition, the archive must accept a pair of references to an entity and its
|
||||
component for each type to be restored. Therefore, given a type `T`, the
|
||||
archive must contain a function call operator with the following signature:
|
||||
|
||||
```cpp
|
||||
void operator()(entt::entity &, T &);
|
||||
|
||||
@@ -76,6 +76,8 @@ I hope this list can grow much more in the future:
|
||||
developed for educational purposes.
|
||||
* [Lumos](https://github.com/jmorton06/Lumos): game engine written in C++
|
||||
using OpenGL and Vulkan.
|
||||
* [Chrysalis](https://github.com/ivanhawkes/Chrysalis): action RPG SDK for
|
||||
CRYENGINE games.
|
||||
|
||||
* Articles and blog posts:
|
||||
* [Some posts](https://skypjack.github.io/tags/#entt) on my personal
|
||||
@@ -91,6 +93,9 @@ I hope this list can grow much more in the future:
|
||||
giant space battle.
|
||||
* [Conan Adventures (SFML and EnTT in C++)](https://leinnan.github.io/blog/conan-adventuressfml-and-entt-in-c.html):
|
||||
create projects in modern C++ using `SFML`, `EnTT`, `Conan` and `CMake`.
|
||||
* [Adding EnTT ECS to Chrysalis](https://www.tauradius.com/post/adding-an-ecs-to-chrysalis/):
|
||||
a blog entry about the process followed and the results of the integration
|
||||
of `EnTT` into `Chrysalis`.
|
||||
|
||||
* Any Other Business:
|
||||
* The [ArcGIS Runtime SDKs](https://developers.arcgis.com/arcgis-runtime/)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -44,10 +44,10 @@
|
||||
|
||||
#ifndef ENTT_DISABLE_ETO
|
||||
# include <type_traits>
|
||||
# define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
|
||||
# define ENTT_ENABLE_ETO(Type) (std::is_default_constructible_v<Type> && std::is_empty_v<Type>)
|
||||
#else
|
||||
# // sfinae-friendly definition
|
||||
# define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
|
||||
# define ENTT_ENABLE_ETO(Type) (false && std::is_void_v<Type>)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define ENTT_VERSION_MAJOR 3
|
||||
#define ENTT_VERSION_MINOR 3
|
||||
#define ENTT_VERSION_PATCH 0
|
||||
#define ENTT_VERSION_PATCH 2
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -130,7 +130,7 @@ struct basic_actor {
|
||||
*/
|
||||
template<typename... Component>
|
||||
bool has() const {
|
||||
return (reg->template has<Component>(entt) && ...);
|
||||
return reg->template has<Component...>(entt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,7 +54,7 @@ class basic_group;
|
||||
* all of them because they _share_ entities and components).
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of a group must overcome the one of the registry that generated it.
|
||||
* Lifetime of a group must not overcome that of the registry that generated it.
|
||||
* In any other case, attempting to use a group results in undefined behavior.
|
||||
*
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
@@ -484,7 +484,7 @@ private:
|
||||
* of them because they share the underlying data structure).
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of a group must overcome the one of the registry that generated it.
|
||||
* Lifetime of a group must not overcome that of the registry that generated it.
|
||||
* In any other case, attempting to use a group results in undefined behavior.
|
||||
*
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
|
||||
@@ -159,7 +159,7 @@ constexpr basic_collector<> collector{};
|
||||
* behavior.
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of an observer doesn't necessarily have to overcome the one of the
|
||||
* Lifetime of an observer doesn't necessarily have to overcome that of the
|
||||
* registry to which it is connected. However, the observer must be disconnected
|
||||
* from the registry before being destroyed to avoid crashes due to dangling
|
||||
* pointers.
|
||||
@@ -177,7 +177,7 @@ class basic_observer {
|
||||
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
|
||||
template<std::size_t Index>
|
||||
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> ®, const Entity entt) {
|
||||
if(reg.template has<Require...>(entt) && !(reg.template has<Reject>(entt) || ...)) {
|
||||
if(reg.template has<Require...>(entt) && !reg.template any<Reject...>(entt)) {
|
||||
if(auto *comp = obs.view.try_get(entt); !comp) {
|
||||
obs.view.construct(entt);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ class basic_observer {
|
||||
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
|
||||
template<std::size_t Index>
|
||||
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> ®, const Entity entt) {
|
||||
if(reg.template has<AllOf..., Require...>(entt) && !(reg.template has<NoneOf>(entt) || ...) && !(reg.template has<Reject>(entt) || ...)) {
|
||||
if(reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt)) {
|
||||
if(auto *comp = obs.view.try_get(entt); !comp) {
|
||||
obs.view.construct(entt);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@ class basic_registry {
|
||||
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
|
||||
std::size_t super{};
|
||||
|
||||
using storage<Entity, Component>::storage;
|
||||
|
||||
auto on_construct() ENTT_NOEXCEPT {
|
||||
return sink{construction};
|
||||
}
|
||||
@@ -110,11 +108,11 @@ class basic_registry {
|
||||
};
|
||||
|
||||
struct pool_data {
|
||||
ENTT_ID_TYPE type_id;
|
||||
std::unique_ptr<sparse_set<Entity>> pool;
|
||||
void(* assure)(basic_registry &, const sparse_set<Entity> &);
|
||||
void(* remove)(sparse_set<Entity> &, basic_registry &, const Entity);
|
||||
void(* stamp)(basic_registry &, const Entity, const sparse_set<Entity> &, const Entity);
|
||||
ENTT_ID_TYPE type_id{};
|
||||
std::unique_ptr<sparse_set<Entity>> pool{};
|
||||
void(* assure)(basic_registry &, const sparse_set<Entity> &){};
|
||||
void(* remove)(sparse_set<Entity> &, basic_registry &, const Entity){};
|
||||
void(* stamp)(basic_registry &, const Entity, const sparse_set<Entity> &, const Entity){};
|
||||
};
|
||||
|
||||
template<typename...>
|
||||
@@ -717,7 +715,7 @@ public:
|
||||
auto &cpool = assure<Component>();
|
||||
|
||||
return cpool.has(entity)
|
||||
? (cpool.replace(*this, entity, [args = std::forward_as_tuple(std::forward<Args>(args)...)](auto &&component) { component = std::make_from_tuple<Component>(std::move(args)); }), cpool.get(entity))
|
||||
? (cpool.replace(*this, entity, [&args...](auto &&component) { component = Component{std::forward<Args>(args)...}; }), cpool.get(entity))
|
||||
: cpool.assign(*this, entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -1406,13 +1404,9 @@ public:
|
||||
handler->current.construct(entity);
|
||||
}
|
||||
} else {
|
||||
const auto curr = view<Owned..., Get...>(exclude<Exclude...>);
|
||||
|
||||
// we cannot iterate backwards because we want to leave behind valid entities in case of owned types
|
||||
std::for_each(std::make_reverse_iterator(curr.end()), std::make_reverse_iterator(curr.begin()), [cpools, handler](const auto entity) {
|
||||
if(const auto pos = handler->current; !(std::get<0>(cpools).index(entity) < ++handler->current)) {
|
||||
(std::get<pool_handler<std::decay_t<Owned>> &>(cpools).swap(std::get<pool_handler<std::decay_t<Owned>> &>(cpools).data()[pos], entity), ...);
|
||||
}
|
||||
std::for_each(std::get<0>(cpools).data(), std::get<0>(cpools).data() + std::get<0>(cpools).size(), [this, handler](const auto entity) {
|
||||
handler->template maybe_valid_if<std::tuple_element_t<0, std::tuple<std::decay_t<Owned>...>>>(*this, entity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace entt {
|
||||
* have a valid reference and won't be updated accordingly).
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of a view must overcome the one of the registry that generated it.
|
||||
* Lifetime of a view must not overcome that of the registry that generated it.
|
||||
* In any other case, attempting to use a view results in undefined behavior.
|
||||
*
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
|
||||
@@ -186,41 +186,12 @@ public:
|
||||
/*! @brief Default constructor. */
|
||||
sparse_set() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @param other The instance to copy from.
|
||||
*/
|
||||
sparse_set(const sparse_set &other)
|
||||
: reverse{},
|
||||
direct{other.direct}
|
||||
{
|
||||
for(size_type pos{}, last = other.reverse.size(); pos < last; ++pos) {
|
||||
if(other.reverse[pos]) {
|
||||
std::copy_n(other.reverse[pos].get(), entt_per_page, assure(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! @brief Default move constructor. */
|
||||
sparse_set(sparse_set &&) = default;
|
||||
|
||||
/*! @brief Default destructor. */
|
||||
virtual ~sparse_set() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator.
|
||||
* @param other The instance to copy from.
|
||||
* @return This sparse set.
|
||||
*/
|
||||
sparse_set & operator=(const sparse_set &other) {
|
||||
if(&other != this) {
|
||||
auto tmp{other};
|
||||
*this = std::move(tmp);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*! @brief Default move assignment operator. @return This sparse set. */
|
||||
sparse_set & operator=(sparse_set &&) = default;
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Assigns one or more entities to a storage and constructs their
|
||||
* objects with from a given instance.
|
||||
* objects from a given instance.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to assign an entity that already belongs to the storage
|
||||
|
||||
@@ -55,7 +55,7 @@ class basic_view;
|
||||
* made by means of the registry are immediately reflected by views.
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of a view must overcome the one of the registry that generated it.
|
||||
* Lifetime of a view must not overcome that of the registry that generated it.
|
||||
* In any other case, attempting to use a view results in undefined behavior.
|
||||
*
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
@@ -559,7 +559,7 @@ private:
|
||||
* made by means of the registry are immediately reflected by views.
|
||||
*
|
||||
* @warning
|
||||
* Lifetime of a view must overcome the one of the registry that generated it.
|
||||
* Lifetime of a view must not overcome that of the registry that generated it.
|
||||
* In any other case, attempting to use a view results in undefined behavior.
|
||||
*
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
|
||||
@@ -24,9 +24,8 @@ namespace entt {
|
||||
* type `Event`, listeners are such that they can be invoked with an argument of
|
||||
* type `const Event &`, no matter what the return type is.
|
||||
*
|
||||
* The types of the instances are `Class &`. Users must guarantee that the
|
||||
* lifetimes of the objects overcome the one of the dispatcher itself to avoid
|
||||
* crashes.
|
||||
* The dispatcher creates instances of the `sigh` class internally. Refer to the
|
||||
* documentation of the latter for more details.
|
||||
*/
|
||||
class dispatcher {
|
||||
struct basic_pool {
|
||||
|
||||
@@ -407,13 +407,13 @@ public:
|
||||
*
|
||||
* The signal isn't responsible for the connected object or the payload.
|
||||
* Users must always guarantee that the lifetime of the instance overcomes
|
||||
* the one of the delegate. On the other side, the signal handler performs
|
||||
* the one of the signal. On the other side, the signal handler performs
|
||||
* checks to avoid multiple connections for the same function.<br/>
|
||||
* When used to connect a free function with payload, its signature must be
|
||||
* such that the instance is the first argument before the ones used to
|
||||
* define the delegate itself.
|
||||
* define the signal itself.
|
||||
*
|
||||
* @tparam Candidate Function or member to connect to the delegate.
|
||||
* @tparam Candidate Function or member to connect to the signal.
|
||||
* @tparam Type Type of class or type of payload.
|
||||
* @param value_or_instance A valid object that fits the purpose.
|
||||
* @return A properly initialized connection object.
|
||||
@@ -433,7 +433,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Disconnects a free function or an unbound member from a signal.
|
||||
* @tparam Candidate Function or member to disconnect from the delegate.
|
||||
* @tparam Candidate Function or member to disconnect from the signal.
|
||||
*/
|
||||
template<auto Candidate>
|
||||
void disconnect() {
|
||||
@@ -446,7 +446,7 @@ public:
|
||||
/**
|
||||
* @brief Disconnects a free function with payload or a bound member from a
|
||||
* signal.
|
||||
* @tparam Candidate Function or member to disconnect from the delegate.
|
||||
* @tparam Candidate Function or member to disconnect from the signal.
|
||||
* @tparam Type Type of class or type of payload.
|
||||
* @param value_or_instance A valid object that fits the purpose.
|
||||
*/
|
||||
|
||||
@@ -1120,3 +1120,33 @@ TEST(OwningGroup, SignalRace) {
|
||||
|
||||
ASSERT_EQ(registry.group<int>(entt::get<double>).size(), 1u);
|
||||
}
|
||||
|
||||
TEST(OwningGroup, StableLateInitialization) {
|
||||
entt::registry registry;
|
||||
|
||||
for(std::size_t i{}; i < 30u; ++i) {
|
||||
auto entity = registry.create();
|
||||
if(!(i % 2u)) registry.assign<int>(entity);
|
||||
if(!(i % 3u)) registry.assign<char>(entity);
|
||||
}
|
||||
|
||||
// thanks to @pgruenbacher for pointing out this corner case
|
||||
ASSERT_EQ((registry.group<int, char>().size()), 5u);
|
||||
}
|
||||
|
||||
TEST(OwningGroup, PreventEarlyOptOut) {
|
||||
entt::registry registry;
|
||||
|
||||
registry.assign<int>(registry.create(), 3);
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.assign<char>(entity, 'c');
|
||||
registry.assign<int>(entity, 2);
|
||||
|
||||
// thanks to @pgruenbacher for pointing out this corner case
|
||||
registry.group<char, int>().each([entity](const auto entt, const auto &c, const auto &i) {
|
||||
ASSERT_EQ(entity, entt);
|
||||
ASSERT_EQ(c, 'c');
|
||||
ASSERT_EQ(i, 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ struct non_default_constructible {
|
||||
int value;
|
||||
};
|
||||
|
||||
struct aggregate {
|
||||
int value{};
|
||||
};
|
||||
|
||||
struct listener {
|
||||
template<typename Component>
|
||||
static void sort(entt::registry ®istry) {
|
||||
@@ -256,6 +260,14 @@ TEST(Registry, Functionalities) {
|
||||
ASSERT_EQ(registry.capacity<char>(), entt::registry::size_type{});
|
||||
}
|
||||
|
||||
TEST(Registry, AssignOrReplaceAggregates) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
auto &instance = registry.assign_or_replace<aggregate>(entity, 42);
|
||||
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST(Registry, Identifiers) {
|
||||
entt::registry registry;
|
||||
const auto pre = registry.create();
|
||||
|
||||
@@ -53,14 +53,6 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
|
||||
ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
|
||||
|
||||
entt::sparse_set<entt::entity> cpy{set};
|
||||
set = cpy;
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_FALSE(cpy.empty());
|
||||
ASSERT_EQ(set.index(entt::entity{42}), 0u);
|
||||
ASSERT_EQ(cpy.index(entt::entity{42}), 0u);
|
||||
|
||||
entt::sparse_set<entt::entity> other{std::move(set)};
|
||||
|
||||
set = std::move(other);
|
||||
|
||||
Reference in New Issue
Block a user