Skip to content

Commit

Permalink
Merge branch 'master' into doc
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Feb 4, 2018
2 parents 586f590 + 8c49985 commit 2ea8e89
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 100,160 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# QtCreator
*.user
TODO
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -851,28 +851,51 @@ whether all the components have to be accessed or not.
function template of a registry during iterations, if possible. However, keep in
mind that it works only with the components of the view itself.

### Give me everything
### Give me everything, whatever it means

Views are narrow windows on the entire list of entities. They work by filtering
entities according to their components.<br/>
In some cases there may be the need to iterate all the entities regardless of
their components. The registry offers a specific member function to do that:
their components. The registry offers a couple of member functions to do that:
`each` and `alive`.

The former returns all the entities ever created, no matter if they are still in
use or not:

```cpp
registry.each([](auto entity) {
// ...
});
```

Each entity ever created is returned, no matter if it's in use or not.<br/>
Usually, filtering entities that aren't currently in use is more expensive than
iterating them all and filtering out those in which one isn't interested.
The latter returns an entity only if it's still in use (in other words, the
entity is returned only if it hasn't been destroyed):

```cpp
registry.alive([](auto entity) {
// ...
});
```

As a rule of thumb, consider using a view if the goal is to iterate entities
that have a determinate set of components. A view is usually faster than
combining this function with a bunch of custom tests.<br/>
combining these functions with a bunch of custom tests.<br/>
In all the other cases, this is the way to go.

There exists also another function to use to retrieve orphans. An orphan is an
entity that is still in use and has no assigned components.<br/>
The signature of the function is the same of `each` and `alive`:

```cpp
registry.orphans([](auto entity) {
// ...
});
```

In general, `each` is pretty fast to run while `alive` is a bit slower because
of the check it must perform on each and every entity. For similar reasons,
`orphans` can be very slow and should not be used frequently.

## Side notes

* Entity identifiers are numbers and nothing more. They are not classes and they
Expand Down
19 changes: 19 additions & 0 deletions cmake/in/duktape.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
project(duktape-download NONE)
cmake_minimum_required(VERSION 3.2)

include(ExternalProject)

