Torque3D Documentation / _generateds / windowInputGenerator.cpp

windowInputGenerator.cpp

Engine/source/windowManager/windowInputGenerator.cpp

More...

Detailed Description

Public Functions

convertModifierBits(const U32 in)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "windowManager/windowInputGenerator.h"
 25#include "windowManager/platformWindow.h"
 26#include "sim/actionMap.h"
 27#include "platform/input/IProcessInput.h"
 28
 29
 30extern InputModifiers convertModifierBits(const U32 in);
 31
 32
 33//-----------------------------------------------------------------------------
 34// Constructor/Destructor
 35//-----------------------------------------------------------------------------
 36WindowInputGenerator::WindowInputGenerator( PlatformWindow *window ) :
 37                                             mWindow(window),
 38                                             mInputController(NULL),
 39                                             mLastCursorPos(0,0),
 40                                             mClampToWindow(true),
 41                                             mFocused(false),
 42                                             mPixelsPerMickey(1.0f),
 43                                             mLastPressWasGlobalActionMap(false)
 44{
 45   AssertFatal(mWindow, "NULL PlatformWindow on WindowInputGenerator creation");
 46
 47   if (mWindow->getOffscreenRender())
 48      mFocused = true;
 49
 50   mWindow->appEvent.notify(this, &WindowInputGenerator::handleAppEvent);
 51   mWindow->mouseEvent.notify(this, &WindowInputGenerator::handleMouseMove);
 52   mWindow->wheelEvent.notify(this, &WindowInputGenerator::handleMouseWheel);
 53   mWindow->buttonEvent.notify(this, &WindowInputGenerator::handleMouseButton);
 54   mWindow->keyEvent.notify(this, &WindowInputGenerator::handleKeyboard);
 55   mWindow->charEvent.notify(this, &WindowInputGenerator::handleCharInput);
 56
 57   // We also want to subscribe to input events.
 58   Input::smInputEvent.notify(this, &WindowInputGenerator::handleInputEvent);
 59}
 60
 61WindowInputGenerator::~WindowInputGenerator()
 62{
 63   if( mWindow )
 64   {
 65      mWindow->mouseEvent.remove(this, &WindowInputGenerator::handleMouseMove);
 66      mWindow->buttonEvent.remove(this, &WindowInputGenerator::handleMouseButton);
 67      mWindow->wheelEvent.remove(this, &WindowInputGenerator::handleMouseWheel);
 68      mWindow->keyEvent.remove(this, &WindowInputGenerator::handleKeyboard);
 69      mWindow->charEvent.remove(this, &WindowInputGenerator::handleCharInput);
 70      mWindow->appEvent.remove(this, &WindowInputGenerator::handleAppEvent);
 71   }
 72
 73   Input::smInputEvent.remove(this, &WindowInputGenerator::handleInputEvent);
 74}
 75
 76//-----------------------------------------------------------------------------
 77// Process an input event and pass it on.
 78// Respect the action map.
 79//-----------------------------------------------------------------------------
 80void WindowInputGenerator::generateInputEvent( InputEventInfo &inputEvent )
 81{
 82   // Reset last press being global
 83   mLastPressWasGlobalActionMap = false;
 84
 85   if (!mInputController)// || !mFocused)
 86      return;
 87
 88   if (inputEvent.action == SI_MAKE && inputEvent.deviceType == KeyboardDeviceType)
 89   {
 90      for (int i = 0; i < mAcceleratorMap.size(); ++i)
 91      {
 92         const AccKeyMap &acc = mAcceleratorMap[i];
 93         if (!mWindow->getKeyboardTranslation() &&
 94            ((acc.modifier == inputEvent.modifier && acc.modifier != 0) || (acc.modifier == 0 && inputEvent.modifier == 0))
 95            && acc.keyCode == inputEvent.objInst)
 96         {
 97            Con::evaluatef(acc.cmd);
 98            return;
 99         }
100      }
101   }
102
103   // Give the ActionMap first shot.
104   if (ActionMap::handleEventGlobal(&inputEvent))
105   {
106      mLastPressWasGlobalActionMap = true;
107      return;
108   }
109
110   if (mInputController->processInputEvent(inputEvent))
111      return;
112
113   if (mWindow->getKeyboardTranslation())
114      return;
115
116   // If we get here we failed to process it with anything prior... so let
117   // the ActionMap handle it.
118   ActionMap::handleEvent(&inputEvent);
119
120}
121
122//-----------------------------------------------------------------------------
123// Mouse Events
124//-----------------------------------------------------------------------------
125void WindowInputGenerator::handleMouseMove( WindowId did, U32 modifier, S32 x, S32 y, bool isRelative )
126{
127   if( !mInputController || !mFocused )
128      return;
129
130   // jddTODO : Clean this up
131   // CodeReview currently the Torque GuiCanvas deals with mouse input 
132   //  as relative movement, even when the cursor is visible.  Because 
133   //  of this there is an asinine bit of code in there that manages
134   //  updating the cursor position on the class based on relative movement.
135   //  Because of this we always have to generate and send off for processing
136   //  relative events, even if the mouse is not locked.  
137   //  I'm considering removing this in the Canvas refactor, thoughts? [7/6/2007 justind]
138   // Now sends the absolute position event whenever an absolute position is received from the OS. [2/13/2019 mar] 
139
140   // Generate a base Movement along and Axis event
141   InputEventInfo event;
142   event.deviceType = MouseDeviceType;
143   event.deviceInst = 0;
144   event.objType    = SI_AXIS;
145#ifdef TORQUE_SDL
146   event.modifier = modifier;
147#else
148   event.modifier = convertModifierBits(modifier);
149#endif
150   event.ascii      = 0;
151
152   // Generate delta movement along each axis
153   Point2F cursDelta;
154   if(isRelative)
155   {
156      cursDelta.x = F32(x) * mPixelsPerMickey;
157      cursDelta.y = F32(y) * mPixelsPerMickey;
158   }
159   else
160   {
161      cursDelta.x = F32(x - mLastCursorPos.x);
162      cursDelta.y = F32(y - mLastCursorPos.y);
163   }
164
165   // If X axis changed, generate a relative event
166   if(mFabs(cursDelta.x) > 0.1)
167   {
168      event.objInst    = SI_XAXIS;
169      event.action     = SI_MOVE;
170      event.fValue     = cursDelta.x;
171      generateInputEvent(event);
172   }
173
174   // If Y axis changed, generate a relative event
175   if(mFabs(cursDelta.y) > 0.1)
176   {
177      event.objInst    = SI_YAXIS;
178      event.action     = SI_MOVE;
179      event.fValue     = cursDelta.y;
180      generateInputEvent(event);
181   }
182
183   //  CodeReview : If we're not relative, pass along a positional update
184   //  so that the canvas can update it's internal cursor tracking
185   //  point. [7/6/2007 justind]
186   if( !isRelative )
187   {
188      if( mClampToWindow )
189      {
190         Point2I winExtent = mWindow->getClientExtent();
191         x = mClampF(x, 0.0f, F32(winExtent.x  - 1));
192         y = mClampF(y, 0.0f, F32(winExtent.y  - 1));
193
194      }
195
196      // We use SI_MAKE to signify that the position is being set, not relatively moved.
197      event.action = SI_MAKE;
198
199      // X Axis
200      event.objInst = SI_XAXIS;
201      event.fValue = (F32)x;
202      generateInputEvent(event);
203
204      // Y Axis
205      event.objInst = SI_YAXIS;
206      event.fValue = (F32)y;
207      generateInputEvent(event);
208
209      mLastCursorPos = Point2I(x,y);
210   }
211   else
212      mLastCursorPos += Point2I(x,y);      
213}
214
215void WindowInputGenerator::handleMouseButton( WindowId did, U32 modifiers, U32 action, U16 button )
216{
217   if( !mInputController || !mFocused )
218      return;
219
220   InputEventInfo event;
221   event.deviceType = MouseDeviceType;
222   event.deviceInst = 0;
223   event.objType    = SI_BUTTON;
224   event.objInst    = (InputObjectInstances)(KEY_BUTTON0 + button);
225#ifdef TORQUE_SDL
226   event.modifier = modifiers;
227#else
228   event.modifier = convertModifierBits(modifiers);
229#endif
230   event.ascii      = 0;
231   event.action     = (action==<a href="/coding/file/journaledsignal_8h/#journaledsignal_8h_1a9c56096a2c51a4a98f907f8f87fd1671a1ff2cf77afe457ec438f62a1f1bd19e6">IA_MAKE</a>) ? SI_MAKE : SI_BREAK;
232   event.fValue     = (action==<a href="/coding/file/journaledsignal_8h/#journaledsignal_8h_1a9c56096a2c51a4a98f907f8f87fd1671a1ff2cf77afe457ec438f62a1f1bd19e6">IA_MAKE</a>) ? 1.0 : 0.0;
233
234   generateInputEvent(event);
235}
236
237void WindowInputGenerator::handleMouseWheel( WindowId did, U32 modifiers, S32 wheelDeltaX, S32 wheelDeltaY )
238{
239   if( !mInputController || !mFocused )
240      return;
241
242   InputEventInfo event;
243   event.deviceType = MouseDeviceType;
244   event.deviceInst = 0;
245   event.objType    = SI_AXIS;
246#ifdef TORQUE_SDL
247   event.modifier = modifiers;
248#else
249   event.modifier = convertModifierBits(modifiers);
250#endif
251   event.ascii      = 0;
252   event.action     = SI_MOVE;
253
254   if( wheelDeltaY ) // Vertical
255   {
256      event.objInst    = SI_ZAXIS;
257      event.fValue     = (F32)wheelDeltaY;
258
259      generateInputEvent(event);
260   }
261   if( wheelDeltaX ) // Horizontal
262   {
263      event.objInst    = SI_RZAXIS;
264      event.fValue     = (F32)wheelDeltaX;
265
266      generateInputEvent(event);
267   }
268}
269
270//-----------------------------------------------------------------------------
271// Key/Character Input
272//-----------------------------------------------------------------------------
273void WindowInputGenerator::handleCharInput( WindowId did, U32 modifier, U16 key )
274{
275   if( !mInputController || !mFocused )
276      return;
277
278   InputEventInfo event;
279   event.deviceType  = KeyboardDeviceType;
280   event.deviceInst  = 0;
281   event.objType     = SI_KEY;
282   event.objInst     = KEY_NULL;
283#ifdef TORQUE_SDL
284   event.modifier = modifier;
285#else
286   event.modifier = convertModifierBits(modifier);
287#endif
288   event.ascii       = key;
289   event.action      = SI_MAKE;
290   event.fValue      = 1.0;
291   generateInputEvent(event);
292
293   event.action = SI_BREAK;
294   event.fValue = 0.f;
295   generateInputEvent(event);
296}
297
298
299void WindowInputGenerator::handleKeyboard( WindowId did, U32 modifier, U32 action, U16 key )
300{
301   if( !mInputController || !mFocused )
302      return;
303
304   InputEventInfo event;
305   event.deviceType  = KeyboardDeviceType;
306   event.deviceInst  = 0;
307   event.objType     = SI_KEY;
308   event.objInst     = (InputObjectInstances)key;
309#ifdef TORQUE_SDL
310   event.modifier    = modifier;
311#else
312   event.modifier = convertModifierBits(modifier);
313#endif
314   event.ascii       = 0;
315
316   switch(action)
317   {
318   case IA_MAKE:
319      event.action = SI_MAKE;
320      event.fValue = 1.f;
321      break;
322
323   case IA_REPEAT:
324      event.action = SI_REPEAT;
325      event.fValue = 1.f;
326      break;
327
328   case IA_BREAK:
329      event.action = SI_BREAK;
330      event.fValue = 0.f;
331      break;
332
333      // If we encounter an unknown don't submit the event.
334   default:
335      //Con::warnf("GuiCanvas::handleKeyboard - got an unknown action type %d!", action);
336      return;
337   }
338
339   generateInputEvent(event);
340}
341
342//-----------------------------------------------------------------------------
343// Raw input 
344//-----------------------------------------------------------------------------
345void 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 )
346{
347   // Skip it if we don't have focus.
348   if(!mInputController)// || !mFocused)
349      return;
350
351   // Convert to an InputEventInfo and pass it around for processing.
352   InputEventInfo event;
353   event.deviceInst  = deviceInst;
354   event.fValue      = fValue;
355   event.fValue2     = fValue2;
356   event.fValue3     = fValue3;
357   event.fValue4     = fValue4;
358   event.iValue      = iValue;
359   event.deviceType  = (InputDeviceTypes)deviceType;
360   event.objType     = (InputEventType)objType;
361   event.ascii       = ascii;
362   event.objInst     = (InputObjectInstances)objInst;
363   event.action      = (InputActionType)action;
364   event.modifier    = (InputModifiers)modifier;
365   
366   generateInputEvent(event);
367}
368
369//-----------------------------------------------------------------------------
370// Window Events
371//-----------------------------------------------------------------------------
372void WindowInputGenerator::handleAppEvent( WindowId did, S32 event )
373{
374   if(event == LoseFocus)
375   {
376      // Fire all breaks; this will prevent issues with dangling keys.
377      ActionMap::clearAllBreaks();
378      mFocused = false;
379   }
380   else if(event == GainFocus)
381   {
382      mFocused = true;
383   }
384
385   // always focused with offscreen rendering
386   if (mWindow->getOffscreenRender())
387      mFocused = true;
388}
389
390//-----------------------------------------------------------------------------
391// Character Input Mapping
392//-----------------------------------------------------------------------------
393
394bool WindowInputGenerator::wantAsKeyboardEvent( U32 modifiers, U32 keyCode )
395{
396   // Disallow translation on keys that are bound in the global action map.
397   
398   return ActionMap::getGlobalMap()->isAction(
399      KeyboardDeviceType,
400      0,
401      modifiers,
402      keyCode
403   );
404}
405