// // Copyright (c) 2010-2011 Matthew Jack and Doug Binks // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. #include "IPerceptionManager.h" #include "IObjectUtils.h" #include "IGameObject.h" #include "GlobalParameters.h" #include "../../RuntimeObjectSystem/ObjectInterfacePerModule.h" #include "../../Systems/SystemTable.h" #include "../../Systems/IEntitySystem.h" #include "../../Systems/ILogSystem.h" #include "../../RuntimeObjectSystem/ISimpleSerializer.h" #include #include #include #include const AUVec3f ZERO(0,0,0); class PerceptionManager: public IPerceptionManager { // We have two sets of typedefs here, one for fast access during runtime, and another // that is used for safe storage during serialization typedef std::vector TGameObjects; typedef std::vector TGameObjectIds; public: PerceptionManager() : m_bDoUpdate(false) , m_pGlobalParameters(0) { m_Objects.resize(EGO_COUNT); } virtual ~PerceptionManager() { ((IGameManager*)IObjectUtils::GetUniqueInterface( "GameManager", IID_IGAMEMANAGER ))->RemoveListener(this); } // IObject virtual void Serialize( ISimpleSerializer *pSerializer ) { AU_ASSERT(pSerializer); SERIALIZE(m_bDoUpdate); SerializeObjectsList( pSerializer ); } virtual void Init( bool isFirstInit ) { IGameManager* pGameManager = (IGameManager*)IObjectUtils::GetUniqueInterface( "GameManager", IID_IGAMEMANAGER ); pGameManager->AddListener(this); m_pGlobalParameters = pGameManager->GetGlobalParameters(); } // ~IObject // IGameEventListener virtual void OnGameReset() { for (int i=0; iGetGameObjectType()].push_back( pGameObject ); } virtual void OnGameObjectAboutToDestroy( IGameObject* pGameObject ) { TGameObjects& data = m_Objects[pGameObject->GetGameObjectType()]; TGameObjects::iterator it = std::find(data.begin(), data.end(), pGameObject); if (it != data.end()) { data.erase(it); } } // ~IGameEventListener // IPerceptionManager virtual int GetNumberPerceived( const IGameObject* pPerceiver, EGameObject perceivedType ) const { AUVec3f center = pPerceiver->GetEntity()->GetPosition(); float radius = m_pGlobalParameters->go[pPerceiver->GetGameObjectType()].perceptionDist[perceivedType]; m_workingData.clear(); // Fill working array with results DoGetPerceived( m_Objects[perceivedType], pPerceiver, center, radius ); return (int)m_workingData.size(); } virtual int GetNumberPerceived( const IGameObject* pPerceiver ) const { int num = 0; for (int i=0; i& objects ) const { objects.Clear(); DoAddPerceived( pPerceiver, perceivedType, objects ); } virtual void AddPerceived( const IGameObject* pPerceiver, EGameObject perceivedType, IAUDynArray& objects ) const { DoAddPerceived( pPerceiver, perceivedType, objects ); } virtual void GetPerceived( const IGameObject* pPerceiver, IAUDynArray& objects ) const { objects.Clear(); AUVec3f center = pPerceiver->GetEntity()->GetPosition(); m_workingData.clear(); // Fill working array with results for (int i=0; igo[pPerceiver->GetGameObjectType()].perceptionDist[i]; DoGetPerceived( m_Objects[i], pPerceiver, center, radius ); } DoAddToArray(objects); } virtual AUVec3f GetGlobalAveragePos( EGameObject perceivedType ) const { AUVec3f avg = ZERO; const TGameObjects& data = m_Objects[perceivedType]; size_t count = data.size(); if (count > 0) { for (size_t i=0; iGetEntity()->GetPosition(); } avg /= (float)count; } return avg; } virtual AUVec3f GetGlobalAveragePos() const { AUVec3f avg = ZERO; for (int i=0; iGetEntity()->GetPosition(); float radius = m_pGlobalParameters->go[pPerceiver->GetGameObjectType()].perceptionDist[perceivedType]; m_workingData.clear(); // Fill working array with results DoGetPerceived( m_Objects[perceivedType], pPerceiver, center, radius ); // Calculate average position AUVec3f avg = ZERO; size_t count = m_workingData.size(); if (count > 0) { for (size_t i=0; iGetEntity()->GetPosition(); } avg /= (float)count; } return avg; } virtual AUVec3f GetPerceivedAveragePos( const IGameObject* pPerceiver ) const { AUVec3f avg = ZERO; for (int i=0; i& objects ) const { AUVec3f center = pPerceiver->GetEntity()->GetPosition(); float radius = m_pGlobalParameters->go[pPerceiver->GetGameObjectType()].perceptionDist[perceivedType]; m_workingData.clear(); // Fill working array with results DoGetPerceived( m_Objects[perceivedType], pPerceiver, center, radius ); DoAddToArray(objects); } // Pushes results into m_workingData void DoGetPerceived( const TGameObjects& data, const IGameObject* pPerceiver, const AUVec3f& center, float radius ) const { size_t count = data.size(); for (size_t j=0; jGetEntity()->GetPosition() - center).Magnitude(); if ( pObj->GetEntityId() != pPerceiver->GetEntityId() && dist < radius ) { m_workingData.push_back( pObj ); } } } // Fills with current contents of m_workingData void DoAddToArray( IAUDynArray& objects ) const { size_t count = m_workingData.size(); size_t origCount = objects.Size(); objects.Resize(origCount + count); for (size_t i=0; i < count; ++i) { objects[i+origCount] = m_workingData[i]->GetObjectId(); } } void SerializeObjectsList( ISimpleSerializer *pSerializer ) { std::vector m_ObjectIds; if ( !pSerializer->IsLoading() ) { // Create a collection of ObjectIds that matches m_Objects pointer collection m_ObjectIds.resize(EGO_COUNT); for (int i=0; iGetObjectId(); } } } SERIALIZE(m_ObjectIds); if ( pSerializer->IsLoading() ) { // Rebuild m_objects pointer collection for (int i=0; i m_Objects; // Keeps its own set of valid GameObjects for more efficient calculations bool m_bDoUpdate; GlobalParameters* m_pGlobalParameters; mutable TGameObjects m_workingData; // Vector to be used when making calculations to avoid constant allocations }; REGISTERCLASS(PerceptionManager);