|
|
@@ -1,6 +1,7 @@
|
|
|
#ifndef ENTT_ENTITY_HANDLE_HPP
|
|
|
#define ENTT_ENTITY_HANDLE_HPP
|
|
|
|
|
|
+#include <iterator>
|
|
|
#include <tuple>
|
|
|
#include <type_traits>
|
|
|
#include <utility>
|
|
|
@@ -10,6 +11,88 @@
|
|
|
|
|
|
namespace entt {
|
|
|
|
|
|
+/**
|
|
|
+ * @cond TURN_OFF_DOXYGEN
|
|
|
+ * Internal details not to be documented.
|
|
|
+ */
|
|
|
+
|
|
|
+namespace internal {
|
|
|
+
|
|
|
+template<typename It>
|
|
|
+class handle_storage_iterator final {
|
|
|
+ template<typename Other>
|
|
|
+ friend class handle_storage_iterator;
|
|
|
+
|
|
|
+ using underlying_type = std::remove_reference_t<typename It::value_type::second_type>;
|
|
|
+ using entity_type = typename underlying_type::entity_type;
|
|
|
+
|
|
|
+public:
|
|
|
+ using value_type = typename std::iterator_traits<It>::value_type;
|
|
|
+ using pointer = input_iterator_pointer<value_type>;
|
|
|
+ using reference = value_type;
|
|
|
+ using difference_type = std::ptrdiff_t;
|
|
|
+ using iterator_category = std::input_iterator_tag;
|
|
|
+
|
|
|
+ constexpr handle_storage_iterator() noexcept
|
|
|
+ : entt{null},
|
|
|
+ it{},
|
|
|
+ last{} {}
|
|
|
+
|
|
|
+ constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept
|
|
|
+ : entt{value},
|
|
|
+ it{from},
|
|
|
+ last{to} {
|
|
|
+ while(it != last && !it->second.contains(entt)) { ++it; }
|
|
|
+ }
|
|
|
+
|
|
|
+ template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
|
|
|
+ constexpr handle_storage_iterator(const handle_storage_iterator<Other> &other) noexcept
|
|
|
+ : handle_storage_iterator{other.entt, other it, other.last} {}
|
|
|
+
|
|
|
+ constexpr handle_storage_iterator &operator++() noexcept {
|
|
|
+ while(++it != last && !it->second.contains(entt)) {}
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ constexpr handle_storage_iterator operator++(int) noexcept {
|
|
|
+ handle_storage_iterator orig = *this;
|
|
|
+ return ++(*this), orig;
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] constexpr reference operator*() const noexcept {
|
|
|
+ return *it;
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] constexpr pointer operator->() const noexcept {
|
|
|
+ return operator*();
|
|
|
+ }
|
|
|
+
|
|
|
+ template<typename ILhs, typename IRhs>
|
|
|
+ friend constexpr bool operator==(const handle_storage_iterator<ILhs> &, const handle_storage_iterator<IRhs> &) noexcept;
|
|
|
+
|
|
|
+private:
|
|
|
+ entity_type entt;
|
|
|
+ It it;
|
|
|
+ It last;
|
|
|
+};
|
|
|
+
|
|
|
+template<typename ILhs, typename IRhs>
|
|
|
+[[nodiscard]] constexpr bool operator==(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
|
|
|
+ return lhs.it == rhs.it;
|
|
|
+}
|
|
|
+
|
|
|
+template<typename ILhs, typename IRhs>
|
|
|
+[[nodiscard]] constexpr bool operator!=(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
|
|
|
+ return !(lhs == rhs);
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace internal
|
|
|
+
|
|
|
+/**
|
|
|
+ * Internal details not to be documented.
|
|
|
+ * @endcond
|
|
|
+ */
|
|
|
+
|
|
|
/**
|
|
|
* @brief Non-owning handle to an entity.
|
|
|
*
|
|
|
@@ -43,6 +126,29 @@ struct basic_handle {
|
|
|
: reg{&ref},
|
|
|
entt{value} {}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns an iterable object to use to _visit_ a handle.
|
|
|
+ *
|
|
|
+ * The iterable object returns a pair that contains the name and a reference
|
|
|
+ * to the current storage.<br/>
|
|
|
+ * Returned storage are those that contain the entity associated with the
|
|
|
+ * handle.
|
|
|
+ *
|
|
|
+ * @return An iterable object to use to _visit_ the handle.
|
|
|
+ */
|
|
|
+ [[nodiscard]] auto storage() noexcept {
|
|
|
+ auto iterable = reg->storage();
|
|
|
+ using iterator_type = internal::handle_storage_iterator<typename decltype(iterable)::iterator>;
|
|
|
+ return iterable_adaptor{iterator_type{entt, iterable.begin(), iterable.end()}, iterator_type{entt, iterable.end(), iterable.end()}};
|
|
|
+ }
|
|
|
+
|
|
|
+ /*! @copydoc storage */
|
|
|
+ [[nodiscard]] auto storage() const noexcept {
|
|
|
+ auto iterable = reg->storage();
|
|
|
+ using iterator_type = internal::handle_storage_iterator<typename decltype(iterable)::const_iterator>;
|
|
|
+ return iterable_adaptor{iterator_type{entt, iterable.cbegin(), iterable.cend()}, iterator_type{entt, iterable.cend(), iterable.cend()}};
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @brief Constructs a const handle from a non-const one.
|
|
|
* @tparam Other A valid entity type (see entt_traits for more details).
|
|
|
@@ -263,30 +369,6 @@ struct basic_handle {
|
|
|
return reg->orphan(entt);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * @brief Visits a handle and returns the pools for its components.
|
|
|
- *
|
|
|
- * The signature of the function should be equivalent to the following:
|
|
|
- *
|
|
|
- * @code{.cpp}
|
|
|
- * void(id_type, const basic_sparse_set<entity_type> &);
|
|
|
- * @endcode
|
|
|
- *
|
|
|
- * Returned pools are those that contain the entity associated with the
|
|
|
- * handle.
|
|
|
- *
|
|
|
- * @tparam Func Type of the function object to invoke.
|
|
|
- * @param func A valid function object.
|
|
|
- */
|
|
|
- template<typename Func>
|
|
|
- void visit(Func &&func) const {
|
|
|
- for(auto [id, storage]: reg->storage()) {
|
|
|
- if(storage.contains(entt)) {
|
|
|
- func(id, storage);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private:
|
|
|
registry_type *reg;
|
|
|
entity_type entt;
|