!I (1670409):
[CRYENGINE.git] / Code / CryEngine / CryAction / RangeSignalingSystem / PersonalRangeSignaling.cpp
blobd60546b15ef70aeafefe05a8f1d27cf454e888e9
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 /********************************************************************
4 ---------------------------------------------------------------------
5 File name: Range.h
6 $Id$
7 $DateTime$
8 Description: Manager per-actor signals to other actors by range
9 ---------------------------------------------------------------------
10 History:
11 - 09:04:2007 : Created by Ricardo Pillosu
13 *********************************************************************/
14 #include "StdAfx.h"
15 #include "PersonalRangeSignaling.h"
16 #include "RangeSignaling.h"
17 #include "Range.h"
18 #include "AngleAlert.h"
19 #include "IUIDraw.h"
21 #include <functional>
22 #include <CryAISystem/IAIObject.h>
24 // Description:
25 // Constructor
26 // Arguments:
28 // Return:
30 CPersonalRangeSignaling::CPersonalRangeSignaling(CRangeSignaling* pParent) : m_bInit(false), m_bEnabled(false), m_pParent(pParent), m_EntityId(0)
32 CRY_ASSERT(pParent != NULL);
34 m_pDefaultFont = gEnv->pCryFont->GetFont("default");
35 CRY_ASSERT(m_pDefaultFont);
38 // Description:
39 // Destructor
40 // Arguments:
42 // Return:
44 CPersonalRangeSignaling::~CPersonalRangeSignaling()
46 Reset();
48 for (int i = 0; i < m_vecRanges.size(); ++i)
50 SAFE_DELETE(m_vecRanges[i]);
53 m_vecRanges.clear();
55 MapTargetRanges::iterator itTargetRange = m_mapTargetRanges.begin();
56 MapTargetRanges::iterator itTargetRangeEnd = m_mapTargetRanges.end();
57 for (; itTargetRange != itTargetRangeEnd; ++itTargetRange)
59 for (int i = 0; i < itTargetRange->second.size(); ++i)
61 SAFE_DELETE(itTargetRange->second[i]);
65 m_mapTargetRanges.clear();
67 for (int i = 0; i < m_vecAngles.size(); ++i)
69 SAFE_DELETE(m_vecAngles[i]);
72 m_vecAngles.clear();
74 SetListener(false);
77 // Description:
79 // Arguments:
81 // Return:
83 bool CPersonalRangeSignaling::Init(EntityId Id)
85 CRY_ASSERT(m_bInit == false);
87 m_EntityId = Id;
88 m_bInit = true;
90 // Enabled state starts off matching proxy's state
91 IAIActorProxy* pAIProxy = GetEntityAIProxy(m_EntityId);
92 SetEnabled(pAIProxy && pAIProxy->IsEnabled());
94 if (GetActor() == NULL)
96 m_bInit = false;
98 else
100 SetListener(true);
103 return(m_bInit);
106 // Description: std::less functor template specialization, so to make comparison of two CRange pointers
107 // work properly
109 // Arguments: two pointers to CRange instances
111 // Return: comparison result
113 namespace std
116 template<>
117 struct less<CRange*>
119 bool operator()(const CRange* pRange1, const CRange* pRange2) const
121 CRY_ASSERT(pRange1 != NULL);
122 CRY_ASSERT(pRange2 != NULL);
124 return((*pRange1) < (*pRange2));
130 bool CompareRange(CRange* pRange1, CRange* pRange2)
132 CRY_ASSERT(pRange1 != NULL);
133 CRY_ASSERT(pRange2 != NULL);
135 return((*pRange1) < (*pRange2));
138 bool CompareAngle(CAngleAlert* pAngle1, CAngleAlert* pAngle2)
140 CRY_ASSERT(pAngle1 != NULL);
141 CRY_ASSERT(pAngle2 != NULL);
143 return((*pAngle1) < (*pAngle2));
146 // Description:
148 // Arguments:
150 // Return:
152 bool CPersonalRangeSignaling::AddRangeSignal(float fRadius, float fBoundary, const char* sSignal, IAISignalExtraData* pData /*=NULL*/)
154 CRY_ASSERT(m_bInit == true);
155 CRY_ASSERT(sSignal != NULL);
156 CRY_ASSERT(fRadius > 0.5f);
157 CRY_ASSERT(fBoundary >= 0.0f);
159 bool bRet = true;
160 CRange* pRange = SearchRange(sSignal, m_vecRanges);
162 if (pRange == NULL)
164 pRange = new CRange(this);
165 m_vecRanges.push_back(pRange);
168 pRange->Init(fRadius, fBoundary, sSignal, pData);
169 std::sort(m_vecRanges.begin(), m_vecRanges.end(), &CompareRange); // std::less is properly overridden
171 return(bRet);
174 // Description:
176 // Arguments:
178 // Return:
180 bool CPersonalRangeSignaling::AddTargetRangeSignal(EntityId IdTarget, float fRadius, float fBoundary, const char* sSignal, IAISignalExtraData* pData /*= NULL*/)
182 CRY_ASSERT(m_bInit == true);
183 CRY_ASSERT(GetActor());
184 CRY_ASSERT(IdTarget > 0);
185 CRY_ASSERT(sSignal != NULL);
186 CRY_ASSERT(fRadius > 0.5f);
187 CRY_ASSERT(fBoundary >= 0.0f);
189 bool bRet = true;
190 CRange* pRange = SearchRange(sSignal, m_mapTargetRanges[IdTarget]);
192 if (pRange == NULL)
194 pRange = new CRange(this);
195 m_mapTargetRanges[IdTarget].push_back(pRange);
198 pRange->Init(fRadius, fBoundary, sSignal, pData);
199 std::sort(m_mapTargetRanges[IdTarget].begin(), m_mapTargetRanges[IdTarget].end(), &CompareRange); // std::less is properly overridden
201 return(bRet);
204 // Description:
206 // Arguments:
208 // Return:
210 bool CPersonalRangeSignaling::AddAngleSignal(float fAngle, float fBoundary, const char* sSignal, IAISignalExtraData* pData /*=NULL*/)
212 CRY_ASSERT(m_bInit == true);
213 CRY_ASSERT(sSignal != NULL);
214 CRY_ASSERT(fAngle > 0.5f);
215 CRY_ASSERT(fBoundary >= 0.0f);
217 bool bRet = true;
218 CAngleAlert* pAngle = SearchAngle(sSignal);
220 if (pAngle == NULL)
222 pAngle = new CAngleAlert(this);
223 m_vecAngles.push_back(pAngle);
226 pAngle->Init(fAngle, fBoundary, sSignal, pData);
227 std::sort(m_vecAngles.begin(), m_vecAngles.end(), &CompareAngle);
229 return(bRet);
232 // Description:
234 // Arguments:
236 // Return:
238 bool CPersonalRangeSignaling::Update(float fElapsedTime, uint32 uDebugOrder)
240 CRY_ASSERT(m_bInit == true);
242 bool bRet = false;
244 if (m_bEnabled)
246 if (uDebugOrder > 0)
248 DebugDraw(uDebugOrder);
251 // Iterate all actors and check range to them
252 IActorIteratorPtr pActorIt = CCryAction::GetCryAction()->GetIActorSystem()->CreateActorIterator();
253 while (IActor* pActor = pActorIt->Next())
255 EntityId entityId = pActor->GetEntityId();
256 if (entityId != GetEntityId())
258 // Skip over if not enabled
259 IAIObject const* pAIObject = GetEntityAI(entityId);
260 if (!pAIObject || pAIObject->IsEnabled())
262 CheckActorRanges(pActor);
263 CheckActorAngles(pActor);
265 // Do check on target ranges
266 MapTargetRanges::iterator itTargetRanges = m_mapTargetRanges.find(entityId);
267 if (itTargetRanges != m_mapTargetRanges.end())
269 CheckActorTargetRanges(pActor);
275 bRet = true;
278 return(bRet);
281 // Description:
283 // Arguments:
285 // Return:
287 void CPersonalRangeSignaling::CheckActorRanges(IActor* pActor)
289 CRY_ASSERT(pActor != NULL);
291 MapRangeSignals::iterator it = m_mapRangeSignalsSent.find(pActor->GetEntityId());
292 CRange const* pRange = GetRangeTo(pActor->GetEntity()->GetPos(), m_vecRanges);
293 CRange const* pOldRange = ((it != m_mapRangeSignalsSent.end()) ? it->second : NULL);
295 if (pRange != pOldRange)
297 if (pRange != NULL)
299 // Check boundary
300 if (GetRangeTo(pActor->GetEntity()->GetPos(), m_vecRanges, true) != pOldRange)
302 if (pOldRange == NULL)
304 m_mapRangeSignalsSent.insert(std::pair<EntityId, CRange const*>(pActor->GetEntityId(), pRange));
306 else
308 it->second = pRange;
311 SendSignal(pActor, pRange->GetSignal(), pRange->GetSignalData());
314 else
316 m_mapRangeSignalsSent.erase(it);
321 // Description:
323 // Arguments:
325 // Return:
327 void CPersonalRangeSignaling::CheckActorTargetRanges(IActor* pActor)
329 CRY_ASSERT(pActor != NULL);
331 MapTargetRanges::iterator itTargetRanges = m_mapTargetRanges.find(pActor->GetEntityId());
332 CRY_ASSERT(itTargetRanges != m_mapTargetRanges.end());
334 MapRangeSignals::iterator it = m_mapTargetRangeSignalsSent.find(pActor->GetEntityId());
335 CRange const* pRange = GetRangeTo(pActor->GetEntity()->GetPos(), itTargetRanges->second);
336 CRange const* pOldRange = ((it != m_mapTargetRangeSignalsSent.end()) ? it->second : NULL);
338 if (pRange != pOldRange)
340 if (pRange != NULL)
342 // Check boundary
343 if (GetRangeTo(pActor->GetEntity()->GetPos(), itTargetRanges->second, true) != pOldRange)
345 if (pOldRange == NULL)
347 m_mapTargetRangeSignalsSent.insert(std::pair<EntityId, CRange const*>(pActor->GetEntityId(), pRange));
349 else
351 it->second = pRange;
354 IActor* pMe = GetActor();
355 CRY_ASSERT_MESSAGE(pMe, "An actor has been removed without cleaning up its range signals.");
356 if (pMe)
358 SendSignal(pMe, pRange->GetSignal(), pRange->GetSignalData());
362 else
364 m_mapTargetRangeSignalsSent.erase(it);
369 // Description:
371 // Arguments:
373 // Return:
375 void CPersonalRangeSignaling::CheckActorAngles(IActor* pActor)
377 CRY_ASSERT(pActor != NULL);
379 MapAngleSignals::iterator it = m_mapAngleSignalsSent.find(pActor->GetEntityId());
380 CAngleAlert const* pAngle = GetAngleTo(pActor->GetEntity()->GetPos());
381 CAngleAlert const* pOldAngle = ((it != m_mapAngleSignalsSent.end()) ? it->second : NULL);
383 if (pAngle != pOldAngle)
385 if (pAngle != NULL)
387 // Check boundary
388 if (GetAngleTo(pActor->GetEntity()->GetPos(), true) != pOldAngle)
390 if (pOldAngle == NULL)
392 m_mapAngleSignalsSent.insert(std::pair<EntityId, CAngleAlert const*>(pActor->GetEntityId(), pAngle));
394 else
396 it->second = pAngle;
399 SendSignal(pActor, pAngle->GetSignal(), pAngle->GetSignalData());
402 else
404 m_mapAngleSignalsSent.erase(it);
409 // Description:
411 // Arguments:
413 // Return:
415 void CPersonalRangeSignaling::Reset()
417 m_mapRangeSignalsSent.clear();
418 m_mapTargetRangeSignalsSent.clear();
419 m_mapAngleSignalsSent.clear();
420 m_mapTargetRanges.clear();
423 // Description:
425 // Arguments:
427 // Return:
429 void CPersonalRangeSignaling::OnProxyReset()
431 // Reset listener
432 SetListener(true);
435 // Description:
437 // Arguments:
439 // Return:
441 void CPersonalRangeSignaling::SetEnabled(bool bEnable)
443 CRY_ASSERT(m_bInit == true);
445 m_bEnabled = bEnable;
448 // Description:
450 // Arguments:
452 // Return:
454 EntityId CPersonalRangeSignaling::GetEntityId() const
456 CRY_ASSERT(m_bInit == true);
458 return(m_EntityId);
461 // Description:
463 // Arguments:
465 // Return:
467 IEntity* CPersonalRangeSignaling::GetEntity()
469 CRY_ASSERT(m_bInit == true);
471 return(gEnv->pEntitySystem->GetEntity(m_EntityId));
474 // Description:
476 // Arguments:
478 // Return:
480 IEntity const* CPersonalRangeSignaling::GetEntity() const
482 CRY_ASSERT(m_bInit == true);
484 return(gEnv->pEntitySystem->GetEntity(m_EntityId));
487 // Description:
489 // Arguments:
491 // Return:
493 IActor* CPersonalRangeSignaling::GetActor()
495 CRY_ASSERT(m_bInit == true);
497 return(CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_EntityId));
500 // Description:
502 // Arguments:
504 // Return:
506 void CPersonalRangeSignaling::SendSignal(IActor* pActor, const string& sSignal, IAISignalExtraData* pData /*= NULL*/) const
508 CRY_ASSERT(m_bInit == true);
509 CRY_ASSERT(pActor != NULL);
510 CRY_ASSERT(sSignal.length() > 0);
512 IAIObject* pAI = pActor->GetEntity()->GetAI();
513 //CRY_ASSERT(pAI); Not every actor has an ai, and nor do they need it
514 if (pAI && gEnv->pAISystem)
516 gEnv->pAISystem->SendSignal(SIGNALFILTER_SENDER, 1, sSignal, pAI, PrepareSignalData(pData));
520 // Description:
522 // Arguments:
524 // Return:
526 IAISignalExtraData* CPersonalRangeSignaling::PrepareSignalData(IAISignalExtraData* pRequestedData) const
528 IAISignalExtraData* pSendData = gEnv->pAISystem->CreateSignalExtraData();
529 if (pRequestedData)
531 // Clone requested data and send it over
532 *pSendData = *pRequestedData;
534 else
536 // Send useful info
537 pSendData->nID = GetEntityId();
538 pSendData->point = (GetEntity() ? GetEntity()->GetWorldPos() : Vec3Constants<float>::fVec3_Zero);
541 return (pSendData);
544 // Description:
546 // Arguments:
548 // Return:
550 CRange const* CPersonalRangeSignaling::GetRangeTo(const Vec3& vPos, const VecRanges& vecRangeList, bool bUseBoundary) const
552 IEntity const* pEntity = GetEntity();
553 if (!pEntity)
554 return(NULL);
556 CRange const* pRange = NULL;
557 Vec3 vOrigin = pEntity->GetPos();
558 float fSquaredDist = (vPos - vOrigin).GetLengthSquared();
560 for (int i = 0; i < vecRangeList.size(); ++i)
562 bool bInRange = false;
564 if (bUseBoundary == true)
566 bInRange = (vecRangeList[i]->IsInRangePlusBoundary(fSquaredDist) == true);
568 else
570 bInRange = (vecRangeList[i]->IsInRange(fSquaredDist) == true);
573 if (bInRange == true)
575 pRange = vecRangeList[i];
576 break;
580 return(pRange);
583 // Description:
585 // Arguments:
587 // Return:
589 CAngleAlert const* CPersonalRangeSignaling::GetAngleTo(const Vec3& vPos, bool bUseBoundary) const
591 CAngleAlert const* pAngle = NULL;
592 float fAngleDiff = -1.0f;
594 for (int i = 0; i < m_vecAngles.size(); ++i)
596 bool bInAngle = false;
598 if (fAngleDiff < 0.0f)
600 fAngleDiff = m_vecAngles[i]->GetAngleTo(vPos);
603 if (bUseBoundary == true)
605 bInAngle = (m_vecAngles[i]->CheckPlusBoundary(fAngleDiff) == true);
607 else
609 bInAngle = (m_vecAngles[i]->Check(fAngleDiff) == true);
612 if (bInAngle == true)
614 pAngle = m_vecAngles[i];
615 break;
619 return(pAngle);
622 // Description:
624 // Arguments:
626 // Return:
628 CRange* CPersonalRangeSignaling::SearchRange(const char* sSignal, const VecRanges& vecRangeList) const
630 CRange* pRange = NULL;
632 for (int i = 0; i < vecRangeList.size(); ++i)
634 if (vecRangeList[i]->GetSignal().compareNoCase(sSignal) == 0)
636 pRange = vecRangeList[i];
637 break;
641 return(pRange);
644 // Description:
646 // Arguments:
648 // Return:
650 CAngleAlert* CPersonalRangeSignaling::SearchAngle(const char* sSignal) const
652 CAngleAlert* pAngle = NULL;
654 for (int i = 0; i < m_vecAngles.size(); ++i)
656 if (m_vecAngles[i]->GetSignal().compareNoCase(sSignal) == 0)
658 pAngle = m_vecAngles[i];
659 break;
663 return(pAngle);
666 // Description:
668 // Arguments:
670 // Return:
672 void CPersonalRangeSignaling::DebugDraw(uint32 uOrder) const
674 CRY_ASSERT(m_bInit == true);
676 float x = 120.0f;
677 float y = 100.0f + (float(uOrder) * 10.0f);
678 float r = 0.0f;
679 float g = 8.0f;
680 float b = 0.0f;
682 char txt[512] = "\0";
684 //cry_sprintf( txt, "%s > %s: %0.1f / %0.1f", GetActor()->GetEntity()->GetName(), m_sSignal.c_str(), m_fTimer, m_fRateMax );
685 //IRenderAuxText::Draw2dLabel( x,y, 13.0f, ColorF(r,g,b), false, "%s", txt);
688 // Description:
690 // Arguments:
692 // Return:
694 IAIObject const* CPersonalRangeSignaling::GetEntityAI(EntityId entityId) const
696 IAIObject const* pAIObject = NULL;
698 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entityId);
699 if (pEntity)
701 pAIObject = pEntity->GetAI();
704 return pAIObject;
707 // Description:
709 // Arguments:
711 // Return:
713 IAIActorProxy* CPersonalRangeSignaling::GetEntityAIProxy(EntityId entityId) const
715 IAIActorProxy* pAIProxy = NULL;
717 IAIObject const* pAIObject = GetEntityAI(m_EntityId);
718 if (pAIObject)
720 pAIProxy = pAIObject->GetProxy();
723 return pAIProxy;
726 // Description:
728 // Arguments:
730 // Return:
732 void CPersonalRangeSignaling::SetListener(bool bAdd)
734 CAIProxy* pAIProxy = static_cast<CAIProxy*>(GetEntityAIProxy(m_EntityId));
735 if (pAIProxy)
737 if (bAdd)
738 pAIProxy->AddListener(this);
739 else
740 pAIProxy->RemoveListener(this);
744 // Description:
746 // Arguments:
748 // Return:
750 void CPersonalRangeSignaling::OnAIProxyEnabled(bool bEnabled)
752 if (bEnabled)
754 Reset();
755 SetEnabled(true);
757 else
759 SetEnabled(false);