Skip to content

Instantly share code, notes, and snippets.

@ArnCarveris
Created November 14, 2018 22:20
Show Gist options
  • Select an option

  • Save ArnCarveris/414bfbab2be5a367346942baf9bb63c7 to your computer and use it in GitHub Desktop.

Select an option

Save ArnCarveris/414bfbab2be5a367346942baf9bb63c7 to your computer and use it in GitHub Desktop.
EnTT Entity Exporter/Importer
#ifndef ENTT_ENTITY_EXPORTER_HPP
#define ENTT_ENTITY_EXPORTER_HPP
#include <array>
#include <cstddef>
#include <utility>
#include <cassert>
#include <iterator>
#include <type_traits>
#include <unordered_map>
#include "../config/config.h"
#include "entt_traits.hpp"
#include "utility.hpp"
namespace entt {
/**
* @brief Forward declaration of the registry class.
*/
template<typename>
class Registry;
template<typename Entity>
class Prototype;
template<typename Entity, typename KeyType, template<class> class KeyValuePair>
class Exporter final {
friend class Registry<Entity>;
Exporter(const Registry<Entity> &registry) ENTT_NOEXCEPT
: registry{ registry }
{}
template<typename Component>
inline KeyValuePair<Component> make_kvp(KeyType key, Component&& component) const {
return KeyValuePair<Component>{key, component};
}
template<typename Component, typename Archive>
void component(Archive &archive, const Entity& entity, KeyType key) const {
if (registry.template has<Component>(entity)) {
archive(make_kvp(key, registry.template get<Component>(entity)));
}
}
template<typename Component, typename Archive>
void component(Archive &archive, const Prototype<Entity>& prototype, KeyType key) const {
if (prototype.has<Component>()) {
archive(make_kvp(key, prototype.get<Component>()));
}
}
template<typename... Component, typename Archive, typename Source, std::size_t... Indexes>
void components(Archive &archive, const Source& source, const std::array<KeyType, sizeof...(Component)>& keys, std::index_sequence<Indexes...>) const {
using accumulator_type = int[];
accumulator_type accumulator = { (component<Component>(archive, source, keys[Indexes]), 0)... };
(void)accumulator;
}
template<typename Tag, typename Archive>
void tag(Archive &archive, const Entity& entity, KeyType key) const {
if (registry.template has<Tag>() && registry.template attachee<Tag>() == entity) {
archive(make_kvp(key, registry.template get<Tag>()));
}
}
template<typename... Tag, typename Archive, std::size_t... Indexes>
void tags(Archive &archive, const Entity& entity, const std::array<KeyType, sizeof...(Tag)>& keys, std::index_sequence<Indexes...>) const {
using accumulator_type = int[];
accumulator_type accumulator = { (tag<Tag>(archive, entity, keys[Indexes]), 0)... };
(void)accumulator;
}
public:
/*! @brief Copying a exporter isn't allowed. */
Exporter(const Exporter &) = delete;
/*! @brief Default move constructor. */
Exporter(Exporter &&) = default;
/*! @brief Copying a exporter isn't allowed. @return This exporter. */
Exporter & operator=(const Exporter &) = delete;
/*! @brief Default move assignment operator. @return This exporter. */
Exporter & operator=(Exporter &&) = default;
template<typename... Component, typename Archive, typename Source>
const Exporter & component(Archive &archive, const Source& source, const std::array<KeyType, sizeof...(Component)>& keys) const {
components<Component...>(archive, source, keys, std::make_index_sequence<sizeof...(Component)>{});
return *this;
}
template<typename... Tag, typename Archive>
const Exporter & tag(Archive &archive, const Entity& entity, const std::array<KeyType, sizeof...(Tag)>& keys) const {
tags<Tag...>(archive, entity, keys, std::make_index_sequence<sizeof...(Tag)>{});
return *this;
}
private:
const Registry<Entity> &registry;
};
}
#endif // ENTT_ENTITY_EXPORTER_HPP
#ifndef ENTT_ENTITY_IMPORTER_HPP
#define ENTT_ENTITY_IMPORTER_HPP
#include <array>
#include <cstddef>
#include <utility>
#include <cassert>
#include <iterator>
#include <type_traits>
#include <unordered_map>
#include "../config/config.h"
#include "entt_traits.hpp"
#include "utility.hpp"
namespace entt {
/**
* @brief Forward declaration of the registry class.
*/
template<typename>
class Registry;
template<typename Entity>
class Prototype;
template<typename Entity, typename KeyType, template<class> class KeyValuePair>
class Importer final {
friend class Registry<Entity>;
Importer(Registry<Entity> &registry) ENTT_NOEXCEPT
: registry{ registry }
{}
template<typename Type, typename Func, typename... Args>
void build(Entity& entity, Func&& func, Args... args) const {
registry.template build<Type>(std::move(func), std::forward<Args>(args)...);
}
template<typename Type, typename Func, typename... Args>
void build(Prototype<Entity>& prototype, Func&& func, Args... args) const {
prototype.build<Type>(std::move(func), std::forward<Args>(args)...);
}
template<typename Type, typename Archive, typename Predicate, typename Destination>
bool load(Archive &archive, const Predicate& predicate, Destination& destination, KeyType key) const {
if (predicate(archive, key)) {
build<Type>(destination, [](Type& value, Archive &archive, KeyType& key) {
archive(KeyValuePair<Type>{ key, value });
}, archive, key);
return true;
}
return false;
}
template<typename... Component, typename Archive, typename Predicate, typename Destination, std::size_t... Indexes>
void components(Archive &archive, const Predicate& predicate, Destination& destination, const std::array<KeyType, sizeof...(Component)>& keys, std::index_sequence<Indexes...>) const {
using accumulator_type = int[];
accumulator_type accumulator = { (load<Component>(archive, predicate, destination, keys[Indexes]), 0)... };
(void)accumulator;
}
template<typename... Tag, typename Archive, typename Predicate, std::size_t... Indexes>
void tags(Archive &archive, const Predicate& predicate, Entity& entity, const std::array<KeyType, sizeof...(Tag)>& keys, std::index_sequence<Indexes...>) const {
using accumulator_type = int[];
accumulator_type accumulator = { (load<Tag>(archive, predicate, entity, keys[Indexes], tag_t{}), 0)... };
(void)accumulator;
}
public:
/*! @brief Copying a importer isn't allowed. */
Importer(const Importer &) = delete;
/*! @brief Default move constructor. */
Importer(Importer &&) = default;
/*! @brief Copying a importer isn't allowed. @return This importer. */
Importer & operator=(const Importer &) = delete;
/*! @brief Default move assignment operator. @return This importer. */
Importer & operator=(Importer &&) = default;
template<typename... Component, typename Archive, typename Predicate, typename Destination>
const Importer & component(Archive &archive, const Predicate& predicate, Destination& destination, const std::array<KeyType, sizeof...(Component)>& keys) const {
components<Component...>(archive, predicate, destination, keys, std::make_index_sequence<sizeof...(Component)>{});
return *this;
}
template<typename... Tag, typename Archive, typename Predicate>
const Importer & tag(Archive &archive, const Predicate& predicate, Entity& entity, const std::array<KeyType, sizeof...(Tag)>& keys) const {
tags<Tag...>(archive, predicate, entity, keys, std::make_index_sequence<sizeof...(Tag)>{});
return *this;
}
private:
Registry<Entity> &registry;
};
}
#endif // ENTT_ENTITY_IMPORTER_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment