123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- //-----------------------------------------------------------------------------
- // 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 "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
- );
- }
|