Skip to content

Commit

Permalink
Entity is a namespace. Cid-based functions public instead of private.…
Browse files Browse the repository at this point in the history
… Faster due to less function call overhead. Simplified.
  • Loading branch information
NatWeiss committed May 1, 2016
1 parent 2895258 commit 8db283e
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 142 deletions.
51 changes: 29 additions & 22 deletions EntityFu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,41 @@ using namespace std;
/// Turn this on to have a faster yet riskier ECS.
#define kTrustPointers 0

/// Auto-define a log method.
/// Log macro.
#ifndef Log
#ifndef NDEBUG
#include <stdio.h>
#define Log(...) {printf(__VA_ARGS__); printf("\n");}
#else
#define Log(...) do {} while (0)
#endif
#endif

/// Auto-define an assert method.
/// Assert macro.
#ifndef Assert
#ifndef NDEBUG
#define Assert(condition, format, ...) {if(!condition) throw format;}
#else
#define Assert(...) do {} while (0)
#endif
#endif

/// Turn this to 1 or 2 to debug the ECS.
/// 1 == log creation, 2 == log creation and deletion.
static int verbosity = 0;

bool* Entity::entities = nullptr;
Entity::Component*** Entity::components = nullptr;
vector<Eid>* Entity::componentEids = nullptr;
/// Static pointers to the ECS data.
static bool* entities = nullptr;
static Entity::Component*** components = nullptr;
static vector<Eid>* componentEids = nullptr;

static void log(Cid cid)
{
auto n = Entity::count(cid);
auto& eids = Entity::getAll(cid);
if (eids.size() > 0)
{Log("Cid %u has %d entities ranging from %u to %u", cid, n, eids.front(), eids.back());}
}

void Entity::alloc()
{
Expand Down Expand Up @@ -138,7 +155,7 @@ void Entity::addComponent(Cid cid, Eid eid, Component* c)
if (verbosity > 0)
{
Log(" ");
Entity::log(cid);
log(cid);
Log("Adding component cid %u eid %u (%x)", cid, eid, (int)(long)c);
}

Expand All @@ -154,7 +171,7 @@ void Entity::addComponent(Cid cid, Eid eid, Component* c)
componentEids[cid].push_back(eid);

if (verbosity > 0)
Entity::log(cid);
log(cid);
}

void Entity::removeComponent(Cid cid, Eid eid)
Expand All @@ -173,7 +190,7 @@ void Entity::removeComponent(Cid cid, Eid eid)
if (verbosity > 1)
{
Log(" ");
Entity::log(cid);
log(cid);
Log("Removing component cid %u eid %u (%x)", cid, eid, (int)(long)ptr);
}

Expand All @@ -190,7 +207,7 @@ void Entity::removeComponent(Cid cid, Eid eid)
it = eids.erase(it);

if (verbosity > 1)
Entity::log(cid);
log(cid);
}

Entity::Component* Entity::getComponent(Cid cid, Eid eid)
Expand Down Expand Up @@ -237,19 +254,9 @@ bool Entity::exists(Eid eid)
return entities != nullptr && entities[eid];
}

void Entity::log(Cid cid)
{
auto n = Entity::count(cid);
auto& eids = Entity::getAll(cid);
if (eids.size() > 0)
{Log("Cid %u has %d entities ranging from %u to %u", cid, n, eids.front(), eids.back());}
}

void Entity::logAll()
{
for (Cid cid = 0, max = Component::numCids; cid < max; cid++)
Entity::log(cid);
}
//
// Entity::Component
//

