actionMap.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _ACTIONMAP_H_
  23. #define _ACTIONMAP_H_
  24. #ifndef _PLATFORM_H_
  25. #include "platform/platform.h"
  26. #endif
  27. #ifndef _TVECTOR_H_
  28. #include "core/util/tVector.h"
  29. #endif
  30. #ifndef _SIMBASE_H_
  31. #include "console/simBase.h"
  32. #endif
  33. #ifndef _ITICKABLE_H_
  34. #include "core/iTickable.h"
  35. #endif
  36. class ContextAction;
  37. struct InputEventInfo;
  38. struct EventDescriptor
  39. {
  40. U8 flags; ///< Combination of any modifier flags.
  41. U8 eventType; ///< SI_KEY, etc.
  42. U16 eventCode; ///< From event.h
  43. };
  44. /// Map raw inputs to a variety of actions. This is used for all keymapping
  45. /// in the engine.
  46. /// @see ActionMap::Node
  47. class ActionMap : public SimObject
  48. {
  49. typedef SimObject Parent;
  50. friend class ContextAction;
  51. protected:
  52. bool onAdd();
  53. struct Node {
  54. U32 modifiers;
  55. U32 action;
  56. enum Flags {
  57. Ranged = BIT(0), ///< Ranged input.
  58. HasScale = BIT(1), ///< Scaled input.
  59. HasDeadZone = BIT(2), ///< Dead zone is present.
  60. Inverted = BIT(3), ///< Input is inverted.
  61. NonLinear = BIT(4), ///< Input should be re-fit to a non-linear scale
  62. BindCmd = BIT(5), ///< Bind a console command to this.
  63. Held = BIT(6),
  64. DoubleTap = BIT(7)
  65. };
  66. U32 flags; ///< @see Node::Flags
  67. F32 deadZoneBegin;
  68. F32 deadZoneEnd;
  69. F32 scaleFactor;
  70. SimObject* object; ///< Object to call consoleFunction on.
  71. StringTableEntry consoleFunction; ///< Console function to call with new values.
  72. char *makeConsoleCommand; ///< Console command to execute when we make this command.
  73. char *breakConsoleCommand; ///< Console command to execute when we break this command.
  74. ContextAction* contextEvent; ///< Event that kicks off via context-keybind actions such as holding or double-tapping
  75. };
  76. /// Used to represent a devices.
  77. struct DeviceMap
  78. {
  79. U32 deviceType;
  80. U32 deviceInst;
  81. Vector<Node> nodeMap;
  82. DeviceMap():deviceType(0), deviceInst(0){
  83. VECTOR_SET_ASSOCIATION(nodeMap);
  84. }
  85. ~DeviceMap();
  86. };
  87. struct BreakEntry
  88. {
  89. U32 deviceType;
  90. U32 deviceInst;
  91. U32 objInst;
  92. SimObject* object;
  93. StringTableEntry consoleFunction;
  94. char *breakConsoleCommand;
  95. // It's possible that the node could be deleted (unlikely, but possible,
  96. // so we replicate the node flags here...
  97. //
  98. U32 flags;
  99. F32 deadZoneBegin;
  100. F32 deadZoneEnd;
  101. F32 scaleFactor;
  102. };
  103. Vector<DeviceMap*> mDeviceMaps;
  104. static Vector<BreakEntry> smBreakTable;
  105. // Find: return NULL if not found in current map, Get: create if not
  106. // found.
  107. const Node* findNode(const U32 inDeviceType, const U32 inDeviceInst,
  108. const U32 inModifiers, const U32 inAction);
  109. bool findBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex );
  110. bool nextBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex );
  111. Node* getNode(const U32 inDeviceType, const U32 inDeviceInst,
  112. const U32 inModifiers, const U32 inAction,
  113. SimObject* object = NULL);
  114. void removeNode(const U32 inDeviceType, const U32 inDeviceInst,
  115. const U32 inModifiers, const U32 inAction,
  116. SimObject* object = NULL);
  117. void enterBreakEvent(const InputEventInfo* pEvent, const Node* pNode);
  118. static const char* getModifierString(const U32 modifiers);
  119. /// Pass index to a break entry, and this function will fire it off.
  120. static void fireBreakEvent(U32 idx, F32 value = 0.f);
  121. public:
  122. ActionMap();
  123. ~ActionMap();
  124. void dumpActionMap(const char* fileName, const bool append) const;
  125. static bool createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor);
  126. bool processBind(const U32 argc, const char** argv, SimObject* object = NULL);
  127. bool processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd);
  128. bool processUnbind(const char *device, const char *action, SimObject* object = NULL);
  129. bool processHoldBind(const char *device, const char *action, const char *holdFunc, const char *tapFunc, const U32 holdTime, const bool holdOnly, const bool returnHoldTime = false);
  130. /// @name Console Interface Functions
  131. /// @{
  132. const char* getBinding ( const char* command ); ///< Find what the given command is bound to.
  133. const char* getCommand ( const char* device, const char* action ); ///< Find what command is bound to the given event descriptor .
  134. bool isInverted ( const char* device, const char* action );
  135. F32 getScale ( const char* device, const char* action );
  136. const char* getDeadZone( const char* device, const char* action );
  137. /// @}
  138. static bool getKeyString(const U32 action, char* buffer);
  139. static bool getDeviceName(const U32 deviceType, const U32 deviceInstance, char* buffer);
  140. static const char* buildActionString( const InputEventInfo* event );
  141. bool processAction(const InputEventInfo*);
  142. /// Return true if the given event triggers is bound to an action in this map.
  143. bool isAction( U32 deviceType, U32 deviceInst, U32 modifiers, U32 action );
  144. /// Returns the global ActionMap.
  145. static ActionMap* getGlobalMap();
  146. static bool checkBreakTable(const InputEventInfo*);
  147. static bool handleEvent(const InputEventInfo*);
  148. static bool handleEventGlobal(const InputEventInfo*);
  149. /// Called when we lose focus, to make sure we have no dangling inputs.
  150. ///
  151. /// This fires a break event for every currently pending item in the break
  152. /// table.
  153. static void clearAllBreaks();
  154. /// Returns true if the specified key + modifiers are bound to something
  155. /// on the global action map.
  156. static bool checkAsciiGlobal(U16 key, U32 modifiers);
  157. static bool getDeviceTypeAndInstance(const char *device, U32 &deviceType, U32 &deviceInstance);
  158. DECLARE_CONOBJECT(ActionMap);
  159. };
  160. class ContextAction : public ITickable
  161. {
  162. ActionMap::Node* mButton; ///< our button we're holding
  163. F32 mMinHoldTime; ///< minimum time to qualify as 'held'. If we hold less than this,
  164. ///< it's a 'press', otherwise it's a 'held'
  165. public:
  166. F32 mStartTime; ///< Our timestamp when we first pressed.
  167. F32 mEventValue; ///< Event value from our key event.
  168. StringTableEntry mConsoleFunctionHeld; ///< Console function to call with new values if we held over
  169. ///< a certain time.
  170. bool mHoldOnly; ///< does this only care if we're holding?
  171. ///< true means that it only fires a function while holding
  172. ///< false time-contexts it
  173. bool mBreakEvent; ///< Button is no longer being pressed!
  174. bool mDidHold; ///< did we, at some point in the process, hold the button?
  175. bool mActive; ///< do we be tickin?
  176. bool mReturnHoldTime; ///< Do we return back our time held?
  177. ContextAction(StringTableEntry func, F32 minHoldTime, ActionMap::Node* button, bool holdOnly);
  178. virtual void processTick();
  179. virtual void interpolateTick(F32 delta) {}
  180. virtual void advanceTime(F32 timeDelta) {}
  181. };
  182. #endif // _ACTIONMAP_H_