375 lines
8.9 KiB
C++
375 lines
8.9 KiB
C++
#include "ModelBase.h"
|
|
|
|
#include "PhysicsBase.h"
|
|
#include "EntityBase.h"
|
|
#include "EntityFactoryBase.h"
|
|
|
|
#include <coll2d.h>
|
|
|
|
#include <assert.h>
|
|
|
|
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<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
|
|
std::map<unsigned int, EntityBase*>::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
|
|
EntityIter entity_iter = mEntities.begin();
|
|
do {
|
|
if (entity_iter->second == NULL) {
|
|
LogError ("Entity with id %d does not exist!", entity_iter->first);
|
|
}
|
|
entity_iter->second->Update(mDeltaSec);
|
|
entity_iter++;
|
|
} while (entity_iter != mEntities.end());
|
|
|
|
/*
|
|
// Update the timers
|
|
for (TimerIter timer_iter = mTimers.begin(); timer_iter != mTimers.end(); timer_iter++) {
|
|
timer_iter->second.Update(mDeltaSec);
|
|
timer_iter++;
|
|
}
|
|
*/
|
|
|
|
// simulate the world
|
|
mPhysics->Simulate (mDeltaSec, this);
|
|
|
|
assert (mKilledEntities.size() <= mEntities.size());
|
|
|
|
// remove killed entities
|
|
if (mKilledEntities.size() > 0) {
|
|
unsigned int i;
|
|
LogDebug ("There are %d entities to kill", mKilledEntities.size());
|
|
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 '%u' and type '%u'", id, entity->mType);
|
|
|
|
if (mEntities.find(id) != mEntities.end ()) {
|
|
LogError ("Replacing Entity with id '%u' and type '%u'", id, entity->mType);
|
|
}
|
|
|
|
if (entity->mPhysicState)
|
|
mPhysics->RegisterEntity (entity->mPhysicState);
|
|
|
|
mEntities[id] = entity;
|
|
}
|
|
|
|
void ModelBase::KillEntity (const unsigned int id) {
|
|
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
|
|
|
LogDebug ("Killing entity with id '%u'", id);
|
|
|
|
if (iter == mEntities.end ()) {
|
|
LogError ("Could not kill Entity with id '%u': Entity not found!", id);
|
|
return;
|
|
} else {
|
|
EntityBase *entity = iter->second;
|
|
|
|
LogDebug ("Entity pointer = 0x%u", entity);
|
|
// call the event handler
|
|
OnKillEntity (entity);
|
|
LogDebug ("Entity pointer (after kill) = 0x%u", entity);
|
|
|
|
if (entity->mPhysicState) {
|
|
entity->mPhysicState->mAlive = false;
|
|
}
|
|
|
|
mKilledEntities.push_back (iter->first);
|
|
}
|
|
}
|
|
|
|
void ModelBase::UnregisterEntity (const unsigned int id) {
|
|
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
|
|
|
if (iter == mEntities.end ()) {
|
|
LogDebug ("iter id=%u entitypointer=0x%x type=%d", iter->first, iter->second, iter->second->mType);
|
|
LogError ("Could not unregister Entity with id '%d': Entity not found!", id);
|
|
return;
|
|
} else {
|
|
EntityBase *entity = iter->second;
|
|
if (entity->mPhysicState) {
|
|
mPhysics->UnregisterEntity (id);
|
|
entity->mPhysicState = NULL;
|
|
}
|
|
|
|
if (entity->mControllerState) {
|
|
delete entity->mControllerState;
|
|
entity->mControllerState = NULL;
|
|
}
|
|
|
|
delete entity;
|
|
|
|
mEntities.erase (iter);
|
|
}
|
|
}
|
|
|
|
EntityBase* ModelBase::GetEntity (const unsigned int id) {
|
|
if (id == NullEntityId)
|
|
return NULL;
|
|
|
|
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
|
|
|
|
if (iter != mEntities.end ()) {
|
|
return iter->second;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
EntityBase* ModelBase::GetEntityAt (const vector3d &pos) {
|
|
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin();
|
|
|
|
while (iter != mEntities.end ()) {
|
|
EntityPhysicState* entity = iter->second->mPhysicState;
|
|
/// \todo fix const casting!
|
|
vector3d temp_pos (pos);
|
|
|
|
if ( (temp_pos - entity->GetPosition()).length() < entity->mRadius)
|
|
return iter->second;
|
|
|
|
iter++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
unsigned int ModelBase::CreateEntityId () {
|
|
if (mEntityIdCounter == NullEntityId - 1)
|
|
LogError ("Could not create valid entity id, reached maximum value of %u", mEntityIdCounter);
|
|
|
|
return ++mEntityIdCounter;
|
|
}
|
|
|
|
void ModelBase::ClearEntities () {
|
|
LogDebug ("Clearing all %d entities.", mEntities.size());
|
|
|
|
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
|
|
std::map<unsigned int, EntityBase*>::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;
|
|
|
|
// we alsohave to clear the vector of killed entities!
|
|
mKilledEntities.clear();
|
|
}
|
|
|
|
unsigned int ModelBase::GetPlayerEntityId () {
|
|
return mPlayerEntityId;
|
|
}
|
|
|
|
void ModelBase::SetPlayerEntityId(unsigned int entity_id) {
|
|
mPlayerEntityId = entity_id;
|
|
}
|
|
|
|
/**
|
|
* \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 point, 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, point, normal))
|
|
return;
|
|
|
|
reference_entity->CollisionEvent (incidence_entity, point, normal * -1.);
|
|
}
|
|
|
|
/*
|
|
* Global functions
|
|
*/
|
|
unsigned int GetPlayerEntityId () {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't get Player id: Model not initialized!");
|
|
}
|
|
|
|
return ModelInstance->GetPlayerEntityId ();
|
|
}
|
|
|
|
void SetPlayerEntityId(unsigned int entity_id) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't set Player id: Model not initialized!");
|
|
}
|
|
|
|
ModelInstance->SetPlayerEntityId (entity_id);
|
|
}
|
|
|
|
float GetFrameDuration () {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't create Entity: Model not initialized!");
|
|
}
|
|
|
|
return ModelInstance->GetFrameDuration ();
|
|
}
|
|
|
|
EntityBase * CreateEntity (int type) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't create Entity: Model not initialized!");
|
|
}
|
|
|
|
EntityBase *result = ModelInstance->CreateEntity (type);
|
|
|
|
return result;
|
|
}
|
|
|
|
void DestroyEntity (unsigned int id) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't destroy Entity: Model not initialized!");
|
|
}
|
|
|
|
ModelInstance->UnregisterEntity (id);
|
|
}
|
|
|
|
void KillEntity (unsigned int id) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't kill Entity: Model not initialized!");
|
|
}
|
|
|
|
ModelInstance->KillEntity (id);
|
|
}
|
|
|
|
EntityBase* GetEntity (unsigned int id) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't execute GetEntity(): Model not initialized!");
|
|
}
|
|
|
|
return ModelInstance->GetEntity (id);
|
|
}
|
|
|
|
EntityBase* GetEntityAt(const vector3d &pos) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't execute GetEntityAt(): Model not initialized!");
|
|
}
|
|
|
|
return ModelInstance->GetEntityAt (pos);
|
|
}
|
|
|
|
EntityPhysicState * GetEntityPhysicState (unsigned int id) {
|
|
EntityBase *entity = GetEntity (id);
|
|
|
|
if (entity)
|
|
return entity->mPhysicState;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
void StartTimer(const std::string &id, float sec) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't execute GetEntity(): Model not initialized!");
|
|
}
|
|
|
|
ModelInstance->StartTimer(id, sec);
|
|
}
|
|
|
|
bool CheckTimer(const std::string &id) {
|
|
if (!ModelInstance) {
|
|
LogError ("Couldn't execute GetEntity(): Model not initialized!");
|
|
}
|
|
|
|
return ModelInstance->CheckTimer(id);
|
|
}
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|