#include "ModelBase.h" #include "PhysicsBase.h" #include "EntityBase.h" #include "EntityFactoryBase.h" #include #include namespace Engine { static ModelBase* ModelInstance = NULL; /* * Inherited Module functions */ int ModelBase::OnInit (int argc, char* argv[]) { LogDebug ("Model Init"); ModelInstance = this; mKilledEntities.clear (); mEntityIdCounter = 0; mDeltaSec = 0.; return 0; } void ModelBase::OnDestroy () { LogDebug ("Model Destroy"); std::map::iterator iter = mEntities.begin (); std::map::iterator next = iter; // Since DestroyEntity () also erases the entry in mEntities iter gets // invalid. Therefore we have to store the iterator that follows iter while (iter != mEntities.end ()) { next = iter; next ++; DestroyEntity (iter->first); iter = next; } ModelInstance = NULL; } /* * Model specific functions */ void ModelBase::Process () { // Process the controllers and state of all entities std::map::iterator entity_iter = mEntities.begin(); do { if (entity_iter->second == NULL) { LogError ("Entity with id %d does not exist!", entity_iter->first); assert (0); } entity_iter->second->Update(mDeltaSec); entity_iter++; } while (entity_iter != mEntities.end()); // simulate the world mPhysics->Simulate (mDeltaSec, this); // remove killed entities unsigned int i; for (i = 0; i < mKilledEntities.size(); i++) UnregisterEntity (mKilledEntities[i]); mKilledEntities.clear(); } EntityBase* ModelBase::CreateEntity (int type) { // Create a new entity id unsigned int entity_id = CreateEntityId(); // Call the event OnCreateEntity (type, entity_id); // Create the entity EntityBase* result = mEntityFactory->CreateEntity (type); result->SetId (entity_id); // And register it RegisterEntity (result); return result; } void ModelBase::RegisterEntity (EntityBase* entity) { unsigned int id = entity->mId; LogDebug ("Registering Entity with id '%d'", id); if (mEntities.find(id) != mEntities.end ()) { LogError ("Replacing Entity with id '%d'", id); assert (0); } if (entity->mPhysicState) mPhysics->RegisterEntity (entity->mPhysicState); mEntities[id] = entity; } void ModelBase::KillEntity (const unsigned int id) { std::map::iterator iter = mEntities.find (id); if (iter == mEntities.end ()) { LogError ("Could not kill Entity with id '%d': Entity not found!", id); assert (0); return; } else { EntityBase *entity = iter->second; // call the event handler OnKillEntity (entity); if (entity->mPhysicState) { entity->mPhysicState->mAlive = false; } mKilledEntities.push_back (iter->first); } } void ModelBase::UnregisterEntity (const unsigned int id) { std::map::iterator iter = mEntities.find (id); if (iter == mEntities.end ()) { LogError ("Could not unregister Entity with id '%d': Entity not found!", id); assert (0); return; } else { EntityBase *entity = iter->second; if (entity->mPhysicState) { mPhysics->UnregisterEntity (id); entity->mPhysicState = NULL; } delete entity; mEntities.erase (iter); } } EntityBase* ModelBase::GetEntity (const unsigned int id) { std::map::iterator iter = mEntities.find (id); if (iter != mEntities.end ()) { return iter->second; } return NULL; } unsigned int ModelBase::CreateEntityId () { return ++mEntityIdCounter; } void ModelBase::ClearEntities () { LogDebug ("Clearing all %d entities.", mEntities.size()); std::map::iterator iter = mEntities.begin (); std::map::iterator next = iter; // Since DestroyEntity () also erases the entry in mEntities iter gets // invalid. Therefore we have to store the iterator that follows iter while (iter != mEntities.end ()) { next = iter; next ++; DestroyEntity (iter->first); iter = next; } mEntityIdCounter = 0; } unsigned int ModelBase::GetPlayerEntityId () { return mPlayerEntityId; } /** * \param collision_time The time when the collision occured relative to the start of the simulation frame */ void ModelBase::SendEntityCollisionEvent (const unsigned int reference_entity_id, const unsigned int incidence_entity_id, float collision_time, vector3d normal) { // Check whether we report the same contact over and over static unsigned int last_reference_entity_id = 0; static unsigned int last_incidence_entity_id = 0; static float last_collision_time = -1.; if (!reference_entity_id || !incidence_entity_id) return; if (last_reference_entity_id != 0) { if (last_reference_entity_id == reference_entity_id && last_incidence_entity_id == incidence_entity_id && last_collision_time == collision_time) { return; } } // update the last_* entries last_reference_entity_id = reference_entity_id; last_incidence_entity_id = incidence_entity_id; last_collision_time = collision_time; // now we need to get the Entities and check whether we should // call EntityBase::CollisionEvent() EntityBase* reference_entity = GetEntity (reference_entity_id); EntityBase* incidence_entity = GetEntity (incidence_entity_id); LogDebug ("Received collision type ref = %d type inc = %d", reference_entity->mType, incidence_entity->mType); // If the incidence entity accepted the collision we can return, otherwise // we perform the symmetric collision event. if (incidence_entity->CollisionEvent (reference_entity)) return; reference_entity->CollisionEvent (incidence_entity); } /* * Global functions */ unsigned int GetPlayerEntityId () { if (!ModelInstance) { LogError ("Couldn't create Entity: Model not initialized!"); assert (0); } return ModelInstance->GetPlayerEntityId (); } float GetFrameDuration () { if (!ModelInstance) { LogError ("Couldn't create Entity: Model not initialized!"); assert (0); } return ModelInstance->GetFrameDuration (); } EntityBase * CreateEntity (int type) { if (!ModelInstance) { LogError ("Couldn't create Entity: Model not initialized!"); assert (0); } EntityBase *result = ModelInstance->CreateEntity (type); return result; } void DestroyEntity (unsigned int id) { if (!ModelInstance) { LogError ("Couldn't destroy Entity: Model not initialized!"); assert (0); } ModelInstance->UnregisterEntity (id); } void KillEntity (unsigned int id) { if (!ModelInstance) { LogError ("Couldn't kill Entity: Model not initialized!"); assert (0); } ModelInstance->KillEntity (id); } EntityBase * GetEntity (unsigned int id) { if (!ModelInstance) { LogError ("Couldn't execute GetEntity(): Model not initialized!"); assert (0); } return ModelInstance->GetEntity (id); } EntityPhysicState * GetEntityPhysicState (unsigned int id) { EntityBase *entity = GetEntity (id); if (entity) return entity->mPhysicState; return NULL; } }