| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 | //-----------------------------------------------------------------------------// 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.//-----------------------------------------------------------------------------#include "windowManager/windowInputGenerator.h"#include "console/script.h"#include "windowManager/platformWindow.h"#include "sim/actionMap.h"#include "platform/input/IProcessInput.h"extern InputModifiers convertModifierBits(const U32 in);//-----------------------------------------------------------------------------// Constructor/Destructor//-----------------------------------------------------------------------------WindowInputGenerator::WindowInputGenerator( PlatformWindow *window ) :                                             mWindow(window),                                             mInputController(NULL),                                             mLastCursorPos(0,0),                                             mClampToWindow(true),                                             mFocused(false),                                             mPixelsPerMickey(1.0f),                                             mLastPressWasGlobalActionMap(false){   AssertFatal(mWindow, "NULL PlatformWindow on WindowInputGenerator creation");   if (mWindow->getOffscreenRender())      mFocused = true;   mWindow->appEvent.notify(this, &WindowInputGenerator::handleAppEvent);   mWindow->mouseEvent.notify(this, &WindowInputGenerator::handleMouseMove);   mWindow->wheelEvent.notify(this, &WindowInputGenerator::handleMouseWheel);   mWindow->buttonEvent.notify(this, &WindowInputGenerator::handleMouseButton);   mWindow->keyEvent.notify(this, &WindowInputGenerator::handleKeyboard);   mWindow->charEvent.notify(this, &WindowInputGenerator::handleCharInput);   // We also want to subscribe to input events.   Input::smInputEvent.notify(this, &WindowInputGenerator::handleInputEvent);}WindowInputGenerator::~WindowInputGenerator(){   if( mWindow )   {      mWindow->mouseEvent.remove(this, &WindowInputGenerator::handleMouseMove);      mWindow->buttonEvent.remove(this, &WindowInputGenerator::handleMouseButton);      mWindow->wheelEvent.remove(this, &WindowInputGenerator::handleMouseWheel);      mWindow->keyEvent.remove(this, &WindowInputGenerator::handleKeyboard);      mWindow->charEvent.remove(this, &WindowInputGenerator::handleCharInput);      mWindow->appEvent.remove(this, &WindowInputGenerator::handleAppEvent);   }   Input::smInputEvent.remove(this, &WindowInputGenerator::handleInputEvent);}//-----------------------------------------------------------------------------// Process an input event and pass it on.// Respect the action map.//-----------------------------------------------------------------------------void WindowInputGenerator::generateInputEvent( InputEventInfo &inputEvent ){   // Reset last press being global   mLastPressWasGlobalActionMap = false;   if (!mInputController)// || !mFocused)      return;   if (inputEvent.action == SI_MAKE && inputEvent.deviceType == KeyboardDeviceType)   {      for (int i = 0; i < mAcceleratorMap.size(); ++i)      {         const AccKeyMap &acc = mAcceleratorMap[i];         if (!mWindow->getKeyboardTranslation() &&            ((acc.modifier == inputEvent.modifier && acc.modifier != 0) || (acc.modifier == 0 && inputEvent.modifier == 0))            && acc.keyCode == inputEvent.objInst)         {            Con::evaluatef(acc.cmd);            return;         }      }   }   // Give the ActionMap first shot.   if (ActionMap::handleEventGlobal(&inputEvent))   {      mLastPressWasGlobalActionMap = true;      return;   }   if (mInputController->processInputEvent(inputEvent))      return;   if (mWindow->getKeyboardTranslation())      return;   // If we get here we failed to process it with anything prior... so let   // the ActionMap handle it.   ActionMap::handleEvent(&inputEvent);}//-----------------------------------------------------------------------------// Mouse Events//-----------------------------------------------------------------------------void WindowInputGenerator::handleMouseMove( WindowId did, U32 modifier, S32 x, S32 y, bool isRelative ){   if( !mInputController || !mFocused )      return;   // jddTODO : Clean this up   // CodeReview currently the Torque GuiCanvas deals with mouse input    //  as relative movement, even when the cursor is visible.  Because    //  of this there is an asinine bit of code in there that manages   //  updating the cursor position on the class based on relative movement.   //  Because of this we always have to generate and send off for processing   //  relative events, even if the mouse is not locked.     //  I'm considering removing this in the Canvas refactor, thoughts? [7/6/2007 justind]   // Now sends the absolute position event whenever an absolute position is received from the OS. [2/13/2019 mar]    // Generate a base Movement along and Axis event   InputEventInfo event;   event.deviceType = MouseDeviceType;   event.deviceInst = 0;   event.objType    = SI_AXIS;#ifdef TORQUE_SDL   event.modifier = modifier;#else   event.modifier = convertModifierBits(modifier);#endif   event.ascii      = 0;   // Generate delta movement along each axis   Point2F cursDelta;   if(isRelative)   {      cursDelta.x = F32(x) * mPixelsPerMickey;      cursDelta.y = F32(y) * mPixelsPerMickey;   }   else   {      cursDelta.x = F32(x - mLastCursorPos.x);      cursDelta.y = F32(y - mLastCursorPos.y);   }   // If X axis changed, generate a relative event   if(mFabs(cursDelta.x) > 0.1)   {      event.objInst    = SI_XAXIS;      event.action     = SI_MOVE;      event.fValue     = cursDelta.x;      generateInputEvent(event);   }   // If Y axis changed, generate a relative event   if(mFabs(cursDelta.y) > 0.1)   {      event.objInst    = SI_YAXIS;      event.action     = SI_MOVE;      event.fValue     = cursDelta.y;      generateInputEvent(event);   }   //  CodeReview : If we're not relative, pass along a positional update   //  so that the canvas can update it's internal cursor tracking   //  point. [7/6/2007 justind]   if( !isRelative )   {      if( mClampToWindow )      {         Point2I winExtent = mWindow->getClientExtent();         x = mClampF(x, 0.0f, F32(winExtent.x  - 1));         y = mClampF(y, 0.0f, F32(winExtent.y  - 1));      }      // We use SI_MAKE to signify that the position is being set, not relatively moved.      event.action = SI_MAKE;      // X Axis      event.objInst = SI_XAXIS;      event.fValue = (F32)x;      generateInputEvent(event);      // Y Axis      event.objInst = SI_YAXIS;      event.fValue = (F32)y;      generateInputEvent(event);      mLastCursorPos = Point2I(x,y);   }   else      mLastCursorPos += Point2I(x,y);      }void WindowInputGenerator::handleMouseButton( WindowId did, U32 modifiers, U32 action, U16 button ){   if( !mInputController || !mFocused )      return;   InputEventInfo event;   event.deviceType = MouseDeviceType;   event.deviceInst = 0;   event.objType    = SI_BUTTON;   event.objInst    = (InputObjectInstances)(KEY_BUTTON0 + button);#ifdef TORQUE_SDL   event.modifier = modifiers;#else   event.modifier = convertModifierBits(modifiers);#endif   event.ascii      = 0;   event.action     = (action==IA_MAKE) ? SI_MAKE : SI_BREAK;   event.fValue     = (action==IA_MAKE) ? 1.0 : 0.0;   generateInputEvent(event);}void WindowInputGenerator::handleMouseWheel( WindowId did, U32 modifiers, S32 wheelDeltaX, S32 wheelDeltaY ){   if( !mInputController || !mFocused )      return;   InputEventInfo event;   event.deviceType = MouseDeviceType;   event.deviceInst = 0;   event.objType    = SI_AXIS;#ifdef TORQUE_SDL   event.modifier = modifiers;#else   event.modifier = convertModifierBits(modifiers);#endif   event.ascii      = 0;   event.action     = SI_MOVE;   if( wheelDeltaY ) // Vertical   {      event.objInst    = SI_ZAXIS;      event.fValue     = (F32)wheelDeltaY;      generateInputEvent(event);   }   if( wheelDeltaX ) // Horizontal   {      event.objInst    = SI_RZAXIS;      event.fValue     = (F32)wheelDeltaX;      generateInputEvent(event);   }}//-----------------------------------------------------------------------------// Key/Character Input//-----------------------------------------------------------------------------void WindowInputGenerator::handleCharInput( WindowId did, U32 modifier, U16 key ){   if( !mInputController || !mFocused )      return;   InputEventInfo event;   event.deviceType  = KeyboardDeviceType;   event.deviceInst  = 0;   event.objType     = SI_KEY;   event.objInst     = KEY_NULL;#ifdef TORQUE_SDL   event.modifier = modifier;#else   event.modifier = convertModifierBits(modifier);#endif   event.ascii       = key;   event.action      = SI_MAKE;   event.fValue      = 1.0;   generateInputEvent(event);   event.action = SI_BREAK;   event.fValue = 0.f;   generateInputEvent(event);}void WindowInputGenerator::handleKeyboard( WindowId did, U32 modifier, U32 action, U16 key ){   if( !mInputController || !mFocused )      return;   InputEventInfo event;   event.deviceType  = KeyboardDeviceType;   event.deviceInst  = 0;   event.objType     = SI_KEY;   event.objInst     = (InputObjectInstances)key;#ifdef TORQUE_SDL   event.modifier    = modifier;#else   event.modifier = convertModifierBits(modifier);#endif   event.ascii       = 0;   switch(action)   {   case IA_MAKE:      event.action = SI_MAKE;      event.fValue = 1.f;      break;   case IA_REPEAT:      event.action = SI_REPEAT;      event.fValue = 1.f;      break;   case IA_BREAK:      event.action = SI_BREAK;      event.fValue = 0.f;      break;      // If we encounter an unknown don't submit the event.   default:      //Con::warnf("GuiCanvas::handleKeyboard - got an unknown action type %d!", action);      return;   }   generateInputEvent(event);}//-----------------------------------------------------------------------------// Raw input //-----------------------------------------------------------------------------void WindowInputGenerator::handleInputEvent( U32 deviceInst, F32 fValue, F32 fValue2, F32 fValue3, F32 fValue4, S32 iValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier ){   // Skip it if we don't have focus.   if(!mInputController)// || !mFocused)      return;   // Convert to an InputEventInfo and pass it around for processing.   InputEventInfo event;   event.deviceInst  = deviceInst;   event.fValue      = fValue;   event.fValue2     = fValue2;   event.fValue3     = fValue3;   event.fValue4     = fValue4;   event.iValue      = iValue;   event.deviceType  = (InputDeviceTypes)deviceType;   event.objType     = (InputEventType)objType;   event.ascii       = ascii;   event.objInst     = (InputObjectInstances)objInst;   event.action      = (InputActionType)action;   event.modifier    = (InputModifiers)modifier;      generateInputEvent(event);}//-----------------------------------------------------------------------------// Window Events//-----------------------------------------------------------------------------void WindowInputGenerator::handleAppEvent( WindowId did, S32 event ){   if(event == LoseFocus)   {      // Fire all breaks; this will prevent issues with dangling keys.      ActionMap::clearAllBreaks();      mFocused = false;   }   else if(event == GainFocus)   {      mFocused = true;   }   // always focused with offscreen rendering   if (mWindow->getOffscreenRender())      mFocused = true;}//-----------------------------------------------------------------------------// Character Input Mapping//-----------------------------------------------------------------------------bool WindowInputGenerator::wantAsKeyboardEvent( U32 modifiers, U32 keyCode ){   // Disallow translation on keys that are bound in the global action map.      return ActionMap::getGlobalMap()->isAction(      KeyboardDeviceType,      0,      modifiers,      keyCode   );}
 |