Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59cec88a28 | ||
|
|
3ebc75af80 | ||
|
|
4dce474e03 | ||
|
|
31a18da578 | ||
|
|
8c499850fc | ||
|
|
6b6998a247 | ||
|
|
a6cb0fc856 | ||
|
|
e36b93e87b | ||
|
|
1e3723b8bb | ||
|
|
412372289e | ||
|
|
96f7e66073 | ||
|
|
6040f8f263 | ||
|
|
9761b6e14a | ||
|
|
cb49910ed2 | ||
|
|
62bd742673 | ||
|
|
42d0a3d734 | ||
|
|
f0f8681455 | ||
|
|
c801afddcb | ||
|
|
20e0e1333e | ||
|
|
a6b373fec4 | ||
|
|
41c77720bb | ||
|
|
92e6340120 | ||
|
|
1221f63cbd | ||
|
|
0f24418891 | ||
|
|
f477c0ab87 | ||
|
|
9358691901 | ||
|
|
cd343ba598 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,2 @@
|
||||
# QtCreator
|
||||
*.user
|
||||
TODO
|
||||
|
||||
@@ -16,7 +16,7 @@ endif()
|
||||
# Project configuration
|
||||
#
|
||||
|
||||
project(entt VERSION 2.3.0)
|
||||
project(entt VERSION 2.4.2)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
@@ -29,7 +29,7 @@ set(PROJECT_AUTHOR_EMAIL "michele.caini@gmail.com")
|
||||
|
||||
message("*")
|
||||
message("* ${PROJECT_NAME} v${PROJECT_VERSION} (${CMAKE_BUILD_TYPE})")
|
||||
message("* Copyright (c) 2017 ${PROJECT_AUTHOR} <${PROJECT_AUTHOR_EMAIL}>")
|
||||
message("* Copyright (c) 2018 ${PROJECT_AUTHOR} <${PROJECT_AUTHOR_EMAIL}>")
|
||||
message("*")
|
||||
|
||||
#
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Michele Caini
|
||||
Copyright (c) 2018 Michele Caini
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
65
README.md
65
README.md
@@ -377,7 +377,7 @@ registry.assign<Position>(entity, 0., 0.);
|
||||
|
||||
// ...
|
||||
|
||||
auto &velocity = registry.assign<Velocity>(entity);
|
||||
Velocity &velocity = registry.assign<Velocity>(entity);
|
||||
velocity.dx = 0.;
|
||||
velocity.dy = 0.;
|
||||
```
|
||||
@@ -390,7 +390,7 @@ registry.replace<Position>(entity, 0., 0.);
|
||||
|
||||
// ...
|
||||
|
||||
auto &velocity = registry.replace<Velocity>(entity);
|
||||
Velocity &velocity = registry.replace<Velocity>(entity);
|
||||
velocity.dx = 0.;
|
||||
velocity.dy = 0.;
|
||||
```
|
||||
@@ -405,7 +405,7 @@ registry.accomodate<Position>(entity, 0., 0.);
|
||||
|
||||
// ...
|
||||
|
||||
auto &velocity = registry.accomodate<Velocity>(entity);
|
||||
Velocity &velocity = registry.accomodate<Velocity>(entity);
|
||||
velocity.dx = 0.;
|
||||
velocity.dy = 0.;
|
||||
```
|
||||
@@ -464,13 +464,16 @@ their components are destroyed:
|
||||
Finally, references to components can be retrieved simply by doing this:
|
||||
|
||||
```cpp
|
||||
// either a non-const reference ...
|
||||
entt::DefaultRegistry registry;
|
||||
auto &position = registry.get<Position>(entity);
|
||||
|
||||
// ... or a const one
|
||||
const auto &cregistry = registry;
|
||||
const auto &position = cregistry.get<Position>(entity);
|
||||
|
||||
// const and non-const reference
|
||||
const Position &position = cregistry.get<Position>(entity);
|
||||
Position &position = registry.get<Position>(entity);
|
||||
|
||||
// const and non-const references
|
||||
std::tuple<const Position &, const Velocity &> tup = cregistry.get<Position, Velocity>(entity);
|
||||
std::tuple<Position &, Velocity &> tup = registry.get<Position, Velocity>(entity);
|
||||
```
|
||||
|
||||
The `get` member function template gives direct access to the component of an
|
||||
@@ -516,11 +519,11 @@ References to tags can be retrieved simply by doing this:
|
||||
```cpp
|
||||
// either a non-const reference ...
|
||||
entt::DefaultRegistry registry;
|
||||
auto &player = registry.get<PlayingCharacter>();
|
||||
PlayingCharacter &player = registry.get<PlayingCharacter>();
|
||||
|
||||
// ... or a const one
|
||||
const auto &cregistry = registry;
|
||||
const auto &camera = cregistry.get<Camera>();
|
||||
const Camera &camera = cregistry.get<Camera>();
|
||||
```
|
||||
|
||||
The `get` member function template gives direct access to the tag as stored in
|
||||
@@ -705,7 +708,7 @@ To iterate a single component standard view, either use it in range-for loop:
|
||||
auto view = registry.view<Renderable>();
|
||||
|
||||
for(auto entity: view) {
|
||||
auto &renderable = view.get(entity);
|
||||
Renderable &renderable = view.get(entity);
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -749,8 +752,12 @@ To iterate a multi component standard view, either use it in range-for loop:
|
||||
auto view = registry.view<Position, Velocity>();
|
||||
|
||||
for(auto entity: view) {
|
||||
auto &position = view.get<Position>(entity);
|
||||
auto &velocity = view.get<Velocity>(entity);
|
||||
// a component at a time ...
|
||||
Position &position = view.get<Position>(entity);
|
||||
Velocity &velocity = view.get<Velocity>(entity);
|
||||
|
||||
// ... or multiple components at once
|
||||
std::tuple<Position &, Velocity &> tup = view.get<Position, Velocity>(entity);
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -817,8 +824,12 @@ To iterate a persistent view, either use it in range-for loop:
|
||||
auto view = registry.persistent<Position, Velocity>();
|
||||
|
||||
for(auto entity: view) {
|
||||
auto &position = view.get<Position>(entity);
|
||||
auto &velocity = view.get<Velocity>(entity);
|
||||
// a component at a time ...
|
||||
Position &position = view.get<Position>(entity);
|
||||
Velocity &velocity = view.get<Velocity>(entity);
|
||||
|
||||
// ... or multiple components at once
|
||||
std::tuple<Position &, Velocity &> tup = view.get<Position, Velocity>(entity);
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -840,6 +851,28 @@ 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
|
||||
|
||||
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:
|
||||
|
||||
```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.
|
||||
|
||||
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/>
|
||||
In all the other cases, this is the way to go.
|
||||
|
||||
## Side notes
|
||||
|
||||
* Entity identifiers are numbers and nothing more. They are not classes and they
|
||||
@@ -896,7 +929,7 @@ who has partecipated so far.
|
||||
|
||||
# License
|
||||
|
||||
Code and documentation Copyright (c) 2017 Michele Caini.<br/>
|
||||
Code and documentation Copyright (c) 2018 Michele Caini.<br/>
|
||||
Code released under
|
||||
[the MIT license](https://github.com/skypjack/entt/blob/master/LICENSE).
|
||||
Docs released under
|
||||
|
||||
@@ -14,7 +14,7 @@ configuration:
|
||||
|
||||
before_build:
|
||||
- cd %BUILD_DIR%
|
||||
- cmake .. -G"Visual Studio 15 2017"
|
||||
- cmake .. -DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -G"Visual Studio 15 2017"
|
||||
|
||||
build:
|
||||
parallel: true
|
||||
|
||||
19
cmake/in/duktape.in
Normal file
19
cmake/in/duktape.in
Normal file
@@ -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 ""
|
||||
)
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ENTT_CORE_HASHED_STRING_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -93,4 +93,4 @@ struct entt_traits<std::uint64_t> {
|
||||
}
|
||||
|
||||
|
||||
#endif // ENTT_ENTITY_ENTT_HPP
|
||||
#endif // ENTT_ENTITY_ENTT_TRAITS_HPP
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ENTT_ENTITY_REGISTRY_HPP
|
||||
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@@ -9,9 +10,10 @@
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include "../core/family.hpp"
|
||||
#include "entt_traits.hpp"
|
||||
#include "sparse_set.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "view.hpp"
|
||||
|
||||
|
||||
@@ -231,6 +233,33 @@ public:
|
||||
return entities.size() - available.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increases the capacity of the pool for a given component.
|
||||
*
|
||||
* If the new capacity is greater than the current capacity, new storage is
|
||||
* allocated, otherwise the method does nothing.
|
||||
*
|
||||
* @tparam Component Type of component for which to reserve storage.
|
||||
* @param cap Desired capacity.
|
||||
*/
|
||||
template<typename Component>
|
||||
void reserve(size_type cap) {
|
||||
ensure<Component>().reserve(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increases the capacity of a registry in terms of entities.
|
||||
*
|
||||
* If the new capacity is greater than the current capacity, new storage is
|
||||
* allocated, otherwise the method does nothing.
|
||||
*
|
||||
* @param cap Desired capacity.
|
||||
*/
|
||||
void reserve(size_type cap) {
|
||||
entities.reserve(cap);
|
||||
available.reserve(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of entities ever created.
|
||||
* @return Number of entities ever created.
|
||||
@@ -617,7 +646,7 @@ public:
|
||||
*
|
||||
* @tparam Component Type of component to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return A reference to the instance of the component owned by the entity.
|
||||
* @return A reference to the component owned by the entity.
|
||||
*/
|
||||
template<typename Component>
|
||||
const Component & get(entity_type entity) const noexcept {
|
||||
@@ -637,13 +666,53 @@ public:
|
||||
*
|
||||
* @tparam Component Type of component to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return A reference to the instance of the component owned by the entity.
|
||||
* @return A reference to the component owned by the entity.
|
||||
*/
|
||||
template<typename Component>
|
||||
Component & get(entity_type entity) noexcept {
|
||||
return const_cast<Component &>(const_cast<const Registry *>(this)->get<Component>(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to the given components for an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity or to get components from an entity
|
||||
* that doesn't own them results in undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode in case of
|
||||
* invalid entity or if the entity doesn't own instances of the given
|
||||
* components.
|
||||
*
|
||||
* @tparam Component Type of components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return References to the components owned by the entity.
|
||||
*/
|
||||
template<typename... Component>
|
||||
std::enable_if_t<(sizeof...(Component) > 1), std::tuple<const Component &...>>
|
||||
get(entity_type entity) const noexcept {
|
||||
return std::tuple<const Component &...>{ get<Component>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to the given components for an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity or to get components from an entity
|
||||
* that doesn't own them results in undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode in case of
|
||||
* invalid entity or if the entity doesn't own instances of the given
|
||||
* components.
|
||||
*
|
||||
* @tparam Component Type of components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return References to the components owned by the entity.
|
||||
*/
|
||||
template<typename... Component>
|
||||
std::enable_if_t<(sizeof...(Component) > 1), std::tuple<Component &...>>
|
||||
get(entity_type entity) noexcept {
|
||||
return std::tuple<Component &...>{ get<Component>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replaces the given component for an entity.
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include "traits.hpp"
|
||||
#include "entt_traits.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
@@ -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}
|
||||
{}
|
||||
|
||||
@@ -85,7 +85,7 @@ class SparseSet<Entity> {
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<Entity> *direct;
|
||||
const std::vector<value_type> *direct;
|
||||
std::size_t pos;
|
||||
};
|
||||
|
||||
@@ -117,6 +117,19 @@ public:
|
||||
/*! @brief Default move assignment operator. @return This sparse set. */
|
||||
SparseSet & operator=(SparseSet &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Increases the capacity of a sparse set.
|
||||
*
|
||||
* If the new capacity is greater than the current capacity, new storage is
|
||||
* allocated, otherwise the method does nothing.
|
||||
*
|
||||
* @param cap Desired capacity.
|
||||
*/
|
||||
void reserve(size_type cap) {
|
||||
reverse.reserve(cap);
|
||||
direct.reserve(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of elements in a sparse set.
|
||||
*
|
||||
@@ -293,7 +306,9 @@ public:
|
||||
void swap(pos_type lhs, pos_type rhs) noexcept {
|
||||
assert(lhs < direct.size());
|
||||
assert(rhs < direct.size());
|
||||
std::swap(reverse[direct[lhs]], reverse[direct[rhs]]);
|
||||
const auto src = direct[lhs] & traits_type::entity_mask;
|
||||
const auto dst = direct[rhs] & traits_type::entity_mask;
|
||||
std::swap(reverse[src], reverse[dst]);
|
||||
std::swap(direct[lhs], direct[rhs]);
|
||||
}
|
||||
|
||||
@@ -400,6 +415,19 @@ public:
|
||||
/*! @brief Default move assignment operator. @return This sparse set. */
|
||||
SparseSet & operator=(SparseSet &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Increases the capacity of a sparse set.
|
||||
*
|
||||
* If the new capacity is greater than the current capacity, new storage is
|
||||
* allocated, otherwise the method does nothing.
|
||||
*
|
||||
* @param cap Desired capacity.
|
||||
*/
|
||||
void reserve(size_type cap) {
|
||||
underlying_type::reserve(cap);
|
||||
instances.reserve(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the array of objects.
|
||||
*
|
||||
@@ -488,7 +516,7 @@ public:
|
||||
object_type & construct(entity_type entity, Args&&... args) {
|
||||
underlying_type::construct(entity);
|
||||
// emplace_back doesn't work well with PODs because of its placement new
|
||||
instances.push_back({ std::forward<Args>(args)... });
|
||||
instances.push_back(object_type{ std::forward<Args>(args)... });
|
||||
return instances.back();
|
||||
}
|
||||
|
||||
@@ -505,7 +533,9 @@ public:
|
||||
*/
|
||||
void destroy(entity_type entity) override {
|
||||
// swapping isn't required here, we are getting rid of the last element
|
||||
instances[underlying_type::get(entity)] = std::move(instances.back());
|
||||
// however, we must protect ourselves from self assignments (see #37)
|
||||
auto tmp = std::move(instances.back());
|
||||
instances[underlying_type::get(entity)] = std::move(tmp);
|
||||
instances.pop_back();
|
||||
underlying_type::destroy(entity);
|
||||
}
|
||||
@@ -541,8 +571,8 @@ public:
|
||||
return compare(const_cast<const object_type &>(instances[rhs]), const_cast<const object_type &>(instances[lhs]));
|
||||
});
|
||||
|
||||
for(pos_type i = 0; i < copy.size(); ++i) {
|
||||
auto curr = i;
|
||||
for(pos_type pos = 0, last = copy.size(); pos < last; ++pos) {
|
||||
auto curr = pos;
|
||||
auto next = copy[curr];
|
||||
|
||||
while(curr != next) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include "sparse_set.hpp"
|
||||
|
||||
|
||||
@@ -188,6 +189,52 @@ public:
|
||||
return const_cast<Comp &>(const_cast<const PersistentView *>(this)->get<Comp>(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the components assigned to the given entity.
|
||||
*
|
||||
* Prefer this function instead of `Registry::get` during iterations. It has
|
||||
* far better performance than its companion function.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use invalid component types results in a compilation error.
|
||||
* Attempting to use an entity that doesn't belong to the view results in
|
||||
* undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode if
|
||||
* the view doesn't contain the given entity.
|
||||
*
|
||||
* @tparam Comp Types of the components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The components assigned to the entity.
|
||||
*/
|
||||
template<typename... Comp>
|
||||
std::enable_if_t<(sizeof...(Comp) > 1), std::tuple<const Comp &...>>
|
||||
get(entity_type entity) const noexcept {
|
||||
return std::tuple<const Comp &...>{ get<Comp>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the components assigned to the given entity.
|
||||
*
|
||||
* Prefer this function instead of `Registry::get` during iterations. It has
|
||||
* far better performance than its companion function.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use invalid component types results in a compilation error.
|
||||
* Attempting to use an entity that doesn't belong to the view results in
|
||||
* undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode if
|
||||
* the view doesn't contain the given entity.
|
||||
*
|
||||
* @tparam Comp Types of the components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The components assigned to the entity.
|
||||
*/
|
||||
template<typename... Comp>
|
||||
std::enable_if_t<(sizeof...(Comp) > 1), std::tuple<Comp &...>>
|
||||
get(entity_type entity) noexcept {
|
||||
return std::tuple<Comp &...>{ get<Comp>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterate the entities and applies them the given function object.
|
||||
*
|
||||
@@ -457,6 +504,52 @@ public:
|
||||
return const_cast<Comp &>(const_cast<const View *>(this)->get<Comp>(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the components assigned to the given entity.
|
||||
*
|
||||
* Prefer this function instead of `Registry::get` during iterations. It has
|
||||
* far better performance than its companion function.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use invalid component types results in a compilation error.
|
||||
* Attempting to use an entity that doesn't belong to the view results in
|
||||
* undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode if
|
||||
* the view doesn't contain the given entity.
|
||||
*
|
||||
* @tparam Comp Types of the components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The components assigned to the entity.
|
||||
*/
|
||||
template<typename... Comp>
|
||||
std::enable_if_t<(sizeof...(Comp) > 1), std::tuple<const Comp &...>>
|
||||
get(entity_type entity) const noexcept {
|
||||
return std::tuple<const Comp &...>{ get<Comp>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the components assigned to the given entity.
|
||||
*
|
||||
* Prefer this function instead of `Registry::get` during iterations. It has
|
||||
* far better performance than its companion function.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use invalid component types results in a compilation error.
|
||||
* Attempting to use an entity that doesn't belong to the view results in
|
||||
* undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode if
|
||||
* the view doesn't contain the given entity.
|
||||
*
|
||||
* @tparam Comp Types of the components to get.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The components assigned to the entity.
|
||||
*/
|
||||
template<typename... Comp>
|
||||
std::enable_if_t<(sizeof...(Comp) > 1), std::tuple<Comp &...>>
|
||||
get(entity_type entity) noexcept {
|
||||
return std::tuple<Comp &...>{ get<Comp>(entity)... };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterate the entities and applies them the given function object.
|
||||
*
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -10,28 +10,6 @@
|
||||
namespace entt {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
struct BaseProcess {
|
||||
enum class State: unsigned int {
|
||||
UNINITIALIZED = 0,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
SUCCEEDED,
|
||||
FAILED,
|
||||
ABORTED,
|
||||
FINISHED
|
||||
};
|
||||
|
||||
template<State state>
|
||||
using tag = std::integral_constant<State, state>;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Base class for processes.
|
||||
*
|
||||
@@ -82,17 +60,30 @@ struct BaseProcess {
|
||||
* @tparam Delta Type to use to provide elapsed time.
|
||||
*/
|
||||
template<typename Derived, typename Delta>
|
||||
class Process: private BaseProcess {
|
||||
class Process {
|
||||
enum class State: unsigned int {
|
||||
UNINITIALIZED = 0,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
SUCCEEDED,
|
||||
FAILED,
|
||||
ABORTED,
|
||||
FINISHED
|
||||
};
|
||||
|
||||
template<State state>
|
||||
using tag = std::integral_constant<State, state>;
|
||||
|
||||
template<typename Target = Derived>
|
||||
auto tick(int, tag<State::UNINITIALIZED>)
|
||||
-> decltype(std::declval<Target>().init()) {
|
||||
static_cast<Target *>(this)->init();
|
||||
auto tick(int, tag<State::UNINITIALIZED>, void *data)
|
||||
-> decltype(std::declval<Target>().init(data)) {
|
||||
static_cast<Target *>(this)->init(data);
|
||||
}
|
||||
|
||||
template<typename Target = Derived>
|
||||
auto tick(int, tag<State::RUNNING>, Delta delta)
|
||||
-> decltype(std::declval<Target>().update(delta)) {
|
||||
static_cast<Target *>(this)->update(delta);
|
||||
auto tick(int, tag<State::RUNNING>, Delta delta, void *data)
|
||||
-> decltype(std::declval<Target>().update(delta, data)) {
|
||||
static_cast<Target *>(this)->update(delta, data);
|
||||
}
|
||||
|
||||
template<typename Target = Derived>
|
||||
@@ -227,15 +218,16 @@ public:
|
||||
/**
|
||||
* @brief Updates a process and its internal state if required.
|
||||
* @param delta Elapsed time.
|
||||
* @param data Optional data.
|
||||
*/
|
||||
void tick(Delta delta) {
|
||||
void tick(Delta delta, void *data = nullptr) {
|
||||
switch (current) {
|
||||
case State::UNINITIALIZED:
|
||||
tick(0, tag<State::UNINITIALIZED>{});
|
||||
tick(0, tag<State::UNINITIALIZED>{}, data);
|
||||
current = State::RUNNING;
|
||||
// no break on purpose, tasks are executed immediately
|
||||
case State::RUNNING:
|
||||
tick(0, tag<State::RUNNING>{}, delta);
|
||||
tick(0, tag<State::RUNNING>{}, delta, data);
|
||||
default:
|
||||
// suppress warnings
|
||||
break;
|
||||
@@ -322,9 +314,10 @@ struct ProcessAdaptor: Process<ProcessAdaptor<Func, Delta>, Delta>, private Func
|
||||
/**
|
||||
* @brief Updates a process and its internal state if required.
|
||||
* @param delta Elapsed time.
|
||||
* @param data Optional data.
|
||||
*/
|
||||
void update(Delta delta) {
|
||||
Func::operator()(delta, [this](){ this->succeed(); }, [this](){ this->fail(); });
|
||||
void update(Delta delta, void *data) {
|
||||
Func::operator()(delta, data, [this](){ this->succeed(); }, [this](){ this->fail(); });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class Scheduler final {
|
||||
|
||||
struct ProcessHandler final {
|
||||
using instance_type = std::unique_ptr<void, void(*)(void *)>;
|
||||
using update_type = bool(*)(ProcessHandler &, Delta);
|
||||
using update_type = bool(*)(ProcessHandler &, Delta, void *);
|
||||
using abort_type = void(*)(ProcessHandler &, bool);
|
||||
using next_type = std::unique_ptr<ProcessHandler>;
|
||||
|
||||
@@ -81,16 +81,16 @@ class Scheduler final {
|
||||
};
|
||||
|
||||
template<typename Proc>
|
||||
static bool update(ProcessHandler &handler, Delta delta) {
|
||||
static bool update(ProcessHandler &handler, Delta delta, void *data) {
|
||||
auto *process = static_cast<Proc *>(handler.instance.get());
|
||||
process->tick(delta);
|
||||
process->tick(delta, data);
|
||||
|
||||
auto dead = process->dead();
|
||||
|
||||
if(dead) {
|
||||
if(handler.next && !process->rejected()) {
|
||||
handler = std::move(*handler.next);
|
||||
dead = handler.update(handler, delta);
|
||||
dead = handler.update(handler, delta, data);
|
||||
} else {
|
||||
handler.instance.reset();
|
||||
}
|
||||
@@ -269,13 +269,14 @@ public:
|
||||
* with its child.
|
||||
*
|
||||
* @param delta Elapsed time.
|
||||
* @param data Optional data.
|
||||
*/
|
||||
void update(Delta delta) {
|
||||
void update(Delta delta, void *data = nullptr) {
|
||||
bool clean = false;
|
||||
|
||||
for(auto i = handlers.size(); i > 0; --i) {
|
||||
auto &handler = handlers[i-1];
|
||||
const bool dead = handler.update(handler, delta);
|
||||
for(auto pos = handlers.size(); pos > 0; --pos) {
|
||||
auto &handler = handlers[pos-1];
|
||||
const bool dead = handler.update(handler, delta, data);
|
||||
clean = clean || dead;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads the resource that corresponds to the given identifier.
|
||||
* @brief Loads the resource that corresponds to a given identifier.
|
||||
*
|
||||
* In case an identifier isn't already present in the cache, it loads its
|
||||
* resource and stores it aside for future uses. Arguments are forwarded
|
||||
@@ -130,7 +130,24 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a handle for the given resource identifier.
|
||||
* @brief Creates a temporary handle for a resource.
|
||||
*
|
||||
* Arguments are forwarded directly to the loader in order to construct
|
||||
* properly the requested resource. The handle isn't stored aside and the
|
||||
* cache isn't in charge of the lifetime of the resource itself.
|
||||
*
|
||||
* @tparam Loader Type of loader to use to load the resource.
|
||||
* @tparam Args Types of arguments to use to load the resource.
|
||||
* @param args Arguments to use to load the resource.
|
||||
* @return A handle for the given resource.
|
||||
*/
|
||||
template<typename Loader, typename... Args>
|
||||
ResourceHandle<Resource> temp(Args&&... args) const {
|
||||
return { Loader{}.get(std::forward<Args>(args)...) };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a handle for a given resource identifier.
|
||||
*
|
||||
* A resource handle can be in a either valid or invalid state. In other
|
||||
* terms, a resource handle is properly initialized with a resource if the
|
||||
@@ -148,7 +165,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if a cache contains the given identifier.
|
||||
* @brief Checks if a cache contains a given identifier.
|
||||
* @param id Unique resource identifier.
|
||||
* @return True if the cache contains the resource, false otherwise.
|
||||
*/
|
||||
@@ -157,7 +174,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discards the resource that corresponds to the given identifier.
|
||||
* @brief Discards the resource that corresponds to a given identifier.
|
||||
*
|
||||
* Handles are not invalidated and the memory used by the resource isn't
|
||||
* freed as long as at least a handle keeps the resource itself alive.
|
||||
|
||||
@@ -181,7 +181,9 @@ public:
|
||||
const auto buf = buffer(mode);
|
||||
mode = !mode;
|
||||
|
||||
for(auto &&wrapper: wrappers) {
|
||||
for(auto pos = wrappers.size(); pos > decltype(pos){0}; --pos) {
|
||||
auto &wrapper = wrappers[pos-1];
|
||||
|
||||
if(wrapper) {
|
||||
wrapper->publish(buf);
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ struct Invoker<Ret(Args...), Collector> {
|
||||
virtual ~Invoker() = default;
|
||||
|
||||
template<typename SFINAE = Ret>
|
||||
typename std::enable_if<std::is_void<SFINAE>::value, bool>::type
|
||||
typename std::enable_if_t<std::is_void<SFINAE>::value, bool>
|
||||
invoke(Collector &, proto_type proto, void *instance, Args... args) {
|
||||
proto(instance, args...);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename SFINAE = Ret>
|
||||
typename std::enable_if<!std::is_void<SFINAE>::value, bool>::type
|
||||
typename std::enable_if_t<!std::is_void<SFINAE>::value, bool>
|
||||
invoke(Collector &collector, proto_type proto, void *instance, Args... args) {
|
||||
return collector(proto(instance, args...));
|
||||
}
|
||||
@@ -229,7 +229,8 @@ public:
|
||||
* @param args Arguments to use to invoke listeners.
|
||||
*/
|
||||
void publish(Args... args) {
|
||||
for(auto &&call: calls) {
|
||||
for(auto pos = calls.size(); pos > size_type{0}; --pos) {
|
||||
auto &call = calls[pos-1];
|
||||
call.second(call.first, args...);
|
||||
}
|
||||
}
|
||||
@@ -242,7 +243,9 @@ public:
|
||||
collector_type collect(Args... args) {
|
||||
collector_type collector;
|
||||
|
||||
for(auto &&call: calls) {
|
||||
for(auto pos = calls.size(); pos > size_type{0}; --pos) {
|
||||
auto &call = calls[pos-1];
|
||||
|
||||
if(!this->invoke(collector, call.second, call.first, args...)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -167,11 +167,17 @@ public:
|
||||
* @param args Arguments to use to invoke listeners.
|
||||
*/
|
||||
void publish(Args... args) {
|
||||
for(auto it = calls.rbegin(), end = calls.rend(); it != end; it++) {
|
||||
if(!(it->second)(it->first, args...)) {
|
||||
calls.erase(std::next(it).base());
|
||||
std::vector<call_type> next;
|
||||
|
||||
for(auto pos = calls.size(); pos > size_type{0}; --pos) {
|
||||
auto &call = calls[pos-1];
|
||||
|
||||
if((call.second)(call.first, args...)) {
|
||||
next.push_back(call);
|
||||
}
|
||||
}
|
||||
|
||||
calls.swap(next);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/registry.hpp>
|
||||
@@ -6,6 +7,7 @@ TEST(DefaultRegistry, Functionalities) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{0});
|
||||
ASSERT_NO_THROW(registry.reserve(42));
|
||||
ASSERT_TRUE(registry.empty());
|
||||
|
||||
ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{0});
|
||||
@@ -56,6 +58,10 @@ TEST(DefaultRegistry, Functionalities) {
|
||||
ASSERT_TRUE(registry.has<char>(e3));
|
||||
ASSERT_EQ(registry.get<int>(e1), 42);
|
||||
ASSERT_EQ(registry.get<char>(e1), 'c');
|
||||
|
||||
ASSERT_EQ(std::get<0>(registry.get<int, char>(e1)), 42);
|
||||
ASSERT_EQ(std::get<1>(static_cast<const entt::DefaultRegistry &>(registry).get<int, char>(e1)), 'c');
|
||||
|
||||
ASSERT_EQ(registry.get<int>(e1), registry.get<int>(e3));
|
||||
ASSERT_EQ(registry.get<char>(e1), registry.get<char>(e3));
|
||||
ASSERT_NE(®istry.get<int>(e1), ®istry.get<int>(e3));
|
||||
@@ -345,3 +351,11 @@ TEST(DefaultRegistry, SortMulti) {
|
||||
ASSERT_EQ(registry.get<int>(entity), ival++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, ComponentsWithTypesFromStandardTemplateLibrary) {
|
||||
// see #37 - the test shouldn't crash, that's all
|
||||
entt::DefaultRegistry registry;
|
||||
auto entity = registry.create();
|
||||
registry.assign<std::unordered_set<int>>(entity).insert(42);
|
||||
registry.destroy(entity);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
TEST(SparseSetNoType, Functionalities) {
|
||||
entt::SparseSet<unsigned int> set;
|
||||
|
||||
ASSERT_NO_THROW(set.reserve(42));
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_EQ(set.begin(), set.end());
|
||||
@@ -79,6 +80,7 @@ TEST(SparseSetWithType, AggregatesMustWork) {
|
||||
TEST(SparseSetWithType, Functionalities) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
ASSERT_NO_THROW(set.reserve(42));
|
||||
ASSERT_TRUE(set.empty());
|
||||
ASSERT_EQ(set.size(), 0u);
|
||||
ASSERT_EQ(set.begin(), set.end());
|
||||
|
||||
@@ -90,10 +90,13 @@ TEST(View, MultipleComponent) {
|
||||
|
||||
view.get<char>(e1) = '1';
|
||||
view.get<char>(e2) = '2';
|
||||
view.get<int>(e2) = 42;
|
||||
|
||||
for(auto entity: view) {
|
||||
const auto &cview = static_cast<const decltype(view) &>(view);
|
||||
ASSERT_TRUE(cview.get<char>(entity) == '2');
|
||||
ASSERT_EQ(std::get<0>(cview.get<int, char>(entity)), 42);
|
||||
ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
|
||||
ASSERT_EQ(cview.get<char>(entity), '2');
|
||||
}
|
||||
|
||||
registry.remove<char>(e1);
|
||||
@@ -161,10 +164,13 @@ TEST(PersistentView, Prepare) {
|
||||
|
||||
view.get<char>(e1) = '1';
|
||||
view.get<char>(e2) = '2';
|
||||
view.get<int>(e2) = 42;
|
||||
|
||||
for(auto entity: view) {
|
||||
const auto &cview = static_cast<const decltype(view) &>(view);
|
||||
ASSERT_TRUE(cview.get<char>(entity) == '2');
|
||||
ASSERT_EQ(std::get<0>(cview.get<int, char>(entity)), 42);
|
||||
ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
|
||||
ASSERT_EQ(cview.get<char>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(*(view.data() + 0), e2);
|
||||
@@ -199,10 +205,13 @@ TEST(PersistentView, NoPrepare) {
|
||||
|
||||
view.get<char>(e1) = '1';
|
||||
view.get<char>(e2) = '2';
|
||||
view.get<int>(e2) = 42;
|
||||
|
||||
for(auto entity: view) {
|
||||
const auto &cview = static_cast<const decltype(view) &>(view);
|
||||
ASSERT_TRUE(cview.get<char>(entity) == '2');
|
||||
ASSERT_EQ(std::get<0>(cview.get<int, char>(entity)), 42);
|
||||
ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
|
||||
ASSERT_EQ(cview.get<char>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(*(view.data() + 0), e2);
|
||||
|
||||
@@ -10,12 +10,19 @@ struct FakeProcess: entt::Process<FakeProcess, int> {
|
||||
void pause() noexcept { process_type::pause(); }
|
||||
void unpause() noexcept { process_type::unpause(); }
|
||||
|
||||
void init() { initInvoked = true; }
|
||||
void update(delta_type) { updateInvoked = true; }
|
||||
void init(void *) { initInvoked = true; }
|
||||
void succeeded() { succeededInvoked = true; }
|
||||
void failed() { failedInvoked = true; }
|
||||
void aborted() { abortedInvoked = true; }
|
||||
|
||||
void update(delta_type, void *data) {
|
||||
if(data) {
|
||||
(*static_cast<int *>(data))++;
|
||||
}
|
||||
|
||||
updateInvoked = true;
|
||||
}
|
||||
|
||||
bool initInvoked{false};
|
||||
bool updateInvoked{false};
|
||||
bool succeededInvoked{false};
|
||||
@@ -95,6 +102,26 @@ TEST(Process, Fail) {
|
||||
ASSERT_FALSE(process.abortedInvoked);
|
||||
}
|
||||
|
||||
TEST(Process, Data) {
|
||||
FakeProcess process;
|
||||
int value = 0;
|
||||
|
||||
process.tick(0, &value);
|
||||
process.succeed();
|
||||
process.tick(0, &value);
|
||||
|
||||
ASSERT_FALSE(process.alive());
|
||||
ASSERT_TRUE(process.dead());
|
||||
ASSERT_FALSE(process.paused());
|
||||
|
||||
ASSERT_EQ(value, 1);
|
||||
ASSERT_TRUE(process.initInvoked);
|
||||
ASSERT_TRUE(process.updateInvoked);
|
||||
ASSERT_TRUE(process.succeededInvoked);
|
||||
ASSERT_FALSE(process.failedInvoked);
|
||||
ASSERT_FALSE(process.abortedInvoked);
|
||||
}
|
||||
|
||||
TEST(Process, AbortNextTick) {
|
||||
FakeProcess process;
|
||||
|
||||
@@ -132,7 +159,7 @@ TEST(Process, AbortImmediately) {
|
||||
|
||||
TEST(ProcessAdaptor, Resolved) {
|
||||
bool updated = false;
|
||||
auto lambda = [&updated](std::uint64_t, auto resolve, auto) {
|
||||
auto lambda = [&updated](std::uint64_t, void *, auto resolve, auto) {
|
||||
ASSERT_FALSE(updated);
|
||||
updated = true;
|
||||
resolve();
|
||||
@@ -148,7 +175,7 @@ TEST(ProcessAdaptor, Resolved) {
|
||||
|
||||
TEST(ProcessAdaptor, Rejected) {
|
||||
bool updated = false;
|
||||
auto lambda = [&updated](std::uint64_t, auto, auto rejected) {
|
||||
auto lambda = [&updated](std::uint64_t, void *, auto, auto rejected) {
|
||||
ASSERT_FALSE(updated);
|
||||
updated = true;
|
||||
rejected();
|
||||
@@ -161,3 +188,19 @@ TEST(ProcessAdaptor, Rejected) {
|
||||
ASSERT_TRUE(process.rejected());
|
||||
ASSERT_TRUE(updated);
|
||||
}
|
||||
|
||||
TEST(ProcessAdaptor, Data) {
|
||||
int value = 0;
|
||||
|
||||
auto lambda = [](std::uint64_t, void *data, auto resolve, auto) {
|
||||
*static_cast<int *>(data) = 42;
|
||||
resolve();
|
||||
};
|
||||
|
||||
auto process = entt::ProcessAdaptor<decltype(lambda), std::uint64_t>{lambda};
|
||||
|
||||
process.tick(0, &value);
|
||||
|
||||
ASSERT_TRUE(process.dead());
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ struct FooProcess: entt::Process<FooProcess, int> {
|
||||
: onUpdate{onUpdate}, onAborted{onAborted}
|
||||
{}
|
||||
|
||||
void update(delta_type) { onUpdate(); }
|
||||
void update(delta_type, void *) { onUpdate(); }
|
||||
void aborted() { onAborted(); }
|
||||
|
||||
std::function<void()> onUpdate;
|
||||
@@ -16,7 +16,7 @@ struct FooProcess: entt::Process<FooProcess, int> {
|
||||
};
|
||||
|
||||
struct SucceededProcess: entt::Process<SucceededProcess, int> {
|
||||
void update(delta_type) {
|
||||
void update(delta_type, void *) {
|
||||
ASSERT_FALSE(updated);
|
||||
updated = true;
|
||||
++invoked;
|
||||
@@ -30,7 +30,7 @@ struct SucceededProcess: entt::Process<SucceededProcess, int> {
|
||||
unsigned int SucceededProcess::invoked = 0;
|
||||
|
||||
struct FailedProcess: entt::Process<FailedProcess, int> {
|
||||
void update(delta_type) {
|
||||
void update(delta_type, void *) {
|
||||
ASSERT_FALSE(updated);
|
||||
updated = true;
|
||||
fail();
|
||||
@@ -92,11 +92,11 @@ TEST(Scheduler, Functor) {
|
||||
bool firstFunctor = false;
|
||||
bool secondFunctor = false;
|
||||
|
||||
scheduler.attach([&firstFunctor](auto, auto resolve, auto){
|
||||
scheduler.attach([&firstFunctor](auto, void *, auto resolve, auto){
|
||||
ASSERT_FALSE(firstFunctor);
|
||||
firstFunctor = true;
|
||||
resolve();
|
||||
}).then([&secondFunctor](auto, auto, auto reject){
|
||||
}).then([&secondFunctor](auto, void *, auto, auto reject){
|
||||
ASSERT_FALSE(secondFunctor);
|
||||
secondFunctor = true;
|
||||
reject();
|
||||
|
||||
@@ -77,4 +77,7 @@ TEST(ResourceCache, Functionalities) {
|
||||
|
||||
ASSERT_EQ(cache.size(), entt::ResourceCache<Resource>::size_type{});
|
||||
ASSERT_TRUE(cache.empty());
|
||||
|
||||
ASSERT_TRUE(cache.temp<Loader>(42));
|
||||
ASSERT_TRUE(cache.empty());
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
95118
test/mod/duktape.c
95118
test/mod/duktape.c
File diff suppressed because it is too large
Load Diff
1349
test/mod/duktape.h
1349
test/mod/duktape.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user