From 8db283e734b7beae7f05d40998ad2dc76bc37df5 Mon Sep 17 00:00:00 2001 From: Nat Weiss Date: Sun, 1 May 2016 16:30:02 -0700 Subject: [PATCH] Entity is a namespace. Cid-based functions public instead of private. Faster due to less function call overhead. Simplified. --- EntityFu.cpp | 51 ++++--- EntityFu.h | 220 ++++++++++++++--------------- EntityFu.xcodeproj/project.pbxproj | 4 +- 3 files changed, 133 insertions(+), 142 deletions(-) diff --git a/EntityFu.cpp b/EntityFu.cpp index c077eab..4fba605 100644 --- a/EntityFu.cpp +++ b/EntityFu.cpp @@ -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 #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* Entity::componentEids = nullptr; +/// Static pointers to the ECS data. +static bool* entities = nullptr; +static Entity::Component*** components = nullptr; +static vector* 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() { @@ -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); } @@ -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) @@ -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); } @@ -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) @@ -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 { diff --git a/EntityFu.h b/EntityFu.h index 842559c..295f610 100644 --- a/EntityFu.h +++ b/EntityFu.h @@ -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& getAll(Cid cid); + unsigned count(Cid cid); + + /// Add the given component to the given entity. + /// Note that components must be allocated with new. + template inline static void addComponent(Eid eid, ComponentClass* c) + { + return Entity::addComponent(ComponentClass::cid, eid, c); + } + + /// Remove a component from an entity. + template 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 inline static ComponentClass& get(Eid eid) + { + auto p = static_cast(Entity::getComponent(ComponentClass::cid, eid)); + if (p != nullptr) + return *p; + static ComponentClass s; + return s; + } + + /// Get a pointer to a component. + template inline static ComponentClass* getPointer(Eid eid) + { + return static_cast(Entity::getComponent(ComponentClass::cid, eid)); + } + + /// Get a vector of all Eids for the given component class. + template inline static const std::vector& getAll() + { + return Entity::getAll(ComponentClass::cid); + } + + /// Count all the entities with the given component class. + template inline static unsigned count() + { + return Entity::count(ComponentClass::cid); + } + + /// A utility method for `Entity::create(...)`. + /// The final call to `addComponents`. + template 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 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 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 inline static void addComponent(Eid eid, ComponentClass* c) - { - return Entity::addComponent(ComponentClass::cid, eid, c); - } - - /// Remove a component from an entity. - template inline static void removeComponent(Eid eid) - { - return Entity::removeComponent(ComponentClass::cid, eid); - } - - /// Get a pointer to a component. - template inline static ComponentClass* getPointer(Eid eid) - { - return static_cast(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 inline static ComponentClass& get(Eid eid) - { - return Entity::ref(Entity::getPointer(eid)); - } - - /// Get a vector of all Eids for the given component class. - template inline static const std::vector& getAll() - { - return Entity::getAll(ComponentClass::cid); - } - - /// Count all the entities with the given component class. - template 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 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& 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* componentEids; - - /// Get a guaranteed reference to a component. - template static ComponentClass& ref(ComponentClass* p) - { - if (p != nullptr) - return *p; - static ComponentClass s; - return s; - } - - /// The variadic template version of `addComponents`. - template 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 static void addComponents(Eid eid, C* c) - { - Entity::addComponent(C::cid, eid, c); - } }; /// @@ -156,7 +142,7 @@ struct Entity::Component /// #define Entity__get(componentClass, eid, varName, orElseCode) \ auto& (varName) = Entity::get((eid)); \ - if ((varName).empty()) orElseCode; + if ((varName).empty()) orElseCode /// /// System diff --git a/EntityFu.xcodeproj/project.pbxproj b/EntityFu.xcodeproj/project.pbxproj index a8d5b18..e8074b1 100644 --- a/EntityFu.xcodeproj/project.pbxproj +++ b/EntityFu.xcodeproj/project.pbxproj @@ -89,7 +89,7 @@ 419BC9941B0EBA12007C6403 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = "Wizard Fu, Inc."; TargetAttributes = { 419BC99B1B0EBA12007C6403 = { @@ -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; @@ -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; };