This commit is contained in:
ZY4N
2024-12-22 16:58:40 +01:00
parent 2704814de2
commit db8db8f9d7
161 changed files with 17102 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
#include "assets/dynamic_data_stores/dynamic_material_store.hpp"
dynamic_material_store::id_type dynamic_material_store::add(const dynamic_material_buffer& buffer)
{
return m_store.add(buffer.data);
}
std::pair<dynamic_material_store::iterator_type, bool> dynamic_material_store::find(const id_type id)
{
return m_store.find(id);
}
std::pair<dynamic_material_store::const_iterator, bool> dynamic_material_store::find(const id_type id) const
{
return m_store.find(id);
}
void dynamic_material_store::remove(const iterator_type& it)
{
m_store.remove(it);
}
void dynamic_material_store::clear()
{
m_store.clear();
}

View File

@@ -0,0 +1,31 @@
#include "assets/dynamic_data_stores/dynamic_mesh_store.hpp"
dynamic_mesh_store::id_type dynamic_mesh_store::add(const dynamic_mesh_buffer& mesh_buffer)
{
const auto& triangles = mesh_buffer.triangles();
return m_store.add(
std::span{ triangles.front().data(), triangles.size() * 3 },
mesh_buffer.vertices
);
}
std::pair<dynamic_mesh_store::iterator_type, bool> dynamic_mesh_store::find(id_type id)
{
return m_store.find(id);
}
std::pair<dynamic_mesh_store::const_iterator, bool> dynamic_mesh_store::find(id_type id) const
{
return m_store.find(id);
}
void dynamic_mesh_store::remove(const iterator_type& it)
{
m_store.remove(it);
}
void dynamic_mesh_store::clear()
{
m_store.clear();
}

View File

@@ -0,0 +1,27 @@
#include "assets/dynamic_data_stores/dynamic_point_cloud_store.hpp"
dynamic_point_cloud_store::id_type dynamic_point_cloud_store::add(const dynamic_point_cloud_buffer& mesh_buffer)
{
return m_store.add(mesh_buffer.vertices);
}
std::pair<dynamic_point_cloud_store::iterator_type, bool> dynamic_point_cloud_store::find(id_type id)
{
return m_store.find(id);
}
std::pair<dynamic_point_cloud_store::const_iterator, bool> dynamic_point_cloud_store::find(id_type id) const
{
return m_store.find(id);
}
void dynamic_point_cloud_store::remove(const iterator_type& it)
{
m_store.remove(it);
}
void dynamic_point_cloud_store::clear()
{
m_store.clear();
}

View File

