123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #ifndef _ACTIONMAP_H_
- #define _ACTIONMAP_H_
- #ifndef _PLATFORM_H_
- #include "platform/platform.h"
- #endif
- #ifndef _TVECTOR_H_
- #include "core/util/tVector.h"
- #endif
- #ifndef _SIMBASE_H_
- #include "console/simBase.h"
- #endif
- #ifndef _ITICKABLE_H_
- #include "core/iTickable.h"
- #endif
- class ContextAction;
- struct InputEventInfo;
- struct EventDescriptor
- {
- U8 flags; ///< Combination of any modifier flags.
- U8 eventType; ///< SI_KEY, etc.
- U16 eventCode; ///< From event.h
- };
- /// Map raw inputs to a variety of actions. This is used for all keymapping
- /// in the engine.
- /// @see ActionMap::Node
- class ActionMap : public SimObject
- {
- typedef SimObject Parent;
- friend class ContextAction;
- protected:
- bool onAdd();
- struct Node {
- U32 modifiers;
- U32 action;
- enum Flags {
- Ranged = BIT(0), ///< Ranged input.
- HasScale = BIT(1), ///< Scaled input.
- HasDeadZone = BIT(2), ///< Dead zone is present.
- Inverted = BIT(3), ///< Input is inverted.
- NonLinear = BIT(4), ///< Input should be re-fit to a non-linear scale
- BindCmd = BIT(5), ///< Bind a console command to this.
- Held = BIT(6),
- DoubleTap = BIT(7)
- };
- U32 flags; ///< @see Node::Flags
- F32 deadZoneBegin;
- F32 deadZoneEnd;
- F32 scaleFactor;
- SimObject* object; ///< Object to call consoleFunction on.
- StringTableEntry consoleFunction; ///< Console function to call with new values.
- char *makeConsoleCommand; ///< Console command to execute when we make this command.
- char *breakConsoleCommand; ///< Console command to execute when we break this command.
- ContextAction* contextEvent; ///< Event that kicks off via context-keybind actions such as holding or double-tapping
- };
- /// Used to represent a devices.
- struct DeviceMap
- {
- U32 deviceType;
- U32 deviceInst;
- Vector<Node> nodeMap;
- DeviceMap():deviceType(0), deviceInst(0){
- VECTOR_SET_ASSOCIATION(nodeMap);
- }
- ~DeviceMap();
- };
- struct BreakEntry
- {
- U32 deviceType;
- U32 deviceInst;
- U32 objInst;
- SimObject* object;
- StringTableEntry consoleFunction;
- char *breakConsoleCommand;
- // It's possible that the node could be deleted (unlikely, but possible,
- // so we replicate the node flags here...
- //
- U32 flags;
- F32 deadZoneBegin;
- F32 deadZoneEnd;
- F32 scaleFactor;
- };
- Vector<DeviceMap*> mDeviceMaps;
- static Vector<BreakEntry> smBreakTable;
- // Find: return NULL if not found in current map, Get: create if not
- // found.
- const Node* findNode(const U32 inDeviceType, const U32 inDeviceInst,
- const U32 inModifiers, const U32 inAction);
- bool findBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex );
- bool nextBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex );
- Node* getNode(const U32 inDeviceType, const U32 inDeviceInst,
- const U32 inModifiers, const U32 inAction,
- SimObject* object = NULL);
- void removeNode(const U32 inDeviceType, const U32 inDeviceInst,
- const U32 inModifiers, const U32 inAction,
- SimObject* object = NULL);
- void enterBreakEvent(const InputEventInfo* pEvent, const Node* pNode);
- static const char* getModifierString(const U32 modifiers);
- /// Pass index to a break entry, and this function will fire it off.
- static void fireBreakEvent(U32 idx, F32 value = 0.f);
- public:
- ActionMap();
- ~ActionMap();
- void dumpActionMap(const char* fileName, const bool append) const;
- static bool createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor);
- bool processBind(const U32 argc, const char** argv, SimObject* object = NULL);
- bool processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd);
- bool processUnbind(const char *device, const char *action, SimObject* object = NULL);
- bool processHoldBind(const char *device, const char *action, const char *holdFunc, const char *tapFunc, const U32 holdTime, const bool holdOnly, const bool returnHoldTime = false);
- /// @name Console Interface Functions
- /// @{
- const char* getBinding ( const char* command ); ///< Find what the given command is bound to.
- const char* getCommand ( const char* device, const char* action ); ///< Find what command is bound to the given event descriptor .
- bool isInverted ( const char* device, const char* action );
- F32 getScale ( const char* device, const char* action );
- const char* getDeadZone( const char* device, const char* action );
- /// @}
- static bool getKeyString(const U32 action, char* buffer);
- static bool getDeviceName(const U32 deviceType, const U32 deviceInstance, char* buffer);
- static const char* buildActionString( const InputEventInfo* event );
- bool processAction(const InputEventInfo*);
-
- /// Return true if the given event triggers is bound to an action in this map.
- bool isAction( U32 deviceType, U32 deviceInst, U32 modifiers, U32 action );
- /// Returns the global ActionMap.
- static ActionMap* getGlobalMap();
-
- static bool checkBreakTable(const InputEventInfo*);
- static bool handleEvent(const InputEventInfo*);
- static bool handleEventGlobal(const InputEventInfo*);
- /// Called when we lose focus, to make sure we have no dangling inputs.
- ///
- /// This fires a break event for every currently pending item in the break
- /// table.
- static void clearAllBreaks();
- /// Returns true if the specified key + modifiers are bound to something
- /// on the global action map.
- static bool checkAsciiGlobal(U16 key, U32 modifiers);
- static bool getDeviceTypeAndInstance(const char *device, U32 &deviceType, U32 &deviceInstance);
- DECLARE_CONOBJECT(ActionMap);
- };
- class ContextAction : public ITickable
- {
- ActionMap::Node* mButton; ///< our button we're holding
- F32 mMinHoldTime; ///< minimum time to qualify as 'held'. If we hold less than this,
- ///< it's a 'press', otherwise it's a 'held'
- public:
- F32 mStartTime; ///< Our timestamp when we first pressed.
- F32 mEventValue; ///< Event value from our key event.
- StringTableEntry mConsoleFunctionHeld; ///< Console function to call with new values if we held over
- ///< a certain time.
- bool mHoldOnly; ///< does this only care if we're holding?
- ///< true means that it only fires a function while holding
- ///< false time-contexts it
- bool mBreakEvent; ///< Button is no longer being pressed!
- bool mDidHold; ///< did we, at some point in the process, hold the button?
- bool mActive; ///< do we be tickin?
- bool mReturnHoldTime; ///< Do we return back our time held?
- ContextAction(StringTableEntry func, F32 minHoldTime, ActionMap::Node* button, bool holdOnly);
- virtual void processTick();
- virtual void interpolateTick(F32 delta) {}
- virtual void advanceTime(F32 timeDelta) {}
- };
- #endif // _ACTIONMAP_H_
|