ExternalProject_Add(
duktape
GIT_REPOSITORY https://github.com/svaarala/duktape-releases.git
GIT_TAG v2.2.0
DOWNLOAD_DIR ${DUKTAPE_DEPS_DIR}
TMP_DIR ${DUKTAPE_DEPS_DIR}/tmp
STAMP_DIR ${DUKTAPE_DEPS_DIR}/stamp
SOURCE_DIR ${DUKTAPE_DEPS_DIR}/src
BINARY_DIR ${DUKTAPE_DEPS_DIR}/build
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
1 change: 1 addition & 0 deletions src/entt/core/hashed_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define ENTT_CORE_HASHED_STRING_HPP


#include <cstddef>
#include <cstdint>


Expand Down
2 changes: 2 additions & 0 deletions src/entt/entity/actor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ template<typename Entity, typename Delta>
struct Actor {
/*! @brief Type of registry used internally. */
using registry_type = Registry<Entity>;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
/*! @brief Type used to provide elapsed time. */
using delta_type = Delta;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef ENTT_ENTITY_ENTT_HPP
#define ENTT_ENTITY_ENTT_HPP
#ifndef ENTT_ENTITY_ENTT_TRAITS_HPP
#define ENTT_ENTITY_ENTT_TRAITS_HPP


#include <cstdint>
Expand Down Expand Up @@ -93,4 +93,4 @@ struct entt_traits<std::uint64_t> {
}


#endif // ENTT_ENTITY_ENTT_HPP
#endif // ENTT_ENTITY_ENTT_TRAITS_HPP
74 changes: 69 additions & 5 deletions src/entt/entity/registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#include <cstddef>
#include <cstdint>
#include <cassert>
#include <numeric>
#include <algorithm>
#include <type_traits>
#include "../core/family.hpp"
#include "entt_traits.hpp"
#include "sparse_set.hpp"
#include "traits.hpp"
#include "view.hpp"


Expand Down Expand Up @@ -401,7 +402,7 @@ class Registry {
* function can be used to know if they are still valid or the entity has
* been destroyed and potentially recycled.
*
* The returned entity has no components assigned.
* The returned entity has no assigned components.
*
* @return A valid entity identifier.
*/
Expand Down Expand Up @@ -922,7 +923,7 @@ class Registry {
}

/**
* @brief Iterate entities and applies them the given function object.
* @brief Iterate all the entities ever created.
*
* The function object is invoked for each entity, no matter if it's in use
* or not.<br/>
Expand All @@ -941,11 +942,74 @@ class Registry {
*/
template<typename Func>
void each(Func func) const {
for(auto pos = entities.size(); pos > size_type{0}; --pos) {
func(entities[pos-1]);
for(size_type pos{}, last = entities.size(); pos < last; ++pos) {
func(entities[pos]);
}
}

/**
* @brief Iterate all the entities still in use.
*
* The function object is invoked for each entity that is still in use.<br/>
* The signature of the function should be equivalent to the following:
*
* @code{.cpp}
* void(entity_type);
* @endcode
*
* This function is fairly slow and should not be used frequently.<br/>
* Consider using a view if the goal is to iterate entities that have a
* determinate set of components. A view is usually faster than combining
* this function with a bunch of custom tests.
*
* @tparam Func Type of the function object to invoke.
* @param func A valid function object.
*/
template<typename Func>
void alive(Func func) {
std::sort(available.begin(), available.end());

const auto end= available.cend();
auto it = available.cbegin();

each([func = std::move(func), it, end](auto entity) mutable {
if(it != end && *it == entity) {
++it;
} else {
func(entity);
}
});
}

/**
* @brief Iterate orphans and applies them the given function object.
*
* The function object is invoked for each entity that is still in use and
* has no assigned components.<br/>
* The signature of the function should be equivalent to the following:
*
* @code{.cpp}
* void(entity_type);
* @endcode
*
* This function can be very slow and should not be used frequently.
*
* @tparam Func Type of the function object to invoke.
* @param func A valid function object.
*/
template<typename Func>
void orphans(Func func) {
alive([func = std::move(func), this](auto entity) {
for(const auto &pool: pools) {
if(pool && pool->has(entity)) {
return;
}
}

func(entity);
});
}

/**
* @brief Returns a standard view for the given components.
*
Expand Down
8 changes: 4 additions & 4 deletions src/entt/entity/sparse_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <cstddef>
#include <cassert>
#include <type_traits>
#include "traits.hpp"
#include "entt_traits.hpp"


namespace entt {
Expand Down Expand Up @@ -56,10 +56,10 @@ template<typename Entity>
class SparseSet<Entity> {
using traits_type = entt_traits<Entity>;

struct Iterator {
struct Iterator final {
using value_type = Entity;

Iterator(const std::vector<Entity> *direct, std::size_t pos)
Iterator(const std::vector<value_type> *direct, std::size_t pos)
: direct{direct}, pos{pos}
{}

Expand All @@ -85,7 +85,7 @@ class SparseSet<Entity> {
}

private:
const std::vector<Entity> *direct;
const std::vector<value_type> *direct;
std::size_t pos;
};

Expand Down
2 changes: 1 addition & 1 deletion src/entt/entt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
#include "core/hashed_string.hpp"
#include "core/ident.hpp"
#include "entity/actor.hpp"
#include "entity/entt_traits.hpp"
#include "entity/registry.hpp"
#include "entity/sparse_set.hpp"
#include "entity/traits.hpp"
#include "entity/view.hpp"
#include "locator/locator.hpp"
#include "process/process.hpp"
Expand Down
9 changes: 8 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ endif()
# Test mod

if(BUILD_MOD)
set(DUKTAPE_DEPS_DIR ${entt_SOURCE_DIR}/deps/duktape)
configure_file(${entt_SOURCE_DIR}/cmake/in/duktape.in ${DUKTAPE_DEPS_DIR}/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${DUKTAPE_DEPS_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${DUKTAPE_DEPS_DIR})
set(DUKTAPE_SRC_DIR ${DUKTAPE_DEPS_DIR}/src/src)

add_executable(
mod
$<TARGET_OBJECTS:odr>
mod/duktape.c
${DUKTAPE_SRC_DIR}/duktape.c
mod/mod.cpp
)
target_include_directories(mod PRIVATE ${DUKTAPE_SRC_DIR})
target_link_libraries(mod PRIVATE gtest_main Threads::Threads m)
add_test(NAME mod COMMAND mod)
endif()
Expand Down
85 changes: 85 additions & 0 deletions test/entt/entity/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,91 @@ TEST(DefaultRegistry, Each) {
ASSERT_EQ(match, 0u);
}

TEST(DefaultRegistry, Alive) {
entt::DefaultRegistry registry;
entt::DefaultRegistry::size_type tot;
entt::DefaultRegistry::size_type match;

registry.create<int>();
registry.create<int>();

tot = 0u;
match = 0u;

registry.alive([&](auto entity) {
if(registry.has<int>(entity)) { ++match; }
registry.create();
++tot;
});

ASSERT_EQ(tot, 2u);
ASSERT_EQ(match, 2u);

tot = 0u;
match = 0u;

registry.alive([&](auto entity) {
if(registry.has<int>(entity)) {
registry.destroy(entity);
++match;
}

++tot;
});

ASSERT_EQ(tot, 4u);
ASSERT_EQ(match, 2u);

tot = 0u;
match = 0u;

registry.alive([&](auto entity) {
if(registry.has<int>(entity)) { ++match; }
++tot;
});

ASSERT_EQ(tot, 2u);
ASSERT_EQ(match, 0u);
}

TEST(DefaultRegistry, Orphans) {
entt::DefaultRegistry registry;
entt::DefaultRegistry::size_type tot;

registry.create<int>();
registry.create();
registry.create<int>();
registry.create();

tot = 0u;

registry.orphans([&](auto) {
++tot;
});

ASSERT_EQ(tot, 2u);

registry.each([&](auto entity) {
registry.reset<int>(entity);
});

tot = 0u;

registry.orphans([&](auto) {
++tot;
});

ASSERT_EQ(tot, 4u);

registry.reset();
tot = 0u;

registry.orphans([&](auto) {
++tot;
});

ASSERT_EQ(tot, 0u);
}

TEST(DefaultRegistry, Types) {
entt::DefaultRegistry registry;
Expand Down
Loading

0 comments on commit 2ea8e89

Please sign in to comment.