@@ -0,0 +1,387 @@
#ifndef INCLUDE_GENERIC_DYNAMIC_COMPONENT_ARRAY_STORE_IMPLEMENTATION
# error Never include this file directly include 'generic_dynamic_component_array_store.hpp'
#endif
#include <bits/ranges_algo.h>
template<typename C, typename... Ts>
component_array_iterator<C, Ts...>::component_array_iterator(
component_array_pointer_type components,
flag_count_pointer_type flags,
std::size_t index,
const offsets_type& offsets
) :
m_components{ components },
m_flag_counts{ flags },
m_index{ index },
m_offsets{ offsets } {}
template<typename C, typename... Ts>
typename component_array_iterator<C, Ts...>::reference component_array_iterator<C, Ts...>::operator*() const {
return dereference(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...>& component_array_iterator<C, Ts...>::operator++() {
adjust_offsets(std::index_sequence_for<Ts...>{}, 1);
++m_index;
return *this;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...> component_array_iterator<C, Ts...>::operator++(int) {
component_array_iterator tmp = *this;
++(*this);
return tmp;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...>& component_array_iterator<C, Ts...>::operator--() {
adjust_offsets(std::index_sequence_for<Ts...>{}, -1);
--m_index;
return *this;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...> component_array_iterator<C, Ts...>::operator--(int) {
auto tmp = *this;
--(*this);
return tmp;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...>& component_array_iterator<C, Ts...>::operator+=(const difference_type n)
{
adjust_offsets(std::index_sequence_for<Ts...>{}, n);
m_index += n;
return *this;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...>& component_array_iterator<C, Ts...>::operator-=(const difference_type n)
{
return (*this) += -n;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...> component_array_iterator<C, Ts...>::operator+(const difference_type n) const
{
auto tmp = *this;
return tmp += n;
}
template<typename C, typename... Ts>
component_array_iterator<C, Ts...> component_array_iterator<C, Ts...>::operator-(const difference_type n) const
{
auto tmp = *this;
return tmp -= n;
}
template<typename C, typename... Ts>
typename component_array_iterator<C, Ts...>::difference_type
component_array_iterator<C, Ts...>::operator-(const component_array_iterator& other) const
{
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
}
template<typename C, typename... Ts>
typename component_array_iterator<C, Ts...>::reference component_array_iterator<C, Ts...>::operator[](
const difference_type n
) const {
return *((*this) + n);
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator==(const component_array_iterator& other) const
{
return m_components == other.m_components and m_index == other.m_index;
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator!=(const component_array_iterator& other) const
{
return not (*this == other);
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator<(const component_array_iterator& other) const
{
return m_index < other.m_index;
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator<=(const component_array_iterator& other) const
{
return m_index <= other.m_index;
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator>(const component_array_iterator& other) const
{
return m_index > other.m_index;
}
template<typename C, typename... Ts>
bool component_array_iterator<C, Ts...>::operator>=(const component_array_iterator& other) const
{
return m_index >= other.m_index;
}
template<typename C, typename... Ts>
template<std::size_t I>
bool component_array_iterator<C, Ts...>::is_component_enabled(C flag)
{
return (flag & (C{1} << I)) != C{};
}
template<typename C, typename... Ts>
template<std::size_t... Is>
void component_array_iterator<C, Ts...>::calc_offsets(std::index_sequence<Is...>, difference_type n)
{
const auto negative = n < difference_type{ 0 };
const auto positive = n > difference_type{ 0 };
const auto step = difference_type{ positive } - difference_type{ negative };
n = negative ? -n : n;
// TODO template optimize for single steps
while (n--)
{
const auto& [ flags, count ] = m_flag_counts[m_index + n];
([&] {
if (is_component_enabled<Is>(flags)) {
std::get<Is>(m_offsets) += step * count;
}
}(), ...);
m_index += step;
}
}
template<typename C, typename... Ts>
template<std::size_t... Is>
typename component_array_iterator<C, Ts...>::reference
component_array_iterator<C, Ts...>::dereference(std::index_sequence<Is...>) const
{
return std::make_tuple(get_span<Is>()...);
}
template<typename C, typename... Ts>
template<std::size_t N>
std::tuple_element_t<N, typename component_array_iterator<C, Ts...>::value_type>
component_array_iterator<C, Ts...>::get_span() const
{
const auto& [ flags, count ] = m_flag_counts[m_index];
if (is_component_enabled<N>(flags))
{
return { &std::get<N>(m_components)[m_offsets[N]], count };
}
return nullptr;
}
template<typename C, typename... Ts>
std::tuple<std::add_pointer_t<Ts>...> generic_dynamic_component_array_store<C, Ts...>::data_ptrs()
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> generic_dynamic_component_array_store<C, Ts...>::data_ptrs() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
std::array<std::size_t, sizeof...(Ts)> generic_dynamic_component_array_store<C, Ts...>::data_counts() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::array{ std::get<Is>(m_component_arrays).size()... };
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::id_type generic_dynamic_component_array_store<C, Ts...>::add(
const std::tuple<std::vector<Ts>...>& component_arrays
) {
auto component_flags = C{};
auto count = count_type{};
[&]<auto... Is>(std::integer_sequence<Is...>)
{
const auto& array = std::get<Is>(component_arrays);
if (not array.empty())
{
const auto array_count = static_cast<count_type>(array.size());
count = count ? std::min(array_count, count) : array_count;
component_flags |= C{ 1 } << Is;
}
}
(std::index_sequence_for<Ts...>{});
[&]<auto... Is>(std::integer_sequence<Is...>)
{
const auto& src_array = std::get<Is>(component_arrays);
auto& dst_array = std::get<Is>(m_component_arrays);
if (not src_array.empty())
{
dst_array.insert(dst_array.end(), src_array.begin(), src_array.begin() + count);
}
}
(std::index_sequence_for<Ts...>{});
m_component_flag_counts.emplace_back(component_flags, count);
const auto id = id_type{ m_next_data_id.index++ };
m_ids.push_back(id);
return id;
}
template<typename C, typename... Ts>
std::pair<typename generic_dynamic_component_array_store<C, Ts...>::iterator_type, bool> generic_dynamic_component_array_store<C, Ts...>::find(id_type id)
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename... Ts>
std::pair<typename generic_dynamic_component_array_store<C, Ts...>::const_iterator, bool> generic_dynamic_component_array_store<C, Ts...>::find(id_type id) const
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename... Ts>
void generic_dynamic_component_array_store<C, Ts...>::remove(const iterator_type& it)
{
[&]<auto... Is>(std::index_sequence<Is>)
{
([&]{
auto& component_vector = std::get<Is>(m_component_arrays);
const auto begin = component_vector.begin() + it.m_offsets[Is];
const auto end = begin + it.m_flag_counts[it.m_index];
component_vector.erase(begin, end);
}(), ...);
} (std::index_sequence_for<Ts...>{});
m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index);
m_ids.erase(m_ids.begin() + it.m_index);
}
template<typename C, typename... Ts>
void generic_dynamic_component_array_store<C, Ts...>::clear()
{
[&]<auto... Is>(std::index_sequence<Is>)
{
std::get<Is>(m_component_arrays).clear();
} (std::index_sequence_for<Ts...>{});
m_component_flag_counts.clear();
m_ids.clear();
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::iterator_type generic_dynamic_component_array_store<C, Ts...>::begin()
{
return iterator_type{
data_ptrs(),
m_component_flag_counts.data(),
0,
{}
};
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::iterator_type generic_dynamic_component_array_store<C, Ts...>::end()
{
return iterator_type{
data_ptrs(),
m_component_flag_counts.data(),
m_component_flag_counts.size(),
data_counts()
};
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::const_iterator generic_dynamic_component_array_store<C, Ts...>::begin() const
{
return iterator_type{
data_ptrs(),
m_component_flag_counts.data(),
0,
{}
};
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::const_iterator generic_dynamic_component_array_store<C, Ts...>::end() const
{
return iterator_type{
data_ptrs(),
m_component_flag_counts.data(),
m_component_flag_counts.size(),
data_counts()
};
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::const_iterator generic_dynamic_component_array_store<C, Ts...>::cbegin() const
{
return const_cast<const generic_dynamic_component_array_store*>(this)->begin();
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::const_iterator generic_dynamic_component_array_store<C, Ts...>::cend() const
{
return const_cast<const generic_dynamic_component_array_store*>(this)->end();
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::view_type generic_dynamic_component_array_store<C, Ts...>::view()
{
return { begin(), end() };
}
template<typename C, typename... Ts>
typename generic_dynamic_component_array_store<C, Ts...>::const_view_type generic_dynamic_component_array_store<C, Ts...>::view() const
{
return { begin(), end() };
}

View File

@@ -0,0 +1,373 @@
#ifndef INCLUDE_GENERIC_DYNAMIC_COMPONENT_STORE_IMPLEMENTATION
# error Never include this file directly include 'basic_dynamic_component_store.hpp'
#endif
#pragma once
#include <vector>
#include <span>
#include "util/uix.hpp"
#include "util/id_type.hpp"
#include <tuple>
#include <cstddef>
#include <type_traits>
#include <algorithm>
template<typename C, typename... Ts>
component_iterator<C, Ts...>::component_iterator(
const value_type components,
const C* flags,
std::size_t index,
const offsets_type& offsets
) : m_components{ components }, m_flags{ flags }, m_index{ index }, m_offsets{ offsets } {}
template<typename C, typename... Ts>
typename component_iterator<C, Ts...>::reference component_iterator<C, Ts...>::operator*() const {
return dereference(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
component_iterator<C, Ts...>& component_iterator<C, Ts...>::operator++() {
adjust_offsets(std::index_sequence_for<Ts...>{}, 1);
++m_index;
return *this;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...> component_iterator<C, Ts...>::operator++(int) {
component_iterator tmp = *this;
++(*this);
return tmp;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...>& component_iterator<C, Ts...>::operator--() {
adjust_offsets(std::index_sequence_for<Ts...>{}, -1);
--m_index;
return *this;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...> component_iterator<C, Ts...>::operator--(int) {
auto tmp = *this;
--(*this);
return tmp;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...>& component_iterator<C, Ts...>::operator+=(const difference_type n)
{
adjust_offsets(std::index_sequence_for<Ts...>{}, n);
m_index += n;
return *this;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...>& component_iterator<C, Ts...>::operator-=(const difference_type n)
{
return (*this) += -n;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...> component_iterator<C, Ts...>::operator+(const difference_type n) const
{
auto tmp = *this;
return tmp += n;
}
template<typename C, typename... Ts>
component_iterator<C, Ts...> component_iterator<C, Ts...>::operator-(const difference_type n) const
{
auto tmp = *this;
return tmp -= n;
}
template<typename C, typename... Ts>
typename component_iterator<C, Ts...>::difference_type
component_iterator<C, Ts...>::operator-(const component_iterator& other) const
{
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
}
template<typename C, typename... Ts>
typename component_iterator<C, Ts...>::reference component_iterator<C, Ts...>::operator[](
const difference_type n
) const {
return *((*this) + n);
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator==(const component_iterator& other) const
{
return m_components == other.m_components and m_index == other.m_index;
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator!=(const component_iterator& other) const
{
return not (*this == other);
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator<(const component_iterator& other) const
{
return m_index < other.m_index;
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator<=(const component_iterator& other) const
{
return m_index <= other.m_index;
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator>(const component_iterator& other) const
{
return m_index > other.m_index;
}
template<typename C, typename... Ts>
bool component_iterator<C, Ts...>::operator>=(const component_iterator& other) const
{
return m_index >= other.m_index;
}
template<typename C, typename... Ts>
template<std::size_t I>
bool component_iterator<C, Ts...>::is_component_enabled(C flag)
{
return (flag & (C{1} << I)) != C{};
}
template<typename C, typename... Ts>
template<std::size_t... Is>
void component_iterator<C, Ts...>::calc_offsets(std::index_sequence<Is...>, difference_type n)
{
const auto negative = n < difference_type{ 0 };
const auto positive = n > difference_type{ 0 };
const auto step = difference_type{ positive } - difference_type{ negative };
n = negative ? -n : n;
// TODO template optimize for single steps
while (n--)
{
const C& flag = m_flags[m_index + n];
([&] {
if (is_component_enabled<Is>(flag)) {
std::get<Is>(m_offsets) += step;
}
}(), ...);
m_index += step;
}
}
template<typename C, typename... Ts>
template<std::size_t... Is>
typename component_iterator<C, Ts...>::reference
component_iterator<C, Ts...>::dereference(std::index_sequence<Is...>) const
{
return std::make_tuple(get_pointer<Is>()...);
}
template<typename C, typename... Ts>
template<std::size_t N>
std::tuple_element_t<N, typename component_iterator<C, Ts...>::value_type>
component_iterator<C, Ts...>::get_pointer() const
{
if (is_component_enabled<N>(m_flags[m_index]))
{
return &std::get<N>(m_components)[m_offsets[N]];
}
return nullptr;
}
template<typename C, typename... Ts>
std::tuple<std::add_pointer_t<Ts>...> component_iterator<C, Ts...>::data_ptrs()
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_components).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> component_iterator<C, Ts...>::data_ptrs() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_components).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
std::array<std::size_t, sizeof...(Ts)> component_iterator<C, Ts...>::data_counts() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::array{ std::get<Is>(m_components).size()... };
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename... Ts>
typename generic_dynamic_component_store<C, Ts...>::id_type generic_dynamic_component_store<C, Ts...>::add(
const std::tuple<std::optional<Ts>...>& data
) {
auto component_flags = C{};
[&]<auto... Is>(std::integer_sequence<Is...>)
{
if (const auto& component_opt = std::get<Is>(data))
{
std::get<Is>(m_components).push_back(*component_opt);
component_flags |= C{ 1 } << Is;
}
}
(std::index_sequence_for<Ts...>{});
m_component_flags.push_back(component_flags);
const auto id = id_type{ m_next_data_id.index++ };
m_ids.push_back(id);
return id;
}
template<typename C, typename... Ts>
std::pair<typename generic_dynamic_component_store<C, Ts...>::iterator_type, bool> generic_dynamic_component_store<C, Ts...>::find(id_type id)
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename... Ts>
std::pair<typename generic_dynamic_component_store<C, Ts...>::const_iterator, bool> generic_dynamic_component_store<C, Ts...>::find(id_type id) const
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename... Ts>
void generic_dynamic_component_store<C, Ts...>::remove(const iterator_type& it)
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
auto& component_vector = std::get<Is>(m_components);
(component_vector.erase(component_vector.begin() + it.m_offsets[Is]), ...);
} (std::index_sequence_for<Ts...>{});
m_component_flags.erase(m_component_flags.begin() + it.m_index);
m_ids.erase(m_ids.begin() + it.m_index);
}
template<typename C, typename... Ts>
void generic_dynamic_component_store<C, Ts...>::clear()
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
std::get<Is>(m_component_counts).clear();
} (std::index_sequence_for<Ts...>{});
m_component_flags.clear();
m_ids.clear();
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::iterator_type generic_dynamic_component_store<C, Ts...>::begin()
{
return iterator_type{
data_ptrs(),
m_component_flags.data(),
0,
{}
};
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::iterator_type generic_dynamic_component_store<C, Ts...>::end()
{
return iterator_type{
data_ptrs(),
m_component_flags.data(),
m_component_flags.size(),
data_counts()
};
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::const_iterator generic_dynamic_component_store<C, Ts...>::begin() const
{
return iterator_type{
data_ptrs(),
m_component_flags.data(),
0,
{}
};
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::const_iterator generic_dynamic_component_store<C, Ts...>::end() const
{
return iterator_type{
data_ptrs(),
m_component_flags.data(),
m_component_flags.size(),
data_counts()
};
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::const_iterator generic_dynamic_component_store<C, Ts...>::cbegin() const
{
return const_cast<const generic_dynamic_component_store*>(this)->begin();
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::const_iterator generic_dynamic_component_store<C, Ts...>::cend() const
{
return const_cast<const generic_dynamic_component_store*>(this)->end();
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::view_type generic_dynamic_component_store<C, Ts...>::view()
{
return { begin(), end() };
}
template<typename C, typename... Ts>
generic_dynamic_component_store<C, Ts...>::const_view_type generic_dynamic_component_store<C, Ts...>::view() const
{
return { begin(), end() };
}

View File

@@ -0,0 +1,418 @@
#ifndef INCLUDE_GENERIC_DYNAMIC_INDEXED_COMPONENT_ARRAY_STORE_IMPLEMENTATION
# error Never include this file directly include 'generic_dynamic_indexed_component_array_store.hpp'
#endif
#pragma once
#include <vector>
#include <span>
#include <tuple>
#include <cstddef>
#include <type_traits>
#include <algorithm>
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...>::indexed_component_array_iterator(
const index_array_pointer_type indices,
const component_array_pointer_type& components,
const flag_count_pointer_type flag_counts,
std::size_t index,
const offsets_type& offsets
) :
m_indices{ indices },
m_components{ components },
m_flag_counts{ flag_counts },
m_index{ index },
m_offsets{ offsets } {}
template<typename C, typename I, typename... Ts>
typename indexed_component_array_iterator<C, I, Ts...>::reference indexed_component_array_iterator<C, I, Ts...>::operator*() const {
return dereference(std::index_sequence_for<Ts...>{});
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...>& indexed_component_array_iterator<C, I, Ts...>::operator++() {
adjust_offsets(std::index_sequence_for<Ts...>{}, 1);
++m_index;
return *this;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...> indexed_component_array_iterator<C, I, Ts...>::operator++(int) {
indexed_component_array_iterator tmp = *this;
++(*this);
return tmp;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...>& indexed_component_array_iterator<C, I, Ts...>::operator--() {
adjust_offsets(std::index_sequence_for<Ts...>{}, -1);
--m_index;
return *this;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...> indexed_component_array_iterator<C, I, Ts...>::operator--(int) {
auto tmp = *this;
--(*this);
return tmp;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...>& indexed_component_array_iterator<C, I, Ts...>::operator+=(const difference_type n)
{
adjust_offsets(std::index_sequence_for<Ts...>{}, n);
m_index += n;
return *this;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...>& indexed_component_array_iterator<C, I, Ts...>::operator-=(const difference_type n)
{
return (*this) += -n;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...> indexed_component_array_iterator<C, I, Ts...>::operator+(const difference_type n) const
{
auto tmp = *this;
return tmp += n;
}
template<typename C, typename I, typename... Ts>
indexed_component_array_iterator<C, I, Ts...> indexed_component_array_iterator<C, I, Ts...>::operator-(const difference_type n) const
{
auto tmp = *this;
return tmp -= n;
}
template<typename C, typename I, typename... Ts>
typename indexed_component_array_iterator<C, I, Ts...>::difference_type
indexed_component_array_iterator<C, I, Ts...>::operator-(const indexed_component_array_iterator& other) const
{
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
}
template<typename C, typename I, typename... Ts>
typename indexed_component_array_iterator<C, I, Ts...>::reference indexed_component_array_iterator<C, I, Ts...>::operator[](
const difference_type n
) const {
return *((*this) + n);
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator==(const indexed_component_array_iterator& other) const
{
return m_components == other.m_components and m_index == other.m_index;
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator!=(const indexed_component_array_iterator& other) const
{
return not (*this == other);
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator<(const indexed_component_array_iterator& other) const
{
return m_index < other.m_index;
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator<=(const indexed_component_array_iterator& other) const
{
return m_index <= other.m_index;
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator>(const indexed_component_array_iterator& other) const
{
return m_index > other.m_index;
}
template<typename C, typename I, typename... Ts>
bool indexed_component_array_iterator<C, I, Ts...>::operator>=(const indexed_component_array_iterator& other) const
{
return m_index >= other.m_index;
}
template<typename C, typename I, typename... Ts>
template<std::size_t N>
bool indexed_component_array_iterator<C, I, Ts...>::is_component_enabled(C flag)
{
return (flag & (C{1} << N)) != C{};
}
template<typename C, typename I, typename... Ts>
template<std::size_t... Is>
void indexed_component_array_iterator<C, I, Ts...>::calc_offsets(
std::index_sequence<Is...>,
difference_type n
) {
const auto negative = n < difference_type{ 0 };
const auto positive = n > difference_type{ 0 };
const auto step = difference_type{ positive } - difference_type{ negative };
n = negative ? -n : n;
// TODO template optimize for single steps
while (n--)
{
const auto& [ flags, index_count, component_count ] = m_flag_counts[m_index + n];
std::get<0>(m_offsets) += step * index_count;
([&] {
if (is_component_enabled<Is>(flags)) {
std::get<1 + Is>(m_offsets) += step * component_count;
}
}(), ...);
m_index += step;
}
}
template<typename C, typename I, typename... Ts>
template<std::size_t... Is>
typename indexed_component_array_iterator<C, I, Ts...>::reference
indexed_component_array_iterator<C, I, Ts...>::dereference(std::index_sequence<Is...>) const
{
const auto& [ flags, index_count, component_count ] = m_flag_counts[m_index];
return std::make_tuple(
std::span(
m_indices[m_offsets[0]],
index_count
),
std::span(
(
is_component_enabled<Is>(flags)
? &std::get<Is>(m_components)[m_offsets[1 + Is]]
: nullptr
),
component_count
)...
);
}
template<typename C, typename I, typename... Ts>
std::tuple<std::add_pointer_t<Ts>...> generic_dynamic_indexed_component_array_store<C, I, Ts...>::component_array_ptrs()
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename I, typename... Ts>
std::tuple<std::add_pointer_t<std::add_const_t<Ts>>...> generic_dynamic_indexed_component_array_store<C, I, Ts...>::component_array_ptrs() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::make_tuple(std::get<Is>(m_component_arrays).data()...);
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename I, typename... Ts>
std::array<std::size_t, 1 + sizeof...(Ts)> generic_dynamic_indexed_component_array_store<C, I, Ts...>::array_counts() const
{
return [&]<auto... Is>(std::index_sequence<Is>)
{
return std::array{
m_indices.size(),
std::get<Is>(m_component_arrays).size()...
};
}
(std::index_sequence_for<Ts...>{});
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::id_type generic_dynamic_indexed_component_array_store<C, I,Ts...>::add(
std::span<const I> indices,
const std::tuple<std::vector<Ts>...>& component_arrays
) {
auto component_flags = C{};
auto min_component_count = count_type{};
[&]<auto... Is>(std::integer_sequence<Is...>)
{
const auto& component_array = std::get<Is>(component_arrays);
if (not component_array.empty())
{
const auto component_count = static_cast<count_type>(component_array.size());
if (min_component_count != 0 and component_count < min_component_count)
{
min_component_count = component_count;
}
component_flags |= C{ 1 } << Is;
}
}
(std::index_sequence_for<Ts...>{});
m_indices.insert(m_indices.end(), indices.begin(), indices.end());
[&]<auto... Is>(std::integer_sequence<Is...>)
{
const auto& src_array = std::get<Is>(component_arrays);
auto& dst_array = std::get<Is>(m_component_arrays);
if (not src_array.empty())
{
dst_array.insert(dst_array.end(), src_array.begin(), src_array.begin() + min_component_count);
}
}
(std::index_sequence_for<Ts...>{});
m_component_flag_counts.emplace_back(component_flags, indices.size(), min_component_count);
const auto id = id_type{ m_next_data_id.index++ };
m_ids.push_back(id);
return id;
}
template<typename C, typename I, typename... Ts>
std::pair<typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::iterator_type, bool> generic_dynamic_indexed_component_array_store<C, I,Ts...>::find(id_type id)
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename I, typename... Ts>
std::pair<typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_iterator, bool> generic_dynamic_indexed_component_array_store<C, I,Ts...>::find(id_type id) const
{
const auto id_it = std::ranges::upper_bound(m_ids, id);
const auto match = (
id_it != m_ids.begin() and
*std::prev(id_it) == id
);
const auto index = id_it - m_ids.begin() - match;
auto it = begin();
it += index;
return { it, match };
}
template<typename C, typename I, typename... Ts>
void generic_dynamic_indexed_component_array_store<C, I,Ts...>::remove(const iterator_type& it)
{
m_indices.erase(m_indices.begin() + it.m_offsets[0]);
[&]<auto... Is>(std::index_sequence<Is>)
{
([&]{
auto& component_vector = std::get<Is>(m_component_arrays);
const auto begin = component_vector.begin() + it.m_offsets[1 + Is];
const auto end = begin + it.m_flag_counts[it.m_index];
component_vector.erase(begin, end);
}(), ...);
} (std::index_sequence_for<Ts...>{});
m_component_flag_counts.erase(m_component_flag_counts.begin() + it.m_index);
m_ids.erase(m_ids.begin() + it.m_index);
}
template<typename C, typename I, typename... Ts>
void generic_dynamic_indexed_component_array_store<C, I,Ts...>::clear()
{
m_indices.clear();
[&]<auto... Is>(std::index_sequence<Is>)
{
std::get<Is>(m_component_arrays).clear();
} (std::index_sequence_for<Ts...>{});
m_component_flag_counts.clear();
m_ids.clear();
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::iterator_type generic_dynamic_indexed_component_array_store<C, I,Ts...>::begin()
{
return iterator_type{
m_indices.data(),
component_array_ptrs(),
m_component_flag_counts.data(),
0,
{}
};
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::iterator_type generic_dynamic_indexed_component_array_store<C, I,Ts...>::end()
{
return iterator_type{
m_indices.data(),
component_array_ptrs(),
m_component_flag_counts.data(),
m_component_flag_counts.size(),
array_counts()
};
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_iterator generic_dynamic_indexed_component_array_store<C, I,Ts...>::begin() const
{
return iterator_type{
m_indices.data(),
component_array_ptrs(),
m_component_flag_counts.data(),
0,
{}
};
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_iterator generic_dynamic_indexed_component_array_store<C, I,Ts...>::end() const
{
return iterator_type{
m_indices.data(),
component_array_ptrs(),
m_component_flag_counts.data(),
m_component_flag_counts.size(),
array_counts()
};
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_iterator generic_dynamic_indexed_component_array_store<C, I,Ts...>::cbegin() const
{
return const_cast<const generic_dynamic_indexed_component_array_store*>(this)->begin();
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_iterator generic_dynamic_indexed_component_array_store<C, I,Ts...>::cend() const
{
return const_cast<const generic_dynamic_indexed_component_array_store*>(this)->end();
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::view_type generic_dynamic_indexed_component_array_store<C, I,Ts...>::view()
{
return { begin(), end() };
}
template<typename C, typename I, typename... Ts>
typename generic_dynamic_indexed_component_array_store<C, I,Ts...>::const_view_type generic_dynamic_indexed_component_array_store<C, I,Ts...>::view() const
{
return { begin(), end() };
}

View File

@@ -0,0 +1,61 @@
#ifndef INCLUDE_GENERIC_DYNAMIC_STORE_IMPLEMENTATION
# error Never include this file directly include 'basic_dynamic_store.hpp'
#endif
#include <algorithm>
template<typename T>
typename generic_dynamic_store<T>::id_type generic_dynamic_store<T>::add(const T& data)
{
auto id = id_type{ m_next_data_id.index++ };
m_data.emplace_back(data);
m_ids.emplace_back(id);
return id;
}
template<typename T>
std::pair<typename generic_dynamic_store<T>::iterator_type, bool> generic_dynamic_store<T>::find(id_type id)
{
const auto it = std::ranges::upper_bound(m_ids, id);
const auto found = it != m_ids.begin() and *std::prev(it) == id;
const auto index = it - m_ids.begin() - found;
return { m_data.begin() + index, found };
}
template<typename T>
std::pair<typename generic_dynamic_store<T>::const_iterator, bool> generic_dynamic_store<T>::find(id_type id) const
{
const auto it = std::ranges::upper_bound(m_ids, id);
const auto found = it != m_ids.begin() and *std::prev(it) == id;
const auto index = it - m_ids.begin() - found;
return { m_data.begin() + index, found };
}
template<typename T>
void generic_dynamic_store<T>::remove(iterator_type it)
{
const auto index = it - m_data.begin();
m_data.erase(it);
m_ids.erase(m_ids.begin() + index);
}
template<typename T>
void generic_dynamic_store<T>::clear()
{
m_data.clear();
m_ids.clear();
}
template<typename T>
std::span<T> generic_dynamic_store<T>::data()
{
return m_data;
}
template<typename T>
std::span<const T> generic_dynamic_store<T>::data() const
{
return m_data;
}