Skip to content

Commit

Permalink
Use C++20 concepts to constrain component-specific functions
Browse files Browse the repository at this point in the history
  • Loading branch information
iWas-Coder committed Oct 8, 2024
1 parent 700e96a commit 08ef7cb
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 16 deletions.
15 changes: 15 additions & 0 deletions src/Runtime/BehaviourComponent.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "BehaviourComponent.hh"

namespace volt::runtime {
BehaviourComponent::BehaviourComponent(std::unique_ptr<IBehaviour> &&b)
: behaviour{std::move(b)}
{}

void BehaviourComponent::Serialize(YAML::Emitter &) {}

bool BehaviourComponent::Deserialize(YAML::Node &) {
return false;
}

void BehaviourComponent::Draw(void) {}
}
10 changes: 8 additions & 2 deletions src/Runtime/BehaviourComponent.hh
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
#pragma once

#include <memory>
#include "IComponent.hh"
#include "IBehaviour.hh"
#include "../Core/LogSystem.hh"

namespace volt::runtime {
template <typename T>
template <IBehaviour_t T>
inline constexpr std::unique_ptr<T> Instantiate(void) {
auto ptr { std::make_unique<T>() };
// NOTE: `typeid(T).name()` is mangled
VOLT_LOG_INFO("Behaviour instantiated [{}|{}]", fmt::ptr(ptr.get()), typeid(T).name());
return ptr;
}

struct BehaviourComponent {
struct BehaviourComponent : public IComponent {
std::unique_ptr<IBehaviour> behaviour { nullptr };
BehaviourComponent(std::unique_ptr<IBehaviour> &&b);
void Serialize(YAML::Emitter &) final;
bool Deserialize(YAML::Node &) final;
void Draw(void) final;
};
}
5 changes: 5 additions & 0 deletions src/Runtime/IBehaviour.hh
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#pragma once

#include <type_traits>

namespace volt::runtime {
class Entity;

struct IBehaviour {
virtual ~IBehaviour(void) = default;
virtual void Update(Entity &e) = 0;
};

template <typename T>
concept IBehaviour_t = std::is_base_of<IBehaviour, T>::value;
}
5 changes: 5 additions & 0 deletions src/Runtime/IComponent.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <type_traits>

namespace YAML {
class Emitter;
class Node;
Expand All @@ -12,4 +14,7 @@ namespace volt::runtime {
virtual bool Deserialize(YAML::Node &in) = 0;
virtual void Draw(void) = 0;
};

template <typename T>
concept IComponent_t = std::is_base_of<IComponent, T>::value;
}
15 changes: 15 additions & 0 deletions src/Runtime/IDComponent.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "IDComponent.hh"

namespace volt::runtime {
IDComponent::IDComponent(core::SnowflakeID i)
: id{i}
{}

void IDComponent::Serialize(YAML::Emitter &) {}

bool IDComponent::Deserialize(YAML::Node &) {
return false;
}

void IDComponent::Draw(void) {}
}
7 changes: 6 additions & 1 deletion src/Runtime/IDComponent.hh
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#pragma once

#include "IComponent.hh"
#include "../Core/SnowflakeID.hh"

namespace volt::runtime {
struct IDComponent {
struct IDComponent : public IComponent {
core::SnowflakeID id;
IDComponent(core::SnowflakeID i);
void Serialize(YAML::Emitter &) final;
bool Deserialize(YAML::Node &) final;
void Draw(void) final;
};
}
3 changes: 1 addition & 2 deletions src/Runtime/Scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ namespace volt::runtime {
Entity Scene::CreateEntity(core::SnowflakeID id, const std::string &name) {
Entity e { m_registry.create(), this };
e.AddComponent<IDComponent>(id);
auto &t { e.AddComponent<TagComponent>() };
t.tag = name.empty() ? "Entity" : name;
e.AddComponent<TagComponent>(name.empty() ? "Entity" : name);
e.AddComponent<TransformComponent>();
m_ids[id] = e;
VOLT_LOG_INFO("Scene: Entity created [{}|{}]", static_cast<core::SnowflakeID::value_type>(id), name);
Expand Down
20 changes: 10 additions & 10 deletions src/Runtime/Scene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ namespace volt::runtime {
Entity(EID id, Scene *scene);
inline const std::string &GetName(void) { return GetComponent<TagComponent>().tag; }
inline core::SnowflakeID::value_type GetID(void) { return static_cast<core::SnowflakeID::value_type>(GetComponent<IDComponent>().id); }
template <typename T>
template <IComponent_t T>
bool HasComponent(void) const;
template <typename T, typename... Args>
template <IComponent_t T, typename... Args>
T &AddComponent(Args &&... args);
template <typename T>
template <IComponent_t T>
void RemoveComponent(void);
template <typename T>
template <IComponent_t T>
T &GetComponent(void) const;
template <typename T>
template <IComponent_t T>
T *TryGetComponent(void) const;
inline operator EID(void) const noexcept { return m_id; }
};
Expand Down Expand Up @@ -64,30 +64,30 @@ namespace volt::runtime {
inline void SetName(const std::string &name) { m_name = name; }
};

template <typename T>
template <IComponent_t T>
inline bool Entity::HasComponent(void) const {
return m_scene->m_registry.any_of<T>(m_id);
}

template <typename T, typename... Args>
template <IComponent_t T, typename... Args>
inline T &Entity::AddComponent(Args &&... args) {
assert(not HasComponent<T>());
return m_scene->m_registry.emplace<T>(m_id, std::forward<Args>(args)...);
}

template <typename T>
template <IComponent_t T>
inline void Entity::RemoveComponent(void) {
assert(HasComponent<T>());
m_scene->m_registry.remove<T>(m_id);
}

template <typename T>
template <IComponent_t T>
inline T &Entity::GetComponent(void) const {
assert(HasComponent<T>());
return m_scene->m_registry.get<T>(m_id);
}

template <typename T>
template <IComponent_t T>
inline T *Entity::TryGetComponent(void) const {
if (not HasComponent<T>()) return nullptr;
return &GetComponent<T>();
Expand Down
15 changes: 15 additions & 0 deletions src/Runtime/TagComponent.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "TagComponent.hh"

namespace volt::runtime {
TagComponent::TagComponent(const std::string &t)
: tag{t}
{}

void TagComponent::Serialize(YAML::Emitter &) {}

bool TagComponent::Deserialize(YAML::Node &) {
return false;
}

void TagComponent::Draw(void) {}
}
7 changes: 6 additions & 1 deletion src/Runtime/TagComponent.hh
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#pragma once

#include <string>
#include "IComponent.hh"

namespace volt::runtime {
struct TagComponent {
struct TagComponent : public IComponent {
std::string tag;
TagComponent(const std::string &t);
void Serialize(YAML::Emitter &) final;
bool Deserialize(YAML::Node &) final;
void Draw(void) final;
};
}

0 comments on commit 08ef7cb

Please sign in to comment.