Created
May 20, 2018 02:08
-
-
Save veryjos/ae448fa48a12d1e0926375866c1ab407 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <memory> | |
#include <unordered_map> | |
#include <vector> | |
namespace tdrp { | |
// ComponentID's uniquely identify a Component | |
using ComponentID = int; | |
struct ComponentMeta { | |
const char* name = nullptr; | |
const ComponentID componentID = -1; | |
}; | |
/** | |
* Base class for each Component. | |
* | |
* Anything that wants to implement Component should derive from this class | |
* and also expand the COMPONENT_ENABLE inside the class before anything else | |
*/ | |
class Component { | |
public: | |
Component() {}; | |
virtual ~Component() {}; | |
virtual const ComponentMeta& GetComponentMeta() const = 0; | |
virtual ComponentID GetComponentID() const { | |
return GetComponentMeta().componentID; | |
}; | |
protected: | |
const ComponentMeta _2drp_com_meta; | |
protected: | |
static ComponentID AllocComponentID() { | |
static ComponentID componentIDCounter; | |
return componentIDCounter++; | |
}; | |
static ComponentMeta AllocComponentMeta(const char* name) { | |
return { | |
name, | |
AllocComponentID() | |
}; | |
}; | |
}; | |
/** | |
* ComponentEntity can hold any number of Components | |
*/ | |
class ComponentEntity { | |
public: | |
ComponentEntity() {}; | |
virtual ~ComponentEntity() {}; | |
/** | |
* Adds a component by template parameter. | |
* Accepts any number of arguments for the constructor.. | |
* | |
* @return true if success, false if fail | |
*/ | |
template <typename T, typename ...Args> | |
bool AddComponent(Args ...args) { | |
// Don't allow adding two of the same component | |
if (HasComponent<T>()) { | |
return false; | |
} | |
// Create and add the component | |
auto component = std::make_shared<T>(args...); | |
m_components[T::GetMeta().componentID] = std::move(component); | |
return true; | |
}; | |
template <typename T> | |
bool AddComponent() { | |
if (HasComponent<T>()) { | |
return false; | |
} | |
// Create and add the component | |
auto component = std::make_shared<T>(); | |
m_components[T::GetMeta().componentID] = std::move(component); | |
return true; | |
}; | |
/** | |
* Adds a component. | |
* | |
* @return true if success, false if fail | |
*/ | |
bool AddComponent(const std::shared_ptr<Component>& component) { | |
// Don't allow adding two of the same component | |
if (HasComponent(component->GetComponentMeta().componentID)) { | |
return false; | |
} | |
m_components[component->GetComponentMeta().componentID] = std::move(component); | |
return true; | |
}; | |
/** | |
* Checks if this entity has as specific component type by template parameter. | |
* | |
* @retunr true if yes, false if no | |
*/ | |
template <typename T> | |
bool HasComponent() { | |
return HasComponent(T::GetMeta().componentID); | |
}; | |
/** | |
* Checks if this entity has a specific component type | |
* | |
* @return true if yes, false if no | |
*/ | |
bool HasComponent(const ComponentID componentID) { | |
return m_components.find(componentID) != m_components.end(); | |
}; | |
/** | |
* Gets a component, if this ComponentEntity has it. | |
*/ | |
template <typename T> | |
std::weak_ptr<T> GetComponent() { | |
if (!HasComponent<T>()) { | |
return std::weak_ptr<T>(); | |
} | |
return std::weak_ptr(std::static_pointer_cast<T>(m_components[T::GetMeta().componentID])); | |
}; | |
private: | |
std::unordered_map<ComponentID, std::shared_ptr<Component>> m_components; | |
}; | |
} | |
#define COMPONENT_ENABLE(name) \ | |
private: \ | |
static inline ComponentMeta _2d_com_meta_ = tdrp::Component::AllocComponentMeta(#name); \ | |
public: \ | |
static const ComponentMeta& GetMeta() { \ | |
return _2d_com_meta_; \ | |
} \ | |
\ | |
const ComponentMeta& GetComponentMeta() const override { \ | |
return name::GetMeta(); \ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment