
19 changed files with 33 additions and 1325 deletions
Binary file not shown.
@ -1,95 +0,0 @@ |
|||
#ifndef COMPONENT_CPP |
|||
#define COMPONENT_CPP |
|||
|
|||
#include <iostream> |
|||
|
|||
#include "Component.hpp" |
|||
#include "ObjectType.hpp" |
|||
#include "Object.hpp" |
|||
|
|||
Component::Component() |
|||
{ |
|||
|
|||
} |
|||
|
|||
Component::~Component() |
|||
{ |
|||
|
|||
} |
|||
|
|||
ComponentType Component::getType() |
|||
{ |
|||
return type; |
|||
} |
|||
ObjectType Component::getOwnerType() |
|||
{ |
|||
return ownerType; |
|||
} |
|||
ObjectID Component::getOwnerID() |
|||
{ |
|||
return ownerID; |
|||
} |
|||
|
|||
// This function should NEVER return NULL on a valid initialized Component.
|
|||
// This function is used by ComponentManagers when moving Components in memory
|
|||
// Make SURE you set your parentObject pointer in initialize()!
|
|||
Object* Component::getParentObject() |
|||
{ |
|||
return parentObject; |
|||
} |
|||
|
|||
// Initialize the component. Components should be able to be reused after initialize is called.
|
|||
// Components should store their parent object's address for later use
|
|||
// Return false if initialization failed for any reason, and the object creation will
|
|||
// be aborted
|
|||
bool Component::initialize(Object* newParentObject) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// Once all sibling components in an object have been initialize, postInitialize is executed.
|
|||
// Use this function to find all sibling components that your component is dependent on, as well
|
|||
// as any component-component initialization communication that might need to happen.
|
|||
bool Component::postInitialize() |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
// The parent Object has been scheduled to be destroyed. preDestroy() is called on every component
|
|||
// before components are actually destroyed. This is the "last supper" for components. Use
|
|||
// this time to do any component-component destruction communication
|
|||
void Component::preDestroy() |
|||
{ |
|||
|
|||
} |
|||
|
|||
// The parent Object is being destroyed. Perform any destruction necessary here. It is up to
|
|||
// you to decide what is destroyed in destroy() and what is cleared in initialize().
|
|||
void Component::destroy() |
|||
{ |
|||
|
|||
} |
|||
|
|||
// Perform all logic for your component here
|
|||
void Component::update(ComponentUpdateParams& updateParams) |
|||
{ |
|||
|
|||
} |
|||
|
|||
// Output or render as much helpful information as you can about your component in this
|
|||
// function.
|
|||
void Component::debugPrint() |
|||
{ |
|||
std::cout << "WARNING: Undefined debugPrint for component of type " << (int)type << "\n"; |
|||
} |
|||
|
|||
// Copy all data needed to make an exact replica of the current component to the
|
|||
// new component. This function will be used when an entire Object or Component is moved.
|
|||
// Return false if there was an error copying (or it is impossible to copy)
|
|||
// The new component has already been initialized, but not postInitialized (should it be?)
|
|||
// You should NOT set the current Component's parentObject pointer to the newComponent's
|
|||
bool Component::copyComponent(Object* newParentObject, Component* newComponent) |
|||
{ |
|||
return false; |
|||
} |
|||
#endif |
@ -1,89 +0,0 @@ |
|||
#ifndef COMPONENT_HPP |
|||
#define COMPONENT_HPP |
|||
|
|||
#include "ObjectID.hpp" |
|||
#include "ObjectType.hpp" |
|||
|
|||
/* --Component--
|
|||
* Components are modular bits of logic and data designed to work with other |
|||
* modular components. Objects are collections of components. Component is an abstract |
|||
* class. |
|||
*/ |
|||
enum ComponentType; |
|||
struct ComponentUpdateParams; |
|||
class Object; |
|||
class ComponentManager; |
|||
class Component |
|||
{ |
|||
public: |
|||
Component(); |
|||
|
|||
// Note that the constructor and destructor shouldn't have to be executed
|
|||
// every time a Component is created. Initialize and Deinitalize should do everything
|
|||
// necessary for a component to be reused
|
|||
virtual ~Component(); |
|||
|
|||
// Getters for types
|
|||
ComponentType getType(); |
|||
ObjectType getOwnerType(); |
|||
ObjectID getOwnerID(); |
|||
|
|||
// This function should NEVER return NULL on a valid initialized Component.
|
|||
// This function is used by ComponentManagers when moving Components in memory
|
|||
// Make SURE you set your parentObject pointer in initialize()!
|
|||
Object* getParentObject(); |
|||
|
|||
// Initialize the component. Components should be able to be reused after initialize is called.
|
|||
// Components should store their parent object's address for later use
|
|||
// Return false if initialization failed for any reason, and the object creation will
|
|||
// be aborted
|
|||
virtual bool initialize(Object* newParentObject); |
|||
|
|||
// Once all sibling components in an object have been initialize, postInitialize is executed.
|
|||
// Use this function to find all sibling components that your component is dependent on, as well
|
|||
// as any component-component initialization communication that might need to happen.
|
|||
virtual bool postInitialize(); |
|||
|
|||
// The parent Object has been scheduled to be destroyed. preDestroy() is called on every component
|
|||
// before components are actually destroyed. This is the "last supper" for components. Use
|
|||
// this time to do any component-component destruction communication
|
|||
virtual void preDestroy(); |
|||
|
|||
// The parent Object is being destroyed. Perform any destruction necessary here. It is up to
|
|||
// you to decide what is destroyed in destroy() and what is cleared in initialize().
|
|||
virtual void destroy(); |
|||
|
|||
// Perform all logic for your component here
|
|||
virtual void update(ComponentUpdateParams& updateParams); |
|||
|
|||
// Output or render as much helpful information as you can about your component in this
|
|||
// function.
|
|||
virtual void debugPrint(); |
|||
|
|||
// Copy all data needed to make an exact replica of the current component to the
|
|||
// new component. This function will be used when an entire Object or Component is moved.
|
|||
// Return false if there was an error copying (or it is impossible to copy)
|
|||
// The new component has already been initialized, but not postInitialized (should it be?)
|
|||
// You should NOT set the current Component's parentObject pointer to the newComponent's
|
|||
virtual bool copyComponent(Object* newParentObject, Component* newComponent); |
|||
|
|||
// TODO: Component save and load functions
|
|||
//virtual bool save(SaveBuffer *saveBuffer);
|
|||
//virtual bool load(LoadBuffer *loadBuffer);
|
|||
|
|||
// This value can be used by the ComponentManager to find a component
|
|||
// in a Pool, array, list, etc
|
|||
int localID; |
|||
protected: |
|||
|
|||
// The parent object of this component. This value should always be
|
|||
// valid and set as the ComponentManager will use it
|
|||
Object* parentObject; |
|||
|
|||
ComponentType type; |
|||
private: |
|||
ObjectType ownerType; |
|||
ObjectID ownerID; |
|||
}; |
|||
|
|||
#endif // COMPONENT_HPP
|
@ -1,54 +0,0 @@ |
|||
#ifndef COMPONENTMANAGER_CPP |
|||
#define COMPONENTMANAGER_CPP |
|||
|
|||
#include "ComponentManager.hpp" |
|||
|
|||
ComponentType ComponentManager::getType() |
|||
{ |
|||
return type; |
|||
} |
|||
|
|||
ComponentManager::ComponentManager() |
|||
{ |
|||
|
|||
} |
|||
|
|||
ComponentManager::~ComponentManager() |
|||
{ |
|||
|
|||
} |
|||
|
|||
// Initialize the ComponentManager. The manager should work without
|
|||
// the constructor having been run before
|
|||
bool ComponentManager::initialize() |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
// Do any destruction necessary for this manager.
|
|||
void ComponentManager::destroy() |
|||
{ |
|||
|
|||
} |
|||
|
|||
// Update all of the active Components, passing them the ComponentUpdateParams
|
|||
void ComponentManager::updateAllComponents(ComponentUpdateParams& componentUpdateParams) |
|||
{ |
|||
|
|||
} |
|||
|
|||
// Return a pointer to a fresh Component. Do not run initialize() or
|
|||
// anything on the component - this function's caller should handle that.
|
|||
// Return NULL if the request cannot be completed (e.g., the pool is full)
|
|||
Component* ComponentManager::getNewRawComponent() |
|||
{ |
|||
return nullptr; |
|||
} |
|||
|
|||
// Run destroy() on the Component and remove the component from this manager's memory.
|
|||
void ComponentManager::destroyComponent(Component* component) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endif |
@ -1,46 +0,0 @@ |
|||
#ifndef COMPONENTMANAGER_HPP |
|||
#define COMPONENTMANAGER_HPP |
|||
|
|||
#include "ComponentTypes.hpp" |
|||
|
|||
/* --ComponentManager--
|
|||
* ComponentManagers handle the storage, creation, and updating of a single |
|||
* type of Component. ComponentManager is a polymorphic class so that |
|||
* unique behaviors can be determined for all of these functions. |
|||
* */ |
|||
|
|||
class Object; |
|||
class Component; |
|||
struct ComponentUpdateParams; |
|||
class ComponentManager |
|||
{ |
|||
public: |
|||
ComponentManager(); |
|||
|
|||
virtual ~ComponentManager(); |
|||
|
|||
ComponentType getType(); |
|||
|
|||
// Initialize the ComponentManager. The manager should work without
|
|||
// the constructor having been run before
|
|||
virtual bool initialize(); |
|||
|
|||
// Do any destruction necessary for this manager.
|
|||
virtual void destroy(); |
|||
|
|||
// Update all of the active Components, passing them the ComponentUpdateParams
|
|||
virtual void updateAllComponents(ComponentUpdateParams& componentUpdateParams); |
|||
|
|||
// Return a pointer to a fresh Component. Do not run initialize() or
|
|||
// anything on the component - this function's caller should handle that.
|
|||
// Return NULL if the request cannot be completed (e.g., the pool is full)
|
|||
virtual Component* getNewRawComponent(); |
|||
|
|||
// Run destroy() on the Component and remove the component from this manager's memory.
|
|||
virtual void destroyComponent(Component* component); |
|||
|
|||
private: |
|||
ComponentType type; |
|||
}; |
|||
#endif |
|||
|
@ -1,10 +0,0 @@ |
|||
#ifndef COMPONENTTYPES_HPP |
|||
#define COMPONENTTYPES_HPP |
|||
|
|||
enum class ComponentType : int |
|||
{ |
|||
NONE = 0, |
|||
TEST |
|||
}; |
|||
|
|||
#endif |
@ -1,169 +0,0 @@ |
|||
#ifndef OBJECT_CPP |
|||
#define OBJECT_CPP |
|||
|
|||
#include <assert.h> |
|||
|
|||
#include "Object.hpp" |
|||
#include "Component.hpp" |
|||
|
|||
const int COMPONENTHANDLE_NULL = -1; |
|||
|
|||
|
|||
Object::Object() |
|||
{ |
|||
initialize(); |
|||
} |
|||
|
|||
Object::~Object() |
|||
{ |
|||
|
|||
} |
|||
|
|||
void Object::initialize() |
|||
{ |
|||
shouldDestroy = false; |
|||
numActiveComponents = 0; |
|||
id = OBJECT_ID_NONE; |
|||
type = nullptr; |
|||
} |
|||
|
|||
ObjectID Object::getObjectID() |
|||
{ |
|||
return id; |
|||
} |
|||
|
|||
// Provides a layer of abstraction around the internal storage of Component pointers
|
|||
Component* Object::getComponentAtIndex(int i) |
|||
{ |
|||
if (i >= 0 && i < numActiveComponents) |
|||
return components[i]; |
|||
return nullptr; |
|||
} |
|||
|
|||
// Searches through components this object is composed of for one of
|
|||
// the provided type. Returns a handle
|
|||
// Returns a ComponentHandle which can be used to get a pointer to
|
|||
// a component of the requested type.
|
|||
Object::ComponentHandle Object::getComponentHandleForType(ComponentType componentType) |
|||
{ |
|||
for (int i = 0; i < numActiveComponents; i++) |
|||
{ |
|||
Component* currentComponent = getComponentAtIndex(i); |
|||
|
|||
if (currentComponent) |
|||
{ |
|||
if (currentComponent->getType() == componentType) |
|||
return i; |
|||
} |
|||
} |
|||
|
|||
return COMPONENTHANDLE_NULL; |
|||
} |
|||
|
|||
// Returns true if the ComponentHandle is valid, and points to a valid
|
|||
// Component.
|
|||
bool Object::isValidComponentHandle(ComponentHandle componentHandle) |
|||
{ |
|||
if (componentHandle == Object::COMPONENTHANDLE_NULL |
|||
|| componentHandle >= numActiveComponents) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
// Returns a pointer to the component indicated by the handle.
|
|||
// This pointer should NOT be stored on the heap! Components can
|
|||
// move around in memory, so storing direct pointers is not ok!
|
|||
Component* Object::getComponent(Object::ComponentHandle componentHandle) |
|||
{ |
|||
if (isValidComponentHandle(componentHandle)) |
|||
return getComponentAtIndex(componentHandle); |
|||
return nullptr; |
|||
} |
|||
|
|||
// Returns the value of shouldDestroy. If true, whatever is managing
|
|||
// the object should notify all components of the impending destruction,
|
|||
// destroy the components, then destroy the object
|
|||
bool Object::shouldDestroyObject() |
|||
{ |
|||
return shouldDestroy; |
|||
} |
|||
|
|||
// Sets the value of shouldDestroy to true. Once set, it cannot be
|
|||
// undone. The actual destruction should be handled by the object's
|
|||
// manager after checking shouldDestroyObject()
|
|||
// This function is meant to be used by the object's components to self-destruct
|
|||
// Destruction will not happen immediately - it is up to the object's manager
|
|||
void Object::requestObjectDestruction() |
|||
{ |
|||
shouldDestroy = true; |
|||
} |
|||
|
|||
void Object::setObjectID(ObjectID newObjectID) |
|||
{ |
|||
id = newObjectID; |
|||
} |
|||
|
|||
void Object::setObjectType(ObjectType* newObjectType) |
|||
{ |
|||
type = newObjectType; |
|||
} |
|||
|
|||
void Object::addComponent(Component* newComponent) |
|||
{ |
|||
if (numActiveComponents < OBJECT_MAX_COMPONENTS) |
|||
{ |
|||
components[numActiveComponents] = newComponent; |
|||
numActiveComponents++; |
|||
} |
|||
else |
|||
{ |
|||
// Tried to add more than OBJECT_MAX_COMPONENTS
|
|||
assert(0); |
|||
} |
|||
} |
|||
|
|||
int Object::getNumActiveComponents() |
|||
{ |
|||
return numActiveComponents; |
|||
} |
|||
|
|||
// Run postInitialize on all components
|
|||
bool Object::postInitializeComponents() |
|||
{ |
|||
// For each active component
|
|||
for (int i = 0; i < numActiveComponents; i++) |
|||
{ |
|||
Component* currentComponent = getComponentAtIndex(i); |
|||
|
|||
if (currentComponent) |
|||
{ |
|||
// Run postInitialize on the component
|
|||
if (!currentComponent->postInitialize()) |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
// Run preDestroy on all components
|
|||
void Object::preDestroyComponents() |
|||
{ |
|||
// For each active component
|
|||
for (int i = 0; i < numActiveComponents; i++) |
|||
{ |
|||
Component* currentComponent = getComponentAtIndex(i); |
|||
|
|||
if (currentComponent) |
|||
{ |
|||
currentComponent->preDestroy(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Resets components[] by changing numActiveComponents to 0; this is
|
|||
// only used if a partially initialized Object's component failed to initialize
|
|||
void Object::resetComponentsArray() |
|||
{ |
|||
numActiveComponents = 0; |
|||
} |
|||
#endif |
@ -1,113 +0,0 @@ |
|||
#ifndef OBJECT_HPP |
|||
#define OBJECT_HPP |
|||
|
|||
#include "ObjectID.hpp" |
|||
#include "ObjectType.hpp" |
|||
#include "ComponentTypes.hpp" |
|||
|
|||
/* --Object--
|
|||
* Objects hold a collection of Components. Object provides an abstraction |
|||
* layer for Components so that components can be moved in memory without |
|||
* affecting other Components. |
|||
* |
|||
* Note that Objects cannot hold more than one Component of the same type. |
|||
* If this is required for some reason, you should redesign the system, or |
|||
* make the component support it internally |
|||
*/ |
|||
class Component; |
|||
struct ObjectType; |
|||
class ObjectComponentManager; |
|||
class Object |
|||
{ |
|||
public: |
|||
Object(); |
|||
~Object(); |
|||
|
|||
// Initialize the object
|
|||
// Objects should work completely after initialize, even if the constructor isn't called
|
|||
void initialize(); |
|||
|
|||
ObjectID getObjectID(); |
|||
|
|||
// A handle to a Component this Object has
|
|||
// Components (and all other external users of an Object's components) should
|
|||
// NEVER store pointers to an Object's components on anything other than
|
|||
// the stack. ComponentHandles, however, are safe to store. This is so
|
|||
// that Components can be moved around in memory without breaking references
|
|||
typedef int ComponentHandle; |
|||
|
|||
// Searches through components this object is composed of for one of
|
|||
// the provided type.
|
|||
// Returns a ComponentHandle which can be used to get a pointer to
|
|||
// a component of the requested type.
|
|||
// Note that Objects can only have one Component of the same type
|
|||
// Check your ComponentHandle's validity with isValidComponentHandle()
|
|||
ComponentHandle getComponentHandleForType(ComponentType componentType); |
|||
|
|||
// Returns true if the ComponentHandle is valid, and points to a valid
|
|||
// Component.
|
|||
bool isValidComponentHandle(ComponentHandle componentHandle); |
|||
|
|||
// Returns a pointer to the component indicated by the handle.
|
|||
// This pointer should NOT be stored on the heap! Components can
|
|||
// move around in memory, so storing direct pointers is not ok!
|
|||
// Note that getComponent() checks the validity of the ComponentHandle
|
|||
// Returns nullptr if the Handle is invalid
|
|||
Component* getComponent(ComponentHandle componentHandle); |
|||
|
|||
// Returns the value of shouldDestroy. If true, whatever is managing
|
|||
// the object should notify all components of the impending destruction,
|
|||
// destroy the components, then destroy the object
|
|||
bool shouldDestroyObject(); |
|||
|
|||
// Sets the value of shouldDestroy to true. Once set, it cannot be
|
|||
// undone. The actual destruction should be handled by the object's
|
|||
// manager after checking shouldDestroyObject()
|
|||
// This function is meant to be used by the object's components to self-destruct
|
|||
// Destruction will not happen immediately - it is up to the object's manager
|
|||
void requestObjectDestruction(); |
|||
|
|||
friend class ObjectComponentManager; |
|||
protected: |
|||
// Functions for ObjectComponentManager
|
|||
void setObjectID(ObjectID newObjectID); |
|||
void setObjectType(ObjectType* newObjectType); |
|||
|
|||
// Add a new, initialized component to this object
|
|||
void addComponent(Component* newComponent); |
|||
|
|||
// Run postInitialize on all components
|
|||
bool postInitializeComponents(); |
|||
|
|||
// Run preDestroy on all components
|
|||
void preDestroyComponents(); |
|||
|
|||
int getNumActiveComponents(); |
|||
|
|||
// Provides a layer of abstraction around the internal storage of Component pointers
|
|||
Component* getComponentAtIndex(int i); |
|||
|
|||
// Resets components[] by changing numActiveComponents to 0; this is
|
|||
// only used if a partially initialized Object's component failed to initialize
|
|||
void resetComponentsArray(); |
|||
|
|||
private: |
|||
// A list of pointers to Components the Object currently has (up to numActiveComponents)
|
|||
// OBJECT_MAX_COMPONENTS is defined in ObjectType.hpp
|
|||
Component* components[OBJECT_MAX_COMPONENTS]; |
|||
int numActiveComponents; |
|||
|
|||
ObjectType* type; |
|||
ObjectID id; |
|||
|
|||
// shouldDestroy indicates whether or not the Object should be
|
|||
// destroyed. This is meant to be used by Components to self-destruct.
|
|||
// shouldDestroy should be checked by whatever is managing
|
|||
// the object after the object's components have been updated
|
|||
bool shouldDestroy; |
|||
|
|||
// The NULL value for ComponentHandles
|
|||
static const int COMPONENTHANDLE_NULL = -1; |
|||
}; |
|||
|
|||
#endif |
@ -1,381 +0,0 @@ |
|||
#ifndef OBJECTCOMPONENTMANAGER_CPP |
|||
#define OBJECTCOMPONENTMANAGER_CPP |
|||
|
|||
#include <assert.h> |
|||
#include <iostream> |
|||
|
|||
#include "ObjectComponentManager.hpp" |
|||
|
|||
#include "ComponentManager.hpp" |
|||
#include "Component.hpp" |
|||
|
|||
ObjectComponentManager::ObjectComponentManager():objectPool(ObjectComponentManager::OBJECT_POOL_SIZE) |
|||
{ |
|||
|
|||
} |
|||
|
|||
ObjectComponentManager::~ObjectComponentManager() |
|||
{ |
|||
destroyAllActiveObjects(); |
|||
} |
|||
|
|||
// Destroys all active objects
|
|||
void ObjectComponentManager::destroyAllActiveObjects() |
|||
{ |
|||
destroyObjectsWithRequestedDestructionInternal(true); |
|||
} |
|||
|
|||
// Adds a ComponentManager to the ComponentManagerDictionary. If
|
|||
// there is already a manager for the specified type, it will be overwritten
|
|||
void ObjectComponentManager::addComponentManager(ComponentType managerComponentType, ComponentManager* newManager) |
|||
{ |
|||
addComponentManagerToDictionary(managerComponentType, newManager); |
|||
} |
|||
|
|||
// Adds an ObjectType of newObjectTypeID to the ObjectType dictionary.
|
|||
// If there is already an ObjectType of the specified ObjectTypeID, it will
|
|||
// be overwritten. This is the function where ObjectTypeIDs are tied to
|
|||
// a specific ObjectType
|
|||
void ObjectComponentManager::addObjectType(ObjectTypeID newObjectTypeID, ObjectType newObjectType) |
|||
{ |
|||
addObjectTypeToDictionary(newObjectTypeID, newObjectType); |
|||
} |
|||
|
|||
// Create a new Object of the specified type. Returns NULL if
|
|||
// the ObjectType couldn't be found, the object pool is full, or
|
|||
// Object failed to initialize
|
|||
// TODO: IMPORTANT! Do extensive testing on this function, making sure things
|
|||
// are being deleted when they should be if initialization fails for any reason
|
|||
Object* ObjectComponentManager::createObjectOfTypeID(ObjectTypeID newObjectTypeID) |
|||
{ |
|||
// Get the new Object's ObjectType
|
|||
ObjectType* newObjectType = getObjectTypeByID(newObjectTypeID); |
|||
|
|||
// Couldn't find the requested ObjectType
|
|||
if (!newObjectType) |
|||
return nullptr; |
|||
|
|||
// Create the Object
|
|||
Object* newObject = createNewEmptyObject(); |
|||
|
|||
if (newObject) |
|||
{ |
|||
// Set the Object's ObjectType
|
|||
newObject->setObjectType(newObjectType); |
|||
|
|||
// Add components to the new Object
|
|||
if (createAndAddComponentsForObject(newObject, newObjectType)) |
|||
{ |
|||
// Run postInitialize on the object's components
|
|||
if (postInitializeObject(newObject)) |
|||
return newObject; |
|||
} |
|||
} |
|||
|
|||
// Object creation failed; remove the Object
|
|||
removeEmptyObject(newObject); |
|||
return nullptr; |
|||
} |
|||
|
|||
bool ObjectComponentManager::addComponentOfTypeToObject(Object* object, ComponentType componentToAdd) |
|||
{ |
|||
// Find the ComponentManager for the specified type
|
|||
ComponentManager* componentManager = getComponentManagerForType(componentToAdd); |
|||
|
|||
if (!componentManager) |
|||
{ |
|||
// ComponentManager couldn't be found
|
|||
return false; |
|||
} |
|||
|
|||
// Get a fresh new component from the manager
|
|||
Component* newComponent = componentManager->getNewRawComponent(); |
|||
|
|||
if (!newComponent) |
|||
{ |
|||
// Failed to get new component from manager
|
|||
return false; |
|||
} |
|||
|
|||
// Initialize the component
|
|||
if (!newComponent->initialize(object)) |
|||
{ |
|||
// Component failed to initialize
|
|||
return false; |
|||
} |
|||
|
|||
object->addComponent(newComponent); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool ObjectComponentManager::createAndAddComponentsForObject(Object* object, ObjectType* newObjectType) |
|||
{ |
|||
bool allComponentsSuccessfullyCreated = true; |
|||
|
|||
if (!object || !newObjectType) |
|||
return false; |
|||
|
|||
// Add components one by one according to the ObjectType spec
|
|||
for (int i = 0; i < newObjectType->totalUsedComponents; i++) |
|||
{ |
|||
ComponentType currentComponentType = newObjectType->components[i]; |
|||
|
|||
if (!addComponentOfTypeToObject(object, currentComponentType)) |
|||
{ |
|||
allComponentsSuccessfullyCreated = false; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// Make sure the Object has all of its needed components
|
|||
if (object->getNumActiveComponents() != newObjectType->totalUsedComponents) |
|||
{ |
|||
allComponentsSuccessfullyCreated = false; |
|||
} |
|||
|
|||
if (!allComponentsSuccessfullyCreated) |
|||
{ |
|||
// Something went wrong during Component creation - destroy all other components on the object
|
|||
// and return failure
|
|||
destroyAllComponentsOnObject(object); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
// Tells the ComponentManager of each component on an object to destroy the component
|
|||
// Make sure to run preDestroy on all of the components before calling this function
|
|||
// (it is not called within the function because this function is used when Objects
|
|||
// might not be fully formed (like in createAndAddComponentsForObject) or haven't been
|
|||
// postInitialized)
|
|||
void ObjectComponentManager::destroyAllComponentsOnObject(Object* object) |
|||
{ |
|||
for (int i = 0; i < object->getNumActiveComponents(); i++) |
|||
{ |
|||
Component* currentComponent = object->getComponentAtIndex(i); |
|||
|
|||
if (!currentComponent) |
|||
continue; |
|||
|
|||
ComponentType currentComponentType = currentComponent->getType(); |
|||
|
|||
if (currentComponentType != ComponentType::NONE) |
|||
{ |
|||
ComponentManager* currentComponentManager = getComponentManagerForType(currentComponentType); |
|||
|
|||
if (currentComponentManager) |
|||
{ |
|||
currentComponentManager->destroyComponent(currentComponent); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Run postInitialize() on all of the Object's components
|
|||
bool ObjectComponentManager::postInitializeObject(Object* newObject) |
|||
{ |
|||
if (newObject) |
|||
{ |
|||
return newObject->postInitializeComponents(); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void ObjectComponentManager::preDestroyObject(Object* object) |
|||
{ |
|||
if (object) |
|||
{ |
|||
object->preDestroyComponents(); |
|||
} |
|||
} |
|||
|
|||
// Update the ComponentManager of the specified type
|
|||
// There is no updateAll() function because it is expected that there
|
|||
// will be a specific order the ComponentManagers should be updated.
|
|||
// Having updateComponentManagerOfType allows that order to be explicitly determined
|
|||
void ObjectComponentManager::updateComponentManagerOfType(ComponentType componentType, ComponentUpdateParams& componentUpdateParams) |
|||
{ |
|||
ComponentManager* componentManager = getComponentManagerForType(componentType); |
|||
|
|||
if (componentManager) |
|||
{ |
|||
componentManager->updateAllComponents(componentUpdateParams); |
|||
} |
|||
else |
|||
{ |
|||
// Tried to update a component manager which doesn't exist
|
|||
assert(0); |
|||
} |
|||
} |
|||
|
|||
// Destroy all Objects which have shouldDestroy set to true
|
|||
// This function should be called once per frame/after updating all ComponentManagers
|
|||
// TODO: This is currently looping through all objects. May need to optimize later
|
|||
void ObjectComponentManager::destroyObjectsWithRequestedDestruction() |
|||
{ |
|||
destroyObjectsWithRequestedDestructionInternal(false); |
|||
} |
|||
|
|||
void ObjectComponentManager::destroyObjectsWithRequestedDestructionInternal(bool forceDestroyAllObjects) |
|||
{ |
|||
std::vector<ObjectPoolHandle> objectsToDestroy; |
|||
|
|||
// Build a list of all Objects that have impending destruction
|
|||
// A separate list must be used because any other list could have
|
|||
// data moving due to the destruction
|
|||
for (ActiveObjectsDictionary::iterator it = activeObjects.begin(); it != activeObjects.end(); ++it) |
|||
{ |
|||
ObjectPoolHandle currentObjectHandle = it->second; |
|||
|
|||
if (currentObjectHandle) |
|||
{ |
|||
Object* currentObject = ¤tObjectHandle->data; |
|||
|
|||
if (currentObject->shouldDestroyObject() || forceDestroyAllObjects) |
|||
objectsToDestroy.push_back(currentObjectHandle); |
|||
} |
|||
} |
|||
|
|||
// Destroy all Objects in the destroy list
|
|||
for (std::vector<ObjectPoolHandle>::iterator it = objectsToDestroy.begin(); it != objectsToDestroy.end(); ++it) |
|||
{ |
|||
if (!(*it)) |
|||
continue; |
|||
|
|||
Object* currentObject = &(*it)->data; |
|||
|
|||
// Have the Object tell its components that they are going to be destroyed
|
|||
preDestroyObject(currentObject); |
|||
|
|||
// Destroy the object's components
|
|||
destroyAllComponentsOnObject(currentObject); |
|||
|
|||
// Remove the now empty object from the Active Objects dictionary and the Object Pool
|
|||
removeEmptyObject(currentObject); |
|||
} |
|||
} |
|||
|
|||
/////////////////////////////////////////////////////////////////
|
|||
// Abstraction layer for ObjectComponentManager data structures
|
|||
/////////////////////////////////////////////////////////////////
|
|||
|
|||
// Creates a new Object, assigns its ID, and adds it to the Active Objects dictionary
|
|||
// This function does not run initialize() etc
|
|||
// Make sure to run removeObject() once finished with the object
|
|||
Object* ObjectComponentManager::createNewEmptyObject() |
|||
{ |
|||
ObjectPoolHandle newPooledObject = objectPool.getNewData(); |
|||
|
|||
if (newPooledObject) |
|||
{ |
|||
Object* newObject = &newPooledObject->data; |
|||
|
|||
// Initialize the object
|
|||
newObject->initialize(); |
|||
|
|||
// Set the new object's ID
|
|||
ObjectID newObjectID = generateUniqueObjectID(); |
|||
newObject->setObjectID(newObjectID); |
|||
|
|||
// Make sure the ID is unique
|
|||
assert(getObjectByID(newObjectID) == nullptr); |
|||
|
|||
// Add the Object to the Active Objects Dictionary
|
|||
activeObjects[newObjectID] = newPooledObject; |
|||
|
|||
return newObject; |
|||
} |
|||
|
|||
// Pool is full!
|
|||
std::cout << "WARNING: Object Pool is FULL!\n"; |
|||
return nullptr; |
|||
} |
|||
|
|||
Object* ObjectComponentManager::getObjectByID(ObjectID objectID) |
|||
{ |
|||
ActiveObjectsDictionary::iterator findIt = activeObjects.find(objectID); |
|||
|
|||
if (findIt != activeObjects.end()) |
|||
{ |
|||
return &findIt->second->data; |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
// Removes an object from the ActiveObjects Dictionary and frees it from the object pool.
|
|||
// This function DOES NOT remove an object's components (hence the "Empty")
|
|||
// This function should NOT be called if you are iterating over activeObjects, because
|
|||
// it removes values from activeObjects.
|
|||
void ObjectComponentManager::removeEmptyObject(Object* objectToRemove) |
|||
{ |
|||
if (objectToRemove) |
|||
{ |
|||
// Find the Object in the activeObjects dictionary
|
|||
ActiveObjectsDictionary::iterator findIt = activeObjects.find(objectToRemove->getObjectID()); |
|||
|
|||
if (findIt != activeObjects.end()) |
|||
{ |
|||
ObjectPoolHandle pooledObject = findIt->second; |
|||
|
|||
if (pooledObject) |
|||
{ |
|||
// Free the object in the pool
|
|||
objectPool.removeData(pooledObject); |
|||
|
|||
// Remove the Object from hte Active Objects dictionary
|
|||
activeObjects.erase(findIt); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// Tried to remove an Object which isn't in this ObjectComponentManager's ActiveObjects
|
|||
assert(0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
ComponentManager* ObjectComponentManager::getComponentManagerForType(ComponentType componentType) |
|||
{ |
|||
ComponentManagerDictionary::iterator findIt = componentManagers.find(componentType); |
|||
|
|||
if (findIt != componentManagers.end()) |
|||
{ |
|||
return findIt->second; |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
void ObjectComponentManager::addComponentManagerToDictionary(ComponentType componentType, ComponentManager* newManager) |
|||
{ |
|||
componentManagers[componentType] = newManager; |
|||
} |
|||
|
|||
ObjectType* ObjectComponentManager::getObjectTypeByID(ObjectTypeID objectTypeID) |
|||
{ |
|||
ObjectTypeDictionary::iterator findIt = objectTypes.find(objectTypeID); |
|||
|
|||
if (findIt != objectTypes.end()) |
|||
{ |
|||
return &findIt->second; |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
void ObjectComponentManager::addObjectTypeToDictionary(ObjectTypeID objectTypeID, ObjectType newObjectType) |
|||
{ |
|||
objectTypes[objectTypeID] = newObjectType; |
|||
} |
|||
|
|||
// TODO: Have a more explicit way to get runtime-unique object ids
|
|||
static ObjectID currentAvailableObjectID = OBJECT_ID_FIRST; |
|||
ObjectID ObjectComponentManager::generateUniqueObjectID() |
|||
{ |
|||
return currentAvailableObjectID++; |
|||
} |
|||
#endif |
@ -1,120 +0,0 @@ |
|||
#ifndef OBJECTCOMPONENTMANAGER_HPP |
|||
#define OBJECTCOMPONENTMANAGER_HPP |
|||
|
|||
#include <base2.0/dataStructures/pool.hpp> |
|||
#include <map> |
|||
|
|||
#include "Object.hpp" |
|||
#include "ObjectType.hpp" |
|||
#include "ComponentTypes.hpp" |
|||
#include "ObjectID.hpp" |
|||
|
|||
/* --ObjectComponentManager--
|
|||
* ObjectComponentManager manages ComponentManagers and Objects. It |
|||
* performs the necessary interactions between these two systems |
|||
* */ |
|||
class ComponentManager; |
|||
struct ComponentUpdateParams; |
|||
class ObjectComponentManager |
|||
{ |
|||
public: |
|||
ObjectComponentManager(); |
|||
~ObjectComponentManager(); |
|||
|
|||
// Adds a ComponentManager to the ComponentManagerDictionary. If
|
|||
// there is already a manager for the specified type, it will be overwritten
|
|||
void addComponentManager(ComponentType managerComponentType, ComponentManager* newManager); |
|||
|
|||
// Adds an ObjectType of newObjectTypeID to the ObjectType dictionary.
|
|||
// If there is already an ObjectType of the specified ObjectTypeID, it will
|
|||
// be overwritten. This is the function where ObjectTypeIDs are tied to
|
|||
// a specific ObjectType
|
|||
void addObjectType(ObjectTypeID newObjectTypeID, ObjectType newObjectType); |
|||
|
|||
// Create a new Object of the specified type. Returns NULL if
|
|||
// the ObjectType couldn't be found, the object pool is full, or
|
|||
// Object failed to initalize
|
|||
Object* createObjectOfTypeID(ObjectTypeID newObjectTypeID); |
|||
|
|||
// Update the ComponentManager of the specified type
|
|||
// There is no updateAll() function because it is expected that there
|
|||
// will be a specific order the ComponentManagers should be updated.
|
|||
// Having updateComponentManagerOfType allows that order to be explicitly determined
|
|||
void updateComponentManagerOfType(ComponentType componentType, ComponentUpdateParams& componentUpdateParams); |
|||
|
|||
// Destroys all active objects
|
|||
void destroyAllActiveObjects(); |
|||
|
|||
// Destroy all Objects which have shouldDestroy set to true
|
|||
// This function should be called once per frame/after updating all ComponentManagers
|
|||
void destroyObjectsWithRequestedDestruction(); |
|||
|
|||
private: |
|||
// The structure that holds all ComponentManagers
|
|||
typedef std::map<ComponentType, ComponentManager*> ComponentManagerDictionary; |
|||
ComponentManagerDictionary componentManagers; |
|||
|
|||
// The pooled structure that holds all Objects
|
|||
typedef Pool<Object> ObjectPool; |
|||
|
|||
static const int OBJECT_POOL_SIZE = 100; |
|||
ObjectPool objectPool; |
|||
|
|||
// A handle to a pooled object
|
|||
typedef PoolData<Object>* ObjectPoolHandle; |
|||
|
|||
// The dictionary which holds Objects associated with their IDs
|
|||
typedef std::map<ObjectID, ObjectPoolHandle> ActiveObjectsDictionary; |
|||
ActiveObjectsDictionary activeObjects; |
|||
|
|||
// The structure that holds all ObjectTypes
|
|||
typedef std::map<ObjectTypeID, ObjectType> ObjectTypeDictionary; |
|||
ObjectTypeDictionary objectTypes; |
|||
|
|||
// Abstraction layer for ObjectComponentManager data structures
|
|||
|
|||
// Creates a new Object, assigns its ID, and adds it to the Active Objects dictionary
|
|||
// This function does not run initialize() etc
|
|||
// Make sure to run removeObject() once finished with the object
|
|||
Object* createNewEmptyObject(); |
|||
|
|||
Object* getObjectByID(ObjectID objectID); |
|||
|
|||
// Removes an object from the ActiveObjects Dictionary and frees it from the object pool.
|
|||
// This function DOES NOT remove an object's components (hence the "Empty")
|
|||
// This function should NOT be called if you are iterating over activeObjects, because
|
|||
// it removes values from activeObjects. Do not call this function if you are iterating
|
|||
// over active objects in the object pool either
|
|||
void removeEmptyObject(Object* objectToRemove); |
|||
|
|||
ComponentManager* getComponentManagerForType(ComponentType componentType); |
|||
|
|||
void addComponentManagerToDictionary(ComponentType componentType, ComponentManager* newManager); |
|||
|
|||
ObjectType* getObjectTypeByID(ObjectTypeID objectTypeID); |
|||
|
|||
void addObjectTypeToDictionary(ObjectTypeID objectTypeID, ObjectType newObjectType); |
|||
|
|||
// Generates a globally unique ObjectID (runtime only; these aren't persisted)
|
|||
ObjectID generateUniqueObjectID(); |
|||
|
|||
bool addComponentOfTypeToObject(Object* object, ComponentType componentToAdd); |
|||
|
|||
bool createAndAddComponentsForObject(Object* newObject, ObjectType* newObjectType); |
|||
|
|||
void destroyObjectsWithRequestedDestructionInternal(bool forceDestroyAllObjects); |
|||
|
|||
// Tells the ComponentManager of each component on an object to destroy the component
|
|||
// Make sure to run preDestroy on all of the components before calling this function
|
|||
// (it is not called within the function because this function is used when Objects
|
|||
// might not be fully formed (like in createAndAddComponentsForObject) or haven't been
|
|||
// postInitialized)
|
|||
void destroyAllComponentsOnObject(Object* newObject); |
|||
|
|||
// Run postInitialize() on all of the Object's components
|
|||
bool postInitializeObject(Object* newObject); |
|||
|
|||
// Run preDestroy() on all of the Object's components
|
|||
void preDestroyObject(Object* object); |
|||
}; |
|||
#endif |
@ -1,16 +0,0 @@ |
|||
#ifndef OBJECTID_CPP |
|||
#define OBJECTID_CPP |
|||
|
|||
#include "ObjectID.hpp" |
|||
|
|||
// The Object hasn't been assigned an ID
|
|||
const ObjectID OBJECT_ID_NONE = -1; |
|||
|
|||
// The last possible ID that can be assigned
|
|||
// TODO: Set to a better value (this was completely arbitrary)
|
|||
const ObjectID OBJECT_ID_MAX = 1000000; |
|||
|
|||
// Start assigning IDs at this value
|
|||
const ObjectID OBJECT_ID_FIRST = 1; |
|||
|
|||
#endif |
@ -1,15 +0,0 @@ |
|||
#ifndef OBJECTID_HPP |
|||
#define OBJECTID_HPP |
|||
|
|||
typedef int ObjectID; |
|||
|
|||
// The Object hasn't been assigned an ID
|
|||
extern const ObjectID OBJECT_ID_NONE; |
|||
|
|||
// The last possible ID that can be assigned
|
|||
extern const ObjectID OBJECT_ID_MAX; |
|||
|
|||
// Start assigning IDs at this value
|
|||
extern const ObjectID OBJECT_ID_FIRST; |
|||
|
|||
#endif |
@ -1,5 +0,0 @@ |
|||
#ifndef OBJECTTYPE_CPP |
|||
#define OBJECTTYPE_CPP |
|||
|
|||
|
|||
#endif |
@ -1,25 +0,0 @@ |
|||
#ifndef OBJECTTYPE_HPP |
|||
#define OBJECTTYPE_HPP |
|||
|
|||
#include "ComponentTypes.hpp" |
|||
|
|||
#define OBJECT_MAX_COMPONENTS 10 |
|||
|
|||
// ObjectTypeIDs are not tied to ObjectTypes automatically. This association
|
|||
// happens in ObjectComponentManager
|
|||
enum class ObjectTypeID : int |
|||
{ |
|||
NONE = 0, |
|||
TEST |
|||
}; |
|||
|
|||
struct ObjectType |
|||
{ |
|||
// An array of ComponentTypes that this ObjectType requires
|
|||
ComponentType components[OBJECT_MAX_COMPONENTS]; |
|||
|
|||
// The number of Components this Object will actually use
|
|||
int totalUsedComponents; |
|||
}; |
|||
|
|||
#endif |
@ -1,4 +0,0 @@ |
|||
ObjectComponent |
|||
================ |
|||
|
|||
ObjectComponent is my first try at getting an Object-Component System (or Entity Component System) set up. Since then, I've redesigned how I want to do it, so this code is *DEPRECATED*. Do not use it. Use src/EntityComponentSystem instead. |
@ -1,167 +0,0 @@ |
|||
#include <iostream> |
|||
#include <base2.0/dataStructures/pool.hpp> |
|||
#include "../objectComponent/ObjectComponentManager.hpp" |
|||
#include "../objectComponent/ObjectType.hpp" |
|||
#include "../objectComponent/Component.hpp" |
|||
#include "../objectComponent/ComponentManager.hpp" |
|||
|
|||
struct ComponentUpdateParams |
|||
{ |
|||
float timeStep; |
|||
}; |
|||
|
|||
class TestComponent : public Component |
|||
{ |
|||
public: |
|||
TestComponent() |
|||
{ |
|||
std::cout << "+++ TestComponent constructed!\n"; |
|||
} |
|||
virtual ~TestComponent() |
|||
{ |
|||
std::cout << "--- TestComponent destructed\n"; |
|||
} |
|||
virtual bool initialize(Object* newParentObject) |
|||
{ |
|||
parentObject = newParentObject; |
|||
type = ComponentType::TEST; |
|||
std::cout << "Initialized new TestComponent!\n"; |
|||
return true; |
|||
} |
|||
virtual bool postInitialize() |
|||
{ |
|||
std::cout << " postInitialized new TestComponent!\n"; |
|||
return true; |
|||
} |
|||
virtual void preDestroy() |
|||
{ |
|||
std::cout << " preDestroy TestComponent!\n"; |
|||
} |
|||
virtual void destroy() |
|||
{ |
|||
std::cout << "destroy TestComponent!\n"; |
|||
} |
|||
virtual void update(ComponentUpdateParams& updateParams) |
|||
{ |
|||
std::cout << " updating TestComponent!\n"; |
|||
} |
|||
virtual void debugPrint() |
|||
{ |
|||
std::cout << " debugPrint TestComponent! parent obj: " << parentObject << "\n"; |
|||
} |
|||
virtual bool copyComponent(Object* newParentObject, Component* newComponent) |
|||
{ |
|||
std::cout << " Copying TestComponent!\n"; |
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
|
|||
class TestComponentManager : public ComponentManager |
|||
{ |
|||
private: |
|||
Component* activeComponents[100]; |
|||
public: |
|||
TestComponentManager() |
|||
{ |
|||
std::cout << "+++ TestComponentManager created\n"; |
|||
initialize(); |
|||
} |
|||
virtual ~TestComponentManager() |
|||
{ |
|||
std::cout << "--- TestComponentManager destructor\n"; |
|||
destroy(); |
|||
} |
|||
virtual bool initialize() |
|||
{ |
|||
std::cout << "TestComponentManager initialized\n"; |
|||
for (int i = 0; i < 100; i++) |
|||
{ |
|||
activeComponents[i] = nullptr; |
|||
} |
|||
return true; |
|||
} |
|||
virtual void destroy() |
|||
{ |
|||
for (int i = 0; i < 100; i++) |
|||
{ |
|||
if (activeComponents[i]) |
|||
{ |
|||
destroyComponent(activeComponents[i]); |
|||
} |
|||
} |
|||
std::cout << "TestComponentManager destroyed\n"; |
|||
} |
|||
virtual void updateAllComponents(ComponentUpdateParams& componentUpdateParams) |
|||
{ |
|||
std::cout << " Manager: Updating components\n"; |
|||
for (int i = 0; i < 100; i++) |
|||
{ |
|||
Component* currentComponent = activeComponents[i]; |
|||
|
|||
if (currentComponent != nullptr) |
|||
{ |
|||
std::cout << " Manager: Running update on " << currentComponent << "\n"; |
|||
currentComponent->update(componentUpdateParams); |
|||
} |
|||
} |
|||
} |
|||
virtual Component* getNewRawComponent() |
|||
{ |
|||
std::cout << " Manager: Creating component\n"; |
|||
Component* newComponent = new TestComponent; |
|||
|
|||
for (int i = 0; i < 100; i++) |
|||
{ |
|||
Component* currentComponent = activeComponents[i]; |
|||
if (currentComponent == nullptr) |
|||
{ |
|||
newComponent->localID = i; |
|||
activeComponents[i] = newComponent; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return newComponent; |
|||
} |
|||
virtual void destroyComponent(Component* component) |
|||
{ |
|||
std::cout << " Manager: Destroying component\n"; |
|||
activeComponents[component->localID] = nullptr; |
|||
component->destroy(); |
|||
delete component; |
|||
} |
|||
}; |
|||
|
|||
int main() |
|||
{ |
|||
std::cout << "Testing ObjectComponent system\n"; |
|||
TestComponentManager testComponentManager; |
|||
testComponentManager.initialize(); |
|||
|
|||
ObjectComponentManager objectComponentManager; |
|||
objectComponentManager.addComponentManager(ComponentType::TEST, &testComponentManager); |
|||
|
|||
ObjectType testObject; |
|||
testObject.components[0] = ComponentType::TEST; |
|||
testObject.totalUsedComponents = 1; |
|||
|
|||
objectComponentManager.addObjectType(ObjectTypeID::TEST, testObject); |
|||
|
|||
std::cout << "First object addr: " << objectComponentManager.createObjectOfTypeID(ObjectTypeID::TEST) << "\n"; |
|||
|
|||
{ |
|||
ComponentUpdateParams updateParams; |
|||
|
|||
updateParams.timeStep = 0.016; |
|||
|
|||
objectComponentManager.updateComponentManagerOfType(ComponentType::TEST, updateParams); |
|||
|
|||
objectComponentManager.destroyObjectsWithRequestedDestruction(); |
|||
} |
|||
|
|||
std::cout << "Destroying all objects\n"; |
|||
|
|||
objectComponentManager.destroyAllActiveObjects(); |
|||
return 1; |
|||
} |
Loading…
Reference in new issue