161 lines
4.3 KiB
C++
161 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include <psemek/ecs/exceptions.hpp>
|
|
#include <psemek/ecs/detail/table.hpp>
|
|
|
|
namespace psemek::ecs
|
|
{
|
|
|
|
struct accessor
|
|
{
|
|
/** Create an invalid accessor, i.e. one that doesn't refer to an entity.
|
|
*/
|
|
accessor() = default;
|
|
|
|
/** Copy-construct the accessor.
|
|
*/
|
|
accessor(accessor const &) = default;
|
|
|
|
/** Copy-assign the accessor.
|
|
*/
|
|
accessor & operator = (accessor const & other) = default;
|
|
|
|
/** Check if this accessor is valid, i.e. refers to an entity.
|
|
*
|
|
* @return True if the accessor is valid, false otherwise
|
|
*/
|
|
explicit operator bool() const;
|
|
|
|
/** Obtain the component of the specified type of the accessed entity.
|
|
*
|
|
* @tparam Component The type of component to obtain
|
|
* @return A pointer to the component of the specified type, or a null
|
|
* pointer if the entity doesn't contain a component of this type
|
|
* @pre The accessor is valid
|
|
*/
|
|
template <typename Component>
|
|
Component * get_if();
|
|
|
|
template <typename Component>
|
|
Component const * get_if() const;
|
|
|
|
/** Obtain the component of the specified type of the accessed entity.
|
|
*
|
|
* @tparam Component The type of component to obtain
|
|
* @return A reference to the component of the specified type
|
|
* @throw component_not_found_exception if the entity doesn't
|
|
* contain a component of this type
|
|
* @pre The accessor is valid
|
|
*/
|
|
template <typename Component>
|
|
Component & get();
|
|
|
|
template <typename Component>
|
|
Component const & get() const;
|
|
|
|
/** Obtain the component by uuid of the accessed entity.
|
|
* As the runtime type of the component is unknown,
|
|
* the function returns pointer-to-void.
|
|
*
|
|
* @param uuid The uuid of component to obtain
|
|
* @return A pointer to the component of the specified type, or a null
|
|
* pointer if the entity doesn't contain a component of this type
|
|
* @pre The accessor is valid
|
|
*/
|
|
void * get_if(util::uuid const & uuid);
|
|
|
|
void const * get_if(util::uuid const & uuid) const;
|
|
|
|
/** Check if the entity contains this component type.
|
|
*
|
|
* @tparam Component The type of component to obtain
|
|
* @return True if the entity contains a component of the specified
|
|
* type, false otherwise
|
|
* @pre The accessor is valid
|
|
*/
|
|
template <typename Component>
|
|
bool contains() const;
|
|
|
|
/** Check if the entity contains this component type by uuid.
|
|
*
|
|
* @param uuid The uuid of the component
|
|
* @return True if the entity contains a component with the specified
|
|
* uuid, false otherwise
|
|
* @pre The accessor is valid
|
|
*/
|
|
bool contains(util::uuid const & uuid) const;
|
|
|
|
private:
|
|
detail::table * table_ = nullptr;
|
|
std::uint32_t row_ = 0;
|
|
|
|
friend struct container;
|
|
|
|
accessor(detail::table * table, std::uint32_t row);
|
|
};
|
|
|
|
inline accessor::operator bool() const
|
|
{
|
|
return table_ != nullptr;
|
|
}
|
|
|
|
template <typename Component>
|
|
Component * accessor::get_if()
|
|
{
|
|
return const_cast<Component *>(static_cast<accessor const *>(this)->get_if<Component>());
|
|
}
|
|
|
|
template <typename Component>
|
|
Component const * accessor::get_if() const
|
|
{
|
|
util::uuid const uuid = std::remove_const_t<Component>::uuid();
|
|
return reinterpret_cast<Component const *>(get_if(uuid));
|
|
}
|
|
|
|
template <typename Component>
|
|
Component & accessor::get()
|
|
{
|
|
if (auto ptr = get_if<Component>())
|
|
return *ptr;
|
|
throw component_not_found_exception(typeid(std::remove_const_t<Component>), table_->entity_handles()[row_], table_->describe_short());
|
|
}
|
|
|
|
template <typename Component>
|
|
Component const & accessor::get() const
|
|
{
|
|
if (auto ptr = get_if<Component const>())
|
|
return *ptr;
|
|
throw component_not_found_exception(typeid(std::remove_const_t<Component>), table_->entity_handles()[row_], table_->describe_short());
|
|
}
|
|
|
|
inline void * accessor::get_if(util::uuid const & uuid)
|
|
{
|
|
return const_cast<void *>(static_cast<accessor const *>(this)->get_if(uuid));
|
|
}
|
|
|
|
inline void const * accessor::get_if(util::uuid const & uuid) const
|
|
{
|
|
auto column = table_->column(uuid);
|
|
if (!column)
|
|
return nullptr;
|
|
|
|
return column->data() + column->stride() * row_;
|
|
}
|
|
|
|
template <typename Component>
|
|
bool accessor::contains() const
|
|
{
|
|
return get_if<Component const>() != nullptr;
|
|
}
|
|
|
|
inline bool accessor::contains(util::uuid const & uuid) const
|
|
{
|
|
return table_->column_index(uuid) != std::nullopt;
|
|
}
|
|
|
|
inline accessor::accessor(detail::table * table, std::uint32_t row)
|
|
: table_(table)
|
|
, row_(row)
|
|
{}
|
|
|
|
}
|