c49d65226dca4fd2ba16c7566425968edeed204d
[blender-staging.git] / source / gameengine / GameLogic / SCA_KeyboardSensor.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Sensor for keyboard input
29  */
30 #include "SCA_KeyboardSensor.h"
31 #include "SCA_KeyboardManager.h"
32 #include "SCA_LogicManager.h"
33 #include "StringValue.h"
34 #include "SCA_IInputDevice.h"
35
36 /* ------------------------------------------------------------------------- */
37 /* Native functions                                                          */
38 /* ------------------------------------------------------------------------- */
39
40 SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
41                                                                            short int hotkey,
42                                                                            short int qual,
43                                                                            short int qual2,
44                                                                            bool bAllKeys,
45                                                                            const STR_String& targetProp,
46                                                                            const STR_String& toggleProp,
47                                                                            SCA_IObject* gameobj)
48         :SCA_ISensor(gameobj,keybdmgr),
49          m_hotkey(hotkey),
50          m_qual(qual),
51          m_qual2(qual2),
52          m_bAllKeys(bAllKeys),
53          m_targetprop(targetProp),
54          m_toggleprop(toggleProp)
55 {
56         if (hotkey == SCA_IInputDevice::KX_ESCKEY)
57                 keybdmgr->GetInputDevice()->HookEscape();
58 //      SetDrawColor(0xff0000ff);
59         Init();
60 }
61
62
63
64 SCA_KeyboardSensor::~SCA_KeyboardSensor()
65 {
66 }
67
68 void SCA_KeyboardSensor::Init()
69 {
70         // this function is used when the sensor is disconnected from all controllers
71         // by the state engine. It reinitializes the sensor as if it was just created.
72         // However, if the target key is pressed when the sensor is reactivated, it
73         // will not generated an event (see remark in Evaluate()).
74         m_val = (m_invert)?1:0;
75         m_reset = true;
76 }
77
78 CValue* SCA_KeyboardSensor::GetReplica()
79 {
80         SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this);
81         // this will copy properties and so on...
82         replica->ProcessReplica();
83         replica->Init();
84         return replica;
85 }
86
87
88
89 short int SCA_KeyboardSensor::GetHotkey()
90 {
91         return m_hotkey;
92 }
93
94
95
96 bool SCA_KeyboardSensor::IsPositiveTrigger()
97
98         bool result = (m_val != 0);
99
100         if (m_invert)
101                 result = !result;
102                 
103         return result;
104 }
105
106
107
108 bool SCA_KeyboardSensor::TriggerOnAllKeys()
109
110         return m_bAllKeys;
111 }
112
113
114
115 bool SCA_KeyboardSensor::Evaluate()
116 {
117         bool result    = false;
118         bool reset     = m_reset && m_level;
119         bool qual          = true;
120         bool qual_change = false;
121         short int m_val_orig = m_val;
122         
123         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
124         //      cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n";
125
126         /* See if we need to do logging: togPropState exists and is
127      * different from 0 */
128         CValue* myparent = GetParent();
129         CValue* togPropState = myparent->GetProperty(m_toggleprop);
130         if (togPropState &&
131                 (((int)togPropState->GetNumber()) != 0) )
132         {
133                 LogKeystrokes();
134         }
135
136         m_reset = false;
137
138         /* Now see whether events must be bounced. */
139         if (m_bAllKeys)
140         {
141                 bool justactivated = false;
142                 bool justreleased = false;
143                 bool active = false;
144
145                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
146                 {
147                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
148                         switch (inevent.m_status) 
149                         { 
150                         case SCA_InputEvent::KX_JUSTACTIVATED:
151                                 justactivated = true;
152                                 break;
153                         case SCA_InputEvent::KX_JUSTRELEASED:
154                                 justreleased = true;
155                                 break;
156                         case SCA_InputEvent::KX_ACTIVE:
157                                 active = true;
158                                 break;
159                         }
160                 }
161
162                 if (justactivated)
163                 {
164                         m_val=1;
165                         result = true;
166                 } else
167                 {
168                         if (justreleased)
169                         {
170                                 m_val=(active)?1:0;
171                                 result = true;
172                         } else
173                         {
174                                 if (active)
175                                 {
176                                         if (m_val == 0)
177                                         {
178                                                 m_val = 1;
179                                                 if (m_level) {
180                                                         result = true;
181                                                 }
182                                         }
183                                 } else
184                                 {
185                                         if (m_val == 1)
186                                         {
187                                                 m_val = 0;
188                                                 result = true;
189                                         }
190                                 }
191                         }
192                         if (m_tap)
193                                 // special case for tap mode: only generate event for new activation
194                                 result = false;
195                 }
196
197
198         } else
199         {
200
201         //              cerr << "======= SCA_KeyboardSensor::Evaluate:: peeking at key status" << endl;
202                 const SCA_InputEvent & inevent = inputdev->GetEventValue(
203                         (SCA_IInputDevice::KX_EnumInputs) m_hotkey);
204         
205         //              cerr << "======= SCA_KeyboardSensor::Evaluate:: status: " << inevent.m_status << endl;
206                 
207                 
208                 /* Check qualifier keys
209                  * - see if the qualifiers we request are pressed - 'qual' true/false
210                  * - see if the qualifiers we request changed their state - 'qual_change' true/false
211                  */
212                 if (m_qual > 0) {
213                         const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual);
214                         switch(qualevent.m_status) {
215                         case SCA_InputEvent::KX_NO_INPUTSTATUS:
216                                 qual = false;
217                                 break;
218                         case SCA_InputEvent::KX_JUSTRELEASED:
219                                 qual_change = true;
220                                 qual = false;
221                                 break;
222                         case SCA_InputEvent::KX_JUSTACTIVATED:
223                                 qual_change = true;
224                         }
225                 }
226                 if (m_qual2 > 0 && qual==true) {
227                         const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual2);
228                         /* copy of above */
229                         switch(qualevent.m_status) {
230                         case SCA_InputEvent::KX_NO_INPUTSTATUS:
231                                 qual = false;
232                                 break;
233                         case SCA_InputEvent::KX_JUSTRELEASED:
234                                 qual_change = true;
235                                 qual = false;
236                                 break;
237                         case SCA_InputEvent::KX_JUSTACTIVATED:
238                                 qual_change = true;
239                         }
240                 }
241                 /* done reading qualifiers */
242                 
243                 if (inevent.m_status == SCA_InputEvent::KX_NO_INPUTSTATUS)
244                 {
245                         if (m_val == 1)
246                         {
247                                 // this situation may occur after a scene suspend: the keyboard release 
248                                 // event was not captured, produce now the event off
249                                 m_val = 0;
250                                 result = true;
251                         }
252                 } else
253                 {
254                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
255                         {
256                                 m_val=1;
257                                 result = true;
258                         } else
259                         {
260                                 if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
261                                 {
262                                         m_val = 0;
263                                         result = true;
264                                 } else 
265                                 {
266                                         if (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
267                                         {
268                                                 if (m_val == 0)
269                                                 {
270                                                         m_val = 1;
271                                                         if (m_level) 
272                                                         {
273                                                                 result = true;
274                                                         }
275                                                 }
276                                         }
277                                 }
278                         }
279                 }
280                 
281                 /* Modify the key state based on qual(s)
282                  * Tested carefuly. dont touch unless your really sure.
283                  * note, this will only change the results if key modifiers are set.
284                  *
285                  * When all modifiers and keys are positive
286                  *  - pulse true
287                  * 
288                  * When ANY of the modifiers or main key become inactive,
289                  *  - pulse false
290                  */
291                 if (qual==false) { /* one of the qualifiers are not pressed */
292                         if (m_val_orig && qual_change) { /* we were originally enabled, but a qualifier changed */
293                                 result = true;
294                         } else {
295                                 result = false;
296                         }
297                         m_val = 0; /* since one of the qualifiers is not on, set the state to false */
298                 } else {                                                /* we done have any qualifiers or they are all pressed */
299                         if (m_val && qual_change) {     /* the main key state is true and our qualifier just changed */
300                                 result = true;
301                         }
302                 }
303                 /* done with key quals */
304                 
305         }
306         
307         if (reset)
308                 // force an event
309                 result = true;
310         return result;
311
312 }
313
314 void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
315 {
316         if (IsPrintable(keyIndex)) {
317                 CValue* tprop = GetParent()->GetProperty(m_targetprop);
318                 
319                 if (tprop) {
320                         /* overwrite the old property */
321                         if (IsDelete(keyIndex)) {
322                                 /* strip one char, if possible */
323                                 STR_String newprop = tprop->GetText();
324                                 int oldlength = newprop.Length();
325                                 if (oldlength >= 1 ) {
326                                         newprop.SetLength(oldlength - 1);
327                                         CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
328                                         GetParent()->SetProperty(m_targetprop, newstringprop);
329                                         newstringprop->Release();
330                                 }                               
331                         } else {
332                                 /* append */
333                                 char pchar = ToCharacter(keyIndex, IsShifted());
334                                 STR_String newprop = tprop->GetText() + pchar;
335                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
336                                 GetParent()->SetProperty(m_targetprop, newstringprop);
337                                 newstringprop->Release();
338                         }
339                 } else {
340                         if (!IsDelete(keyIndex)) {
341                                 /* Make a new property. Deletes can be ignored. */
342                                 char pchar = ToCharacter(keyIndex, IsShifted());
343                                 STR_String newprop = pchar;
344                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
345                                 GetParent()->SetProperty(m_targetprop, newstringprop);
346                                 newstringprop->Release();
347                         }
348                 }
349         }
350         
351 }
352         
353 /**
354  * Tests whether shift is pressed
355  */     
356 bool SCA_KeyboardSensor::IsShifted(void)
357 {
358         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
359         
360         if ( (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
361                   == SCA_InputEvent::KX_ACTIVE)
362                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
363                          == SCA_InputEvent::KX_JUSTACTIVATED)
364                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
365                          == SCA_InputEvent::KX_ACTIVE)
366                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
367                          == SCA_InputEvent::KX_JUSTACTIVATED)
368                 ) {
369                 return true;
370         } else {
371                 return false;
372         }       
373 }
374
375 void SCA_KeyboardSensor::LogKeystrokes(void) 
376 {
377         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
378         int num = inputdev->GetNumActiveEvents();
379
380         /* weird loop, this one... */
381         if (num > 0)
382         {
383                 
384                 int index = 0;
385                 /* Check on all keys whether they were pushed. This does not
386          * untangle the ordering, so don't type too fast :) */
387                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
388                 {
389                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
390                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
391                         {
392                                 if (index < num)
393                                 {
394                                         AddToTargetProp(i);
395                                         index++;
396                                 }
397                         }
398                 }
399         }
400 }
401
402 #ifndef DISABLE_PYTHON
403
404 /* ------------------------------------------------------------------------- */
405 /* Python Functions                                                    */
406 /* ------------------------------------------------------------------------- */
407
408 KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
409 "getKeyStatus(keycode)\n"
410 "\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
411 {
412         if (!PyLong_Check(value)) {
413                 PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int");
414                 return NULL;
415         }
416         
417         int keycode = PyLong_AsSsize_t(value);
418         
419         if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
420                 || (keycode > SCA_IInputDevice::KX_ENDKEY)){
421                 PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!");
422                 return NULL;
423         }
424         
425         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice();
426         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
427         return PyLong_FromSsize_t(inevent.m_status);
428 }
429
430 /* ------------------------------------------------------------------------- */
431 /* Python Integration Hooks                                            */
432 /* ------------------------------------------------------------------------- */
433
434 PyTypeObject SCA_KeyboardSensor::Type = {
435         PyVarObject_HEAD_INIT(NULL, 0)
436         "SCA_KeyboardSensor",
437         sizeof(PyObjectPlus_Proxy),
438         0,
439         py_base_dealloc,
440         0,
441         0,
442         0,
443         0,
444         py_base_repr,
445         0,0,0,0,0,0,0,0,0,
446         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
447         0,0,0,0,0,0,0,
448         Methods,
449         0,
450         0,
451         &SCA_ISensor::Type,
452         0,0,0,0,0,0,
453         py_base_new
454 };
455
456 PyMethodDef SCA_KeyboardSensor::Methods[] = {
457         KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus),
458         {NULL,NULL} //Sentinel
459 };
460
461 PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
462         KX_PYATTRIBUTE_RO_FUNCTION("events", SCA_KeyboardSensor, pyattr_get_events),
463         KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys),
464         KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey),
465         KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual),
466         KX_PYATTRIBUTE_SHORT_RW("hold2",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual2),
467         KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,false,SCA_KeyboardSensor,m_toggleprop),
468         KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,false,SCA_KeyboardSensor,m_targetprop),
469         { NULL }        //Sentinel
470 };
471
472
473 PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
474 {
475         SCA_KeyboardSensor* self= static_cast<SCA_KeyboardSensor*>(self_v);
476         
477         SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)self->m_eventmgr)->GetInputDevice();
478
479         PyObject* resultlist = PyList_New(0);
480         
481         for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
482         {
483                 const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
484                 if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
485                 {
486                         PyObject* keypair = PyList_New(2);
487                         PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i));
488                         PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status));
489                         PyList_Append(resultlist,keypair);
490                 }
491         }       
492         return resultlist;
493 }
494
495 #endif // DISABLE_PYTHON
496
497 /* Accessed from python */
498
499 // this code looks ugly, please use an ordinary hashtable
500
501 char ToCharacter(int keyIndex, bool shifted)
502 {
503         /* numerals */
504         if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
505                  && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
506                 if (shifted) {
507                         char numshift[] = ")!@#$%^&*(";
508                         return numshift[keyIndex - '0']; 
509                 } else {
510                         return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
511                 }
512         }
513         
514         /* letters... always lowercase... is that desirable? */
515         if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
516                  && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
517                 if (shifted) {
518                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
519                 } else {
520                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
521                 }
522         }
523         
524         if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
525                 return ' ';
526         }
527         if (keyIndex == SCA_IInputDevice::KX_RETKEY || keyIndex == SCA_IInputDevice::KX_PADENTER) {
528                 return '\n';
529         }
530         
531         
532         if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
533                 return '*';
534         }
535         
536         if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
537                 return '\t';
538         }
539         
540         /* comma to period */
541         char commatoperiod[] = ",-.";
542         char commatoperiodshifted[] = "<_>";
543         if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
544                 if (shifted) {
545                         return commatoperiodshifted[0];
546                 } else {
547                         return commatoperiod[0];
548                 }
549         }
550         if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
551                 if (shifted) {
552                         return commatoperiodshifted[1];
553                 } else {
554                         return commatoperiod[1];
555                 }
556         }
557         if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
558                 if (shifted) {
559                         return commatoperiodshifted[2];
560                 } else {
561                         return commatoperiod[2];
562                 }
563         }
564         
565         /* semicolon to rightbracket */
566         char semicolontorightbracket[] = ";\'`/\\=[]";
567         char semicolontorightbracketshifted[] = ":\"~\?|+{}";
568         if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
569                 && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
570                 if (shifted) {
571                         return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
572                 } else {
573                         return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
574                 }
575         }
576         
577         /* keypad2 to padplus */
578         char pad2topadplus[] = "246813579. 0- +";
579         if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
580                 && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
581                 return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
582         }
583
584         return '!';
585 }
586
587
588
589 /**
590  * Determine whether this character can be printed. We cannot use
591  * the library functions here, because we need to test our own
592  * keycodes. */
593 bool IsPrintable(int keyIndex)
594 {
595         /* only print 
596          * - numerals: KX_ZEROKEY to KX_NINEKEY
597          * - alphas:   KX_AKEY to KX_ZKEY. 
598          * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
599          *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
600          *             KX_PAD2 to KX_PADPLUSKEY
601          * - delete and backspace: also printable in the sense that they modify 
602          *                         the string
603          * - retkey: should this be printable?
604          * - virgule: prints a space... don't know which key that's supposed
605          *   to be...
606          */
607         if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
608                   && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
609                  || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
610                          && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
611                  || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
612                  || (keyIndex == SCA_IInputDevice::KX_RETKEY)
613                  || (keyIndex == SCA_IInputDevice::KX_PADENTER)
614                  || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
615                  || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
616                  || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
617                          && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
618                  || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
619                          && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
620                  || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
621                          && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
622                  || (keyIndex == SCA_IInputDevice::KX_DELKEY)
623                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)
624                 )
625         {
626                 return true;
627         } else {
628                 return false;
629         }
630 }
631
632 /**
633  * Tests whether this is a delete key.
634  */     
635 bool IsDelete(int keyIndex)
636 {
637         if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
638                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
639                 return true;
640         } else {
641                 return false;
642         }
643 }