Files
GTASource/game/scene/EntityIterator.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

317 lines
8.1 KiB
C++

#ifndef _ENTITY_ITERATOR_H_
#define _ENTITY_ITERATOR_H_
#include "scene/entity.h"
#include "Objects/object.h"
#include "objects/DummyObject.h"
#include "scene/building.h"
#include "scene/AnimatedBuilding.h"
#include "Peds/ped.h"
#if !__SPU
enum EntityIteratorFlags
{
IteratePeds = (1<<0),
IterateObjects = (1<<1),
IterateDummyObjects = (1<<2),
IterateBuildings = (1<<3),
IterateAnimatedBuildings = (1<<4),
IterateVehicles = (1<<5),
CheckDistance = (1<<6),
UseOnScreenPedDistance = (1<<7),
IterateAllTypes = IteratePeds|IterateObjects|IterateDummyObjects|IterateBuildings|IterateAnimatedBuildings|IterateVehicles,
};
#define CEntityIteratorDefaultCacheSize (1120) // Reflects the cumulated sizes of the pools for Peds, Objects & Vehicles on 25/5/2011
//-------------------------------------------------------------------------
// Handy class for iterating over certain entity types
//-------------------------------------------------------------------------
typedef struct _CEntityAndDistance
{
CEntity *pEntity;
float fdistance; // Cache distance, since we must calculate this anyway to account for fMaxDistance, otherwise 0
} CEntityAndDistance;
template <int cacheSize = CEntityIteratorDefaultCacheSize>
class CEntityIteratorImpl
{
public:
CEntityIteratorImpl( s32 iteratorFlags, const CEntity* pException = NULL, const Vector3* pvStartPos = NULL, float fMaxDistance = 999.0f );
~CEntityIteratorImpl();
CEntity* GetNext();
float GetLastSuppliedEntityDistanceSQ();
private:
// Create some storage for nEntities ptr's
atFixedArray< CEntityAndDistance, cacheSize > m_EntityCache;
// Does the distance check, if required, and adds to the cache.
void CheckDistanceAndAdd(CEntity *pEntity);
// Makes the EntityAndDistance cache
int CacheMatchingEntities();
s32 m_iCacheIndex; // Used in GetNext()
s32 m_iIteratorFlags;
const CEntity* m_pException;
float m_fMaxDistanceSq;
Vector3 m_vStartPos;
};
//-------------------------------------------------------------------------
// Sorting compare func
//-------------------------------------------------------------------------
extern int CEntityIterator_SortByDistanceLessThanFunc( const CEntityAndDistance *a, const CEntityAndDistance *b );
//-------------------------------------------------------------------------
// Constructor, sets up defaults including types to iterate over
//-------------------------------------------------------------------------
template <int cacheSize>
CEntityIteratorImpl<cacheSize>::CEntityIteratorImpl( s32 iteratorFlags, const CEntity* pException, const Vector3* pvStartPos, float fMaxDistance )
: m_vStartPos(0.0f, 0.0f, 0.0f)
{
m_iIteratorFlags = iteratorFlags;
m_pException = pException;
m_fMaxDistanceSq = fMaxDistance*fMaxDistance;
if( pvStartPos )
{
m_iIteratorFlags |= CheckDistance;
m_vStartPos = *pvStartPos;
}
m_iCacheIndex = 0;
// Fill it as much as we can
s32 nCachedEntities = CacheMatchingEntities( );
// Sort by whatever type
if( m_iIteratorFlags & CheckDistance )
{
// Sort by distance less than
m_EntityCache.QSort(0, nCachedEntities, CEntityIterator_SortByDistanceLessThanFunc );
}
}
//-------------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------------
template <int cacheSize>
CEntityIteratorImpl<cacheSize>::~CEntityIteratorImpl()
{
}
template <int cacheSize>
void CEntityIteratorImpl<cacheSize>::CheckDistanceAndAdd(CEntity *pEntity)
{
// pEntity == our entity or NULL
if( pEntity )
{
float distSquared = 0;
// Ignore if the exception
if( m_pException && pEntity == m_pException )
{
pEntity = NULL;
}
// Ignore if outside a specified distance
else if( m_iIteratorFlags & CheckDistance )
{
distSquared = m_vStartPos.Dist2(VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition()));
if( distSquared > m_fMaxDistanceSq )
{
pEntity = NULL;
}
}
// His this been rejected?
if( pEntity )
{
// NO, add to the cache
CEntityAndDistance temp;
temp.fdistance = distSquared;
temp.pEntity = pEntity;
if( Verifyf( m_EntityCache.GetCount() != m_EntityCache.GetMaxCount(), "Entity Cache isn't large enough"))
{
m_EntityCache.Push(temp);
}
}
}
}
//-------------------------------------------------------------------------
// Caches the Entities that match the passed flags
//-------------------------------------------------------------------------
template <int cacheSize>
int CEntityIteratorImpl<cacheSize>::CacheMatchingEntities()
{
CEntity *pEntity = NULL;
// PEDS
if( m_iIteratorFlags & IteratePeds )
{
CPed::Pool* pPool = CPed::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
// OBJECTS
if( m_iIteratorFlags & IterateObjects )
{
CObject::Pool* pPool = CObject::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
// DUMMY OBJECTS
if( m_iIteratorFlags & IterateDummyObjects )
{
CDummyObject::Pool* pPool = CDummyObject::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
// BUILDINGS
if( m_iIteratorFlags & IterateBuildings )
{
CBuilding::Pool* pPool = CBuilding::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
// ANIMATED BUILDINGS
if( m_iIteratorFlags & IterateAnimatedBuildings )
{
CAnimatedBuilding::Pool* pPool = CAnimatedBuilding::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
// VEHICLES
if( m_iIteratorFlags & IterateVehicles )
{
CVehicle::Pool* pPool = CVehicle::GetPool();
for(int i = 0;i<pPool->GetSize(); i++)
{
pEntity = pPool->GetSlot(i);
CheckDistanceAndAdd(pEntity);
}
}
return m_EntityCache.GetCount(); // The count of the number of entities in the cache
}
//-------------------------------------------------------------------------
// Returns the next entity to be iterated over
//-------------------------------------------------------------------------
template <int cacheSize>
CEntity* CEntityIteratorImpl<cacheSize>::GetNext()
{
CEntity *pEntity = NULL;
if( m_iCacheIndex < m_EntityCache.GetCount() )
{
pEntity = m_EntityCache[m_iCacheIndex].pEntity;
m_iCacheIndex++;
}
return pEntity;
}
//-------------------------------------------------------------------------
// Returns the distance squared of the last entity returned from GetNext()
//-------------------------------------------------------------------------
template <int cacheSize>
float CEntityIteratorImpl<cacheSize>::GetLastSuppliedEntityDistanceSQ()
{
int index = m_iCacheIndex-1;
float distSQ = 0.0f;
if( index >= 0 && index < m_EntityCache.GetCount() )
{
distSQ = m_EntityCache[index].fdistance;
}
return distSQ;
}
typedef CEntityIteratorImpl<CEntityIteratorDefaultCacheSize> CEntityIteratorSorted;
//**************************************************************************//
// The standard entity iterator, no cache and no sorting //
//**************************************************************************//
class CEntityIterator
{
public:
CEntityIterator( s32 iteratorFlags, const CEntity* pException = NULL, const Vec3V* pvStartPos = NULL, float fMaxDistance = 999.0f, float fMaxOnScreenDistance = 999.9f );
~CEntityIterator();
CEntity* GetNext();
private:
enum IteratorStatus {
IS_NotStarted = 0,
IS_IteratingPeds,
IS_IteratingObjects,
IS_IteratingDummyObjects,
IS_IteratingBuildings,
IS_IteratingAnimatedBuildings,
IS_IteratingVehicles,
IS_Finished
};
void AdvanceIteratorStatus();
CEntity* GetNextPed();
CEntity* GetNextObject();
CEntity* GetNextDummyObject();
CEntity* GetNextVehicle();
CEntity* GetNextBuilding();
CEntity* GetNextAnimatedBuilding();
s32 m_iCurrentIndex;
s32 m_iIteratorFlags;
IteratorStatus m_currentStatus;
const CEntity* m_pException;
float m_fMaxDistanceSq;
float m_fMaxOnScreenDistanceSq;
Vec3V m_vStartPos;
};
#endif //!__SPU
#endif // _ENTITY_ITERATOR_H_