BVB Source Codes

CRYENGINE Show ActionMap.cpp Source code

Return Download CRYENGINE: download ActionMap.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.  
  8.    -------------------------------------------------------------------------
  9.    History:
  10.    - 7:9:2004   17:48 : Created by M谩rcio Martins
  11.    - 15:9:2010  12:30 : Revised by Dean Claassen
  12.  
  13. *************************************************************************/
  14. #include "StdAfx.h"
  15. #include "ActionMap.h"
  16. #include "ActionMapManager.h"
  17. #include <CrySystem/IConsole.h>
  18. #include "GameObjects/GameObject.h"
  19. #include <CryCore/CryCrc32.h>
  20.  
  21. #define ACTIONINPUT_NAME_STR                               "name"
  22.  
  23. #define ACTIONINPUT_ONPRESS_STR                            "onPress"
  24. #define ACTIONINPUT_ONRELEASE_STR                          "onRelease"
  25. #define ACTIONINPUT_ONHOLD_STR                             "onHold"
  26. #define ACTIONINPUT_ALWAYS_STR                             "always"
  27.  
  28. #define ACTIONINPUT_CONSOLECMD_STR                         "consoleCmd"
  29. #define ACTIONINPUT_NOMODIFIERS_STR                        "noModifiers"
  30. #define ACTIONINPUT_RETRIGGERABLE_STR                      "retriggerable"
  31.  
  32. #define ACTIONINPUT_PRESSTRIGGERDELAY_STR                  "pressTriggerDelay"
  33. #define ACTIONINPUT_PRESSTRIGGERDELAY_REPEATOVERRIDE_STR   "pressTriggerDelayRepeatOverride"
  34. #define ACTIONINPUT_PRESSDELAYPRIORITY_STR                 "pressDelayPriority"
  35.  
  36. #define ACTIONINPUT_HOLDTRIGGERDELAY_STR                   "holdTriggerDelay"
  37. #define ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR    "holdTriggerDelayRepeatOverride"
  38. #define ACTIONINPUT_HOLDREPEATDELAY_STR                    "holdRepeatDelay"
  39. #define ACTIONINPUT_RELEASETRIGGERTHRESHOLD_STR            "releaseTriggerThreshold"
  40.  
  41. #define ACTIONINPUT_INPUTSTOBLOCK_STR                      "inputsToBlock"
  42. #define ACTIONINPUT_INPUTBLOCKTIME_STR                     "inputBlockTime"
  43. #define ACTIONINPUT_INPUTBLOCKACTIVATION_STR               "inputBlockActivation"
  44. #define ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR              "inputBlockDeviceIndex"
  45.  
  46. #define ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR "CLEARALL"
  47.  
  48. #define ACTIONINPUT_USEANALOGCOMPARE_STR                   "useAnalogCompare"
  49. #define ACTIONINPUT_ANALOGCOMPAREVAL_STR                   "analogCompareVal"
  50. #define ACTIONINPUT_ANALOGCOMPAREOP_STR                    "analogCompareOp"
  51.  
  52. static const char* s_analogCompareOpEqualsStr = "EQUALS";
  53. static const char* s_analogCompareOpNotEqualsStr = "NOTEQUALS";
  54. static const char* s_analogCompareOpGreaterThanStr = "GREATERTHAN";
  55. static const char* s_analogCompareOpLessThanStr = "LESSTHAN";
  56.  
  57. //------------------------------------------------------------------------
  58. struct CryNameSorter
  59. {
  60.         //------------------------------------------------------------------------
  61.         bool operator()(const CCryName& lhs, const CCryName& rhs) const
  62.         {
  63.                 assert(lhs.c_str() != 0);
  64.                 assert(rhs.c_str() != 0);
  65.                 return strcmp(lhs.c_str(), rhs.c_str()) < 0;
  66.         }
  67. };
  68.  
  69. //------------------------------------------------------------------------
  70. CActionMapAction::CActionMapAction()
  71.         : m_triggeredInput("")
  72.         , m_actionId("")
  73.         , m_iNumRebindedInputs(0)
  74.         , m_pParentActionMap(NULL)
  75. {
  76. }
  77.  
  78. //------------------------------------------------------------------------
  79. CActionMapAction::~CActionMapAction()
  80. {
  81.         RemoveAllActionInputs();
  82. }
  83.  
  84. //------------------------------------------------------------------------
  85. void CActionMapAction::GetMemoryUsage(ICrySizer* pSizer) const
  86. {
  87.         TActionInputs::const_iterator iter = m_actionInputs.begin();
  88.         TActionInputs::const_iterator iterEnd = m_actionInputs.end();
  89.  
  90.         for (; iter != iterEnd; ++iter)
  91.         {
  92.                 const SActionInput* pActionInput = *iter;
  93.                 pSizer->AddObject(pActionInput->input);
  94.                 pSizer->AddObject(pActionInput->defaultInput);
  95.         }
  96. }
  97.  
  98. //------------------------------------------------------------------------
  99. bool CActionMapAction::AddActionInput(const SActionInput& actionInput, const int iByDeviceIndex)
  100. {
  101.         // Double check no invalid inputs
  102.         if (strcmp(actionInput.input, "") == 0)
  103.         {
  104.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddActionInput: Can't add empty input");
  105.                 return false;
  106.         }
  107.  
  108.         // Don't require to have a crc when passing in, but if has one, check it
  109.         uint32 inputCRC = CCrc32::ComputeLowercase(actionInput.input);
  110.         if (actionInput.inputCRC != 0)
  111.         {
  112.                 if (inputCRC != actionInput.inputCRC)
  113.                 {
  114.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddActionInput: Can't add, string crc specified doesn't match actual crc");
  115.                         return false;
  116.                 }
  117.         }
  118.  
  119.         SActionInput* pActionInput = FindActionInput(inputCRC);
  120.         if (pActionInput != NULL)
  121.         {
  122.                 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());
  123.                 return false;
  124.         }
  125.  
  126.         SActionInput* pNewActionInput = new SActionInput();
  127.         *pNewActionInput = actionInput;
  128.         pNewActionInput->input.MakeLower();
  129.         pNewActionInput->defaultInput.MakeLower();
  130.         pNewActionInput->inputCRC = inputCRC;
  131.  
  132.         if (iByDeviceIndex == -1)
  133.         {
  134.                 m_actionInputs.push_back(pNewActionInput);
  135.                 return true;
  136.         }
  137.         else
  138.         {
  139.                 int iCurrentByDeviceIndex = 0;
  140.  
  141.                 // Find actual index
  142.                 TActionInputs::iterator iter = m_actionInputs.begin();
  143.                 TActionInputs::iterator iterEnd = m_actionInputs.end();
  144.                 for (; iter != iterEnd; ++iter)
  145.                 {
  146.                         SActionInput* pContainedActionInput = *iter;
  147.                         CRY_ASSERT(pContainedActionInput != NULL);
  148.  
  149.                         if (pContainedActionInput->inputDevice == actionInput.inputDevice && iCurrentByDeviceIndex == iByDeviceIndex)
  150.                         {
  151.                                 m_actionInputs.insert(iter, pNewActionInput);
  152.                                 return true;
  153.                         }
  154.                         else
  155.                         {
  156.                                 ++iCurrentByDeviceIndex;
  157.                         }
  158.                 }
  159.  
  160.                 // Reached here so iByDeviceIndex must be incorrect
  161.                 SAFE_DELETE(pNewActionInput);
  162.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CAction::AddActionInput: Failed adding input with input: %s, iByDeviceIndex: %d, is incorrect", actionInput.input.c_str(), iByDeviceIndex);
  163.                 return false;
  164.         }
  165. }
  166.  
  167. //------------------------------------------------------------------------
  168. bool CActionMapAction::RemoveActionInput(uint32 inputCRC)
  169. {
  170.         TActionInputs::iterator iter = m_actionInputs.begin();
  171.         TActionInputs::iterator iterEnd = m_actionInputs.end();
  172.         for (; iter != iterEnd; ++iter)
  173.         {
  174.                 SActionInput* pActionInput = *iter;
  175.                 CRY_ASSERT(pActionInput != NULL);
  176.                 if (pActionInput->inputCRC == inputCRC)
  177.                 {
  178.                         SAFE_DELETE(pActionInput);
  179.                         m_actionInputs.erase(iter);
  180.                         return true;
  181.                 }
  182.         }
  183.  
  184.         return false;
  185. }
  186.  
  187. //------------------------------------------------------------------------
  188. void CActionMapAction::RemoveAllActionInputs()
  189. {
  190.         TActionInputs::iterator iter = m_actionInputs.begin();
  191.         TActionInputs::iterator iterEnd = m_actionInputs.end();
  192.         for (; iter != iterEnd; ++iter)
  193.         {
  194.                 SActionInput* pActionInput = *iter;
  195.                 CRY_ASSERT(pActionInput != NULL);
  196.                 SAFE_DELETE(pActionInput);
  197.         }
  198.         m_actionInputs.clear();
  199. }
  200.  
  201. //------------------------------------------------------------------------
  202. SActionInput* CActionMapAction::FindActionInput(uint32 inputCRC)
  203. {
  204.         SActionInput* pFoundActionInput = NULL;
  205.  
  206.         TActionInputs::iterator iter = m_actionInputs.begin();
  207.         TActionInputs::iterator iterEnd = m_actionInputs.end();
  208.         for (; iter != iterEnd; ++iter)
  209.         {
  210.                 SActionInput* pActionInput = *iter;
  211.                 CRY_ASSERT(pActionInput != NULL);
  212.                 if (pActionInput->inputCRC == inputCRC)
  213.                 {
  214.                         pFoundActionInput = pActionInput;
  215.                         break;
  216.                 }
  217.         }
  218.  
  219.         return pFoundActionInput;
  220. }
  221.  
  222. //------------------------------------------------------------------------
  223. const SActionInput* CActionMapAction::FindActionInput(const char* szInput) const
  224. {
  225.         uint32 inputCRC = CCrc32::ComputeLowercase(szInput);
  226.  
  227.         const SActionInput* pFoundActionInput = NULL;
  228.  
  229.         TActionInputs::const_iterator iter = m_actionInputs.begin();
  230.         TActionInputs::const_iterator iterEnd = m_actionInputs.end();
  231.         for (; iter != iterEnd; ++iter)
  232.         {
  233.                 const SActionInput* pActionInput = *iter;
  234.                 CRY_ASSERT(pActionInput != NULL);
  235.                 if (pActionInput->inputCRC == inputCRC)
  236.                 {
  237.                         pFoundActionInput = pActionInput;
  238.                         break;
  239.                 }
  240.         }
  241.  
  242.         return pFoundActionInput;
  243. }
  244.  
  245. //------------------------------------------------------------------------
  246. SActionInput* CActionMapAction::GetActionInput(const int iIndex)
  247. {
  248.         CRY_ASSERT(iIndex >= 0 && iIndex < (int)m_actionInputs.size());
  249.         if (iIndex >= 0 && iIndex < (int)m_actionInputs.size())
  250.         {
  251.                 return m_actionInputs[iIndex];
  252.         }
  253.  
  254.         return NULL;
  255. }
  256.  
  257. //------------------------------------------------------------------------
  258. SActionInput* CActionMapAction::GetActionInput(const EActionInputDevice device, const int iIndexByDevice)
  259. {
  260.         int iCurrentIndexByDevice = 0; // Array may not be sorted, but the index specified by iIndexByDevice means the order in which its found
  261.         SActionInput* pFoundActionInput = NULL;
  262.         for (int i = 0; i < m_actionInputs.size(); i++)
  263.         {
  264.                 SActionInput* pActionInput = m_actionInputs[i];
  265.                 CRY_ASSERT(pActionInput != NULL);
  266.  
  267.                 if (pActionInput->inputDevice == device)
  268.                 {
  269.                         if (iCurrentIndexByDevice == iIndexByDevice)
  270.                         {
  271.                                 pFoundActionInput = pActionInput;
  272.                                 break;
  273.                         }
  274.                         else // Keep looking for next one
  275.                         {
  276.                                 iCurrentIndexByDevice++;
  277.                         }
  278.                 }
  279.         }
  280.  
  281.         return pFoundActionInput;
  282. }
  283.  
  284. //------------------------------------------------------------------------
  285. const SActionInput* CActionMapAction::GetActionInput(const int iIndex) const
  286. {
  287.         CRY_ASSERT(iIndex >= 0 && iIndex < (int)m_actionInputs.size());
  288.         if (iIndex >= 0 && iIndex < (int)m_actionInputs.size())
  289.         {
  290.                 return m_actionInputs[iIndex];
  291.         }
  292.  
  293.         return NULL;
  294. }
  295.  
  296. //------------------------------------------------------------------------
  297. const SActionInput* CActionMapAction::GetActionInput(const EActionInputDevice device, const int iIndexByDevice) const
  298. {
  299.         int iCurrentIndexByDevice = 0; // Array may not be sorted, but the index specified by iIndexByDevice means the order in which its found
  300.         const SActionInput* pFoundActionInput = NULL;
  301.         for (int i = 0; i < m_actionInputs.size(); i++)
  302.         {
  303.                 const SActionInput* pActionInput = m_actionInputs[i];
  304.                 CRY_ASSERT(pActionInput != NULL);
  305.  
  306.                 if (pActionInput->inputDevice == device)
  307.                 {
  308.                         if (iCurrentIndexByDevice == iIndexByDevice)
  309.                         {
  310.                                 pFoundActionInput = pActionInput;
  311.                                 break;
  312.                         }
  313.                         else // Keep looking for next one
  314.                         {
  315.                                 iCurrentIndexByDevice++;
  316.                         }
  317.                 }
  318.         }
  319.  
  320.         return pFoundActionInput;
  321. }
  322.  
  323. //------------------------------------------------------------------------
  324. SActionInput* CActionMapAction::AddAndGetActionInput(const SActionInput& actionInput)
  325. {
  326.         // Don't require to have a crc when passing in, but if has one, check it
  327.         uint32 inputCRC = CCrc32::ComputeLowercase(actionInput.input);
  328.         if (actionInput.inputCRC != 0)
  329.         {
  330.                 if (inputCRC != actionInput.inputCRC)
  331.                 {
  332.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddAndGetActionInput: Can't add, string crc specified doesn't match actual crc");
  333.                         return NULL;
  334.                 }
  335.         }
  336.  
  337.         SActionInput* pActionInput = FindActionInput(inputCRC);
  338.         if (pActionInput != NULL)
  339.         {
  340.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CAction::AddAndGetActionInput::Unable to add input with input: %s, already exists", actionInput.input.c_str());
  341.                 return NULL;
  342.         }
  343.         SActionInput* pNewActionInput = new SActionInput();
  344.         *pNewActionInput = actionInput;
  345.         pNewActionInput->input.MakeLower();
  346.         pNewActionInput->defaultInput.MakeLower();
  347.         pNewActionInput->inputCRC = inputCRC;
  348.         m_actionInputs.push_back(pNewActionInput);
  349.  
  350.         return pNewActionInput;
  351. }
  352.  
  353. //------------------------------------------------------------------------
  354. CActionMap::CActionMap(CActionMapManager* pActionMapManager, const char* name)
  355.         : m_pActionMapManager(pActionMapManager),
  356.         m_enabled(!stricmp(name, "default")),
  357.         m_listenerId(0),
  358.         m_actionMapListeners(2),
  359.         m_flownodesListeners(2),
  360.         m_name(name),
  361.         m_iNumRebindedInputs(0)
  362. {
  363. }
  364.  
  365. //------------------------------------------------------------------------
  366. CActionMap::~CActionMap()
  367. {
  368.         Clear();
  369. }
  370.  
  371. //------------------------------------------------------------------------
  372. void CActionMap::Release()
  373. {
  374.         m_pActionMapManager->RemoveActionMap(m_name);
  375. };
  376.  
  377. //------------------------------------------------------------------------
  378. void CActionMap::Clear()
  379. {
  380.         m_pActionMapManager->RemoveBind(this);
  381.         m_actions.clear();
  382.         SetNumRebindedInputs(0);
  383. }
  384.  
  385. //------------------------------------------------------------------------
  386. bool CActionMap::CreateAction(const ActionId& actionId)
  387. {
  388.         TActionMap::iterator iter = m_actions.find(actionId);
  389.         if (iter != m_actions.end())
  390.         {
  391.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::CreateAction: Unable to create action, %s already exists", actionId.c_str());
  392.                 return false;
  393.         }
  394.  
  395.         CActionMapAction action;
  396.         action.SetActionId(actionId);
  397.         action.SetParentActionMap(this);
  398.  
  399.         m_actions[actionId] = action;
  400.  
  401.         return true;
  402. }
  403.  
  404. //------------------------------------------------------------------------
  405. bool CActionMap::RemoveAction(const ActionId& actionId)
  406. {
  407.         TActionMap::iterator iter = m_actions.find(actionId);
  408.         if (iter == m_actions.end())
  409.         {
  410.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::RemoveAction: Failed to find action: %s", actionId.c_str());
  411.                 return false;
  412.         }
  413.  
  414.         CActionMapAction& action = iter->second;
  415.         m_pActionMapManager->RemoveBind(&action);
  416.  
  417.         // Update new rebind count
  418.         int newRebindCount = GetNumRebindedInputs();
  419.  
  420.         int numActionInputs = action.GetNumActionInputs();
  421.         for (int i = 0; i < numActionInputs; ++i)
  422.         {
  423.                 SActionInput* pActionInput = action.GetActionInput(i);
  424.                 CRY_ASSERT(pActionInput != NULL);
  425.  
  426.                 if (pActionInput->input != pActionInput->defaultInput)
  427.                 {
  428.                         --newRebindCount;
  429.                 }
  430.         }
  431.  
  432.         if (newRebindCount != GetNumRebindedInputs())
  433.         {
  434.                 SetNumRebindedInputs(newRebindCount);
  435.         }
  436.  
  437.         m_actions.erase(iter);
  438.  
  439.         return true;
  440. }
  441.  
  442. //------------------------------------------------------------------------
  443. bool CActionMap::AddActionInput(const ActionId& actionId, const SActionInput& actionInput, const int iByDeviceIndex)
  444. {
  445.         CActionMapAction* pAction = NULL;
  446.  
  447.         TActionMap::iterator iter = m_actions.find(actionId);
  448.         if (iter == m_actions.end()) // Don't have an action, so create one to hold the input
  449.         {
  450.                 pAction = CreateAndGetAction(actionId);
  451.                 CRY_ASSERT(pAction != NULL);
  452.                 if (!pAction)
  453.                 {
  454.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddActionInput: Failed to create action: %s", actionId.c_str());
  455.                         return false;
  456.                 }
  457.         }
  458.         else
  459.         {
  460.                 pAction = &iter->second;
  461.                 CRY_ASSERT(pAction != NULL);
  462.         }
  463.  
  464.         return pAction->AddActionInput(actionInput, iByDeviceIndex);
  465. }
  466.  
  467. //------------------------------------------------------------------------
  468. bool CActionMap::AddAndBindActionInput(const ActionId& actionId, const SActionInput& actionInput)
  469. {
  470.         CActionMapAction* pAction = NULL;
  471.         TActionMap::iterator iAction = m_actions.find(actionId);
  472.         if (iAction == m_actions.end())
  473.         {
  474.                 pAction = CreateAndGetAction(actionId);
  475.                 CRY_ASSERT(pAction != NULL);
  476.                 if (pAction == NULL)
  477.                 {
  478.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddAndBindActionInput: Failed to create action: %s", actionId.c_str());
  479.                         return false;
  480.                 }
  481.         }
  482.         else
  483.         {
  484.                 pAction = &iAction->second;
  485.                 CRY_ASSERT(pAction != NULL);
  486.         }
  487.         SActionInput* pNewActionInput = pAction->AddAndGetActionInput(actionInput);
  488.         if (pNewActionInput != NULL)
  489.         {
  490.                 return m_pActionMapManager->AddBind(this, pAction, pNewActionInput);
  491.         }
  492.         else
  493.         {
  494.                 return false;
  495.         }
  496. }
  497.  
  498. //------------------------------------------------------------------------
  499. bool CActionMap::RemoveActionInput(const ActionId& actionId, const char* szInput)
  500. {
  501.         TActionMap::iterator iter = m_actions.find(actionId);
  502.         if (iter == m_actions.end())
  503.         {
  504.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::RemoveActionInput: Failed to find action: %s", actionId.c_str());
  505.                 return false;
  506.         }
  507.  
  508.         CActionMapAction& action = iter->second;
  509.  
  510.         uint32 inputCRC = CCrc32::ComputeLowercase(szInput);
  511.  
  512.         SActionInput* pActionInput = action.FindActionInput(inputCRC);
  513.         if (pActionInput == NULL)
  514.         {
  515.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::RemoveActionInput: Failed to find action input for input: %s", szInput);
  516.                 return false;
  517.         }
  518.  
  519.         bool bResult = m_pActionMapManager->RemoveBind(this, &action, pActionInput);
  520.         if (!bResult)
  521.         {
  522.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::RemoveActionInput: Failed to remove binding for action input with input: %s", szInput);
  523.                 return false;
  524.         }
  525.  
  526.         return action.RemoveActionInput(inputCRC);
  527. }
  528.  
  529. //------------------------------------------------------------------------
  530. bool CActionMap::ReBindActionInput(const ActionId& actionId, const char* szCurrentInput, const char* szNewInput)
  531. {
  532.         TActionMap::iterator iter = m_actions.find(actionId);
  533.         if (iter != m_actions.end())
  534.         {
  535.                 CActionMapAction& action = iter->second;
  536.                 return ReBindActionInput(&action, szCurrentInput, szNewInput);
  537.         }
  538.  
  539.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::ReBindActionInput: Unable to rebind action, %s, doesn't exist", actionId.c_str());
  540.         return false;
  541. }
  542.  
  543. //------------------------------------------------------------------------
  544. bool CActionMap::ReBindActionInput(const ActionId& actionId,
  545.                                    const char* szNewInput,
  546.                                    const EActionInputDevice device,
  547.                                    const int iByDeviceIndex)
  548. {
  549.         TActionMap::iterator iter = m_actions.find(actionId);
  550.         if (iter == m_actions.end())
  551.         {
  552.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::ReBindActionInput: Can't find action: %s", actionId.c_str());
  553.                 return false;
  554.         }
  555.  
  556.         CActionMapAction& action = iter->second;
  557.         return ReBindActionInput(&action, szNewInput, device, iByDeviceIndex);
  558. }
  559.  
  560. //------------------------------------------------------------------------
  561. CActionMapAction* CActionMap::CreateAndGetAction(const ActionId& actionId)
  562. {
  563.         TActionMap::iterator iter = m_actions.find(actionId);
  564.         if (iter != m_actions.end())
  565.         {
  566.                 return NULL;
  567.         }
  568.  
  569.         CActionMapAction action;
  570.         action.SetActionId(actionId);
  571.         action.SetParentActionMap(this);
  572.  
  573.         m_actions[actionId] = action;
  574.  
  575.         return &m_actions[actionId];
  576. }
  577.  
  578. //------------------------------------------------------------------------
  579. bool CActionMap::AddAndBindActionInput(CActionMapAction* pAction, const SActionInput& actionInput)
  580. {
  581.         CRY_ASSERT(pAction != NULL);
  582.         if (!pAction)
  583.                 return false;
  584.  
  585.         SActionInput* pAddedActionInput = pAction->AddAndGetActionInput(actionInput);
  586.         if (!pAddedActionInput)
  587.         {
  588.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddAndBindActionInput: Failed adding actioninput for input: %s", actionInput.input.c_str());
  589.                 return false;
  590.         }
  591.  
  592.         bool bResult = m_pActionMapManager->AddBind(this, pAction, pAddedActionInput);
  593.         if (!bResult)
  594.         {
  595.                 pAction->RemoveActionInput(pAddedActionInput->inputCRC);
  596.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::AddAndBindActionInput: Failed binding actioninput");
  597.                 return false;
  598.         }
  599.  
  600.         return true;
  601. }
  602.  
  603. //------------------------------------------------------------------------
  604. bool CActionMap::ReBindActionInput(CActionMapAction* pAction, const char* szCurrentInput, const char* szNewInput)
  605. {
  606.         uint32 inputCRC = CCrc32::ComputeLowercase(szCurrentInput);
  607.  
  608.         SActionInput* pActionInput = pAction->FindActionInput(inputCRC);
  609.         if (!pActionInput)
  610.         {
  611.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::ReBindActionInput: Can't find input: %s for action: %s", szCurrentInput, pAction->GetActionId().c_str());
  612.                 return false;
  613.         }
  614.  
  615.         return ReBindActionInput(pAction, *pActionInput, szNewInput);
  616. }
  617.  
  618. //------------------------------------------------------------------------
  619. bool CActionMap::ReBindActionInput(CActionMapAction* pAction, SActionInput& actionInput, const char* szNewInput)
  620. {
  621.         CRY_ASSERT(pAction != NULL);
  622.  
  623.         if (actionInput.input == szNewInput) // Rebinding to same input
  624.                 return false;
  625.  
  626.         if (m_pActionMapManager->HasBind(this, pAction, &actionInput)) // Might not be binded if cleared
  627.         {
  628.                 bool bResult = m_pActionMapManager->RemoveBind(this, pAction, &actionInput);
  629.                 if (!bResult)
  630.                 {
  631.                         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());
  632.                         return false;
  633.                 }
  634.         }
  635.  
  636.         actionInput.input = szNewInput;
  637.  
  638.         // Possible to assign empty to clear the binding
  639.         if (szNewInput != NULL && strcmp(szNewInput, "") != 0)
  640.         {
  641.                 actionInput.inputCRC = CCrc32::ComputeLowercase(szNewInput);
  642.  
  643.                 bool bResult = m_pActionMapManager->AddBind(this, pAction, &actionInput);
  644.                 if (!bResult)
  645.                 {
  646.                         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());
  647.                         return false;
  648.                 }
  649.         }
  650.  
  651.         // If input now equals the default, nolonger needs the mark from the previous rebind
  652.         if (actionInput.input == actionInput.defaultInput)
  653.         {
  654.                 SetNumRebindedInputs(GetNumRebindedInputs() - 1);
  655.                 pAction->SetNumRebindedInputs(pAction->GetNumRebindedInputs() - 1);
  656.         }
  657.         else // Remember this rebind
  658.         {
  659.                 SetNumRebindedInputs(GetNumRebindedInputs() + 1);
  660.                 pAction->SetNumRebindedInputs(pAction->GetNumRebindedInputs() + 1);
  661.         }
  662.  
  663.         return true;
  664. }
  665.  
  666. //------------------------------------------------------------------------
  667. bool CActionMap::ReBindActionInput(CActionMapAction* pAction,
  668.                                    const char* szNewInput,
  669.                                    const EActionInputDevice device,
  670.                                    const int iByDeviceIndex)
  671. {
  672.  
  673.         SActionInput* pActionInput = pAction->GetActionInput(device, iByDeviceIndex);
  674.         if (!pActionInput)
  675.         {
  676.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::ReBindActionInput: Can't get input by index: %d for action: %s", iByDeviceIndex, pAction->GetActionId().c_str());
  677.                 return false;
  678.         }
  679.  
  680.         if (pActionInput->input == szNewInput) // Rebinding to same input
  681.                 return false;
  682.  
  683.         if (m_pActionMapManager->HasBind(this, pAction, pActionInput)) // Might not be binded if cleared
  684.         {
  685.                 bool bResult = m_pActionMapManager->RemoveBind(this, pAction, pActionInput);
  686.                 if (!bResult)
  687.                 {
  688.                         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());
  689.                         return false;
  690.                 }
  691.         }
  692.  
  693.         pActionInput->input = szNewInput;
  694.  
  695.         // Possible to assign empty to clear the binding
  696.         if (szNewInput != NULL && strcmp(szNewInput, "") != 0)
  697.         {
  698.                 pActionInput->inputCRC = CCrc32::ComputeLowercase(szNewInput);
  699.  
  700.                 bool bResult = m_pActionMapManager->AddBind(this, pAction, pActionInput);
  701.                 if (!bResult)
  702.                 {
  703.                         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());
  704.                         return false;
  705.                 }
  706.         }
  707.         else
  708.         {
  709.                 pActionInput->inputCRC = 0;
  710.         }
  711.  
  712.         // If input now equals the default, nolonger needs the mark from the previous rebind
  713.         if (pActionInput->input == pActionInput->defaultInput)
  714.         {
  715.                 SetNumRebindedInputs(GetNumRebindedInputs() - 1);
  716.                 pAction->SetNumRebindedInputs(pAction->GetNumRebindedInputs() - 1);
  717.         }
  718.         else // Remember this rebind
  719.         {
  720.                 SetNumRebindedInputs(GetNumRebindedInputs() + 1);
  721.                 pAction->SetNumRebindedInputs(pAction->GetNumRebindedInputs() + 1);
  722.         }
  723.  
  724.         return true;
  725.  
  726. }
  727.  
  728. //------------------------------------------------------------------------
  729. void CActionMap::SetActionListener(EntityId id)
  730. {
  731.         m_listenerId = id;
  732. }
  733.  
  734. //------------------------------------------------------------------------
  735. EntityId CActionMap::GetActionListener() const
  736. {
  737.         return m_listenerId;
  738. }
  739.  
  740. //------------------------------------------------------------------------
  741. bool CActionMap::Reset()
  742. {
  743.         m_enabled = !stricmp(GetName(), "default");
  744.  
  745.         for (TActionMap::iterator it = m_actions.begin(); it != m_actions.end(); ++it)
  746.         {
  747.                 CActionMapAction& action = it->second;
  748.  
  749.                 const int numInputs = action.GetNumActionInputs();
  750.                 for (int i = 0; i < numInputs; i++)
  751.                 {
  752.                         SActionInput* pActionInput = action.GetActionInput(i);
  753.                         CRY_ASSERT(pActionInput != NULL);
  754.  
  755.                         if (pActionInput->input == pActionInput->defaultInput) // Input is already default
  756.                                 continue;
  757.  
  758.                         if (!ReBindActionInput(&action, *pActionInput, pActionInput->defaultInput))
  759.                         {
  760.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::Reset: Failed resetting binding to default input in action: %s", action.GetActionId().c_str());
  761.                                 return false;
  762.                         }
  763.                 }
  764.         }
  765.  
  766.         return true;
  767. }
  768.  
  769. //------------------------------------------------------------------------
  770. const IActionMapAction* CActionMap::GetAction(const ActionId& actionId) const
  771. {
  772.         TActionMap::const_iterator actionIter = m_actions.find(actionId);
  773.         if (actionIter == m_actions.end())
  774.                 return NULL;
  775.  
  776.         const CActionMapAction& action = actionIter->second;
  777.  
  778.         return &action;
  779. }
  780.  
  781. //------------------------------------------------------------------------
  782. IActionMapAction* CActionMap::GetAction(const ActionId& actionId)
  783. {
  784.         TActionMap::iterator actionIter = m_actions.find(actionId);
  785.         if (actionIter == m_actions.end())
  786.                 return NULL;
  787.  
  788.         IActionMapAction& action = actionIter->second;
  789.  
  790.         return &action;
  791. }
  792.  
  793. //------------------------------------------------------------------------
  794. bool CActionMap::CanProcessInput(const SInputEvent& inputEvent, CActionMap* pActionMap, CActionMapAction* pAction, SActionInput* pActionInput)
  795. {
  796.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  797.         bool bRes = false;
  798.  
  799.         float fCurrTime = gEnv->pTimer->GetCurrTime();
  800.         IGameFramework* pGameFramework = gEnv->pGameFramework;
  801.         if (pGameFramework && pGameFramework->IsGamePaused())
  802.         {
  803.                 fCurrTime = gEnv->pTimer->GetCurrTime(ITimer::ETIMER_UI);
  804.         }
  805.  
  806.         if (m_enabled)
  807.         {
  808.                 // Normal buttons + keys send a press, down, release events
  809.                 // Analog events only send changed
  810.                 // So deal with these totally differently
  811.                 if (pActionInput->activationMode & eAAM_AnalogCompare)
  812.                 {
  813.                         switch (pActionInput->analogCompareOp) // Check if fulfills analog condition
  814.                         {
  815.                         case eAACO_Equals:
  816.                                 {
  817.                                         if (fabs(inputEvent.value - pActionInput->fAnalogCompareVal) < FLT_EPSILON)
  818.                                         {
  819.                                                 bRes = true;
  820.                                         }
  821.                                 }
  822.                                 break;
  823.                         case eAACO_NotEquals:
  824.                                 {
  825.                                         if (fabs(inputEvent.value - pActionInput->fAnalogCompareVal) >= FLT_EPSILON)
  826.                                         {
  827.                                                 bRes = true;
  828.                                         }
  829.                                 }
  830.                                 break;
  831.                         case eAACO_GreaterThan:
  832.                                 {
  833.                                         if (inputEvent.value > pActionInput->fAnalogCompareVal)
  834.                                         {
  835.                                                 bRes = true;
  836.                                         }
  837.                                 }
  838.                                 break;
  839.                         case eAACO_LessThan:
  840.                                 {
  841.                                         if (inputEvent.value < pActionInput->fAnalogCompareVal)
  842.                                         {
  843.                                                 bRes = true;
  844.                                         }
  845.                                 }
  846.                                 break;
  847.                         }
  848.  
  849.                         if (bRes)
  850.                         {
  851.                                 // Since analog inputs dont have the concept of being down, create a refire timer to simulate hold
  852.                                 // and remove this when analog condition nolonger fulfilled
  853.                                 if (!m_pActionMapManager->IsCurrentlyRefiringInput()) // Input event is from refire, dont try to refire a refired event
  854.                                 {
  855.                                         m_pActionMapManager->UpdateRefireData(inputEvent, pActionMap, pAction, pActionInput);
  856.                                 }
  857.  
  858.                                 if (pActionInput->bAnalogConditionFulfilled != true)
  859.                                 {
  860.                                         pActionInput->fPressedTime = fCurrTime;
  861.                                         pActionInput->fLastRepeatTime = fCurrTime;
  862.                                         pActionInput->bHoldTriggerFired = false;
  863.                                         pActionInput->fCurrentHoldValue = 0.f;
  864.                                         pActionInput->bAnalogConditionFulfilled = true;
  865.                                         pActionInput->currentState = eIS_Pressed;
  866.                                 }
  867.                                 else if (pActionInput->bHoldTriggerFired)
  868.                                 {
  869.                                         pActionInput->currentState = eIS_Changed;
  870.                                 }
  871.  
  872.                                 // Although condition is true, result value can be set false again if hold timer conditions aren't true
  873.                                 // Only check if action should be processed here
  874.                                 bRes = IsActionInputTriggered(inputEvent, pActionMap, pAction, pActionInput);
  875.                         }
  876.                         else // Didn't fulfill analog condition
  877.                         {
  878.                                 if (!m_pActionMapManager->IsCurrentlyRefiringInput() && pActionInput->bAnalogConditionFulfilled != false)
  879.                                 {
  880.                                         pActionInput->bAnalogConditionFulfilled = false;
  881.                                         m_pActionMapManager->RemoveRefireData(pActionMap, pAction, pActionInput);
  882.                                 }
  883.                                 pActionInput->fCurrentHoldValue = 0.f;
  884.                                 pActionInput->currentState = eIS_Released;
  885.                         }
  886.                 }
  887.                 else if (inputEvent.state == eIS_Pressed)
  888.                 {
  889.                         pActionInput->fPressedTime = fCurrTime;
  890.  
  891.                         if (pActionInput->activationMode & eAAM_OnHold) // Needed for hold
  892.                         {
  893.                                 pActionInput->fLastRepeatTime = fCurrTime;
  894.                                 if (pActionInput->fHoldTriggerDelay > 0.f)
  895.                                 {
  896.                                         pActionInput->bHoldTriggerFired = false;
  897.                                 }
  898.                                 else // Hold trigger delay is immediate, same with press event, so dont fire twice
  899.                                 {
  900.                                         pActionInput->bHoldTriggerFired = true;
  901.                                 }
  902.  
  903.                                 pActionInput->fCurrentHoldValue = 0.f;
  904.                         }
  905.  
  906.                         // Check if the action should be processed
  907.                         bRes = IsActionInputTriggered(inputEvent, pActionMap, pAction, pActionInput);
  908.                 }
  909.                 else // All other cases
  910.                 {
  911.                         // Check if the action should be processed
  912.                         bRes = IsActionInputTriggered(inputEvent, pActionMap, pAction, pActionInput);
  913.                 }
  914.  
  915.                 // Remember the triggered input
  916.  
  917.                 // Change action's current state
  918.                 if (!bRes)
  919.                 {
  920.                         if (inputEvent.state == eIS_Down && pActionInput->currentState == eIS_Pressed && (pActionInput->activationMode & eAAM_OnRelease))
  921.                                 pActionInput->currentState = eIS_Pressed;
  922.                         else
  923.                                 pActionInput->currentState = eIS_Unknown;
  924.                 }
  925.                 else if (inputEvent.state == eIS_Changed && !(pActionInput->activationMode & eAAM_AnalogCompare))
  926.                 {
  927.                         pActionInput->currentState = eIS_Changed;
  928.                 }
  929.                 else if (inputEvent.state == eIS_Down)
  930.                 {
  931.                         pActionInput->currentState = eIS_Down;
  932.                 }
  933.                 else if (pActionInput->activationMode & (eAAM_OnPress | eAAM_OnRelease))
  934.                 {
  935.                         if (inputEvent.state == eIS_Released || inputEvent.state == eIS_Pressed)
  936.                                 pActionInput->currentState = inputEvent.state;
  937.                 }
  938.         }
  939.  
  940.         return bRes;
  941. }
  942.  
  943. //------------------------------------------------------------------------
  944. bool CActionMap::IsActionInputTriggered(const SInputEvent& inputEvent, CActionMap* pActionMap, CActionMapAction* pAction, SActionInput* pActionInput) const
  945. {
  946.         bool bRes = false;
  947.  
  948.         if ((inputEvent.modifiers & eMM_Modifiers) &&
  949.             (pActionInput->activationMode & eAAM_NoModifiers))
  950.         {
  951.                 return bRes;
  952.         }
  953.  
  954.         float fCurrTime = gEnv->pTimer->GetCurrTime();
  955.         IGameFramework* pGameFramework = gEnv->pGameFramework;
  956.         if (pGameFramework && pGameFramework->IsGamePaused())
  957.         {
  958.                 fCurrTime = gEnv->pTimer->GetCurrTime(ITimer::ETIMER_UI);
  959.         }
  960.  
  961.         // currentMode -> bit flag based on key state needed for trigger, and actual key state
  962.         // Special handling for certain types of logic
  963.         int currentMode = pActionInput->activationMode & inputEvent.state;
  964.         const float fTimePressed = fCurrTime - pActionInput->fPressedTime;
  965.         const bool bJustPressed = fabs(fTimePressed) < FLT_EPSILON;
  966.  
  967.         if ((inputEvent.state == eIS_Down) && (pActionInput->activationMode & eAAM_OnHold))
  968.         {
  969.                 if (bJustPressed)
  970.                 {
  971.                         return bRes; // When holding, a press event is handled and immediately on same time frame a hold event is passed in, ignore it
  972.                 }
  973.                 else
  974.                 {
  975.                         currentMode = eAAM_Always; // Held events aren't checked in the above line, always allow them
  976.                 }
  977.         }
  978.         else if (inputEvent.state == eIS_Changed) // Analog events aren't checked in the above line, always allow them
  979.         {
  980.                 if (bJustPressed && ((pActionInput->activationMode & eAAM_OnPress) == 0)) // This is a press from analog event, but input doesn't handle press, ignore
  981.                 {
  982.                         return bRes;
  983.                 }
  984.  
  985.                 currentMode = eAAM_Always;
  986.         }
  987.         else if (inputEvent.state == eIS_Released)
  988.         {
  989.                 pActionInput->fCurrentHoldValue = 0.f;
  990.  
  991.                 //ignore if we have a release threshold and it's been exceeded
  992.                 if (pActionInput->fReleaseTriggerThreshold >= 0.0f && fTimePressed >= pActionInput->fReleaseTriggerThreshold)
  993.                 {
  994.                         return bRes;
  995.                 }
  996.         }
  997.  
  998.         // Get blocking type based on how the action was triggered
  999.         if (currentMode)
  1000.         {
  1001.                 // Support initial hold trigger delay and repeating
  1002.                 if ((pActionInput->activationMode & eAAM_OnHold) &&
  1003.                     (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.                 {
  1005.                         if (pActionInput->bHoldTriggerFired) // Initial hold trigger already fired
  1006.                         {
  1007.                                 if (fCurrTime < pActionInput->fLastRepeatTime)
  1008.                                 {
  1009.                                         pActionInput->fLastRepeatTime = fCurrTime;
  1010.                                 }
  1011.  
  1012.                                 if (pActionInput->fHoldRepeatDelay != -1.0f && fCurrTime - pActionInput->fLastRepeatTime >= pActionInput->fHoldRepeatDelay) // fHoldRepeatDelay of -1.0f means no repeat
  1013.                                 {
  1014.                                         pActionInput->fLastRepeatTime = fCurrTime;
  1015.                                         bRes = true;
  1016.                                 }
  1017.                         }
  1018.                         else
  1019.                         {
  1020.                                 const bool bIsCurrentKey = (m_pActionMapManager->GetIncomingInputKeyID() == inputEvent.keyId);
  1021.                                 // Support overriding hold trigger timer if repeating same input
  1022.                                 if ((m_pActionMapManager->IsRepeatedInputHoldTriggerFired()) &&     // Could have been interrupted by another held key
  1023.                                     (bIsCurrentKey) &&                                              // Need to check since could have multiple held keys
  1024.                                     (pActionInput->fHoldTriggerDelayRepeatOverride >= FLT_EPSILON)) // Default is -1.0f which won't activate this
  1025.                                 {
  1026.                                         if (fTimePressed >= pActionInput->fHoldTriggerDelayRepeatOverride)
  1027.                                         {
  1028.                                                 pActionInput->bHoldTriggerFired = true;
  1029.                                                 pActionInput->fCurrentHoldValue = 1.f;
  1030.                                                 pActionInput->fLastRepeatTime = fCurrTime;
  1031.                                                 bRes = true;
  1032.                                         }
  1033.                                 }
  1034.                                 else if (fTimePressed >= pActionInput->fHoldTriggerDelay)
  1035.                                 {
  1036.                                         pActionInput->bHoldTriggerFired = true;
  1037.                                         pActionInput->fCurrentHoldValue = 1.f;
  1038.                                         pActionInput->fLastRepeatTime = fCurrTime;
  1039.                                         if (m_pActionMapManager->IsIncomingInputRepeated() && bIsCurrentKey) // Need to check since could have multiple held keys
  1040.                                         {
  1041.                                                 m_pActionMapManager->SetRepeatedInputHoldTriggerFired(true);
  1042.                                         }
  1043.                                         bRes = true;
  1044.                                 }
  1045.                                 else
  1046.                                 {
  1047.                                         if (pActionInput->fHoldTriggerDelay > 0.f)
  1048.                                         {
  1049.                                                 pActionInput->fCurrentHoldValue = (fTimePressed / pActionInput->fHoldTriggerDelay);
  1050.                                         }
  1051.                                         else
  1052.                                         {
  1053.                                                 pActionInput->fCurrentHoldValue = 0.f;
  1054.                                         }
  1055.                                 }
  1056.                         }
  1057.                 }
  1058.                 else if ((inputEvent.state == eIS_Pressed) &&
  1059.                          (pActionInput->fPressTriggerDelay >= FLT_EPSILON) &&  // Handle delayed press situation
  1060.                          (!m_pActionMapManager->IsCurrentlyRefiringInput()))   // Input event is from refire, dont try to refire a refired event
  1061.                 {
  1062.                         if ((m_pActionMapManager->IsIncomingInputRepeated()) &&
  1063.                             (m_pActionMapManager->GetIncomingInputKeyID() == inputEvent.keyId) && // Repeated same input, allow override if is one
  1064.                             (pActionInput->fPressTriggerDelayRepeatOverride >= FLT_EPSILON))      // Default is -1.0f which won't activate this
  1065.                         {
  1066.                                 // Remove delayed press fire
  1067.                                 m_pActionMapManager->RemoveRefireData(pActionMap, pAction, pActionInput);
  1068.  
  1069.                                 bRes = true;
  1070.                         }
  1071.                         else // Not repeated key, must wait for delay before firing
  1072.                         {
  1073.                                 // Check press delay priority, if greater or equal to current, override
  1074.                                 int currentHighestDelayPriority = m_pActionMapManager->GetHighestPressDelayPriority();
  1075.                                 if (pActionInput->iPressDelayPriority >= currentHighestDelayPriority)
  1076.                                 {
  1077.                                         m_pActionMapManager->RemoveAllDelayedPressRefireData();
  1078.                                         m_pActionMapManager->UpdateRefireData(inputEvent, pActionMap, pAction, pActionInput); // Will fire again after delay
  1079.                                 }
  1080.                                 bRes = false;
  1081.                         }
  1082.                 }
  1083.                 else if ((inputEvent.state == eIS_Released) &&
  1084.                          (pActionInput->fPressTriggerDelay >= FLT_EPSILON) &&  // Handle delayed press situation
  1085.                          (!m_pActionMapManager->IsCurrentlyRefiringInput()))   // Input event is from refire, dont try to refire a refired event
  1086.                 {
  1087.                         if (fTimePressed - pActionInput->fPressTriggerDelay < FLT_EPSILON) // Press delay hasn't fired yet, release should be fired right after delayed press
  1088.                         {
  1089.                                 m_pActionMapManager->SetRefireDataDelayedPressNeedsRelease(inputEvent, pActionMap, pAction, pActionInput, true);
  1090.                                 bRes = false;
  1091.                         }
  1092.                         else // Ok to fire release since delayed press already fired
  1093.                         {
  1094.                                 bRes = true;
  1095.                         }
  1096.                 }
  1097.                 else // Not held
  1098.                 {
  1099.                         bRes = true;
  1100.                 }
  1101.         }
  1102.  
  1103.         return bRes;
  1104. }
  1105.  
  1106. //------------------------------------------------------------------------
  1107. void CActionMap::InputProcessed()
  1108. {
  1109.         IActionListener* pEntityListener = NULL;
  1110.  
  1111.         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_listenerId))
  1112.                 if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  1113.                         pEntityListener = pGameObject;
  1114.  
  1115.         if (pEntityListener)
  1116.                 pEntityListener->AfterAction();
  1117.  
  1118.         for (TActionMapListeners::Notifier notify(m_actionMapListeners); notify.IsValid(); notify.Next())
  1119.         {
  1120.                 notify->AfterAction();
  1121.         }
  1122. }
  1123.  
  1124. //------------------------------------------------------------------------
  1125. void CActionMap::ReleaseActionsIfActive()
  1126. {
  1127.         TActionMap::iterator it = m_actions.begin();
  1128.         TActionMap::iterator end = m_actions.end();
  1129.         for (; it != end; ++it)
  1130.         {
  1131.                 CActionMapAction& action = it->second;
  1132.                 ReleaseActionIfActiveInternal(action);
  1133.         }
  1134. }
  1135.  
  1136. //------------------------------------------------------------------------
  1137. void CActionMap::ReleaseFilteredActions()
  1138. {
  1139.         IActionListener* pEntityListener = NULL;
  1140.  
  1141.         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_listenerId))
  1142.                 if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  1143.                         pEntityListener = pGameObject;
  1144.  
  1145.         IActionListener* pListener = pEntityListener;
  1146.         if (!pListener)
  1147.                 return;
  1148.  
  1149.         for (TActionMap::iterator it = m_actions.begin(), eit = m_actions.end(); it != eit; ++it)
  1150.         {
  1151.                 CActionMapAction& action = it->second;
  1152.  
  1153.                 int iNumActionInputs = action.GetNumActionInputs();
  1154.                 for (int i = 0; i < iNumActionInputs; ++i)
  1155.                 {
  1156.                         SActionInput* pActionInput = action.GetActionInput(i);
  1157.                         CRY_ASSERT(pActionInput != NULL);
  1158.  
  1159.                         bool isPressedOrDown = (pActionInput->currentState == eIS_Pressed) || (pActionInput->currentState == eIS_Down);
  1160.                         bool isChanged = pActionInput->currentState == eIS_Changed;
  1161.  
  1162.                         if ((!isPressedOrDown && !isChanged) || !m_pActionMapManager->ActionFiltered(it->first))
  1163.                                 continue;
  1164.  
  1165.                         pActionInput->fCurrentHoldValue = 0.f;
  1166.  
  1167.                         int currentMode = pActionInput->activationMode & eIS_Released;
  1168.                         if (currentMode || isChanged)
  1169.                         {
  1170.                                 pListener->OnAction(it->first, currentMode, 0);
  1171.  
  1172.                                 const TActionListeners& extraActionListeners = m_pActionMapManager->GetExtraActionListeners();
  1173.                                 for (TActionListeners::const_iterator extraListener = extraActionListeners.begin(); extraListener != extraActionListeners.end(); ++extraListener)
  1174.                                         (*extraListener)->OnAction(it->first, currentMode, 0);
  1175.  
  1176.                                 NotifyExtraActionListeners(it->first, currentMode, 0);
  1177.                         }
  1178.                 }
  1179.         }
  1180. }
  1181.  
  1182. //------------------------------------------------------------------------
  1183. void CActionMap::AddExtraActionListener(IActionListener* pExtraActionListener)
  1184. {
  1185.         m_actionMapListeners.Add(pExtraActionListener);
  1186. }
  1187.  
  1188. //------------------------------------------------------------------------
  1189. void CActionMap::RemoveExtraActionListener(IActionListener* pExtraActionListener)
  1190. {
  1191.         m_actionMapListeners.Remove(pExtraActionListener);
  1192. }
  1193.  
  1194. //------------------------------------------------------------------------
  1195. void CActionMap::NotifyFlowNodeActionListeners(const ActionId& action, int currentState, float value)
  1196. {
  1197.         for (TActionMapListeners::Notifier notify(m_flownodesListeners); notify.IsValid(); notify.Next())
  1198.         {
  1199.                 notify->OnAction(action, currentState, value);
  1200.         }
  1201. }
  1202.  
  1203. //------------------------------------------------------------------------
  1204. void CActionMap::AddFlowNodeActionListener(IActionListener* pFlowgraphNodeActionListener)
  1205. {
  1206.         m_flownodesListeners.Add(pFlowgraphNodeActionListener);
  1207. }
  1208.  
  1209. //------------------------------------------------------------------------
  1210. void CActionMap::RemoveFlowNodeActionListener(IActionListener* pFlowgraphNodeActionListener)
  1211. {
  1212.         m_flownodesListeners.Remove(pFlowgraphNodeActionListener);
  1213. }
  1214.  
  1215. //------------------------------------------------------------------------
  1216. void CActionMap::NotifyExtraActionListeners(const ActionId& action, int currentState, float value)
  1217. {
  1218.         for (TActionMapListeners::Notifier notify(m_actionMapListeners); notify.IsValid(); notify.Next())
  1219.         {
  1220.                 notify->OnAction(action, currentState, value);
  1221.         }
  1222. }
  1223.  
  1224. //------------------------------------------------------------------------
  1225. bool CActionMap::LoadFromXML(const XmlNodeRef& actionMapNode)
  1226. {
  1227.         const int iNumDeviceData = m_pActionMapManager->GetNumInputDeviceData();
  1228.         bool bResult;
  1229.  
  1230.         int iNumActions = actionMapNode->getChildCount();
  1231.         for (int i = 0; i < iNumActions; ++i)
  1232.         {
  1233.                 XmlNodeRef actionNode = actionMapNode->getChild(i);
  1234.                 if (strcmp(actionNode->getTag(), "action") != 0)
  1235.                 {
  1236.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Found non action child, actionmaps should only have action children");
  1237.                         continue;
  1238.                 }
  1239.  
  1240.                 const char* szActionName = actionNode->getAttr("name");
  1241.                 if (!szActionName || strcmp(szActionName, "") == 0)
  1242.                 {
  1243.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Action missing name, ignoring action");
  1244.                         continue;
  1245.                 }
  1246.  
  1247.                 ActionId actionName = ActionId(szActionName);
  1248.                 CActionMapAction* pAction = (CActionMapAction*)GetAction(actionName);
  1249.                 if (pAction != NULL)
  1250.                 {
  1251.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Can't add action: %s, already exists", szActionName);
  1252.                         continue;
  1253.                 }
  1254.  
  1255.                 pAction = CreateAndGetAction(actionName);
  1256.                 if (!pAction)
  1257.                 {
  1258.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed to create action: %s", szActionName);
  1259.                         continue;
  1260.                 }
  1261.  
  1262.                 // Actioninput used originally contains default values from constructor, then each LoadActionInputFromXML is cumulative
  1263.                 // i.e. Only the values in xml will be set to allow attributes specified at topmost level in xml to apply to all children
  1264.                 SActionInput actionInput;
  1265.  
  1266.                 if (actionNode->getNumAttributes() > 1) // Contains attributes to apply to all inputs
  1267.                 {
  1268.                         bResult = LoadActionInputAttributesFromXML(actionNode, actionInput);
  1269.                         if (!bResult)
  1270.                         {
  1271.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed loading action input attributes for action: %s", szActionName);
  1272.                                 continue;
  1273.                         }
  1274.  
  1275.                         // Support specifying all devices in 1 line like before
  1276.  
  1277.                         // All inputs are under a devicetype for organization
  1278.                         // Devicemapping data should be called from game level using
  1279.                         // IActionMapManager::AddInputDeviceMapping
  1280.                         for (int j = 0; j < iNumDeviceData; ++j)
  1281.                         {
  1282.                                 const SActionInputDeviceData* pInputDeviceData = m_pActionMapManager->GetInputDeviceDataByIndex(j);
  1283.  
  1284.                                 const char* szInput = actionNode->getAttr(pInputDeviceData->m_typeStr);
  1285.                                 if (szInput == NULL || strcmp(szInput, "") == 0) // Not in xml which is fine
  1286.                                         continue;
  1287.  
  1288.                                 actionInput.input = szInput;
  1289.                                 actionInput.defaultInput = szInput;
  1290.                                 actionInput.inputDevice = pInputDeviceData->m_type;
  1291.  
  1292.                                 bResult = AddAndBindActionInput(pAction, actionInput);
  1293.                                 if (!bResult)
  1294.                                 {
  1295.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName, szInput);
  1296.                                         continue;
  1297.                                 }
  1298.                         }
  1299.                 }
  1300.  
  1301.                 int iNumDeviceChildren = actionNode->getChildCount();
  1302.  
  1303.                 // Check now for action inputs specified per platform
  1304.                 if (iNumDeviceChildren > 0)
  1305.                 {
  1306.                         // Support specifying separate device with attributes in their own child
  1307.                         for (int j = 0; j < iNumDeviceChildren; ++j)
  1308.                         {
  1309.                                 XmlNodeRef inputDeviceNode = actionNode->getChild(j);
  1310.  
  1311.                                 EActionInputDevice inputDeviceNodeDeviceType = eAID_Unknown;
  1312.  
  1313.                                 const SActionInputDeviceData* pInputDeviceData = m_pActionMapManager->GetInputDeviceDataByType(inputDeviceNode->getTag());
  1314.                                 if (pInputDeviceData != NULL)
  1315.                                 {
  1316.                                         inputDeviceNodeDeviceType = pInputDeviceData->m_type;
  1317.                                 }
  1318.                                 else
  1319.                                 {
  1320.                                         continue;
  1321.                                 }
  1322.  
  1323.                                 SActionInput platformInput = actionInput; // Need to copy parent settings since don't want to overwrite for the other nodes
  1324.  
  1325.                                 bResult = LoadActionInputAttributesFromXML(inputDeviceNode, platformInput);
  1326.                                 if (!bResult)
  1327.                                 {
  1328.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed loading action input attributes for action: %s", szActionName);
  1329.                                         continue;
  1330.                                 }
  1331.  
  1332.                                 const char* szPlatformInput = inputDeviceNode->getAttr("input");
  1333.                                 if (szPlatformInput != NULL && strcmp(szPlatformInput, "") != 0) // Device specific key is here, dont need to look for children
  1334.                                 {
  1335.                                         platformInput.input = szPlatformInput;
  1336.                                         platformInput.defaultInput = szPlatformInput;
  1337.                                         platformInput.inputDevice = inputDeviceNodeDeviceType;
  1338.  
  1339.                                         bResult = AddAndBindActionInput(pAction, platformInput);
  1340.                                         if (!bResult)
  1341.                                         {
  1342.                                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName, szPlatformInput);
  1343.                                                 continue;
  1344.                                         }
  1345.                                 }
  1346.                                 else
  1347.                                 {
  1348.                                         int iNumInputData = inputDeviceNode->getChildCount();
  1349.                                         for (int k = 0; k < iNumInputData; k++)
  1350.                                         {
  1351.                                                 // Go through each of the separate inputs
  1352.                                                 SActionInput platformChildInput = platformInput;
  1353.  
  1354.                                                 XmlNodeRef platformChildNode = inputDeviceNode->getChild(k);
  1355.                                                 if (strcmp(platformChildNode->getTag(), "inputdata") != 0)
  1356.                                                 {
  1357.                                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Children inside platform tags must be inputdata");
  1358.                                                         continue;
  1359.                                                 }
  1360.  
  1361.                                                 const char* szPlatformChildInput = platformChildNode->getAttr("input");
  1362.                                                 if (szPlatformChildInput == NULL || strcmp(szPlatformChildInput, "") == 0)
  1363.                                                 {
  1364.                                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: inputdata tag must contain input");
  1365.                                                         continue;
  1366.                                                 }
  1367.  
  1368.                                                 bResult = LoadActionInputAttributesFromXML(platformChildNode, platformChildInput);
  1369.                                                 if (!bResult)
  1370.                                                 {
  1371.                                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed loading action input attributes on platform child input node for action: %s", szActionName);
  1372.                                                         continue;
  1373.                                                 }
  1374.  
  1375.                                                 platformChildInput.input = szPlatformChildInput;
  1376.                                                 platformChildInput.defaultInput = szPlatformChildInput;
  1377.                                                 platformChildInput.inputDevice = pInputDeviceData->m_type;
  1378.  
  1379.                                                 bResult = AddAndBindActionInput(pAction, platformChildInput);
  1380.                                                 if (!bResult)
  1381.                                                 {
  1382.                                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed binding action input for action: %s, with input: %s", szActionName, szPlatformChildInput);
  1383.                                                         continue;
  1384.                                                 }
  1385.                                         }
  1386.                                 }
  1387.                         }
  1388.                 }
  1389.         }
  1390.  
  1391.         return true;
  1392. }
  1393.  
  1394. bool CActionMap::LoadRebindingDataFromXML(const XmlNodeRef& actionMapNode)
  1395. {
  1396.         int iNumActions = actionMapNode->getChildCount();
  1397.         for (int i = 0; i < iNumActions; ++i)
  1398.         {
  1399.                 XmlNodeRef actionNode = actionMapNode->getChild(i);
  1400.                 if (strcmp(actionNode->getTag(), "action") != 0)
  1401.                 {
  1402.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadRebindingDataFromXML: Found non action child, actionmaps should only have action children");
  1403.                         continue;
  1404.                 }
  1405.  
  1406.                 const char* szActionName = actionNode->getAttr("name");
  1407.                 if (szActionName == NULL || strcmp(szActionName, "") == 0)
  1408.                 {
  1409.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadRebindingDataFromXML: Action missing name, ignoring action");
  1410.                         continue;
  1411.                 }
  1412.  
  1413.                 ActionId actionName = ActionId(szActionName);
  1414.                 CActionMapAction* pAction = (CActionMapAction*)GetAction(actionName);
  1415.                 if (pAction == NULL)
  1416.                 {
  1417.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadRebindingDataFromXML: Action: %s, doesn't exist, can't rebind", szActionName);
  1418.                         continue;
  1419.                 }
  1420.  
  1421.                 // Check now for action inputs specified per platform
  1422.                 int iNumRebindInputs = actionNode->getChildCount();
  1423.                 if (iNumRebindInputs == 0)
  1424.                         continue; // Shouldn't have empty action tags
  1425.  
  1426.                 for (int j = 0; j < iNumRebindInputs; ++j)
  1427.                 {
  1428.                         XmlNodeRef inputNode = actionNode->getChild(j);
  1429.                         const char* szInput = inputNode->getAttr("input");
  1430.                         if (szInput == NULL)
  1431.                         {
  1432.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadRebindingDataFromXML: Action: %s, has an input tag missing input attribute", szActionName);
  1433.                                 continue;
  1434.                         }
  1435.  
  1436.                         const char* szDevice = inputNode->getAttr("device");
  1437.                         if (szDevice == NULL || strcmp(szDevice, "") == 0)
  1438.                         {
  1439.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadRebindingDataFromXML: Action: %s, has an input tag missing device attribute", szActionName);
  1440.                                 continue;
  1441.                         }
  1442.  
  1443.                         const SActionInputDeviceData* pInputDeviceData = m_pActionMapManager->GetInputDeviceDataByType(szDevice);
  1444.                         if (pInputDeviceData == NULL)
  1445.                         {
  1446.                                 continue;
  1447.                         }
  1448.  
  1449.                         // Want to allow rebinding without defaultInput to avoid data dependencies
  1450.                         const char* szDefaultInput = inputNode->getAttr("defaultInput");
  1451.                         if (szDefaultInput == NULL || strcmp(szDefaultInput, "") == 0) // Assumes rebinding the first input for that device
  1452.                         {
  1453.                                 if (stricmp(szInput, "DEFAULT") == 0) // Reset to default
  1454.                                 {
  1455.                                         SActionInput* pActionInput = pAction->GetActionInput(pInputDeviceData->m_type, 0);
  1456.                                         if (pActionInput == NULL)
  1457.                                         {
  1458.                                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadFromXML: Failed trying to find actioninput for input device type: %s", szDevice);
  1459.                                                 continue;
  1460.                                         }
  1461.  
  1462.                                         ReBindActionInput(pAction, pActionInput->defaultInput, pInputDeviceData->m_type, 0);
  1463.                                 }
  1464.                                 else
  1465.                                 {
  1466.                                         ReBindActionInput(pAction, szInput, pInputDeviceData->m_type, 0);
  1467.                                 }
  1468.                         }
  1469.                         else
  1470.                         {
  1471.                                 if (stricmp(szInput, "DEFAULT") == 0) // Reset to default
  1472.                                 {
  1473.                                         ReBindActionInput(pAction, szDefaultInput, szDefaultInput);
  1474.                                 }
  1475.                                 else
  1476.                                 {
  1477.                                         ReBindActionInput(pAction, szDefaultInput, szInput);
  1478.                                 }
  1479.                         }
  1480.                 }
  1481.         }
  1482.  
  1483.         return true;
  1484. }
  1485.  
  1486. bool CActionMap::SaveRebindingDataToXML(XmlNodeRef& actionMapNode) const
  1487. {
  1488.         const int iNumDeviceData = m_pActionMapManager->GetNumInputDeviceData();
  1489.  
  1490. #if 0
  1491.         // for debug reasons, we sort the ActionMap alphabetically
  1492.         // CryName normally sorts by pointer address
  1493.         std::map<ActionId, SAction, CryNameSorter> sortedActions(m_actions.begin(), m_actions.end());
  1494.         std::map<ActionId, SAction, CryNameSorter>::const_iterator iter = sortedActions.begin();
  1495.         std::map<ActionId, SAction, CryNameSorter>::const_iterator iterEnd = sortedActions.end();
  1496. #else
  1497.         TActionMap::const_iterator iter = m_actions.begin();
  1498.         TActionMap::const_iterator iterEnd = m_actions.end();
  1499. #endif
  1500.  
  1501.         actionMapNode->setAttr("name", m_name);
  1502.         for (; iter != iterEnd; ++iter)
  1503.         {
  1504.                 ActionId actionId = iter->first;
  1505.                 const CActionMapAction& action = iter->second;
  1506.                 if (action.GetNumRebindedInputs() == 0)
  1507.                         continue;
  1508.  
  1509.                 XmlNodeRef actionNode = actionMapNode->newChild("action");
  1510.                 actionNode->setAttr("name", actionId.c_str());
  1511.  
  1512.                 int numActionInputs = action.GetNumActionInputs();
  1513.                 for (int i = 0; i < numActionInputs; ++i)
  1514.                 {
  1515.                         const SActionInput* pActionInput = action.GetActionInput(i);
  1516.                         CRY_ASSERT(pActionInput != NULL);
  1517.  
  1518.                         if (pActionInput->input == pActionInput->defaultInput)
  1519.                         {
  1520.                                 continue;
  1521.                         }
  1522.  
  1523.                         const SActionInputDeviceData* pInputDeviceData = m_pActionMapManager->GetInputDeviceDataByType(pActionInput->inputDevice);
  1524.                         if (pInputDeviceData == NULL)
  1525.                         {
  1526.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::SaveRebindingDataToXML: Failed to find device string");
  1527.                                 continue;
  1528.                         }
  1529.  
  1530.                         XmlNodeRef inputDeviceNode = actionNode->newChild("rebind");
  1531.                         inputDeviceNode->setAttr("device", pInputDeviceData->m_typeStr.c_str());
  1532.                         inputDeviceNode->setAttr("input", pActionInput->input.c_str());
  1533.                         inputDeviceNode->setAttr("defaultInput", pActionInput->defaultInput.c_str());
  1534.                 }
  1535.         }
  1536.  
  1537.         return true;
  1538. }
  1539.  
  1540. bool CActionMap::LoadActionInputAttributesFromXML(const XmlNodeRef& actionInputNode, SActionInput& actionInput)
  1541. {
  1542.         int& activationFlags = actionInput.activationMode;
  1543.  
  1544.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_ONPRESS_STR, eAAM_OnPress);
  1545.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_ONRELEASE_STR, eAAM_OnRelease);
  1546.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_ONHOLD_STR, eAAM_OnHold);
  1547.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_ALWAYS_STR, eAAM_Always);
  1548.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_CONSOLECMD_STR, eAAM_ConsoleCmd);
  1549.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_NOMODIFIERS_STR, eAAM_NoModifiers);
  1550.         LoadActivationModeBitAttributeFromXML(actionInputNode, activationFlags, ACTIONINPUT_RETRIGGERABLE_STR, eAAM_Retriggerable);
  1551.  
  1552.         // If not specified, value is taken from constructor (0.0f)
  1553.         actionInputNode->getAttr(ACTIONINPUT_PRESSTRIGGERDELAY_STR, actionInput.fPressTriggerDelay);
  1554.         // If not specified, value is taken from constructor (-1.0f) (Disabled)
  1555.         actionInputNode->getAttr(ACTIONINPUT_PRESSTRIGGERDELAY_REPEATOVERRIDE_STR, actionInput.fPressTriggerDelayRepeatOverride);
  1556.         // If not specified, value is taken from constructor (0) (Higher number will override when both delayed (i.e. pressing top right on dpad)
  1557.         actionInputNode->getAttr(ACTIONINPUT_PRESSDELAYPRIORITY_STR, actionInput.iPressDelayPriority);
  1558.  
  1559.         // If not specified, value is taken from constructor (0.0f)
  1560.         actionInputNode->getAttr(ACTIONINPUT_HOLDTRIGGERDELAY_STR, actionInput.fHoldTriggerDelay);
  1561.         // If not specified, value is taken from constructor (0.0f) (Always repeats)
  1562.         actionInputNode->getAttr(ACTIONINPUT_HOLDREPEATDELAY_STR, actionInput.fHoldRepeatDelay);
  1563.         // If not specified, value is taken from constructor (-1.0f) (Disabled)
  1564.         actionInputNode->getAttr(ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR, actionInput.fHoldTriggerDelayRepeatOverride);
  1565.         // If not specified, value is taken from constructor (-1.0f) (Disabled)
  1566.         actionInputNode->getAttr(ACTIONINPUT_RELEASETRIGGERTHRESHOLD_STR, actionInput.fReleaseTriggerThreshold);
  1567.  
  1568.         if (!strcmp(actionInputNode->getAttr(ACTIONINPUT_USEANALOGCOMPARE_STR), "1"))
  1569.         {
  1570.                 activationFlags |= eAAM_AnalogCompare;
  1571.  
  1572.                 const char* analogCompareOp = actionInputNode->getAttr(ACTIONINPUT_ANALOGCOMPAREOP_STR);
  1573.                 if (analogCompareOp == NULL || strcmp(analogCompareOp, "") == 0)
  1574.                 {
  1575.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareOp");
  1576.                         return false;
  1577.                 }
  1578.  
  1579.                 actionInput.analogCompareOp = GetAnalogCompareOpTypeFromStr(analogCompareOp);
  1580.                 if (actionInput.analogCompareOp == eAACO_None)
  1581.                 {
  1582.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareOp");
  1583.                         return false;
  1584.                 }
  1585.  
  1586.                 bool bResult = actionInputNode->getAttr(ACTIONINPUT_ANALOGCOMPAREVAL_STR, actionInput.fAnalogCompareVal);
  1587.                 if (!bResult)
  1588.                 {
  1589.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find analogCompareVal");
  1590.                         return false;
  1591.                 }
  1592.         }
  1593.  
  1594.         // Input blocking
  1595.         const char* inputsToBlock = actionInputNode->getAttr(ACTIONINPUT_INPUTSTOBLOCK_STR);
  1596.         if (inputsToBlock != NULL && strcmp(inputsToBlock, "") != 0)
  1597.         {
  1598.                 SActionInputBlockData& inputBlockData = actionInput.inputBlockData;
  1599.  
  1600.                 if (strcmp(inputsToBlock, ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR) == 0)
  1601.                 {
  1602.                         inputBlockData.blockType = eAIBT_Clear;
  1603.                 }
  1604.                 else // Must contain list of inputs separated by |
  1605.                 {
  1606.                         // Must contain a valid block time
  1607.                         actionInputNode->getAttr(ACTIONINPUT_INPUTBLOCKTIME_STR, inputBlockData.fBlockDuration);
  1608.                         if (inputBlockData.fBlockDuration < FLT_EPSILON)
  1609.                         {
  1610.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Must have a valid blockTime, value is: %.2f", inputBlockData.fBlockDuration);
  1611.                                 return false;
  1612.                         }
  1613.  
  1614.                         // Read in the blocking activation (Default is always, matches all specified action activations)
  1615.                         const char* inputBlockActivation = actionInputNode->getAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR);
  1616.                         bool useAlwaysActivation;
  1617.                         if (inputBlockActivation != NULL && strcmp(inputBlockActivation, "") != 0)
  1618.                         {
  1619.                                 useAlwaysActivation = false;
  1620.                                 string inputsBlockActivationStr(inputBlockActivation);
  1621.                                 int curPos = 0;
  1622.                                 string singleBlockActivation = inputsBlockActivationStr.Tokenize("|", curPos);
  1623.                                 bool bEmpty = singleBlockActivation.empty();
  1624.                                 if (bEmpty) // Only 1 input
  1625.                                 {
  1626.                                         singleBlockActivation = inputsBlockActivationStr;
  1627.                                         curPos = 0;
  1628.                                 }
  1629.  
  1630.                                 do
  1631.                                 {
  1632.                                         if (strcmp(singleBlockActivation, ACTIONINPUT_ONPRESS_STR) == 0)
  1633.                                         {
  1634.                                                 inputBlockData.activationMode |= eIS_Pressed;
  1635.                                         }
  1636.                                         else if (strcmp(singleBlockActivation, ACTIONINPUT_ONHOLD_STR) == 0)
  1637.                                         {
  1638.                                                 inputBlockData.activationMode |= eIS_Down;
  1639.                                         }
  1640.                                         else if (strcmp(singleBlockActivation, ACTIONINPUT_ONRELEASE_STR) == 0)
  1641.                                         {
  1642.                                                 inputBlockData.activationMode |= eIS_Released;
  1643.                                         }
  1644.                                         else if (strcmp(inputBlockActivation, ACTIONINPUT_ALWAYS_STR) == 0)
  1645.                                         {
  1646.                                                 useAlwaysActivation = true;
  1647.                                                 break;
  1648.                                         }
  1649.                                         else
  1650.                                         {
  1651.                                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Invalid block activation: %s", singleBlockActivation.c_str());
  1652.                                                 return false;
  1653.                                         }
  1654.  
  1655.                                         if (bEmpty)
  1656.                                         {
  1657.                                                 break;
  1658.                                         }
  1659.  
  1660.                                         singleBlockActivation = inputsBlockActivationStr.Tokenize("|", curPos);
  1661.                                         bEmpty = singleBlockActivation.empty();
  1662.                                 }
  1663.                                 while (!bEmpty);
  1664.                         }
  1665.                         else
  1666.                         {
  1667.                                 useAlwaysActivation = true;
  1668.                         }
  1669.  
  1670.                         if (useAlwaysActivation)
  1671.                         {
  1672.                                 inputBlockData.activationMode |= eIS_Pressed;
  1673.                                 inputBlockData.activationMode |= eIS_Down;
  1674.                                 inputBlockData.activationMode |= eIS_Released;
  1675.                         }
  1676.  
  1677.                         // Now read in all the inputs to block, separated by |
  1678.                         string inputsToBlockStr(inputsToBlock);
  1679.                         std::vector<string> inputsToBlockVec;
  1680.                         int curPos = 0;
  1681.                         string singleInput = inputsToBlockStr.Tokenize("|", curPos);
  1682.                         if (singleInput.empty()) // Only 1 input
  1683.                         {
  1684.                                 inputsToBlockVec.push_back(inputsToBlockStr);
  1685.                         }
  1686.                         else
  1687.                         {
  1688.                                 do
  1689.                                 {
  1690.                                         inputsToBlockVec.push_back(singleInput);
  1691.                                         singleInput = inputsToBlockStr.Tokenize("|", curPos);
  1692.                                 }
  1693.                                 while (!singleInput.empty());
  1694.                         }
  1695.  
  1696.                         // Read in the device index (Default is all device indices)
  1697.                         int iDeviceIndex = -1;
  1698.                         actionInputNode->getAttr(ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR, iDeviceIndex);
  1699.  
  1700.                         if (iDeviceIndex != -1)
  1701.                         {
  1702.                                 inputBlockData.bAllDeviceIndices = false;
  1703.                                 inputBlockData.deviceIndex = (uint8)iDeviceIndex;
  1704.                         }
  1705.  
  1706.                         for (size_t i = 0; i < inputsToBlockVec.size(); i++)
  1707.                         {
  1708.                                 const SInputSymbol* pInputSymbol = gEnv->pInput ? gEnv->pInput->GetSymbolByName(inputsToBlockVec[i]) : NULL;
  1709.                                 if (!pInputSymbol)
  1710.                                 {
  1711.                                         // Data is currently read all in on pc, dont show warnings until thats changed
  1712.                                         // CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find input symbol for input name: %s", inputsToBlockVec[i].c_str());
  1713.                                         continue;
  1714.                                 }
  1715.  
  1716.                                 SActionInputBlocker inputBlockerToSend(pInputSymbol->keyId);
  1717.                                 inputBlockData.inputs.push_back(inputBlockerToSend);
  1718.                         }
  1719.                         if (!inputBlockData.inputs.empty())
  1720.                         {
  1721.                                 inputBlockData.blockType = eAIBT_BlockInputs; // Only having this makes enables blocking
  1722.                         }
  1723.  
  1724.                         /* Data is currently read all in on pc, dont show warnings until thats changed
  1725.                            else
  1726.                            {
  1727.                            CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to find any inputs to block for inputs: %s", inputsToBlock);
  1728.                            return false;
  1729.                            }
  1730.                          */
  1731.                 }
  1732.         }
  1733.  
  1734.         return true;
  1735. }
  1736.  
  1737. bool CActionMap::SaveActionInputAttributesToXML(XmlNodeRef& actionInputNode, const SActionInput& actionInput) const
  1738. {
  1739.         const int activationFlags = actionInput.activationMode;
  1740.  
  1741.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_ONPRESS_STR, eAAM_OnPress);
  1742.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_ONRELEASE_STR, eAAM_OnRelease);
  1743.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_ALWAYS_STR, eAAM_Always);
  1744.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_CONSOLECMD_STR, eAAM_ConsoleCmd);
  1745.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_NOMODIFIERS_STR, eAAM_NoModifiers);
  1746.         SaveActivationModeBitAttributeToXML(actionInputNode, activationFlags, ACTIONINPUT_RETRIGGERABLE_STR, eAAM_Retriggerable);
  1747.  
  1748.         if (actionInput.activationMode & eAAM_OnHold)
  1749.         {
  1750.                 actionInputNode->setAttr(ACTIONINPUT_ONHOLD_STR, "1");
  1751.                 actionInputNode->setAttr(ACTIONINPUT_HOLDTRIGGERDELAY_STR, actionInput.fHoldTriggerDelay);
  1752.                 actionInputNode->setAttr(ACTIONINPUT_HOLDREPEATDELAY_STR, actionInput.fHoldRepeatDelay);
  1753.                 actionInputNode->setAttr(ACTIONINPUT_HOLDTRIGGERDELAY_REPEATOVERRIDE_STR, actionInput.fHoldTriggerDelayRepeatOverride);
  1754.         }
  1755.         else
  1756.         {
  1757.                 actionInputNode->setAttr(ACTIONINPUT_ONHOLD_STR, "0");
  1758.         }
  1759.  
  1760.         if (actionInput.activationMode & eAAM_AnalogCompare)
  1761.         {
  1762.                 actionInputNode->setAttr(ACTIONINPUT_USEANALOGCOMPARE_STR, "1");
  1763.                 actionInputNode->setAttr(ACTIONINPUT_ANALOGCOMPAREOP_STR, GetAnalogCompareOpStr(actionInput.analogCompareOp));
  1764.                 actionInputNode->setAttr(ACTIONINPUT_ANALOGCOMPAREVAL_STR, actionInput.fAnalogCompareVal);
  1765.         }
  1766.         else
  1767.         {
  1768.                 actionInputNode->setAttr(ACTIONINPUT_USEANALOGCOMPARE_STR, "0");
  1769.         }
  1770.  
  1771.         // Input blocking
  1772.         const SActionInputBlockData& inputBlockData = actionInput.inputBlockData;
  1773.         if (inputBlockData.blockType != eAIBT_None)
  1774.         {
  1775.                 if (inputBlockData.blockType == eAIBT_Clear)
  1776.                 {
  1777.                         actionInputNode->setAttr(ACTIONINPUT_INPUTSTOBLOCK_STR, ACTIONINPUT_INPUTSTOBLOCK_SPECIALTYPE_CLEARALL_STR);
  1778.                 }
  1779.                 else // Normal blocking inputs
  1780.                 {
  1781.                         if (inputBlockData.inputs.empty())
  1782.                         {
  1783.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::SaveActionInputAttributesToXML: Failed, using normal blocking inputs type but dont have any inputs");
  1784.                                 return false;
  1785.                         }
  1786.  
  1787.                         if (inputBlockData.fBlockDuration <= (0.0f - FLT_EPSILON))
  1788.                         {
  1789.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::SaveActionInputAttributesToXML: Failed, using normal blocking inputs type but don't have valid block duration");
  1790.                                 return false;
  1791.                         }
  1792.                         actionInputNode->setAttr(ACTIONINPUT_INPUTBLOCKTIME_STR, inputBlockData.fBlockDuration);
  1793.  
  1794.                         // Save input blocking activation mode
  1795.                         if ((inputBlockData.activationMode & eIS_Pressed) &&
  1796.                             (inputBlockData.activationMode & eIS_Down) &&
  1797.                             (inputBlockData.activationMode & eIS_Released))
  1798.                         {
  1799.                                 actionInputNode->setAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR, ACTIONINPUT_ALWAYS_STR);
  1800.                         }
  1801.                         else
  1802.                         {
  1803.                                 CryFixedStringT<32> inputBlockActivationStr("");
  1804.                                 bool bAddedActivationMode = false;
  1805.                                 if (inputBlockData.activationMode & eIS_Pressed)
  1806.                                 {
  1807.                                         inputBlockActivationStr = ACTIONINPUT_ONPRESS_STR;
  1808.                                         bAddedActivationMode = true;
  1809.                                 }
  1810.                                 if (inputBlockData.activationMode & eIS_Down)
  1811.                                 {
  1812.                                         if (bAddedActivationMode)
  1813.                                         {
  1814.                                                 inputBlockActivationStr += "|";
  1815.                                         }
  1816.                                         inputBlockActivationStr += ACTIONINPUT_ONHOLD_STR;
  1817.                                         bAddedActivationMode = true;
  1818.                                 }
  1819.                                 if (inputBlockData.activationMode & eIS_Released)
  1820.                                 {
  1821.                                         if (bAddedActivationMode)
  1822.                                         {
  1823.                                                 inputBlockActivationStr += "|";
  1824.                                         }
  1825.                                         inputBlockActivationStr += ACTIONINPUT_ONRELEASE_STR;
  1826.                                 }
  1827.  
  1828.                                 actionInputNode->setAttr(ACTIONINPUT_INPUTBLOCKACTIVATION_STR, inputBlockActivationStr.c_str());
  1829.                         }
  1830.  
  1831.                         // Now save the blocked inputs
  1832.                         string blockedInputsStr("");
  1833.                         bool bBlockAllDeviceIndices = true;
  1834.                         for (size_t i = 0; i < inputBlockData.inputs.size(); i++)
  1835.                         {
  1836.                                 const SActionInputBlocker& inputBlocker = inputBlockData.inputs[i];
  1837.  
  1838.                                 if (i != 0)
  1839.                                 {
  1840.                                         blockedInputsStr += "|";
  1841.                                 }
  1842.  
  1843.                                 const char* szKeyName = gEnv->pInput->GetKeyName(inputBlocker.keyId);
  1844.                                 if (!szKeyName)
  1845.                                 {
  1846.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CActionMap::LoadActionInputAttributesFromXML: Failed to translate keyname for key id: %d", (int)inputBlocker.keyId);
  1847.                                         return false;
  1848.                                 }
  1849.  
  1850.                                 blockedInputsStr += szKeyName;
  1851.                         }
  1852.  
  1853.                         // Now save device index data
  1854.                         if (!inputBlockData.bAllDeviceIndices) // Default is true so dont need to save to xml
  1855.                         {
  1856.                                 actionInputNode->setAttr(ACTIONINPUT_INPUTBLOCKDEVICEINDEX_STR, inputBlockData.deviceIndex);
  1857.                         }
  1858.                 }
  1859.         }
  1860.  
  1861.         return true;
  1862. }
  1863.  
  1864. //------------------------------------------------------------------------
  1865. void CActionMap::LoadActivationModeBitAttributeFromXML(const XmlNodeRef& attributeNode, int& activationFlags, const char* szActivationModeName, EActionActivationMode activationMode)
  1866. {
  1867.         int readFlag;
  1868.  
  1869.         if (attributeNode->getAttr(szActivationModeName, readFlag))
  1870.         {
  1871.                 if (readFlag == 1)
  1872.                 {
  1873.                         activationFlags |= activationMode;
  1874.                 }
  1875.                 else
  1876.                 {
  1877.                         activationFlags &= ~activationMode;
  1878.                 }
  1879.         }
  1880. }
  1881.  
  1882. //------------------------------------------------------------------------
  1883. void CActionMap::SaveActivationModeBitAttributeToXML(XmlNodeRef& attributeNode, const int activationFlags, const char* szActivationModeName, EActionActivationMode activationMode) const
  1884. {
  1885.         if (activationFlags & activationMode)
  1886.         {
  1887.                 attributeNode->setAttr(szActivationModeName, "1");
  1888.         }
  1889.         else
  1890.         {
  1891.                 attributeNode->setAttr(szActivationModeName, "0");
  1892.         }
  1893. }
  1894.  
  1895. #define USE_SORTED_ACTIONS_ITERATOR
  1896. #undef  USE_SORTED_ACTIONS_ITERATOR
  1897.  
  1898. //------------------------------------------------------------------------
  1899. IActionMapActionIteratorPtr CActionMap::CreateActionIterator()
  1900. {
  1901.         class CActionInfo : public IActionMapActionIterator
  1902.         {
  1903. #ifndef USE_SORTED_ACTIONS_ITERATOR
  1904.                 typedef TActionMap::iterator                                TIterator;
  1905. #else
  1906.                 typedef std::map<ActionId, CActionMapAction, CryNameSorter> TSortedActionMap;
  1907.                 typedef TSortedActionMap::iterator                          TIterator;
  1908. #endif
  1909.  
  1910.         public:
  1911.                 CActionInfo(TActionMap::iterator& itBegin, TActionMap::iterator& itEnd)
  1912.                         : m_nRefs(0)
  1913.                 {
  1914. #ifdef USE_SORTED_ACTIONS_ITERATOR
  1915.                         m_sortedActions.insert(itBegin, itEnd);
  1916.                         m_cur = m_sortedActions.begin();
  1917.                         m_end = m_sortedActions.end();
  1918. #else
  1919.                         m_cur = itBegin;
  1920.                         m_end = itEnd;
  1921. #endif
  1922.                 }
  1923.  
  1924.                 virtual ~CActionInfo()
  1925.                 {
  1926.                 }
  1927.  
  1928.                 const IActionMapAction* Next()
  1929.                 {
  1930.                         if (m_cur == m_end)
  1931.                                 return NULL;
  1932.                         const ActionId& actionId = m_cur->first;
  1933.                         const CActionMapAction& action = m_cur->second;
  1934.  
  1935.                         ++m_cur;
  1936.                         return &action;
  1937.                 }
  1938.  
  1939.                 void AddRef()
  1940.                 {
  1941.                         ++m_nRefs;
  1942.                 }
  1943.  
  1944.                 void Release()
  1945.                 {
  1946.                         if (--m_nRefs <= 0)
  1947.                                 delete this;
  1948.                 }
  1949.                 int              m_nRefs;
  1950.                 TIterator        m_cur;
  1951.                 TIterator        m_end;
  1952. #ifdef USE_SORTED_ACTIONS_ITERATOR
  1953.                 TSortedActionMap m_sortedActions;
  1954. #endif
  1955.         };
  1956.         TActionMap::iterator actionsBegin(m_actions.begin());
  1957.         TActionMap::iterator actionsEnd(m_actions.end());
  1958.         return new CActionInfo(actionsBegin, actionsEnd);
  1959. }
  1960.  
  1961. void CActionMap::Enable(bool enable)
  1962. {
  1963.         // detect nop
  1964.         if (enable == m_enabled)
  1965.                 return;
  1966.  
  1967.         // now things get a bit interesting, when we get disabled we "release" all our
  1968.         // active actions
  1969.         if (!enable)
  1970.         {
  1971.                 TActionMap::iterator it = m_actions.begin();
  1972.                 TActionMap::iterator end = m_actions.end();
  1973.                 for (; it != end; ++it)
  1974.                 {
  1975.                         ReleaseActionIfActiveInternal(it->second);
  1976.                 }
  1977.         }
  1978.  
  1979.         // finally set the flag
  1980.         m_enabled = enable;
  1981.  
  1982.         if (m_pActionMapManager)
  1983.         {
  1984.                 m_pActionMapManager->BroadcastActionMapEvent(SActionMapEvent(SActionMapEvent::eActionMapManagerEvent_ActionMapStatusChanged, (UINT_PTR)this, (UINT_PTR)m_enabled));
  1985.         }
  1986. }
  1987.  
  1988. void CActionMap::ReleaseActionIfActive(const ActionId& actionId)
  1989. {
  1990.         TActionMap::iterator it = m_actions.find(actionId);
  1991.         if (it != m_actions.end())
  1992.         {
  1993.                 ReleaseActionIfActiveInternal(it->second);
  1994.         }
  1995. }
  1996.  
  1997. void CActionMap::ReleaseActionIfActiveInternal(CActionMapAction& action)
  1998. {
  1999.         bool bFireOnActionRelease = false;
  2000.         bool bFireOnActionAlways = false;
  2001.  
  2002.         int numActionInputs = action.GetNumActionInputs();
  2003.         for (int i = 0; i < numActionInputs; ++i)
  2004.         {
  2005.                 SActionInput* pActionInput = action.GetActionInput(i);
  2006.                 CRY_ASSERT(pActionInput != NULL);
  2007.  
  2008.                 bool hasReleaseMode = (pActionInput->activationMode & eAAM_OnRelease) != 0;
  2009.                 bool isPressedOrDown = (pActionInput->currentState == eIS_Pressed) || (pActionInput->currentState == eIS_Down);
  2010.                 bool isChanged = pActionInput->currentState == eIS_Changed;
  2011.  
  2012.                 if (hasReleaseMode && isPressedOrDown)
  2013.                 {
  2014.                         bFireOnActionRelease = true;
  2015.                 }
  2016.  
  2017.                 if (isChanged)
  2018.                 {
  2019.                         bFireOnActionAlways = true;
  2020.                 }
  2021.  
  2022.                 pActionInput->fCurrentHoldValue = 0.f;
  2023.         }
  2024.  
  2025.         if (bFireOnActionRelease)
  2026.         {
  2027.                 IActionListener* pEntityListener = NULL;
  2028.  
  2029.                 if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_listenerId))
  2030.                 {
  2031.                         if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  2032.                         {
  2033.                                 pEntityListener = pGameObject;
  2034.                         }
  2035.                 }
  2036.                 IActionListener* pListener = pEntityListener;
  2037.                 if (pListener)
  2038.                 {
  2039.                         pListener->OnAction(action.GetActionId(), eAAM_OnRelease, 0.0f);
  2040.                 }
  2041.  
  2042.                 NotifyExtraActionListeners(action.GetActionId(), eAAM_OnRelease, 0.0f);
  2043.         }
  2044.  
  2045.         if (bFireOnActionAlways)
  2046.         {
  2047.                 IActionListener* pEntityListener = NULL;
  2048.  
  2049.                 if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_listenerId))
  2050.                 {
  2051.                         if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  2052.                         {
  2053.                                 pEntityListener = pGameObject;
  2054.                         }
  2055.                 }
  2056.                 IActionListener* pListener = pEntityListener;
  2057.                 if (pListener)
  2058.                 {
  2059.                         pListener->OnAction(action.GetActionId(), eAAM_Always, 0.0f);
  2060.                 }
  2061.  
  2062.                 NotifyExtraActionListeners(action.GetActionId(), eAAM_Always, 0.0f);
  2063.         }
  2064. }
  2065.  
  2066. EActionAnalogCompareOperation CActionMap::GetAnalogCompareOpTypeFromStr(const char* szTypeStr)
  2067. {
  2068.         EActionAnalogCompareOperation compareOpType = eAACO_None;
  2069.         if (!strcmp(szTypeStr, s_analogCompareOpEqualsStr))
  2070.         {
  2071.                 compareOpType = eAACO_Equals;
  2072.         }
  2073.         else if (!strcmp(szTypeStr, s_analogCompareOpNotEqualsStr))
  2074.         {
  2075.                 compareOpType = eAACO_NotEquals;
  2076.         }
  2077.         else if (!strcmp(szTypeStr, s_analogCompareOpGreaterThanStr))
  2078.         {
  2079.                 compareOpType = eAACO_GreaterThan;
  2080.         }
  2081.         else if (!strcmp(szTypeStr, s_analogCompareOpLessThanStr))
  2082.         {
  2083.                 compareOpType = eAACO_LessThan;
  2084.         }
  2085.  
  2086.         return compareOpType;
  2087. }
  2088.  
  2089. const char* CActionMap::GetAnalogCompareOpStr(EActionAnalogCompareOperation compareOpType) const
  2090. {
  2091.         if (compareOpType == eAACO_Equals)
  2092.         {
  2093.                 return s_analogCompareOpEqualsStr;
  2094.         }
  2095.         else if (compareOpType == eAACO_NotEquals)
  2096.         {
  2097.                 return s_analogCompareOpNotEqualsStr;
  2098.         }
  2099.         else if (compareOpType == eAACO_GreaterThan)
  2100.         {
  2101.                 return s_analogCompareOpGreaterThanStr;
  2102.         }
  2103.         else if (compareOpType == eAACO_LessThan)
  2104.         {
  2105.                 return s_analogCompareOpLessThanStr;
  2106.         }
  2107.         else
  2108.         {
  2109.                 return NULL;
  2110.         }
  2111. }
  2112.  
  2113. void CActionMap::EnumerateActions(IActionMapPopulateCallBack* pCallBack) const
  2114. {
  2115.         for (TActionMap::const_iterator actionCit = m_actions.begin(); actionCit != m_actions.end(); ++actionCit)
  2116.         {
  2117.                 pCallBack->AddActionName(actionCit->first.c_str());
  2118.         }
  2119. }
  2120.  
  2121. void CActionMap::GetMemoryUsage(ICrySizer* s) const
  2122. {
  2123.         s->AddObject(m_actions);
  2124.         s->AddObject(m_name);
  2125. }
  2126.  
downloadActionMap.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top