bool Entity::Component::full() const
{
Expand Down
220 changes: 103 additions & 117 deletions EntityFu.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,124 +13,110 @@ typedef unsigned Eid;
/// A `Cid` is a component ID.
typedef unsigned Cid;

class Entity
namespace Entity
{
public:
struct Component;

/// The maximum number of entities. Increase this if you need more.
enum {kMaxEntities = 8192};

/// Allocate the memory for entities and components. Can call this manually or let it allocate automatically.
static void alloc();

/// Deallocate the memory for entities and components. Only do this when you no longer need the ECS.
static void dealloc();

/// Create an entity and return the `Eid`.
static Eid create();

/// Return a count of all entities.
static unsigned count();
struct Component;

/// The maximum number of entities. Increase this if you need more.
enum {kMaxEntities = 8192};

/// Allocate the memory for entities and components. Can call this manually or let it allocate automatically.
void alloc();

/// Deallocate the memory for entities and components. Only do this when you no longer need the ECS.
void dealloc();

/// Create an entity and return the `Eid`.
Eid create();

/// Return a count of all entities.
unsigned count();

/// Return true if the entity has been created.
bool exists(Eid eid);

/// Destroy an entity and all its components right now.
void destroyNow(Eid eid);

/// Destroy all entities and components right now.
void destroyAll();

/// Component-related methods that require a `Cid`.
/// The templated versions of these methods do not require a `Cid`, yet incur an extra function call of overhead.
void addComponent(Cid cid, Eid eid, Component* c);
void removeComponent(Cid cid, Eid eid);
Component* getComponent(Cid cid, Eid eid);
const std::vector<Eid>& getAll(Cid cid);
unsigned count(Cid cid);

/// Add the given component to the given entity.
/// Note that components must be allocated with new.
template<class ComponentClass> inline static void addComponent(Eid eid, ComponentClass* c)
{
return Entity::addComponent(ComponentClass::cid, eid, c);
}

/// Remove a component from an entity.
template<class ComponentClass> inline static void removeComponent(Eid eid)
{
return Entity::removeComponent(ComponentClass::cid, eid);
}

/// Get a reference to a component.
/// Warning, if the Eid does not exist a blank static component will be returned,
/// so be sure to check if it is empty before writing any data to it or else
/// the blank static component will no longer be empty and the Earth will implode.
template<class ComponentClass> inline static ComponentClass& get(Eid eid)
{
auto p = static_cast<ComponentClass*>(Entity::getComponent(ComponentClass::cid, eid));
if (p != nullptr)
return *p;
static ComponentClass s;
return s;
}

/// Get a pointer to a component.
template<class ComponentClass> inline static ComponentClass* getPointer(Eid eid)
{
return static_cast<ComponentClass*>(Entity::getComponent(ComponentClass::cid, eid));
}

/// Get a vector of all Eids for the given component class.
template<class ComponentClass> inline static const std::vector<Eid>& getAll()
{
return Entity::getAll(ComponentClass::cid);
}

/// Count all the entities with the given component class.
template<class ComponentClass> inline static unsigned count()
{
return Entity::count(ComponentClass::cid);
}

/// A utility method for `Entity::create(...)`.
/// The final call to `addComponents`.
template <class C> static void addComponents(Eid eid, C* c)
{
Entity::addComponent(C::cid, eid, c);
}

/// A utility method for `Entity::create(...)`.
/// The variadic template version of `addComponents`.
template <class C, typename ...Args> static void addComponents(Eid eid, C* c, Args... args)
{
Entity::addComponent(C::cid, eid, c);
Entity::addComponents(eid, args...);
}

/// Create an entity with some components.
/// Convenience method which calls `Entity::create()` and `Entity::addComponent`.
template <typename ...Args> static Eid create(Args... args)
{
auto eid = Entity::create();
Entity::addComponents(eid, args...);
return eid;
}

/// Return true if the entity has been created.
static bool exists(Eid eid);

/// Destroy an entity and all its components right now.
static void destroyNow(Eid eid);

/// Destroy all entities and components right now.
static void destroyAll();

/// Add the given component to the given entity.
/// Note that components must be allocated with new.
template<class ComponentClass> inline static void addComponent(Eid eid, ComponentClass* c)
{
return Entity::addComponent(ComponentClass::cid, eid, c);
}

/// Remove a component from an entity.
template<class ComponentClass> inline static void removeComponent(Eid eid)
{
return Entity::removeComponent(ComponentClass::cid, eid);
}

/// Get a pointer to a component.
template<class ComponentClass> inline static ComponentClass* getPointer(Eid eid)
{
return static_cast<ComponentClass*>(Entity::getComponent(ComponentClass::cid, eid));
}

/// Get a reference to a component.
/// Warning, if the Eid does not exist a blank static component will be returned,
/// so be sure to check if it is empty before writing any data to it or else
/// the blank static component will no longer be empty and the Earth will implode.
template<class ComponentClass> inline static ComponentClass& get(Eid eid)
{
return Entity::ref(Entity::getPointer<ComponentClass>(eid));
}

/// Get a vector of all Eids for the given component class.
template<class ComponentClass> inline static const std::vector<Eid>& getAll()
{
return Entity::getAll(ComponentClass::cid);
}

/// Count all the entities with the given component class.
template<class ComponentClass> inline static unsigned count()
{
return Entity::count(ComponentClass::cid);
}

/// Create an entity with some components.
/// Convenience method which calls `Entity::create()` and `Entity::addComponent`.
template <typename ...Args> static Eid create(Args... args)
{
auto eid = Entity::create();
Entity::addComponents(eid, args...);
return eid;
}

private:
/// Disallow construction. Entities are not classes!
Entity() {}
Entity(const Entity& rhs) {}
~Entity() {}
Entity& operator=(const Entity& rhs) {return *this;}

static void addComponent(Cid cid, Eid eid, Component* c);
static void removeComponent(Cid cid, Eid eid);
static Component* getComponent(Cid cid, Eid eid);
static const std::vector<Eid>& getAll(Cid cid);
static unsigned count(Cid cid);
static void log(Cid cid);
static void logAll();

static bool* entities;
static Component*** components;
static std::vector<Eid>* componentEids;

/// Get a guaranteed reference to a component.
template<class ComponentClass> static ComponentClass& ref(ComponentClass* p)
{
if (p != nullptr)
return *p;
static ComponentClass s;
return s;
}

/// The variadic template version of `addComponents`.
template <class C, typename ...Args> static void addComponents(Eid eid, C* c, Args... args)
{
Entity::addComponent(C::cid, eid, c);
Entity::addComponents(eid, args...);
}

/// The final call to `addComponents`.
template <class C> static void addComponents(Eid eid, C* c)
{
Entity::addComponent(C::cid, eid, c);
}
};

///
Expand All @@ -156,7 +142,7 @@ struct Entity::Component
///
#define Entity__get(componentClass, eid, varName, orElseCode) \
auto& (varName) = Entity::get<componentClass>((eid)); \
if ((varName).empty()) orElseCode;
if ((varName).empty()) orElseCode

///
/// System
Expand Down
4 changes: 1 addition & 3 deletions EntityFu.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
419BC9941B0EBA12007C6403 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0720;
LastUpgradeCheck = 0730;
ORGANIZATIONNAME = "Wizard Fu, Inc.";
TargetAttributes = {
419BC99B1B0EBA12007C6403 = {
Expand Down Expand Up @@ -160,7 +160,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
Expand Down Expand Up @@ -195,7 +194,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
Expand Down

0 comments on commit 8db283e

Please sign in to comment.