1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 /*************************************************************************
4 -------------------------------------------------------------------------
8 -------------------------------------------------------------------------
10 - 7:9:2004 17:48 : Created by Márcio Martins
11 - 15:9:2010 12:30 : Revised by Dean Claassen
13 *************************************************************************/
15 #include "ActionMap.h"
16 #include "ActionMapManager.h"
17 #include <CrySystem/IConsole.h>
18 #include <CryCore/CryCrc32.h>
20 #define ACTIONINPUT_NAME_STR "name"
22 #define ACTIONINPUT_ONPRESS_STR "onPress"
23 #define ACTIONINPUT_ONRELEASE_STR "onRelease"
24 #define ACTIONINPUT_ONHOLD_STR "onHold"
25 #define ACTIONINPUT_ALWAYS_STR "always"
27 #define ACTIONINPUT_CONSOLECMD_STR "consoleCmd"
28 #define ACTIONINPUT_NOMODIFIERS_STR "noModifiers"
29 #define ACTIONINPUT_RETRIGGERABLE_STR "retriggerable"
31 #define ACTIONINPUT_PRESSTRIGGERDELAY_STR "pressTriggerDelay"
32 #define ACTIONINPUT_PRESSTRIGGERDELAY_REPEATOVERRIDE_STR "pressTriggerDelayRepeatOverride"
33 #define ACTIONINPUT_PRESSDELAYPRIORITY_STR "pressDelayPriority"
35 #define ACTIONINPUT_HOLDTRIGGERDELAY_STR "holdTriggerDelay"
36 #define ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR "holdTriggerDelayRepeatOverride"
37 #define ACTIONINPUT_HOLDREPEATDELAY_STR "holdRepeatDelay"
38 #define ACTIONINPUT_RELEASETRIGGERTHRESHOLD_STR "releaseTriggerThreshold"
40 #define ACTIONINPUT_INPUTSTOBLOCK_STR "inputsToBlock"
41 #define ACTIONINPUT_INPUTBLOCKTIME_STR "inputBlockTime"
42 #define ACTIONINPUT_INPUTBLOCKACTIVATION_STR "inputBlockActivation"
43 #define ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR "inputBlockDeviceIndex"
45 #define ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR "CLEARALL"
47 #define ACTIONINPUT_USEANALOGCOMPARE_STR "useAnalogCompare"
48 #define ACTIONINPUT_ANALOGCOMPAREVAL_STR "analogCompareVal"
49 #define ACTIONINPUT_ANALOGCOMPAREOP_STR "analogCompareOp"
51 static const char* s_analogCompareOpEqualsStr
= "EQUALS";
52 static const char* s_analogCompareOpNotEqualsStr
= "NOTEQUALS";
53 static const char* s_analogCompareOpGreaterThanStr
= "GREATERTHAN";
54 static const char* s_analogCompareOpLessThanStr
= "LESSTHAN";
56 //------------------------------------------------------------------------
59 //------------------------------------------------------------------------
60 bool operator()(const CCryName
& lhs
, const CCryName
& rhs
) const
62 assert(lhs
.c_str() != 0);
63 assert(rhs
.c_str() != 0);
64 return strcmp(lhs
.c_str(), rhs
.c_str()) < 0;
68 //------------------------------------------------------------------------
69 CActionMapAction::CActionMapAction()
70 : m_triggeredInput("")
72 , m_iNumRebindedInputs(0)
73 , m_pParentActionMap(NULL
)
77 //------------------------------------------------------------------------
78 CActionMapAction::~CActionMapAction()
80 RemoveAllActionInputs();
83 //------------------------------------------------------------------------
84 void CActionMapAction::GetMemoryUsage(ICrySizer
* pSizer
) const
86 TActionInputs::const_iterator iter
= m_actionInputs
.begin();
87 TActionInputs::const_iterator iterEnd
= m_actionInputs
.end();
89 for (; iter
!= iterEnd
; ++iter
)
91 const SActionInput
* pActionInput
= *iter
;
92 pSizer
->AddObject(pActionInput
->input
);
93 pSizer
->AddObject(pActionInput
->defaultInput
);
97 //------------------------------------------------------------------------
98 bool CActionMapAction::AddActionInput(const SActionInput
& actionInput
, const int iByDeviceIndex
)
100 // Double check no invalid inputs
101 if (strcmp(actionInput
.input
, "") == 0)
103 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddActionInput: Can't add empty input");
107 // Don't require to have a crc when passing in, but if has one, check it
108 uint32 inputCRC
= CCrc32::ComputeLowercase(actionInput
.input
);
109 if (actionInput
.inputCRC
!= 0)
111 if (inputCRC
!= actionInput
.inputCRC
)
113 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddActionInput: Can't add, string crc specified doesn't match actual crc");
118 SActionInput
* pActionInput
= FindActionInput(inputCRC
);
119 if (pActionInput
!= NULL
)
121 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CAction::AddActionInput::Unable to add input with input: %s, either input already exists, or possibly 2 different inputs sharing same crc value", actionInput
.input
.c_str());
125 SActionInput
* pNewActionInput
= new SActionInput();
126 *pNewActionInput
= actionInput
;
127 pNewActionInput
->input
.MakeLower();
128 pNewActionInput
->defaultInput
.MakeLower();
129 pNewActionInput
->inputCRC
= inputCRC
;
131 if (iByDeviceIndex
== -1)
133 m_actionInputs
.push_back(pNewActionInput
);
138 int iCurrentByDeviceIndex
= 0;
141 TActionInputs::iterator iter
= m_actionInputs
.begin();
142 TActionInputs::iterator iterEnd
= m_actionInputs
.end();
143 for (; iter
!= iterEnd
; ++iter
)
145 SActionInput
* pContainedActionInput
= *iter
;
146 CRY_ASSERT(pContainedActionInput
!= NULL
);
148 if (pContainedActionInput
->inputDevice
== actionInput
.inputDevice
&& iCurrentByDeviceIndex
== iByDeviceIndex
)
150 m_actionInputs
.insert(iter
, pNewActionInput
);
155 ++iCurrentByDeviceIndex
;
159 // Reached here so iByDeviceIndex must be incorrect
160 SAFE_DELETE(pNewActionInput
);
161 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CAction::AddActionInput: Failed adding input with input: %s, iByDeviceIndex: %d, is incorrect", actionInput
.input
.c_str(), iByDeviceIndex
);
166 //------------------------------------------------------------------------
167 bool CActionMapAction::RemoveActionInput(uint32 inputCRC
)
169 TActionInputs::iterator iter
= m_actionInputs
.begin();
170 TActionInputs::iterator iterEnd
= m_actionInputs
.end();
171 for (; iter
!= iterEnd
; ++iter
)
173 SActionInput
* pActionInput
= *iter
;
174 CRY_ASSERT(pActionInput
!= NULL
);
175 if (pActionInput
->inputCRC
== inputCRC
)
177 SAFE_DELETE(pActionInput
);
178 m_actionInputs
.erase(iter
);
186 //------------------------------------------------------------------------
187 void CActionMapAction::RemoveAllActionInputs()
189 TActionInputs::iterator iter
= m_actionInputs
.begin();
190 TActionInputs::iterator iterEnd
= m_actionInputs
.end();
191 for (; iter
!= iterEnd
; ++iter
)
193 SActionInput
* pActionInput
= *iter
;
194 CRY_ASSERT(pActionInput
!= NULL
);
195 SAFE_DELETE(pActionInput
);
197 m_actionInputs
.clear();
200 //------------------------------------------------------------------------
201 SActionInput
* CActionMapAction::FindActionInput(uint32 inputCRC
)
203 SActionInput
* pFoundActionInput
= NULL
;
205 TActionInputs::iterator iter
= m_actionInputs
.begin();
206 TActionInputs::iterator iterEnd
= m_actionInputs
.end();
207 for (; iter
!= iterEnd
; ++iter
)
209 SActionInput
* pActionInput
= *iter
;
210 CRY_ASSERT(pActionInput
!= NULL
);
211 if (pActionInput
->inputCRC
== inputCRC
)
213 pFoundActionInput
= pActionInput
;
218 return pFoundActionInput
;
221 //------------------------------------------------------------------------
222 const SActionInput
* CActionMapAction::FindActionInput(const char* szInput
) const
224 uint32 inputCRC
= CCrc32::ComputeLowercase(szInput
);
226 const SActionInput
* pFoundActionInput
= NULL
;
228 TActionInputs::const_iterator iter
= m_actionInputs
.begin();
229 TActionInputs::const_iterator iterEnd
= m_actionInputs
.end();
230 for (; iter
!= iterEnd
; ++iter
)
232 const SActionInput
* pActionInput
= *iter
;
233 CRY_ASSERT(pActionInput
!= NULL
);
234 if (pActionInput
->inputCRC
== inputCRC
)
236 pFoundActionInput
= pActionInput
;
241 return pFoundActionInput
;
244 //------------------------------------------------------------------------
245 SActionInput
* CActionMapAction::GetActionInput(const int iIndex
)
247 CRY_ASSERT(iIndex
>= 0 && iIndex
< (int)m_actionInputs
.size());
248 if (iIndex
>= 0 && iIndex
< (int)m_actionInputs
.size())
250 return m_actionInputs
[iIndex
];
256 //------------------------------------------------------------------------
257 SActionInput
* CActionMapAction::GetActionInput(const EActionInputDevice device
, const int iIndexByDevice
)
259 int iCurrentIndexByDevice
= 0; // Array may not be sorted, but the index specified by iIndexByDevice means the order in which its found
260 SActionInput
* pFoundActionInput
= NULL
;
261 for (int i
= 0; i
< m_actionInputs
.size(); i
++)
263 SActionInput
* pActionInput
= m_actionInputs
[i
];
264 CRY_ASSERT(pActionInput
!= NULL
);
266 if (pActionInput
->inputDevice
== device
)
268 if (iCurrentIndexByDevice
== iIndexByDevice
)
270 pFoundActionInput
= pActionInput
;
273 else // Keep looking for next one
275 iCurrentIndexByDevice
++;
280 return pFoundActionInput
;
283 //------------------------------------------------------------------------
284 const SActionInput
* CActionMapAction::GetActionInput(const int iIndex
) const
286 CRY_ASSERT(iIndex
>= 0 && iIndex
< (int)m_actionInputs
.size());
287 if (iIndex
>= 0 && iIndex
< (int)m_actionInputs
.size())
289 return m_actionInputs
[iIndex
];
295 //------------------------------------------------------------------------
296 const SActionInput
* CActionMapAction::GetActionInput(const EActionInputDevice device
, const int iIndexByDevice
) const
298 int iCurrentIndexByDevice
= 0; // Array may not be sorted, but the index specified by iIndexByDevice means the order in which its found
299 const SActionInput
* pFoundActionInput
= NULL
;
300 for (int i
= 0; i
< m_actionInputs
.size(); i
++)
302 const SActionInput
* pActionInput
= m_actionInputs
[i
];
303 CRY_ASSERT(pActionInput
!= NULL
);
305 if (pActionInput
->inputDevice
== device
)
307 if (iCurrentIndexByDevice
== iIndexByDevice
)
309 pFoundActionInput
= pActionInput
;
312 else // Keep looking for next one
314 iCurrentIndexByDevice
++;
319 return pFoundActionInput
;
322 //------------------------------------------------------------------------
323 SActionInput
* CActionMapAction::AddAndGetActionInput(const SActionInput
& actionInput
)
325 // Don't require to have a crc when passing in, but if has one, check it
326 uint32 inputCRC
= CCrc32::ComputeLowercase(actionInput
.input
);
327 if (actionInput
.inputCRC
!= 0)
329 if (inputCRC
!= actionInput
.inputCRC
)
331 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddAndGetActionInput: Can't add, string crc specified doesn't match actual crc");
336 SActionInput
* pActionInput
= FindActionInput(inputCRC
);
337 if (pActionInput
!= NULL
)
339 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CAction::AddAndGetActionInput::Unable to add input with input: %s, already exists", actionInput
.input
.c_str());
342 SActionInput
* pNewActionInput
= new SActionInput();
343 *pNewActionInput
= actionInput
;
344 pNewActionInput
->input
.MakeLower();
345 pNewActionInput
->defaultInput
.MakeLower();
346 pNewActionInput
->inputCRC
= inputCRC
;
347 m_actionInputs
.push_back(pNewActionInput
);
349 return pNewActionInput
;
352 //------------------------------------------------------------------------
353 CActionMap::CActionMap(CActionMapManager
* pActionMapManager
, const char* name
)
354 : m_pActionMapManager(pActionMapManager
),
355 m_enabled(!stricmp(name
, "default")),
357 m_actionMapListeners(2),
358 m_flownodesListeners(2),
360 m_iNumRebindedInputs(0)
364 //------------------------------------------------------------------------
365 CActionMap::~CActionMap()
370 //------------------------------------------------------------------------
371 void CActionMap::Release()
373 m_pActionMapManager
->RemoveActionMap(m_name
);
376 //------------------------------------------------------------------------
377 void CActionMap::Clear()
379 m_pActionMapManager
->RemoveBind(this);
381 SetNumRebindedInputs(0);
384 //------------------------------------------------------------------------
385 bool CActionMap::CreateAction(const ActionId
& actionId
)
387 TActionMap::iterator iter
= m_actions
.find(actionId
);
388 if (iter
!= m_actions
.end())
390 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::CreateAction: Unable to create action, %s already exists", actionId
.c_str());
394 CActionMapAction action
;
395 action
.SetActionId(actionId
);
396 action
.SetParentActionMap(this);
398 m_actions
[actionId
] = action
;
403 //------------------------------------------------------------------------
404 bool CActionMap::RemoveAction(const ActionId
& actionId
)
406 TActionMap::iterator iter
= m_actions
.find(actionId
);
407 if (iter
== m_actions
.end())
409 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::RemoveAction: Failed to find action: %s", actionId
.c_str());
413 CActionMapAction
& action
= iter
->second
;
414 m_pActionMapManager
->RemoveBind(&action
);
416 // Update new rebind count
417 int newRebindCount
= GetNumRebindedInputs();
419 int numActionInputs
= action
.GetNumActionInputs();
420 for (int i
= 0; i
< numActionInputs
; ++i
)
422 SActionInput
* pActionInput
= action
.GetActionInput(i
);
423 CRY_ASSERT(pActionInput
!= NULL
);
425 if (pActionInput
->input
!= pActionInput
->defaultInput
)
431 if (newRebindCount
!= GetNumRebindedInputs())
433 SetNumRebindedInputs(newRebindCount
);
436 m_actions
.erase(iter
);
441 //------------------------------------------------------------------------
442 bool CActionMap::AddActionInput(const ActionId
& actionId
, const SActionInput
& actionInput
, const int iByDeviceIndex
)
444 CActionMapAction
* pAction
= NULL
;
446 TActionMap::iterator iter
= m_actions
.find(actionId
);
447 if (iter
== m_actions
.end()) // Don't have an action, so create one to hold the input
449 pAction
= CreateAndGetAction(actionId
);
450 CRY_ASSERT(pAction
!= NULL
);
453 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddActionInput: Failed to create action: %s", actionId
.c_str());
459 pAction
= &iter
->second
;
460 CRY_ASSERT(pAction
!= NULL
);
463 return pAction
->AddActionInput(actionInput
, iByDeviceIndex
);
466 //------------------------------------------------------------------------
467 bool CActionMap::AddAndBindActionInput(const ActionId
& actionId
, const SActionInput
& actionInput
)
469 CActionMapAction
* pAction
= NULL
;
470 TActionMap::iterator iAction
= m_actions
.find(actionId
);
471 if (iAction
== m_actions
.end())
473 pAction
= CreateAndGetAction(actionId
);
474 CRY_ASSERT(pAction
!= NULL
);
477 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddAndBindActionInput: Failed to create action: %s", actionId
.c_str());
483 pAction
= &iAction
->second
;
484 CRY_ASSERT(pAction
!= NULL
);
486 SActionInput
* pNewActionInput
= pAction
->AddAndGetActionInput(actionInput
);
487 if (pNewActionInput
!= NULL
)
489 return m_pActionMapManager
->AddBind(this, pAction
, pNewActionInput
);
497 //------------------------------------------------------------------------
498 bool CActionMap::RemoveActionInput(const ActionId
& actionId
, const char* szInput
)
500 TActionMap::iterator iter
= m_actions
.find(actionId
);
501 if (iter
== m_actions
.end())
503 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::RemoveActionInput: Failed to find action: %s", actionId
.c_str());
507 CActionMapAction
& action
= iter
->second
;
509 uint32 inputCRC
= CCrc32::ComputeLowercase(szInput
);
511 SActionInput
* pActionInput
= action
.FindActionInput(inputCRC
);
512 if (pActionInput
== NULL
)
514 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::RemoveActionInput: Failed to find action input for input: %s", szInput
);
518 bool bResult
= m_pActionMapManager
->RemoveBind(this, &action
, pActionInput
);
521 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::RemoveActionInput: Failed to remove binding for action input with input: %s", szInput
);
525 return action
.RemoveActionInput(inputCRC
);
528 //------------------------------------------------------------------------
529 bool CActionMap::ReBindActionInput(const ActionId
& actionId
, const char* szCurrentInput
, const char* szNewInput
)
531 TActionMap::iterator iter
= m_actions
.find(actionId
);
532 if (iter
!= m_actions
.end())
534 CActionMapAction
& action
= iter
->second
;
535 return ReBindActionInput(&action
, szCurrentInput
, szNewInput
);
538 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Unable to rebind action, %s, doesn't exist", actionId
.c_str());
542 //------------------------------------------------------------------------
543 bool CActionMap::ReBindActionInput(const ActionId
& actionId
,
544 const char* szNewInput
,
545 const EActionInputDevice device
,
546 const int iByDeviceIndex
)
548 TActionMap::iterator iter
= m_actions
.find(actionId
);
549 if (iter
== m_actions
.end())
551 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Can't find action: %s", actionId
.c_str());
555 CActionMapAction
& action
= iter
->second
;
556 return ReBindActionInput(&action
, szNewInput
, device
, iByDeviceIndex
);
559 //------------------------------------------------------------------------
560 CActionMapAction
* CActionMap::CreateAndGetAction(const ActionId
& actionId
)
562 TActionMap::iterator iter
= m_actions
.find(actionId
);
563 if (iter
!= m_actions
.end())
568 CActionMapAction action
;
569 action
.SetActionId(actionId
);
570 action
.SetParentActionMap(this);
572 m_actions
[actionId
] = action
;
574 return &m_actions
[actionId
];
577 //------------------------------------------------------------------------
578 bool CActionMap::AddAndBindActionInput(CActionMapAction
* pAction
, const SActionInput
& actionInput
)
580 CRY_ASSERT(pAction
!= NULL
);
584 SActionInput
* pAddedActionInput
= pAction
->AddAndGetActionInput(actionInput
);
585 if (!pAddedActionInput
)
587 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddAndBindActionInput: Failed adding actioninput for input: %s", actionInput
.input
.c_str());
591 bool bResult
= m_pActionMapManager
->AddBind(this, pAction
, pAddedActionInput
);
594 pAction
->RemoveActionInput(pAddedActionInput
->inputCRC
);
595 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::AddAndBindActionInput: Failed binding actioninput");
602 //------------------------------------------------------------------------
603 bool CActionMap::ReBindActionInput(CActionMapAction
* pAction
, const char* szCurrentInput
, const char* szNewInput
)
605 uint32 inputCRC
= CCrc32::ComputeLowercase(szCurrentInput
);
607 SActionInput
* pActionInput
= pAction
->FindActionInput(inputCRC
);
610 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Can't find input: %s for action: %s", szCurrentInput
, pAction
->GetActionId().c_str());
614 return ReBindActionInput(pAction
, *pActionInput
, szNewInput
);
617 //------------------------------------------------------------------------
618 bool CActionMap::ReBindActionInput(CActionMapAction
* pAction
, SActionInput
& actionInput
, const char* szNewInput
)
620 CRY_ASSERT(pAction
!= NULL
);
622 if (actionInput
.input
== szNewInput
) // Rebinding to same input
625 if (m_pActionMapManager
->HasBind(this, pAction
, &actionInput
)) // Might not be binded if cleared
627 bool bResult
= m_pActionMapManager
->RemoveBind(this, pAction
, &actionInput
);
630 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Failed removing bind for input: %s for action: %s", actionInput
.input
.c_str(), pAction
->GetActionId().c_str());
635 actionInput
.input
= szNewInput
;
637 // Possible to assign empty to clear the binding
638 if (szNewInput
!= NULL
&& strcmp(szNewInput
, "") != 0)
640 actionInput
.inputCRC
= CCrc32::ComputeLowercase(szNewInput
);
642 bool bResult
= m_pActionMapManager
->AddBind(this, pAction
, &actionInput
);
645 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Failed removing bind for input: %s for action: %s", actionInput
.input
.c_str(), pAction
->GetActionId().c_str());
650 // If input now equals the default, nolonger needs the mark from the previous rebind
651 if (actionInput
.input
== actionInput
.defaultInput
)
653 SetNumRebindedInputs(GetNumRebindedInputs() - 1);
654 pAction
->SetNumRebindedInputs(pAction
->GetNumRebindedInputs() - 1);
656 else // Remember this rebind
658 SetNumRebindedInputs(GetNumRebindedInputs() + 1);
659 pAction
->SetNumRebindedInputs(pAction
->GetNumRebindedInputs() + 1);
665 //------------------------------------------------------------------------
666 bool CActionMap::ReBindActionInput(CActionMapAction
* pAction
,
667 const char* szNewInput
,
668 const EActionInputDevice device
,
669 const int iByDeviceIndex
)
672 SActionInput
* pActionInput
= pAction
->GetActionInput(device
, iByDeviceIndex
);
675 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Can't get input by index: %d for action: %s", iByDeviceIndex
, pAction
->GetActionId().c_str());
679 if (pActionInput
->input
== szNewInput
) // Rebinding to same input
682 if (m_pActionMapManager
->HasBind(this, pAction
, pActionInput
)) // Might not be binded if cleared
684 bool bResult
= m_pActionMapManager
->RemoveBind(this, pAction
, pActionInput
);
687 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Failed removing bind for input: %s for action: %s", pActionInput
->input
.c_str(), pAction
->GetActionId().c_str());
692 pActionInput
->input
= szNewInput
;
694 // Possible to assign empty to clear the binding
695 if (szNewInput
!= NULL
&& strcmp(szNewInput
, "") != 0)
697 pActionInput
->inputCRC
= CCrc32::ComputeLowercase(szNewInput
);
699 bool bResult
= m_pActionMapManager
->AddBind(this, pAction
, pActionInput
);
702 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::ReBindActionInput: Failed removing bind for input: %s for action: %s", pActionInput
->input
.c_str(), pAction
->GetActionId().c_str());
708 pActionInput
->inputCRC
= 0;
711 // If input now equals the default, nolonger needs the mark from the previous rebind
712 if (pActionInput
->input
== pActionInput
->defaultInput
)
714 SetNumRebindedInputs(GetNumRebindedInputs() - 1);
715 pAction
->SetNumRebindedInputs(pAction
->GetNumRebindedInputs() - 1);
717 else // Remember this rebind
719 SetNumRebindedInputs(GetNumRebindedInputs() + 1);
720 pAction
->SetNumRebindedInputs(pAction
->GetNumRebindedInputs() + 1);
727 //------------------------------------------------------------------------
728 void CActionMap::SetActionListener(EntityId id
)
733 //------------------------------------------------------------------------
734 EntityId
CActionMap::GetActionListener() const
739 //------------------------------------------------------------------------
740 bool CActionMap::Reset()
742 m_enabled
= !stricmp(GetName(), "default");
744 for (TActionMap::iterator it
= m_actions
.begin(); it
!= m_actions
.end(); ++it
)
746 CActionMapAction
& action
= it
->second
;
748 const int numInputs
= action
.GetNumActionInputs();
749 for (int i
= 0; i
< numInputs
; i
++)
751 SActionInput
* pActionInput
= action
.GetActionInput(i
);
752 CRY_ASSERT(pActionInput
!= NULL
);
754 if (pActionInput
->input
== pActionInput
->defaultInput
) // Input is already default
757 if (!ReBindActionInput(&action
, *pActionInput
, pActionInput
->defaultInput
))
759 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::Reset: Failed resetting binding to default input in action: %s", action
.GetActionId().c_str());
768 //------------------------------------------------------------------------
769 const IActionMapAction
* CActionMap::GetAction(const ActionId
& actionId
) const
771 TActionMap::const_iterator actionIter
= m_actions
.find(actionId
);
772 if (actionIter
== m_actions
.end())
775 const CActionMapAction
& action
= actionIter
->second
;
780 //------------------------------------------------------------------------
781 IActionMapAction
* CActionMap::GetAction(const ActionId
& actionId
)
783 TActionMap::iterator actionIter
= m_actions
.find(actionId
);
784 if (actionIter
== m_actions
.end())
787 IActionMapAction
& action
= actionIter
->second
;
792 //------------------------------------------------------------------------
793 bool CActionMap::CanProcessInput(const SInputEvent
& inputEvent
, CActionMap
* pActionMap
, CActionMapAction
* pAction
, SActionInput
* pActionInput
)
795 CRY_PROFILE_FUNCTION(PROFILE_ACTION
);
798 float fCurrTime
= gEnv
->pTimer
->GetCurrTime();
799 IGameFramework
* pGameFramework
= gEnv
->pGameFramework
;
800 if (pGameFramework
&& pGameFramework
->IsGamePaused())
802 fCurrTime
= gEnv
->pTimer
->GetCurrTime(ITimer::ETIMER_UI
);
807 // Normal buttons + keys send a press, down, release events
808 // Analog events only send changed
809 // So deal with these totally differently
810 if (pActionInput
->activationMode
& eAAM_AnalogCompare
)
812 switch (pActionInput
->analogCompareOp
) // Check if fulfills analog condition
816 if (fabs(inputEvent
.value
- pActionInput
->fAnalogCompareVal
) < FLT_EPSILON
)
822 case eAACO_NotEquals
:
824 if (fabs(inputEvent
.value
- pActionInput
->fAnalogCompareVal
) >= FLT_EPSILON
)
830 case eAACO_GreaterThan
:
832 if (inputEvent
.value
> pActionInput
->fAnalogCompareVal
)
840 if (inputEvent
.value
< pActionInput
->fAnalogCompareVal
)
850 // Since analog inputs dont have the concept of being down, create a refire timer to simulate hold
851 // and remove this when analog condition nolonger fulfilled
852 if (!m_pActionMapManager
->IsCurrentlyRefiringInput()) // Input event is from refire, dont try to refire a refired event
854 m_pActionMapManager
->UpdateRefireData(inputEvent
, pActionMap
, pAction
, pActionInput
);
857 if (pActionInput
->bAnalogConditionFulfilled
!= true)
859 pActionInput
->fPressedTime
= fCurrTime
;
860 pActionInput
->fLastRepeatTime
= fCurrTime
;
861 pActionInput
->bHoldTriggerFired
= false;
862 pActionInput
->fCurrentHoldValue
= 0.f
;
863 pActionInput
->bAnalogConditionFulfilled
= true;
864 pActionInput
->currentState
= eIS_Pressed
;
866 else if (pActionInput
->bHoldTriggerFired
)
868 pActionInput
->currentState
= eIS_Changed
;
871 // Although condition is true, result value can be set false again if hold timer conditions aren't true
872 // Only check if action should be processed here
873 bRes
= IsActionInputTriggered(inputEvent
, pActionMap
, pAction
, pActionInput
);
875 else // Didn't fulfill analog condition
877 if (!m_pActionMapManager
->IsCurrentlyRefiringInput() && pActionInput
->bAnalogConditionFulfilled
!= false)
879 pActionInput
->bAnalogConditionFulfilled
= false;
880 m_pActionMapManager
->RemoveRefireData(pActionMap
, pAction
, pActionInput
);
882 pActionInput
->fCurrentHoldValue
= 0.f
;
883 pActionInput
->currentState
= eIS_Released
;
886 else if (inputEvent
.state
== eIS_Pressed
)
888 pActionInput
->fPressedTime
= fCurrTime
;
890 if (pActionInput
->activationMode
& eAAM_OnHold
) // Needed for hold
892 pActionInput
->fLastRepeatTime
= fCurrTime
;
893 if (pActionInput
->fHoldTriggerDelay
> 0.f
)
895 pActionInput
->bHoldTriggerFired
= false;
897 else // Hold trigger delay is immediate, same with press event, so dont fire twice
899 pActionInput
->bHoldTriggerFired
= true;
902 pActionInput
->fCurrentHoldValue
= 0.f
;
905 // Check if the action should be processed
906 bRes
= IsActionInputTriggered(inputEvent
, pActionMap
, pAction
, pActionInput
);
908 else // All other cases
910 // Check if the action should be processed
911 bRes
= IsActionInputTriggered(inputEvent
, pActionMap
, pAction
, pActionInput
);
914 // Remember the triggered input
916 // Change action's current state
919 if (inputEvent
.state
== eIS_Down
&& pActionInput
->currentState
== eIS_Pressed
&& (pActionInput
->activationMode
& eAAM_OnRelease
))
920 pActionInput
->currentState
= eIS_Pressed
;
922 pActionInput
->currentState
= eIS_Unknown
;
924 else if (inputEvent
.state
== eIS_Changed
&& !(pActionInput
->activationMode
& eAAM_AnalogCompare
))
926 pActionInput
->currentState
= eIS_Changed
;
928 else if (inputEvent
.state
== eIS_Down
)
930 pActionInput
->currentState
= eIS_Down
;
932 else if (pActionInput
->activationMode
& (eAAM_OnPress
| eAAM_OnRelease
))
934 if (inputEvent
.state
== eIS_Released
|| inputEvent
.state
== eIS_Pressed
)
935 pActionInput
->currentState
= inputEvent
.state
;
942 //------------------------------------------------------------------------
943 bool CActionMap::IsActionInputTriggered(const SInputEvent
& inputEvent
, CActionMap
* pActionMap
, CActionMapAction
* pAction
, SActionInput
* pActionInput
) const
947 if ((inputEvent
.modifiers
& eMM_Modifiers
) &&
948 (pActionInput
->activationMode
& eAAM_NoModifiers
))
953 float fCurrTime
= gEnv
->pTimer
->GetCurrTime();
954 IGameFramework
* pGameFramework
= gEnv
->pGameFramework
;
955 if (pGameFramework
&& pGameFramework
->IsGamePaused())
957 fCurrTime
= gEnv
->pTimer
->GetCurrTime(ITimer::ETIMER_UI
);
960 // currentMode -> bit flag based on key state needed for trigger, and actual key state
961 // Special handling for certain types of logic
962 int currentMode
= pActionInput
->activationMode
& inputEvent
.state
;
963 const float fTimePressed
= fCurrTime
- pActionInput
->fPressedTime
;
964 const bool bJustPressed
= fabs(fTimePressed
) < FLT_EPSILON
;
966 if ((inputEvent
.state
== eIS_Down
) && (pActionInput
->activationMode
& eAAM_OnHold
))
970 return bRes
; // When holding, a press event is handled and immediately on same time frame a hold event is passed in, ignore it
974 currentMode
= eAAM_Always
; // Held events aren't checked in the above line, always allow them
977 else if (inputEvent
.state
== eIS_Changed
) // Analog events aren't checked in the above line, always allow them
979 if (bJustPressed
&& ((pActionInput
->activationMode
& eAAM_OnPress
) == 0)) // This is a press from analog event, but input doesn't handle press, ignore
984 currentMode
= eAAM_Always
;
986 else if (inputEvent
.state
== eIS_Released
)
988 pActionInput
->fCurrentHoldValue
= 0.f
;
990 //ignore if we have a release threshold and it's been exceeded
991 if (pActionInput
->fReleaseTriggerThreshold
>= 0.0f
&& fTimePressed
>= pActionInput
->fReleaseTriggerThreshold
)
997 // Get blocking type based on how the action was triggered
1000 // Support initial hold trigger delay and repeating
1001 if ((pActionInput
->activationMode
& eAAM_OnHold
) &&
1002 (inputEvent
.state
== eIS_Down
|| (inputEvent
.state
== eIS_Changed
&& bJustPressed
== false))) // Down is for digital controls, changed is for analog (For analog, won't reach here if analog condition is false, only for analog hold, press will go below like normal press)
1004 if (pActionInput
->bHoldTriggerFired
) // Initial hold trigger already fired
1006 if (fCurrTime
< pActionInput
->fLastRepeatTime
)
1008 pActionInput
->fLastRepeatTime
= fCurrTime
;
1011 if (pActionInput
->fHoldRepeatDelay
!= -1.0f
&& fCurrTime
- pActionInput
->fLastRepeatTime
>= pActionInput
->fHoldRepeatDelay
) // fHoldRepeatDelay of -1.0f means no repeat
1013 pActionInput
->fLastRepeatTime
= fCurrTime
;
1019 const bool bIsCurrentKey
= (m_pActionMapManager
->GetIncomingInputKeyID() == inputEvent
.keyId
);
1020 // Support overriding hold trigger timer if repeating same input
1021 if ((m_pActionMapManager
->IsRepeatedInputHoldTriggerFired()) && // Could have been interrupted by another held key
1022 (bIsCurrentKey
) && // Need to check since could have multiple held keys
1023 (pActionInput
->fHoldTriggerDelayRepeatOverride
>= FLT_EPSILON
)) // Default is -1.0f which won't activate this
1025 if (fTimePressed
>= pActionInput
->fHoldTriggerDelayRepeatOverride
)
1027 pActionInput
->bHoldTriggerFired
= true;
1028 pActionInput
->fCurrentHoldValue
= 1.f
;
1029 pActionInput
->fLastRepeatTime
= fCurrTime
;
1033 else if (fTimePressed
>= pActionInput
->fHoldTriggerDelay
)
1035 pActionInput
->bHoldTriggerFired
= true;
1036 pActionInput
->fCurrentHoldValue
= 1.f
;
1037 pActionInput
->fLastRepeatTime
= fCurrTime
;
1038 if (m_pActionMapManager
->IsIncomingInputRepeated() && bIsCurrentKey
) // Need to check since could have multiple held keys
1040 m_pActionMapManager
->SetRepeatedInputHoldTriggerFired(true);
1046 if (pActionInput
->fHoldTriggerDelay
> 0.f
)
1048 pActionInput
->fCurrentHoldValue
= (fTimePressed
/ pActionInput
->fHoldTriggerDelay
);
1052 pActionInput
->fCurrentHoldValue
= 0.f
;
1057 else if ((inputEvent
.state
== eIS_Pressed
) &&
1058 (pActionInput
->fPressTriggerDelay
>= FLT_EPSILON
) && // Handle delayed press situation
1059 (!m_pActionMapManager
->IsCurrentlyRefiringInput())) // Input event is from refire, dont try to refire a refired event
1061 if ((m_pActionMapManager
->IsIncomingInputRepeated()) &&
1062 (m_pActionMapManager
->GetIncomingInputKeyID() == inputEvent
.keyId
) && // Repeated same input, allow override if is one
1063 (pActionInput
->fPressTriggerDelayRepeatOverride
>= FLT_EPSILON
)) // Default is -1.0f which won't activate this
1065 // Remove delayed press fire
1066 m_pActionMapManager
->RemoveRefireData(pActionMap
, pAction
, pActionInput
);
1070 else // Not repeated key, must wait for delay before firing
1072 // Check press delay priority, if greater or equal to current, override
1073 int currentHighestDelayPriority
= m_pActionMapManager
->GetHighestPressDelayPriority();
1074 if (pActionInput
->iPressDelayPriority
>= currentHighestDelayPriority
)
1076 m_pActionMapManager
->RemoveAllDelayedPressRefireData();
1077 m_pActionMapManager
->UpdateRefireData(inputEvent
, pActionMap
, pAction
, pActionInput
); // Will fire again after delay
1082 else if ((inputEvent
.state
== eIS_Released
) &&
1083 (pActionInput
->fPressTriggerDelay
>= FLT_EPSILON
) && // Handle delayed press situation
1084 (!m_pActionMapManager
->IsCurrentlyRefiringInput())) // Input event is from refire, dont try to refire a refired event
1086 if (fTimePressed
- pActionInput
->fPressTriggerDelay
< FLT_EPSILON
) // Press delay hasn't fired yet, release should be fired right after delayed press
1088 m_pActionMapManager
->SetRefireDataDelayedPressNeedsRelease(inputEvent
, pActionMap
, pAction
, pActionInput
, true);
1091 else // Ok to fire release since delayed press already fired
1105 //------------------------------------------------------------------------
1106 void CActionMap::InputProcessed()
1108 IActionListener
* pEntityListener
= NULL
;
1110 if (IEntity
* pEntity
= gEnv
->pEntitySystem
->GetEntity(m_listenerId
))
1112 if (IGameObject
* pGameObject
= static_cast<IGameObject
*>(pEntity
->GetProxy(ENTITY_PROXY_USER
)))
1114 pEntityListener
= pGameObject
;
1118 if (pEntityListener
)
1119 pEntityListener
->AfterAction();
1121 for (TActionMapListeners::Notifier
notify(m_actionMapListeners
); notify
.IsValid(); notify
.Next())
1123 notify
->AfterAction();
1127 //------------------------------------------------------------------------
1128 void CActionMap::ReleaseActionsIfActive()
1130 TActionMap::iterator it
= m_actions
.begin();
1131 TActionMap::iterator end
= m_actions
.end();
1132 for (; it
!= end
; ++it
)
1134 CActionMapAction
& action
= it
->second
;
1135 ReleaseActionIfActiveInternal(action
);
1139 //------------------------------------------------------------------------
1140 void CActionMap::ReleaseFilteredActions()
1142 IActionListener
* pEntityListener
= NULL
;
1144 if (IEntity
* pEntity
= gEnv
->pEntitySystem
->GetEntity(m_listenerId
))
1146 if (IGameObject
* pGameObject
= static_cast<IGameObject
*>(pEntity
->GetProxy(ENTITY_PROXY_USER
)))
1148 pEntityListener
= pGameObject
;
1152 IActionListener
* pListener
= pEntityListener
;
1154 for (TActionMap::iterator it
= m_actions
.begin(), eit
= m_actions
.end(); it
!= eit
; ++it
)
1156 CActionMapAction
& action
= it
->second
;
1158 int iNumActionInputs
= action
.GetNumActionInputs();
1159 for (int i
= 0; i
< iNumActionInputs
; ++i
)
1161 SActionInput
* pActionInput
= action
.GetActionInput(i
);
1162 CRY_ASSERT(pActionInput
!= NULL
);
1164 bool isPressedOrDown
= (pActionInput
->currentState
== eIS_Pressed
) || (pActionInput
->currentState
== eIS_Down
);
1165 bool isChanged
= pActionInput
->currentState
== eIS_Changed
;
1167 if ((!isPressedOrDown
&& !isChanged
) || !m_pActionMapManager
->ActionFiltered(it
->first
))
1170 pActionInput
->fCurrentHoldValue
= 0.f
;
1172 int currentMode
= pActionInput
->activationMode
& eIS_Released
;
1173 if (currentMode
|| isChanged
)
1177 pListener
->OnAction(it
->first
, currentMode
, 0);
1180 const TActionListeners
& extraActionListeners
= m_pActionMapManager
->GetExtraActionListeners();
1181 for (TActionListeners::const_iterator extraListener
= extraActionListeners
.begin(); extraListener
!= extraActionListeners
.end(); ++extraListener
)
1182 (*extraListener
)->OnAction(it
->first
, currentMode
, 0);
1184 NotifyExtraActionListeners(it
->first
, currentMode
, 0);
1190 //------------------------------------------------------------------------
1191 void CActionMap::AddExtraActionListener(IActionListener
* pExtraActionListener
)
1193 m_actionMapListeners
.Add(pExtraActionListener
);
1196 //------------------------------------------------------------------------
1197 void CActionMap::RemoveExtraActionListener(IActionListener
* pExtraActionListener
)
1199 m_actionMapListeners
.Remove(pExtraActionListener
);
1202 //------------------------------------------------------------------------
1203 void CActionMap::NotifyFlowNodeActionListeners(const ActionId
& action
, int currentState
, float value
)
1205 for (TActionMapListeners::Notifier
notify(m_flownodesListeners
); notify
.IsValid(); notify
.Next())
1207 notify
->OnAction(action
, currentState
, value
);
1211 //------------------------------------------------------------------------
1212 void CActionMap::AddFlowNodeActionListener(IActionListener
* pFlowgraphNodeActionListener
)
1214 m_flownodesListeners
.Add(pFlowgraphNodeActionListener
);
1217 //------------------------------------------------------------------------
1218 void CActionMap::RemoveFlowNodeActionListener(IActionListener
* pFlowgraphNodeActionListener
)
1220 m_flownodesListeners
.Remove(pFlowgraphNodeActionListener
);
1223 //------------------------------------------------------------------------
1224 void CActionMap::NotifyExtraActionListeners(const ActionId
& action
, int currentState
, float value
)
1226 for (TActionMapListeners::Notifier
notify(m_actionMapListeners
); notify
.IsValid(); notify
.Next())
1228 notify
->OnAction(action
, currentState
, value
);
1232 //------------------------------------------------------------------------
1233 bool CActionMap::LoadFromXML(const XmlNodeRef
& actionMapNode
)
1235 const int iNumDeviceData
= m_pActionMapManager
->GetNumInputDeviceData();
1238 int iNumActions
= actionMapNode
->getChildCount();
1239 for (int i
= 0; i
< iNumActions
; ++i
)
1241 XmlNodeRef actionNode
= actionMapNode
->getChild(i
);
1242 if (strcmp(actionNode
->getTag(), "action") != 0)
1244 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Found non action child, actionmaps should only have action children");
1248 const char* szActionName
= actionNode
->getAttr("name");
1249 if (!szActionName
|| strcmp(szActionName
, "") == 0)
1251 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Action missing name, ignoring action");
1255 ActionId actionName
= ActionId(szActionName
);
1256 CActionMapAction
* pAction
= (CActionMapAction
*)GetAction(actionName
);
1257 if (pAction
!= NULL
)
1259 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Can't add action: %s, already exists", szActionName
);
1263 pAction
= CreateAndGetAction(actionName
);
1266 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed to create action: %s", szActionName
);
1270 // Actioninput used originally contains default values from constructor, then each LoadActionInputFromXML is cumulative
1271 // i.e. Only the values in xml will be set to allow attributes specified at topmost level in xml to apply to all children
1272 SActionInput actionInput
;
1274 if (actionNode
->getNumAttributes() > 1) // Contains attributes to apply to all inputs
1276 bResult
= LoadActionInputAttributesFromXML(actionNode
, actionInput
);
1279 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed loading action input attributes for action: %s", szActionName
);
1283 // Support specifying all devices in 1 line like before
1285 // All inputs are under a devicetype for organization
1286 // Devicemapping data should be called from game level using
1287 // IActionMapManager::AddInputDeviceMapping
1288 for (int j
= 0; j
< iNumDeviceData
; ++j
)
1290 const SActionInputDeviceData
* pInputDeviceData
= m_pActionMapManager
->GetInputDeviceDataByIndex(j
);
1292 const char* szInput
= actionNode
->getAttr(pInputDeviceData
->m_typeStr
);
1293 if (szInput
== NULL
|| strcmp(szInput
, "") == 0) // Not in xml which is fine
1296 actionInput
.input
= szInput
;
1297 actionInput
.defaultInput
= szInput
;
1298 actionInput
.inputDevice
= pInputDeviceData
->m_type
;
1300 bResult
= AddAndBindActionInput(pAction
, actionInput
);
1303 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName
, szInput
);
1309 int iNumDeviceChildren
= actionNode
->getChildCount();
1311 // Check now for action inputs specified per platform
1312 if (iNumDeviceChildren
> 0)
1314 // Support specifying separate device with attributes in their own child
1315 for (int j
= 0; j
< iNumDeviceChildren
; ++j
)
1317 XmlNodeRef inputDeviceNode
= actionNode
->getChild(j
);
1319 EActionInputDevice inputDeviceNodeDeviceType
= eAID_Unknown
;
1321 const SActionInputDeviceData
* pInputDeviceData
= m_pActionMapManager
->GetInputDeviceDataByType(inputDeviceNode
->getTag());
1322 if (pInputDeviceData
!= NULL
)
1324 inputDeviceNodeDeviceType
= pInputDeviceData
->m_type
;
1331 SActionInput platformInput
= actionInput
; // Need to copy parent settings since don't want to overwrite for the other nodes
1333 bResult
= LoadActionInputAttributesFromXML(inputDeviceNode
, platformInput
);
1336 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed loading action input attributes for action: %s", szActionName
);
1340 const char* szPlatformInput
= inputDeviceNode
->getAttr("input");
1341 if (szPlatformInput
!= NULL
&& strcmp(szPlatformInput
, "") != 0) // Device specific key is here, dont need to look for children
1343 platformInput
.input
= szPlatformInput
;
1344 platformInput
.defaultInput
= szPlatformInput
;
1345 platformInput
.inputDevice
= inputDeviceNodeDeviceType
;
1347 bResult
= AddAndBindActionInput(pAction
, platformInput
);
1350 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName
, szPlatformInput
);
1356 int iNumInputData
= inputDeviceNode
->getChildCount();
1357 for (int k
= 0; k
< iNumInputData
; k
++)
1359 // Go through each of the separate inputs
1360 SActionInput platformChildInput
= platformInput
;
1362 XmlNodeRef platformChildNode
= inputDeviceNode
->getChild(k
);
1363 if (strcmp(platformChildNode
->getTag(), "inputdata") != 0)
1365 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Children inside platform tags must be inputdata");
1369 const char* szPlatformChildInput
= platformChildNode
->getAttr("input");
1370 if (szPlatformChildInput
== NULL
|| strcmp(szPlatformChildInput
, "") == 0)
1372 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: inputdata tag must contain input");
1376 bResult
= LoadActionInputAttributesFromXML(platformChildNode
, platformChildInput
);
1379 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed loading action input attributes on platform child input node for action: %s", szActionName
);
1383 platformChildInput
.input
= szPlatformChildInput
;
1384 platformChildInput
.defaultInput
= szPlatformChildInput
;
1385 platformChildInput
.inputDevice
= pInputDeviceData
->m_type
;
1387 bResult
= AddAndBindActionInput(pAction
, platformChildInput
);
1390 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName
, szPlatformChildInput
);
1402 bool CActionMap::LoadRebindingDataFromXML(const XmlNodeRef
& actionMapNode
)
1404 int iNumActions
= actionMapNode
->getChildCount();
1405 for (int i
= 0; i
< iNumActions
; ++i
)
1407 XmlNodeRef actionNode
= actionMapNode
->getChild(i
);
1408 if (strcmp(actionNode
->getTag(), "action") != 0)
1410 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadRebindingDataFromXML: Found non action child, actionmaps should only have action children");
1414 const char* szActionName
= actionNode
->getAttr("name");
1415 if (szActionName
== NULL
|| strcmp(szActionName
, "") == 0)
1417 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadRebindingDataFromXML: Action missing name, ignoring action");
1421 ActionId actionName
= ActionId(szActionName
);
1422 CActionMapAction
* pAction
= (CActionMapAction
*)GetAction(actionName
);
1423 if (pAction
== NULL
)
1425 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadRebindingDataFromXML: Action: %s, doesn't exist, can't rebind", szActionName
);
1429 // Check now for action inputs specified per platform
1430 int iNumRebindInputs
= actionNode
->getChildCount();
1431 if (iNumRebindInputs
== 0)
1432 continue; // Shouldn't have empty action tags
1434 for (int j
= 0; j
< iNumRebindInputs
; ++j
)
1436 XmlNodeRef inputNode
= actionNode
->getChild(j
);
1437 const char* szInput
= inputNode
->getAttr("input");
1438 if (szInput
== NULL
)
1440 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadRebindingDataFromXML: Action: %s, has an input tag missing input attribute", szActionName
);
1444 const char* szDevice
= inputNode
->getAttr("device");
1445 if (szDevice
== NULL
|| strcmp(szDevice
, "") == 0)
1447 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadRebindingDataFromXML: Action: %s, has an input tag missing device attribute", szActionName
);
1451 const SActionInputDeviceData
* pInputDeviceData
= m_pActionMapManager
->GetInputDeviceDataByType(szDevice
);
1452 if (pInputDeviceData
== NULL
)
1457 // Want to allow rebinding without defaultInput to avoid data dependencies
1458 const char* szDefaultInput
= inputNode
->getAttr("defaultInput");
1459 if (szDefaultInput
== NULL
|| strcmp(szDefaultInput
, "") == 0) // Assumes rebinding the first input for that device
1461 if (stricmp(szInput
, "DEFAULT") == 0) // Reset to default
1463 SActionInput
* pActionInput
= pAction
->GetActionInput(pInputDeviceData
->m_type
, 0);
1464 if (pActionInput
== NULL
)
1466 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadFromXML: Failed trying to find actioninput for input device type: %s", szDevice
);
1470 ReBindActionInput(pAction
, pActionInput
->defaultInput
, pInputDeviceData
->m_type
, 0);
1474 ReBindActionInput(pAction
, szInput
, pInputDeviceData
->m_type
, 0);
1479 if (stricmp(szInput
, "DEFAULT") == 0) // Reset to default
1481 ReBindActionInput(pAction
, szDefaultInput
, szDefaultInput
);
1485 ReBindActionInput(pAction
, szDefaultInput
, szInput
);
1494 bool CActionMap::SaveRebindingDataToXML(XmlNodeRef
& actionMapNode
) const
1497 // for debug reasons, we sort the ActionMap alphabetically
1498 // CryName normally sorts by pointer address
1499 std::map
<ActionId
, SAction
, CryNameSorter
> sortedActions(m_actions
.begin(), m_actions
.end());
1500 std::map
<ActionId
, SAction
, CryNameSorter
>::const_iterator iter
= sortedActions
.begin();
1501 std::map
<ActionId
, SAction
, CryNameSorter
>::const_iterator iterEnd
= sortedActions
.end();
1503 TActionMap::const_iterator iter
= m_actions
.begin();
1504 TActionMap::const_iterator iterEnd
= m_actions
.end();
1507 actionMapNode
->setAttr("name", m_name
);
1508 for (; iter
!= iterEnd
; ++iter
)
1510 ActionId actionId
= iter
->first
;
1511 const CActionMapAction
& action
= iter
->second
;
1512 if (action
.GetNumRebindedInputs() == 0)
1515 XmlNodeRef actionNode
= actionMapNode
->newChild("action");
1516 actionNode
->setAttr("name", actionId
.c_str());
1518 int numActionInputs
= action
.GetNumActionInputs();
1519 for (int i
= 0; i
< numActionInputs
; ++i
)
1521 const SActionInput
* pActionInput
= action
.GetActionInput(i
);
1522 CRY_ASSERT(pActionInput
!= NULL
);
1524 if (pActionInput
->input
== pActionInput
->defaultInput
)
1529 const SActionInputDeviceData
* pInputDeviceData
= m_pActionMapManager
->GetInputDeviceDataByType(pActionInput
->inputDevice
);
1530 if (pInputDeviceData
== NULL
)
1532 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::SaveRebindingDataToXML: Failed to find device string");
1536 XmlNodeRef inputDeviceNode
= actionNode
->newChild("rebind");
1537 inputDeviceNode
->setAttr("device", pInputDeviceData
->m_typeStr
.c_str());
1538 inputDeviceNode
->setAttr("input", pActionInput
->input
.c_str());
1539 inputDeviceNode
->setAttr("defaultInput", pActionInput
->defaultInput
.c_str());
1546 bool CActionMap::LoadActionInputAttributesFromXML(const XmlNodeRef
& actionInputNode
, SActionInput
& actionInput
)
1548 int& activationFlags
= actionInput
.activationMode
;
1550 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_ONPRESS_STR
, eAAM_OnPress
);
1551 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_ONRELEASE_STR
, eAAM_OnRelease
);
1552 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_ONHOLD_STR
, eAAM_OnHold
);
1553 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_ALWAYS_STR
, eAAM_Always
);
1554 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_CONSOLECMD_STR
, eAAM_ConsoleCmd
);
1555 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_NOMODIFIERS_STR
, eAAM_NoModifiers
);
1556 LoadActivationModeBitAttributeFromXML(actionInputNode
, activationFlags
, ACTIONINPUT_RETRIGGERABLE_STR
, eAAM_Retriggerable
);
1558 // If not specified, value is taken from constructor (0.0f)
1559 actionInputNode
->getAttr(ACTIONINPUT_PRESSTRIGGERDELAY_STR
, actionInput
.fPressTriggerDelay
);
1560 // If not specified, value is taken from constructor (-1.0f) (Disabled)
1561 actionInputNode
->getAttr(ACTIONINPUT_PRESSTRIGGERDELAY_REPEATOVERRIDE_STR
, actionInput
.fPressTriggerDelayRepeatOverride
);
1562 // If not specified, value is taken from constructor (0) (Higher number will override when both delayed (i.e. pressing top right on dpad)
1563 actionInputNode
->getAttr(ACTIONINPUT_PRESSDELAYPRIORITY_STR
, actionInput
.iPressDelayPriority
);
1565 // If not specified, value is taken from constructor (0.0f)
1566 actionInputNode
->getAttr(ACTIONINPUT_HOLDTRIGGERDELAY_STR
, actionInput
.fHoldTriggerDelay
);
1567 // If not specified, value is taken from constructor (0.0f) (Always repeats)
1568 actionInputNode
->getAttr(ACTIONINPUT_HOLDREPEATDELAY_STR
, actionInput
.fHoldRepeatDelay
);
1569 // If not specified, value is taken from constructor (-1.0f) (Disabled)
1570 actionInputNode
->getAttr(ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR
, actionInput
.fHoldTriggerDelayRepeatOverride
);
1571 // If not specified, value is taken from constructor (-1.0f) (Disabled)
1572 actionInputNode
->getAttr(ACTIONINPUT_RELEASETRIGGERTHRESHOLD_STR
, actionInput
.fReleaseTriggerThreshold
);
1574 if (!strcmp(actionInputNode
->getAttr(ACTIONINPUT_USEANALOGCOMPARE_STR
), "1"))
1576 activationFlags
|= eAAM_AnalogCompare
;
1578 const char* analogCompareOp
= actionInputNode
->getAttr(ACTIONINPUT_ANALOGCOMPAREOP_STR
);
1579 if (analogCompareOp
== NULL
|| strcmp(analogCompareOp
, "") == 0)
1581 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareOp");
1585 actionInput
.analogCompareOp
= GetAnalogCompareOpTypeFromStr(analogCompareOp
);
1586 if (actionInput
.analogCompareOp
== eAACO_None
)
1588 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareOp");
1592 bool bResult
= actionInputNode
->getAttr(ACTIONINPUT_ANALOGCOMPAREVAL_STR
, actionInput
.fAnalogCompareVal
);
1595 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareVal");
1601 const char* inputsToBlock
= actionInputNode
->getAttr(ACTIONINPUT_INPUTSTOBLOCK_STR
);
1602 if (inputsToBlock
!= NULL
&& strcmp(inputsToBlock
, "") != 0)
1604 SActionInputBlockData
& inputBlockData
= actionInput
.inputBlockData
;
1606 if (strcmp(inputsToBlock
, ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR
) == 0)
1608 inputBlockData
.blockType
= eAIBT_Clear
;
1610 else // Must contain list of inputs separated by |
1612 // Must contain a valid block time
1613 actionInputNode
->getAttr(ACTIONINPUT_INPUTBLOCKTIME_STR
, inputBlockData
.fBlockDuration
);
1614 if (inputBlockData
.fBlockDuration
< FLT_EPSILON
)
1616 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Must have a valid blockTime, value is: %.2f", inputBlockData
.fBlockDuration
);
1620 // Read in the blocking activation (Default is always, matches all specified action activations)
1621 const char* inputBlockActivation
= actionInputNode
->getAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR
);
1622 bool useAlwaysActivation
;
1623 if (inputBlockActivation
!= NULL
&& strcmp(inputBlockActivation
, "") != 0)
1625 useAlwaysActivation
= false;
1626 string
inputsBlockActivationStr(inputBlockActivation
);
1628 string singleBlockActivation
= inputsBlockActivationStr
.Tokenize("|", curPos
);
1629 bool bEmpty
= singleBlockActivation
.empty();
1630 if (bEmpty
) // Only 1 input
1632 singleBlockActivation
= inputsBlockActivationStr
;
1638 if (strcmp(singleBlockActivation
, ACTIONINPUT_ONPRESS_STR
) == 0)
1640 inputBlockData
.activationMode
|= eIS_Pressed
;
1642 else if (strcmp(singleBlockActivation
, ACTIONINPUT_ONHOLD_STR
) == 0)
1644 inputBlockData
.activationMode
|= eIS_Down
;
1646 else if (strcmp(singleBlockActivation
, ACTIONINPUT_ONRELEASE_STR
) == 0)
1648 inputBlockData
.activationMode
|= eIS_Released
;
1650 else if (strcmp(inputBlockActivation
, ACTIONINPUT_ALWAYS_STR
) == 0)
1652 useAlwaysActivation
= true;
1657 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Invalid block activation: %s", singleBlockActivation
.c_str());
1666 singleBlockActivation
= inputsBlockActivationStr
.Tokenize("|", curPos
);
1667 bEmpty
= singleBlockActivation
.empty();
1673 useAlwaysActivation
= true;
1676 if (useAlwaysActivation
)
1678 inputBlockData
.activationMode
|= eIS_Pressed
;
1679 inputBlockData
.activationMode
|= eIS_Down
;
1680 inputBlockData
.activationMode
|= eIS_Released
;
1683 // Now read in all the inputs to block, separated by |
1684 string
inputsToBlockStr(inputsToBlock
);
1685 std::vector
<string
> inputsToBlockVec
;
1687 string singleInput
= inputsToBlockStr
.Tokenize("|", curPos
);
1688 if (singleInput
.empty()) // Only 1 input
1690 inputsToBlockVec
.push_back(inputsToBlockStr
);
1696 inputsToBlockVec
.push_back(singleInput
);
1697 singleInput
= inputsToBlockStr
.Tokenize("|", curPos
);
1699 while (!singleInput
.empty());
1702 // Read in the device index (Default is all device indices)
1703 int iDeviceIndex
= -1;
1704 actionInputNode
->getAttr(ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR
, iDeviceIndex
);
1706 if (iDeviceIndex
!= -1)
1708 inputBlockData
.bAllDeviceIndices
= false;
1709 inputBlockData
.deviceIndex
= (uint8
)iDeviceIndex
;
1712 for (size_t i
= 0; i
< inputsToBlockVec
.size(); i
++)
1714 const SInputSymbol
* pInputSymbol
= gEnv
->pInput
? gEnv
->pInput
->GetSymbolByName(inputsToBlockVec
[i
]) : NULL
;
1717 // Data is currently read all in on pc, dont show warnings until thats changed
1718 // CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find input symbol for input name: %s", inputsToBlockVec[i].c_str());
1722 SActionInputBlocker
inputBlockerToSend(pInputSymbol
->keyId
);
1723 inputBlockData
.inputs
.push_back(inputBlockerToSend
);
1725 if (!inputBlockData
.inputs
.empty())
1727 inputBlockData
.blockType
= eAIBT_BlockInputs
; // Only having this makes enables blocking
1730 /* Data is currently read all in on pc, dont show warnings until thats changed
1733 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find any inputs to block for inputs: %s", inputsToBlock);
1743 bool CActionMap::SaveActionInputAttributesToXML(XmlNodeRef
& actionInputNode
, const SActionInput
& actionInput
) const
1745 const int activationFlags
= actionInput
.activationMode
;
1747 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_ONPRESS_STR
, eAAM_OnPress
);
1748 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_ONRELEASE_STR
, eAAM_OnRelease
);
1749 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_ALWAYS_STR
, eAAM_Always
);
1750 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_CONSOLECMD_STR
, eAAM_ConsoleCmd
);
1751 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_NOMODIFIERS_STR
, eAAM_NoModifiers
);
1752 SaveActivationModeBitAttributeToXML(actionInputNode
, activationFlags
, ACTIONINPUT_RETRIGGERABLE_STR
, eAAM_Retriggerable
);
1754 if (actionInput
.activationMode
& eAAM_OnHold
)
1756 actionInputNode
->setAttr(ACTIONINPUT_ONHOLD_STR
, "1");
1757 actionInputNode
->setAttr(ACTIONINPUT_HOLDTRIGGERDELAY_STR
, actionInput
.fHoldTriggerDelay
);
1758 actionInputNode
->setAttr(ACTIONINPUT_HOLDREPEATDELAY_STR
, actionInput
.fHoldRepeatDelay
);
1759 actionInputNode
->setAttr(ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR
, actionInput
.fHoldTriggerDelayRepeatOverride
);
1763 actionInputNode
->setAttr(ACTIONINPUT_ONHOLD_STR
, "0");
1766 if (actionInput
.activationMode
& eAAM_AnalogCompare
)
1768 actionInputNode
->setAttr(ACTIONINPUT_USEANALOGCOMPARE_STR
, "1");
1769 actionInputNode
->setAttr(ACTIONINPUT_ANALOGCOMPAREOP_STR
, GetAnalogCompareOpStr(actionInput
.analogCompareOp
));
1770 actionInputNode
->setAttr(ACTIONINPUT_ANALOGCOMPAREVAL_STR
, actionInput
.fAnalogCompareVal
);
1774 actionInputNode
->setAttr(ACTIONINPUT_USEANALOGCOMPARE_STR
, "0");
1778 const SActionInputBlockData
& inputBlockData
= actionInput
.inputBlockData
;
1779 if (inputBlockData
.blockType
!= eAIBT_None
)
1781 if (inputBlockData
.blockType
== eAIBT_Clear
)
1783 actionInputNode
->setAttr(ACTIONINPUT_INPUTSTOBLOCK_STR
, ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR
);
1785 else // Normal blocking inputs
1787 if (inputBlockData
.inputs
.empty())
1789 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::SaveActionInputAttributesToXML: Failed, using normal blocking inputs type but dont have any inputs");
1793 if (inputBlockData
.fBlockDuration
<= (0.0f
- FLT_EPSILON
))
1795 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::SaveActionInputAttributesToXML: Failed, using normal blocking inputs type but don't have valid block duration");
1798 actionInputNode
->setAttr(ACTIONINPUT_INPUTBLOCKTIME_STR
, inputBlockData
.fBlockDuration
);
1800 // Save input blocking activation mode
1801 if ((inputBlockData
.activationMode
& eIS_Pressed
) &&
1802 (inputBlockData
.activationMode
& eIS_Down
) &&
1803 (inputBlockData
.activationMode
& eIS_Released
))
1805 actionInputNode
->setAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR
, ACTIONINPUT_ALWAYS_STR
);
1809 CryFixedStringT
<32> inputBlockActivationStr("");
1810 bool bAddedActivationMode
= false;
1811 if (inputBlockData
.activationMode
& eIS_Pressed
)
1813 inputBlockActivationStr
= ACTIONINPUT_ONPRESS_STR
;
1814 bAddedActivationMode
= true;
1816 if (inputBlockData
.activationMode
& eIS_Down
)
1818 if (bAddedActivationMode
)
1820 inputBlockActivationStr
+= "|";
1822 inputBlockActivationStr
+= ACTIONINPUT_ONHOLD_STR
;
1823 bAddedActivationMode
= true;
1825 if (inputBlockData
.activationMode
& eIS_Released
)
1827 if (bAddedActivationMode
)
1829 inputBlockActivationStr
+= "|";
1831 inputBlockActivationStr
+= ACTIONINPUT_ONRELEASE_STR
;
1834 actionInputNode
->setAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR
, inputBlockActivationStr
.c_str());
1837 // Now save the blocked inputs
1838 string
blockedInputsStr("");
1839 for (size_t i
= 0; i
< inputBlockData
.inputs
.size(); i
++)
1841 const SActionInputBlocker
& inputBlocker
= inputBlockData
.inputs
[i
];
1845 blockedInputsStr
+= "|";
1848 const char* szKeyName
= gEnv
->pInput
->GetKeyName(inputBlocker
.keyId
);
1851 CryWarning(VALIDATOR_MODULE_GAME
, VALIDATOR_WARNING
, "CActionMap::LoadActionInputAttributesFromXML: Failed to translate keyname for key id: %d", (int)inputBlocker
.keyId
);
1855 blockedInputsStr
+= szKeyName
;
1858 // Now save device index data
1859 if (!inputBlockData
.bAllDeviceIndices
) // Default is true so dont need to save to xml
1861 actionInputNode
->setAttr(ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR
, inputBlockData
.deviceIndex
);
1869 //------------------------------------------------------------------------
1870 void CActionMap::LoadActivationModeBitAttributeFromXML(const XmlNodeRef
& attributeNode
, int& activationFlags
, const char* szActivationModeName
, EActionActivationMode activationMode
)
1874 if (attributeNode
->getAttr(szActivationModeName
, readFlag
))
1878 activationFlags
|= activationMode
;
1882 activationFlags
&= ~activationMode
;
1887 //------------------------------------------------------------------------
1888 void CActionMap::SaveActivationModeBitAttributeToXML(XmlNodeRef
& attributeNode
, const int activationFlags
, const char* szActivationModeName
, EActionActivationMode activationMode
) const
1890 if (activationFlags
& activationMode
)
1892 attributeNode
->setAttr(szActivationModeName
, "1");
1896 attributeNode
->setAttr(szActivationModeName
, "0");
1900 #define USE_SORTED_ACTIONS_ITERATOR
1901 #undef USE_SORTED_ACTIONS_ITERATOR
1903 //------------------------------------------------------------------------
1904 IActionMapActionIteratorPtr
CActionMap::CreateActionIterator()
1906 class CActionInfo
: public IActionMapActionIterator
1908 #ifndef USE_SORTED_ACTIONS_ITERATOR
1909 typedef TActionMap::iterator TIterator
;
1911 typedef std::map
<ActionId
, CActionMapAction
, CryNameSorter
> TSortedActionMap
;
1912 typedef TSortedActionMap::iterator TIterator
;
1916 CActionInfo(TActionMap::iterator
& itBegin
, TActionMap::iterator
& itEnd
)
1919 #ifdef USE_SORTED_ACTIONS_ITERATOR
1920 m_sortedActions
.insert(itBegin
, itEnd
);
1921 m_cur
= m_sortedActions
.begin();
1922 m_end
= m_sortedActions
.end();
1929 virtual ~CActionInfo()
1933 const IActionMapAction
* Next()
1937 const CActionMapAction
& action
= m_cur
->second
;
1956 #ifdef USE_SORTED_ACTIONS_ITERATOR
1957 TSortedActionMap m_sortedActions
;
1960 TActionMap::iterator
actionsBegin(m_actions
.begin());
1961 TActionMap::iterator
actionsEnd(m_actions
.end());
1962 return new CActionInfo(actionsBegin
, actionsEnd
);
1965 void CActionMap::Enable(bool enable
)
1968 if (enable
== m_enabled
)
1971 // now things get a bit interesting, when we get disabled we "release" all our
1975 TActionMap::iterator it
= m_actions
.begin();
1976 TActionMap::iterator end
= m_actions
.end();
1977 for (; it
!= end
; ++it
)
1979 ReleaseActionIfActiveInternal(it
->second
);
1983 // finally set the flag
1986 if (m_pActionMapManager
)
1988 m_pActionMapManager
->BroadcastActionMapEvent(SActionMapEvent(SActionMapEvent::eActionMapManagerEvent_ActionMapStatusChanged
, (UINT_PTR
)this, (UINT_PTR
)m_enabled
));
1992 void CActionMap::ReleaseActionIfActive(const ActionId
& actionId
)
1994 TActionMap::iterator it
= m_actions
.find(actionId
);
1995 if (it
!= m_actions
.end())
1997 ReleaseActionIfActiveInternal(it
->second
);
2001 void CActionMap::ReleaseActionIfActiveInternal(CActionMapAction
& action
)
2003 bool bFireOnActionRelease
= false;
2004 bool bFireOnActionAlways
= false;
2006 int numActionInputs
= action
.GetNumActionInputs();
2007 for (int i
= 0; i
< numActionInputs
; ++i
)
2009 SActionInput
* pActionInput
= action
.GetActionInput(i
);
2010 CRY_ASSERT(pActionInput
!= NULL
);
2012 bool hasReleaseMode
= (pActionInput
->activationMode
& eAAM_OnRelease
) != 0;
2013 bool isPressedOrDown
= (pActionInput
->currentState
== eIS_Pressed
) || (pActionInput
->currentState
== eIS_Down
);
2014 bool isChanged
= pActionInput
->currentState
== eIS_Changed
;
2016 if (hasReleaseMode
&& isPressedOrDown
)
2018 bFireOnActionRelease
= true;
2023 bFireOnActionAlways
= true;
2026 pActionInput
->fCurrentHoldValue
= 0.f
;
2029 if (bFireOnActionRelease
)
2031 IActionListener
* pEntityListener
= nullptr;
2033 if (IEntity
* pEntity
= gEnv
->pEntitySystem
->GetEntity(m_listenerId
))
2035 if (IGameObject
* pGameObject
= static_cast<IGameObject
*>(pEntity
->GetProxy(ENTITY_PROXY_USER
)))
2037 pEntityListener
= pGameObject
;
2041 if (pEntityListener
)
2043 pEntityListener
->OnAction(action
.GetActionId(), eAAM_OnRelease
, 0.0f
);
2046 NotifyExtraActionListeners(action
.GetActionId(), eAAM_OnRelease
, 0.0f
);
2049 if (bFireOnActionAlways
)
2051 IActionListener
* pEntityListener
= nullptr;
2053 if (IEntity
* pEntity
= gEnv
->pEntitySystem
->GetEntity(m_listenerId
))
2055 if (IGameObject
* pGameObject
= static_cast<IGameObject
*>(pEntity
->GetProxy(ENTITY_PROXY_USER
)))
2056 pEntityListener
= pGameObject
;
2059 if (pEntityListener
)
2061 pEntityListener
->OnAction(action
.GetActionId(), eAAM_Always
, 0.0f
);
2064 NotifyExtraActionListeners(action
.GetActionId(), eAAM_Always
, 0.0f
);
2068 EActionAnalogCompareOperation
CActionMap::GetAnalogCompareOpTypeFromStr(const char* szTypeStr
)
2070 EActionAnalogCompareOperation compareOpType
= eAACO_None
;
2071 if (!strcmp(szTypeStr
, s_analogCompareOpEqualsStr
))
2073 compareOpType
= eAACO_Equals
;
2075 else if (!strcmp(szTypeStr
, s_analogCompareOpNotEqualsStr
))
2077 compareOpType
= eAACO_NotEquals
;
2079 else if (!strcmp(szTypeStr
, s_analogCompareOpGreaterThanStr
))
2081 compareOpType
= eAACO_GreaterThan
;
2083 else if (!strcmp(szTypeStr
, s_analogCompareOpLessThanStr
))
2085 compareOpType
= eAACO_LessThan
;
2088 return compareOpType
;
2091 const char* CActionMap::GetAnalogCompareOpStr(EActionAnalogCompareOperation compareOpType
) const
2093 if (compareOpType
== eAACO_Equals
)
2095 return s_analogCompareOpEqualsStr
;
2097 else if (compareOpType
== eAACO_NotEquals
)
2099 return s_analogCompareOpNotEqualsStr
;
2101 else if (compareOpType
== eAACO_GreaterThan
)
2103 return s_analogCompareOpGreaterThanStr
;
2105 else if (compareOpType
== eAACO_LessThan
)
2107 return s_analogCompareOpLessThanStr
;
2115 void CActionMap::EnumerateActions(IActionMapPopulateCallBack
* pCallBack
) const
2117 for (TActionMap::const_iterator actionCit
= m_actions
.begin(); actionCit
!= m_actions
.end(); ++actionCit
)
2119 pCallBack
->AddActionName(actionCit
->first
.c_str());
2123 void CActionMap::GetMemoryUsage(ICrySizer
* s
) const
2125 s
->AddObject(m_actions
);
2126 s
->AddObject(m_name
);