Esempio n. 1
0
void CAreaManager::Unregister(CArea const* const pArea)
{
	// Remove the area reference from the entity's area cache.
	m_mapAreaCache.erase_if(SRemoveIfNoAreasLeft(pArea, m_apAreas, m_apAreas.size()));

	// Also remove the area reference itself.
	TAreaPointers::iterator IterAreas(m_apAreas.begin());
	TAreaPointers::const_iterator const IterAreasEnd(m_apAreas.end());

	for (; IterAreas != IterAreasEnd; ++IterAreas)
	{
		if (pArea == (*IterAreas))
		{
			m_apAreas.erase(IterAreas);

			break;
		}
	}

	if (m_apAreas.empty())
	{
		stl::free_container(m_apAreas);
	}

	m_bAreasDirty = true;
}
bool CAreaManager::QueryAreas(EntityId const nEntityID, Vec3 const& rPos, SAreaManagerResult *pResults, int nMaxResults, int& rNumResults)
{
    rNumResults = 0;

    if (pResults)
    {
        // Make sure the area grid is recompiled, if needed, before accessing it
        UpdateDirtyAreas();

        uint32 numAreas = 0;
        TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos));
        TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin());
        TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end());

        for (; IterAreas != IterAreasEnd; ++IterAreas)
        {
            CArea* const pArea = *IterAreas;

#if defined(DEBUG_AREAMANAGER)
            CheckArea(pArea);
#endif // DEBUG_AREAMANAGER

            // check if Area is hidden
            IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID());

            if (pAreaEntity && !pAreaEntity->IsHidden())
            {
                Vec3 Closest3d(ZERO);
                float const fGreatestFadeDistance = pArea->GetGreatestFadeDistance();

                // This is optimized internally and might not recalculate but rather retrieve the cached data.
                float const fDistanceSq = pArea->CalcPointNearDistSq(nEntityID, rPos, Closest3d, false);
                bool const bIsPointWithin = (pArea->CalcPosType(nEntityID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE);
                bool const isNear = ((fDistanceSq > 0.0f) && (fDistanceSq < fGreatestFadeDistance*fGreatestFadeDistance));

                if (isNear || bIsPointWithin)
                {
                    // still have room to put it in?
                    if (rNumResults == nMaxResults)
                        return false;

                    // found area that should go into the results
                    pResults[rNumResults].pArea = pArea;
                    pResults[rNumResults].fDistanceSq = fDistanceSq;
                    pResults[rNumResults].vPosOnHull = Closest3d;
                    pResults[rNumResults].bInside = bIsPointWithin;
                    pResults[rNumResults].bNear = isNear;

                    ++rNumResults;
                }
            }
        }

        return true;
    }

    return false;
}
Esempio n. 3
0
bool CAreaManager::QueryAudioAreas(Vec3 const& rPos, SAudioAreaInfo *pResults, size_t const nMaxResults, size_t& rNumResults)
{
	rNumResults = 0;

	if (pResults != NULL)
	{
		// Make sure the area grid is recompiled, if needed, before accessing it
		UpdateDirtyAreas();

		uint32 numAreas = 0;
		TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos));
		TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin());
		TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end());

		for (; IterAreas != IterAreasEnd; ++IterAreas)
		{
			CArea* const pArea = *IterAreas;

#if defined(DEBUG_AREAMANAGER)
			if (!stl::find(m_apAreas, pArea))
			{
				CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!");
			}
#endif // DEBUG_AREAMANAGER

			// check if Area is hidden
			IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID());

			if (pAreaEntity && !pAreaEntity->IsHidden())
			{
				size_t const nAttachedEntities = pArea->GetEntityAmount();

				if (nAttachedEntities > 0)
				{
					for (size_t iEntity = 0; iEntity < nAttachedEntities; ++iEntity)
					{
						IEntity const* const pEntity = gEnv->pEntitySystem->GetEntity(pArea->GetEntityByIdx(iEntity));

						if (pEntity != NULL)
						{
							IEntityAudioProxy const* const pAudioProxy = (IEntityAudioProxy*)pEntity->GetProxy(ENTITY_PROXY_AUDIO);

							if (pAudioProxy != NULL)
							{
								TAudioEnvironmentID const nEnvironmentID = pAudioProxy->GetEnvironmentID();
								float const fEnvironmentFadeDistance = pAudioProxy->GetEnvironmentFadeDistance();

								if (nEnvironmentID != INVALID_AUDIO_ENVIRONMENT_ID)
								{
									// This is optimized internally and might not recalculate but rather retrieve the cached data.
									bool const bIsPointWithin = (pArea->CalcPosType(INVALID_ENTITYID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE);
									float fEnvironmentAmount = 0.0f;
									if (!bIsPointWithin && (fEnvironmentFadeDistance > 0.0f))
									{
										Vec3 Closest3d(ZERO);
										float const fDistance = sqrt_tpl(pArea->CalcPointNearDistSq(INVALID_ENTITYID, rPos, Closest3d, false));
										if (fDistance <= fEnvironmentFadeDistance)
										{
											fEnvironmentAmount = 1.0f - (fDistance/fEnvironmentFadeDistance);
										}
									}
									else
									{
										fEnvironmentAmount = 1.0f;
									}

									if (fEnvironmentAmount > 0.0f)
									{
										// still have room to put it in?
										if (rNumResults == nMaxResults)
											return false;

										// found area that should go into the results
										pResults[rNumResults].pArea									= pArea;
										pResults[rNumResults].fEnvironmentAmount		= fEnvironmentAmount;
										pResults[rNumResults].nEnvironmentID				= nEnvironmentID;
										pResults[rNumResults].nEnvProvidingEntityID	= pEntity->GetId();

										++rNumResults;
									}
								}
							}
						}
					}
				}
			}
		}
		return true;
	}

	return false;
}
Esempio n. 4
0
void CAreaManager::UpdateEntity(Vec3 const& rPos, IEntity const* const pEntity)
{
	EntityId const nEntityID = pEntity->GetId();
	SAreasCache* pAreaCache = GetAreaCache(nEntityID);

	// Create a new area cache if necessary.
	if (pAreaCache == NULL)
	{
		pAreaCache = MakeAreaCache(nEntityID);
	}

	assert(pAreaCache != NULL);

	// Audio listeners and moving entities affected by environment changes need to update more often 
	// to ensure smooth fading.
	uint32 const nExtendedFlags = pEntity->GetFlagsExtended();
	float const fPosDelta = 
		((nExtendedFlags & ENTITY_FLAG_EXTENDED_AUDIO_LISTENER) != 0) || ((nExtendedFlags & ENTITY_FLAG_EXTENDED_NEEDS_MOVEINSIDE) != 0)
		? 0.01f
		: CVar::es_EntityUpdatePosDelta;

	if (pAreaCache != NULL && !rPos.IsEquivalent(pAreaCache->vLastUpdatePos, fPosDelta))
	{
		pAreaCache->vLastUpdatePos = rPos;

		// First mark all cache entries that as if they are not in the grid.
		TAreaCacheVector::iterator Iter(pAreaCache->aoAreas.begin());
		TAreaCacheVector::const_iterator IterEnd(pAreaCache->aoAreas.end());

		for (; Iter != IterEnd; ++Iter)
		{
			SAreaCacheEntry& rAreaCacheEntry = (*Iter);
			CArea* const pArea = rAreaCacheEntry.pArea;

#if defined(DEBUG_AREAMANAGER)
			if (!stl::find(m_apAreas, pArea))
			{
				CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!");
			}
#endif // DEBUG_AREAMANAGER

			rAreaCacheEntry.bInGrid = false;
			
			// Now pre-calculate position data.
			pArea->InvalidateCachedAreaData(nEntityID);
			pArea->CalcPosType(nEntityID, rPos);
		}

		TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos));
		TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin());
		TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end());

		for (; IterAreas != IterAreasEnd; ++IterAreas)
		{
			// Mark cache entries as if they are in the grid.
			CArea* const pArea = *IterAreas;
			SAreaCacheEntry* pAreaCacheEntry = NULL;

			if (pAreaCache->GetCacheEntry(pArea, &pAreaCacheEntry))
			{
				// cppcheck-suppress nullPointer
				pAreaCacheEntry->bInGrid = true;
			}
			else
			{
				// if they are not yet in the cache, add them
				pAreaCache->aoAreas.push_back(SAreaCacheEntry(pArea, false, false));
				pArea->OnAddedToAreaCache(pEntity);
			}

#if defined(DEBUG_AREAMANAGER)
			if (!stl::find(m_apAreas, pArea))
			{
				CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!");
			}
#endif // DEBUG_AREAMANAGER
		}

		// Go through all cache entries and process the areas.
		Iter = pAreaCache->aoAreas.begin();
		IterEnd = pAreaCache->aoAreas.end();

		for (; Iter != IterEnd; ++Iter)
		{
			SAreaCacheEntry& rAreaCacheEntry = (*Iter);
			CArea* const pArea = rAreaCacheEntry.pArea;

#if defined(DEBUG_AREAMANAGER)
			if (!stl::find(m_apAreas, pArea))
			{
				CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!");
			}
#endif // DEBUG_AREAMANAGER

			// check if Area is hidden
			IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID());
			bool bIsHidden = (pAreaEntity && pAreaEntity->IsHidden());

			// area was just hidden
			if (bIsHidden && pArea->IsActive())
			{
				pArea->LeaveArea(pEntity);
				pArea->LeaveNearArea(pEntity);
				rAreaCacheEntry.bNear		= false;
				rAreaCacheEntry.bInside	= false;
				pArea->SetActive(false);
				continue;
			}

			// area was just unhidden
			if (!bIsHidden && !pArea->IsActive())
			{
				// ProcessArea will take care of properly setting cache entry data.
				rAreaCacheEntry.bNear		= false;
				rAreaCacheEntry.bInside	= false;
				pArea->SetActive(true);
			}

			// We process only for active areas in which grid we are.
			// Areas in our cache in which grid we are not get removed down below anyhow.
			if (pArea->IsActive())
			{
				ProcessArea(pArea, rAreaCacheEntry, pAreaCache, rPos, pEntity);
			}
		}

		// Go through all areas again and send accumulated events. (needs to be done in a separate step)
		Iter = pAreaCache->aoAreas.begin();

		for (; Iter != IterEnd; ++Iter)
		{
			SAreaCacheEntry& rAreaCacheEntry = (*Iter);
			CArea* const pArea = rAreaCacheEntry.pArea;

#if defined(DEBUG_AREAMANAGER)
			if (!stl::find(m_apAreas, pArea))
			{
				CryFatalError("<AreaManager>: area in entity-area-cache not found in overall areas list!");
			}
#endif // DEBUG_AREAMANAGER

			pArea->SendCachedEventsFor(nEntityID);
		}

		// Remove all entries in the cache which are no longer in the grid.
		if (!pAreaCache->aoAreas.empty())
		{
			pAreaCache->aoAreas.erase(std::remove_if(pAreaCache->aoAreas.begin(), pAreaCache->aoAreas.end(), SIsNotInGrid(pEntity, m_apAreas, m_apAreas.size())), pAreaCache->aoAreas.end());
		}

		if (pAreaCache->aoAreas.empty())
		{
			DeleteAreaCache(nEntityID);
		}
	}
}