예제 #1
0
void CComponentManager::AddMockComponent(CEntityHandle ent, InterfaceId iid, IComponent& component)
{
	// Just add it into the by-interface map, not the by-component-type map,
	// so it won't be considered for messages or deletion etc

	boost::unordered_map<entity_id_t, IComponent*>& emap1 = m_ComponentsByInterface.at(iid);
	if (emap1.find(ent.GetId()) != emap1.end())
		debug_warn(L"Multiple components for interface");
	emap1.insert(std::make_pair(ent.GetId(), &component));

	SEntityComponentCache* cache = ent.GetComponentCache();
	ENSURE(cache != NULL && iid < (int)cache->numInterfaces && cache->interfaces[iid] == NULL);
	cache->interfaces[iid] = &component;
}
예제 #2
0
void CComponentManager::FlushDestroyedComponents()
{
	PROFILE2("Flush Destroyed Components");
	while (!m_DestructionQueue.empty())
	{
		// Make a copy of the destruction queue, so that the iterators won't be invalidated if the
		// CMessageDestroy handlers try to destroy more entities themselves
		std::vector<entity_id_t> queue;
		queue.swap(m_DestructionQueue);

		// Flatten all the dynamic subscriptions to ensure there are no dangling
		// references in the 'removed' lists to components we're going to delete
		FlattenDynamicSubscriptions();

		for (std::vector<entity_id_t>::iterator it = queue.begin(); it != queue.end(); ++it)
		{
			entity_id_t ent = *it;
			CEntityHandle handle = LookupEntityHandle(ent);

			CMessageDestroy msg(ent);
			PostMessage(ent, msg);

			// Destroy the components, and remove from m_ComponentsByTypeId:
			std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::iterator iit = m_ComponentsByTypeId.begin();
			for (; iit != m_ComponentsByTypeId.end(); ++iit)
			{
				std::map<entity_id_t, IComponent*>::iterator eit = iit->second.find(ent);
				if (eit != iit->second.end())
				{
					eit->second->Deinit();
					RemoveComponentDynamicSubscriptions(eit->second);
					m_ComponentTypesById[iit->first].dealloc(eit->second);
					iit->second.erase(ent);
					handle.GetComponentCache()->interfaces[m_ComponentTypesById[iit->first].iid] = NULL;
				}
			}

			free(handle.GetComponentCache());
			m_ComponentCaches.erase(ent);

			// Remove from m_ComponentsByInterface
			std::vector<boost::unordered_map<entity_id_t, IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin();
			for (; ifcit != m_ComponentsByInterface.end(); ++ifcit)
			{
				ifcit->erase(ent);
			}
		}
	}
}
예제 #3
0
bool CCharacterController::RecoverFromPenetration(btCollisionWorld* pCollisionWorld)
{
	if (!IsColliding())
		return false;

	bool bPenetration = false;

	pCollisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_pGhostObject->getOverlappingPairCache(), pCollisionWorld->getDispatchInfo(), pCollisionWorld->getDispatcher());

	btVector3 vecCurrentPosition = m_pGhostObject->getWorldTransform().getOrigin();
	btVector3 vecOriginalPosition = vecCurrentPosition;

	btScalar maxPen = btScalar(0.0);
	for (int i = 0; i < m_pGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
	{
		m_aManifolds.resize(0);

		btBroadphasePair* pCollisionPair = &m_pGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];

		btCollisionObject* pObject0 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy0->m_clientObject);
		btCollisionObject* pObject1 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy1->m_clientObject);

		if (!pObject0->hasContactResponse() || !pObject1->hasContactResponse())
			continue;

		if (pObject0->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER || pObject1->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER)
			continue;

		if (pCollisionPair->m_algorithm)
			pCollisionPair->m_algorithm->getAllContactManifolds(m_aManifolds);

		for (int j = 0; j < m_aManifolds.size(); j++)
		{
			btPersistentManifold* pManifold = m_aManifolds[j];

			const btCollisionObject* obA = static_cast<const btCollisionObject*>(pManifold->getBody0());
			const btCollisionObject* obB = static_cast<const btCollisionObject*>(pManifold->getBody1());

			btScalar directionSign;
			CEntityHandle<CBaseEntity> hOther;
			size_t iExtra;
			if (obA == m_pGhostObject)
			{
				if (obB->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(-1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obB->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obB->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}
			else
			{
				if (obA->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obA->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obA->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}

			for (int p = 0; p < pManifold->getNumContacts(); p++)
			{
				const btManifoldPoint& pt = pManifold->getContactPoint(p);

				if (obA == m_pGhostObject)
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnB())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnB())))
							continue;
					}
				}
				else
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnA())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnA())))
							continue;
					}
				}

				btScalar flDistance = pt.getDistance();
				btScalar flMargin = std::max(obA->getCollisionShape()->getMargin(), obB->getCollisionShape()->getMargin());

				if (flDistance < -flMargin)
				{
					flDistance += flMargin;

					if (flDistance < maxPen)
						maxPen = flDistance;

					btScalar flDot = pt.m_normalWorldOnB.dot(GetUpVector());
					btVector3 vecAdjustment;
					if (flDot > 0.707f)
						vecAdjustment = GetUpVector() * (directionSign * flDistance * 1.001f);
					else
						vecAdjustment = pt.m_normalWorldOnB * (directionSign * flDistance * 1.001f);

					if (vecAdjustment.length2() < 0.001*0.001)
						continue;

					vecCurrentPosition += vecAdjustment;

					bPenetration = true;
				} else {
					//printf("touching %f\n", dist);
				}
			}

			//pManifold->clearManifold();
		}
	}

	btTransform mNew = m_pGhostObject->getWorldTransform();
	mNew.setOrigin(mNew.getOrigin() + (vecCurrentPosition - vecOriginalPosition) * m_vecLinearFactor);
	m_pGhostObject->setWorldTransform(mNew);

	return bPenetration;
}