Skip to content

Commit

Permalink
Redesign entity-component system
Browse files Browse the repository at this point in the history
  • Loading branch information
mogemimi committed Dec 3, 2019
1 parent d44a00d commit 8e3ff47
Show file tree
Hide file tree
Showing 17 changed files with 954 additions and 1,525 deletions.
6 changes: 2 additions & 4 deletions build/pomdog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,12 @@ set(POMDOG_SOURCES_CORE
)

set(POMDOG_SOURCES_EXPERIMENTAL_ECS
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/Component.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/ComponentBuffer.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/ComponentType.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/Entity.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/EntityContext.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/EntityID.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/EntityManager.hpp
${POMDOG_DIR}/include/Pomdog/Experimental/ECS/ComponentTypeIndex.hpp
${POMDOG_DIR}/src/Experimental/ECS/Entity.cpp
${POMDOG_DIR}/src/Experimental/ECS/EntityContext.cpp
${POMDOG_DIR}/src/Experimental/ECS/EntityManager.cpp
${POMDOG_DIR}/src/Experimental/ECS/ComponentTypeIndex.cpp
)
Expand Down
41 changes: 0 additions & 41 deletions include/Pomdog/Experimental/ECS/Component.hpp

This file was deleted.

52 changes: 52 additions & 0 deletions include/Pomdog/Experimental/ECS/ComponentBuffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2013-2019 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Utility/Assert.hpp"
#include <cstddef>
#include <cstdint>
#include <vector>

namespace Pomdog::ECS::Detail {

class ComponentBufferBase {
public:
virtual ~ComponentBufferBase() = default;

[[nodiscard]] virtual std::size_t GetSize() const noexcept = 0;

virtual void Resize(std::size_t size) = 0;

virtual void Reset(std::uint32_t index) = 0;
};

template <typename TComponent>
class ComponentBuffer final : public ComponentBufferBase {
public:
std::size_t GetSize() const noexcept override
{
return components.size();
}

void Resize(std::size_t size) override
{
components.resize(size);
}

void Reset(std::uint32_t index) override
{
POMDOG_ASSERT(index < components.size());
components[index] = TComponent{};
}

[[nodiscard]] TComponent* GetComponent(std::uint32_t index)
{
POMDOG_ASSERT(index < components.size());
return &components[index];
}

private:
std::vector<TComponent> components;
};

} // namespace Pomdog::ECS::Detail
52 changes: 52 additions & 0 deletions include/Pomdog/Experimental/ECS/ComponentType.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2013-2019 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Experimental/ECS/ComponentBuffer.hpp"
#include "Pomdog/Experimental/ECS/ComponentTypeIndex.hpp"
#include <cstdint>
#include <memory>
#include <string>

namespace Pomdog::ECS {

class ComponentTypeBase {
public:
virtual ~ComponentTypeBase() = default;

[[nodiscard]] virtual std::uint8_t
GetTypeIndex() const noexcept = 0;

[[nodiscard]] virtual std::unique_ptr<Detail::ComponentBufferBase>
CreateComponentBuffer() const = 0;
};

template <typename TComponent>
struct ComponentTypeDeclaration final {
static std::uint8_t GetTypeIndex()
{
return Detail::ComponentTypeIndex::Index<TComponent>();
}
};

template <typename T>
class ComponentType final : public ComponentTypeBase {
public:
std::uint8_t GetTypeIndex() const noexcept override
{
return ComponentTypeDeclaration<T>::GetTypeIndex();
}

std::unique_ptr<Detail::ComponentBufferBase> CreateComponentBuffer() const override
{
return std::make_unique<Detail::ComponentBuffer<T>>();
}
};

template <class TComponent, typename... Args>
inline std::shared_ptr<ComponentTypeBase> AddComponent(Args &&... args)
{
return std::make_shared<ComponentType<TComponent>>(std::forward<Args>(args)...);
}

} // namespace Pomdog::ECS
10 changes: 3 additions & 7 deletions include/Pomdog/Experimental/ECS/ComponentTypeIndex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
#include <limits>
#include <type_traits>

namespace Pomdog {
namespace Detail {
namespace Gameplay {
namespace Pomdog::ECS::Detail {

class ComponentTypeIndex {
public:
typedef std::uint8_t IndexType;
using IndexType = std::uint8_t;

template <class TComponent>
static IndexType Index()
Expand All @@ -31,6 +29,4 @@ class ComponentTypeIndex {
static IndexType count;
};

} // namespace Gameplay
} // namespace Detail
} // namespace Pomdog
} // namespace Pomdog::ECS::Detail
112 changes: 52 additions & 60 deletions include/Pomdog/Experimental/ECS/Entity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,66 @@

#pragma once

#include "Pomdog/Experimental/ECS/EntityContext.hpp"
#include "Pomdog/Experimental/ECS/EntityID.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include <algorithm>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <utility>
#include <functional>

namespace Pomdog {
namespace Pomdog::ECS {

class Entity final {
public:
Entity() = default;
constexpr Entity() noexcept
: id(0)
{
}

constexpr Entity(std::uint32_t sequenceNumber, std::uint32_t index) noexcept
: id((static_cast<std::uint64_t>(sequenceNumber) << 32) | (index & 0xffffffffUL))
{
}

[[nodiscard]] std::uint32_t GetVersion() const noexcept
{
return id >> 32;
}

[[nodiscard]] std::uint32_t GetIndex() const noexcept
{
return id & 0xffffffffUL;
}

[[nodiscard]] std::uint64_t GetUInt64Value() const noexcept
{
return id;
}

[[nodiscard]] bool operator==(const Entity& other) const noexcept
{
return id == other.id;
}

[[nodiscard]] bool operator!=(const Entity& other) const noexcept
{
return id != other.id;
}

[[nodiscard]] bool operator<(const Entity& other) const noexcept
{
return id < other.id;
}

static const Entity Null;

Entity(EntityContext* context, const EntityID& id) noexcept;

explicit operator bool() const noexcept;

bool operator==(const Entity& entity) const noexcept;
bool operator!=(const Entity& entity) const noexcept;

EntityID GetID() const noexcept;

template <typename T>
std::shared_ptr<T> GetComponent() const;

template <typename T>
std::shared_ptr<T> GetComponent();

template <typename T>
bool HasComponent() const;
private:
std::uint64_t id;
};

void Destroy();
} // namespace Pomdog::ECS

void DestroyImmediate();
namespace std {

private:
// NOTE: This pointer should be weak or raw pointer instead of shared_ptr.
EntityContext* context = nullptr;
EntityID id;
template <>
struct hash<Pomdog::ECS::Entity> {
std::size_t operator()(const Pomdog::ECS::Entity& key) const noexcept;
};

template <typename T>
std::shared_ptr<T> Entity::GetComponent() const
{
static_assert(std::is_base_of<Component, T>::value, "");
POMDOG_ASSERT(context != nullptr);
POMDOG_ASSERT(context->Valid(id));
return context->GetComponent<T>(id);
}

template <typename T>
std::shared_ptr<T> Entity::GetComponent()
{
static_assert(std::is_base_of<Component, T>::value, "");
POMDOG_ASSERT(context != nullptr);
POMDOG_ASSERT(context->Valid(id));
return context->GetComponent<T>(id);
}

template <typename T>
bool Entity::HasComponent() const
{
static_assert(std::is_base_of<Component, T>::value, "");
POMDOG_ASSERT(context != nullptr);
POMDOG_ASSERT(context->Valid(id));
return context->HasComponent<T>(id);
}

} // namespace Pomdog
} // namespace std
Loading

0 comments on commit 8e3ff47

Please sign in to comment.