Initial revision
[blender.git] / source / gameengine / GameLogic / SCA_KeyboardSensor.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Sensor for keyboard input
32  */
33 #include "SCA_KeyboardSensor.h"
34 #include "SCA_KeyboardManager.h"
35 #include "SCA_LogicManager.h"
36 #include "StringValue.h"
37 #include "SCA_IInputDevice.h"
38
39
40
41 /* ------------------------------------------------------------------------- */
42 /* Native functions                                                          */
43 /* ------------------------------------------------------------------------- */
44
45 SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
46                                                                            short int hotkey,
47                                                                            short int qual,
48                                                                            short int qual2,
49                                                                            bool bAllKeys,
50                                                                            const STR_String& targetProp,
51                                                                            const STR_String& toggleProp,
52                                                                            SCA_IObject* gameobj,
53                                                                            PyTypeObject* T )
54         :SCA_ISensor(gameobj,keybdmgr,T),
55          m_pKeyboardMgr(keybdmgr),
56          m_hotkey(hotkey),
57          m_qual(qual),
58          m_qual2(qual2),
59          m_bAllKeys(bAllKeys),
60          m_targetprop(targetProp),
61          m_toggleprop(toggleProp)
62 {
63         
64 //      SetDrawColor(0xff0000ff);
65         m_val=0;
66 }
67
68
69
70 SCA_KeyboardSensor::~SCA_KeyboardSensor()
71 {
72 }
73
74
75
76 CValue* SCA_KeyboardSensor::GetReplica()
77 {
78         CValue* replica = new SCA_KeyboardSensor(*this);
79         // this will copy properties and so on...
80         CValue::AddDataToReplica(replica);
81
82         return replica;
83 }
84
85
86
87 short int SCA_KeyboardSensor::GetHotkey()
88 {
89         return m_hotkey;
90 }
91
92
93
94 bool SCA_KeyboardSensor::IsPositiveTrigger()
95
96         bool result = (m_val != 0);
97
98         if (m_invert)
99                 result = !result;
100                 
101         return result;
102 }
103
104
105
106 bool SCA_KeyboardSensor::TriggerOnAllKeys()
107
108         return m_bAllKeys;
109 }
110
111
112
113 bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
114 {
115         bool result    = false;
116         SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
117         
118         //      cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n";
119
120         /* See if we need to do logging: togPropState exists and is
121      * different from 0 */
122         CValue* myparent = GetParent();
123         CValue* togPropState = myparent->GetProperty(m_toggleprop);
124         if (togPropState &&
125                 (((int)togPropState->GetNumber()) != 0) )
126         {
127                 LogKeystrokes();
128         }
129
130
131
132         /* Now see whether events must be bounced. */
133         if (m_bAllKeys)
134         {
135                 bool justactivated = false;
136                 bool justreleased = false;
137
138                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
139                 {
140                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
141                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
142                         {
143                                 justactivated = true;
144                         }
145                         if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
146                         {
147                                 justreleased = true;
148                         }
149                 }
150
151                 if (justactivated)
152                 {
153                         m_val=1;
154                         result = true;
155                 } else
156                 {
157                         if (justreleased)
158                         {
159                                 m_val=0;
160                                 result = true;
161                         }
162                 }
163
164
165         } else
166         {
167
168           //            cerr << "======= SCA_KeyboardSensor::Evaluate:: peeking at key status" << endl;
169                 const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_hotkey);
170         
171                 //              cerr << "======= SCA_KeyboardSensor::Evaluate:: status: " << inevent.m_status << endl;
172
173                 if (inevent.m_status == SCA_InputEvent::KX_NO_INPUTSTATUS)
174                 {
175                         int i=4;
176                 } else
177                 {
178                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
179                         {
180                                 m_val=1;
181                                 result = true;
182                         } else
183                         {
184                                 if (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)
185                                 {
186                                         m_val = 0;
187                                         result = true;
188                                 }
189                         }
190                 }
191         }
192
193         return result;
194
195 }
196
197 void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
198 {
199         if (IsPrintable(keyIndex)) {
200                 CValue* tprop = GetParent()->GetProperty(m_targetprop);
201                 
202                 if (tprop) {
203                         /* overwrite the old property */
204                         if (IsDelete(keyIndex)) {
205                                 /* strip one char, if possible */
206                                 STR_String newprop = tprop->GetText();
207                                 int oldlength = newprop.Length();
208                                 if (oldlength >= 1 ) {
209                                         newprop.SetLength(oldlength - 1);
210                                         CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
211                                         GetParent()->SetProperty(m_targetprop, newstringprop);
212                                 }                               
213                         } else {
214                                 /* append */
215                                 char pchar = ToCharacter(keyIndex, IsShifted());
216                                 STR_String newprop = tprop->GetText() + pchar;
217                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
218                                 GetParent()->SetProperty(m_targetprop, newstringprop);
219                         }
220                 } else {
221                         if (!IsDelete(keyIndex)) {
222                                 /* Make a new property. Deletes can be ignored. */
223                                 char pchar = ToCharacter(keyIndex, IsShifted());
224                                 STR_String newprop = pchar;
225                                 CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);                 
226                                 GetParent()->SetProperty(m_targetprop, newstringprop);
227                         }
228                 }
229         }
230         
231 }
232
233 /**
234  * Determine whether this character can be printed. We cannot use
235  * the library functions here, because we need to test our own
236  * keycodes. */
237 bool SCA_KeyboardSensor::IsPrintable(int keyIndex)
238 {
239         /* only print 
240          * - numerals: KX_ZEROKEY to KX_NINEKEY
241          * - alphas:   KX_AKEY to KX_ZKEY. 
242          * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
243          *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
244          *             KX_PAD2 to KX_PADPLUSKEY
245          * - delete and backspace: also printable in the sense that they modify 
246          *                         the string
247          * - retkey: should this be printable?
248          * - virgule: prints a space... don't know which key that's supposed
249          *   to be...
250          */
251         if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
252                   && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
253                  || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
254                          && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
255                  || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
256 /*                       || (keyIndex == KX_RETKEY)  */
257                  || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
258                  || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
259                  || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
260                          && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
261                  || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
262                          && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
263                  || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
264                          && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
265                  || (keyIndex == SCA_IInputDevice::KX_DELKEY)
266                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)                              
267                 )
268         {
269                 return true;
270         } else {
271                 return false;
272         }
273 }
274
275 // this code looks ugly, please use an ordinary hashtable
276
277 char SCA_KeyboardSensor::ToCharacter(int keyIndex, bool shifted)
278 {
279         /* numerals */
280         if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
281                  && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
282                 if (shifted) {
283                         char numshift[] = ")!@#$%^&*(";
284                         return numshift[keyIndex - '0']; 
285                 } else {
286                         return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
287                 }
288         }
289         
290         /* letters... always lowercase... is that desirable? */
291         if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
292                  && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
293                 if (shifted) {
294                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
295                 } else {
296                         return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
297                 }
298         }
299         
300         if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
301                 return ' ';
302         }
303         
304 /*                       || (keyIndex == SCA_IInputDevice::KX_RETKEY)  */
305         
306         if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
307                 return '*';
308         }
309         
310         if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
311                 return '\t';
312         }
313         
314         /* comma to period */
315         char commatoperiod[] = ",-.";
316         char commatoperiodshifted[] = "<_>";
317         if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
318                 if (shifted) {
319                         return commatoperiodshifted[0];
320                 } else {
321                         return commatoperiod[0];
322                 }
323         }
324         if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
325                 if (shifted) {
326                         return commatoperiodshifted[1];
327                 } else {
328                         return commatoperiod[1];
329                 }
330         }
331         if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
332                 if (shifted) {
333                         return commatoperiodshifted[2];
334                 } else {
335                         return commatoperiod[2];
336                 }
337         }
338         
339         /* semicolon to rightbracket */
340         char semicolontorightbracket[] = ";\'` /\\=[]";
341         char semicolontorightbracketshifted[] = ":\"~ \?|+{}";
342         if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
343                 && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
344                 if (shifted) {
345                         return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
346                 } else {
347                         return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
348                 }
349         }
350         
351         /* keypad2 to padplus */
352         char pad2topadplus[] = "246813579. 0- +";
353         if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
354                 && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
355                 return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
356         }
357
358         return '!';
359 }
360         
361 /**
362  * Tests whether this is a delete key.
363  */     
364 bool SCA_KeyboardSensor::IsDelete(int keyIndex)
365 {
366         if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
367                  || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
368                 return true;
369         } else {
370                 return false;
371         }
372 }
373
374 /**
375  * Tests whether shift is pressed
376  */     
377 bool SCA_KeyboardSensor::IsShifted(void)
378 {
379         SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
380         
381         if ( (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
382                   == SCA_InputEvent::KX_ACTIVE)
383                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_RIGHTSHIFTKEY).m_status 
384                          == SCA_InputEvent::KX_JUSTACTIVATED)
385                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
386                          == SCA_InputEvent::KX_ACTIVE)
387                  || (inputdev->GetEventValue(SCA_IInputDevice::KX_LEFTSHIFTKEY).m_status 
388                          == SCA_InputEvent::KX_JUSTACTIVATED)
389                 ) {
390                 return true;
391         } else {
392                 return false;
393         }       
394 }
395
396 void SCA_KeyboardSensor::LogKeystrokes(void) 
397 {
398         SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
399         int num = inputdev->GetNumActiveEvents();
400
401         /* weird loop, this one... */
402         if (num > 0)
403         {
404                 
405                 int index = 0;
406                 /* Check on all keys whether they were pushed. This does not
407          * untangle the ordering, so don't type too fast :) */
408                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
409                 {
410                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
411                         if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
412                         {
413                                 if (index < num)
414                                 {
415                                         AddToTargetProp(i);
416                                         index++;
417                                 }
418                         }
419                 }
420         }
421 }
422
423
424 /* ------------------------------------------------------------------------- */
425 /* Python functions : specific                                               */
426 /* ------------------------------------------------------------------------- */
427
428
429 PyObject* SCA_KeyboardSensor::PySetAllMode(PyObject* self, 
430                                PyObject* args, 
431                                PyObject* kwds)
432 {
433         bool allkeys;
434
435         if (!PyArg_ParseTuple(args, "i", &allkeys))
436         {
437           return NULL;
438         }
439         
440         m_bAllKeys = allkeys;
441         Py_Return
442 }
443
444
445
446 PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, 
447                                        PyObject* args, 
448                                        PyObject* kwds)
449 {
450 //      printf("sPyIsPositive\n");
451     return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
452 }
453
454
455 /** 1. GetKey : check which key this sensor looks at */
456 char SCA_KeyboardSensor::GetKey_doc[] = 
457 "getKey()\n"
458 "\tReturn the code of the key this sensor is listening to.\n" ;
459 PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds)
460 {
461         return PyInt_FromLong(m_hotkey);
462 }
463
464 /** 2. SetKey: change the key to look at */
465 char SCA_KeyboardSensor::SetKey_doc[] = 
466 "setKey(keycode)\n"
467 "\t- keycode: any code from GameKeys\n"
468 "\tSet the key this sensor should listen to.\n" ;
469 PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds)
470 {
471         int keyCode;
472         
473         if(!PyArg_ParseTuple(args, "i", &keyCode)) {
474                 return NULL;
475         }
476
477         /* Since we have symbolic constants for this in Python, we don't guard   */
478         /* anything. It's up to the user to provide a sensible number.           */
479         m_hotkey = keyCode;
480
481         Py_Return;
482 }
483
484 /** 3. GetHold1 : set the first bucky bit */
485 char SCA_KeyboardSensor::GetHold1_doc[] = 
486 "getHold1()\n"
487 "\tReturn the code of the first key modifier to the key this \n"
488 "\tsensor is listening to.\n" ;
489 PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds)
490 {
491         return PyInt_FromLong(m_qual);
492 }
493
494 /** 4. SetHold1: change the first bucky bit */
495 char SCA_KeyboardSensor::SetHold1_doc[] = 
496 "setHold1(keycode)\n"
497 "\t- keycode: any code from GameKeys\n"
498 "\tSet the first modifier to the key this sensor should listen to.\n" ;
499 PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds)
500 {
501         int keyCode;
502
503         if(!PyArg_ParseTuple(args, "i", &keyCode)) {
504                 return NULL;
505         }
506         
507         /* Since we have symbolic constants for this in Python, we don't guard   */
508         /* anything. It's up to the user to provide a sensible number.           */
509         m_qual = keyCode;
510
511         Py_Return;
512 }
513         
514 /** 5. GetHold2 : get the second bucky bit */
515 char SCA_KeyboardSensor::GetHold2_doc[] = 
516 "getHold2()\n"
517 "\tReturn the code of the second key modifier to the key this \n"
518 "\tsensor is listening to.\n" ;
519 PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds)
520 {
521         return PyInt_FromLong(m_qual2);
522 }
523
524 /** 6. SetHold2: change the second bucky bit */
525 char SCA_KeyboardSensor::SetHold2_doc[] = 
526 "setHold2(keycode)\n"
527 "\t- keycode: any code from GameKeys\n"
528 "\tSet the first modifier to the key this sensor should listen to.\n" ;
529 PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds)
530 {
531         int keyCode;
532
533         if(!PyArg_ParseTuple(args, "i", &keyCode)) {
534                 return NULL;
535         }
536         
537         /* Since we have symbolic constants for this in Python, we don't guard   */
538         /* anything. It's up to the user to provide a sensible number.           */
539         m_qual2 = keyCode;
540
541         Py_Return;
542 }
543
544         
545 char SCA_KeyboardSensor::GetPressedKeys_doc[] = 
546 "getPressedKeys()\n"
547 "\tGet a list of pressed keys that have either been pressed, or just released this frame.\n" ;
548
549 PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
550 {
551         SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
552
553         int num = inputdev->GetNumJustEvents();
554         PyObject* resultlist = PyList_New(num);
555
556         if (num > 0)
557         {
558                 
559                 int index = 0;
560                 
561                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
562                 {
563                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
564                         if ((inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
565                                 || (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED))
566                         {
567                                 if (index < num)
568                                 {
569                                         PyObject* keypair = PyList_New(2);
570                                         PyList_SetItem(keypair,0,PyInt_FromLong(i));
571                                         PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
572                                         PyList_SetItem(resultlist,index,keypair);
573                                         index++;
574                                 }
575                         }
576                 }       
577                 if (index>0) return resultlist;
578         }
579         
580         Py_Return;
581 }
582
583
584
585 char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] = 
586 "getCurrentlyPressedKeys()\n"
587 "\tGet a list of keys that are currently pressed.\n" ;
588
589 PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
590 {
591 SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
592
593         int num = inputdev->GetNumActiveEvents();
594         PyObject* resultlist = PyList_New(num);
595
596         if (num > 0)
597         {
598                 int index = 0;
599                 
600                 for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
601                 {
602                         const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
603                         if ( (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
604                                  || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED))
605                         {
606                                 if (index < num)
607                                 {
608                                         PyObject* keypair = PyList_New(2);
609                                         PyList_SetItem(keypair,0,PyInt_FromLong(i));
610                                         PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
611                                         PyList_SetItem(resultlist,index,keypair);
612                                         index++;
613                                 }
614                         }
615                 }
616
617                 /* why?*/
618                 if (index > 0) return resultlist;
619         }
620
621         Py_Return;
622 }
623
624 /* ------------------------------------------------------------------------- */
625 /* Python functions : integration hooks                                      */
626 /* ------------------------------------------------------------------------- */
627
628 PyTypeObject SCA_KeyboardSensor::Type = {
629         PyObject_HEAD_INIT(&PyType_Type)
630         0,
631         "SCA_KeyboardSensor",
632         sizeof(SCA_KeyboardSensor),
633         0,
634         PyDestructor,
635         0,
636         __getattr,
637         __setattr,
638         0, //&MyPyCompare,
639         __repr,
640         0, //&cvalue_as_number,
641         0,
642         0,
643         0,
644         0
645 };
646
647 PyParentObject SCA_KeyboardSensor::Parents[] = {
648         &SCA_KeyboardSensor::Type,
649         &SCA_ISensor::Type,
650         &SCA_ILogicBrick::Type,
651         &CValue::Type,
652         NULL
653 };
654
655 PyMethodDef SCA_KeyboardSensor::Methods[] = {
656   {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, GetKey_doc},
657   {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, SetKey_doc},
658   {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, GetHold1_doc},
659   {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, SetHold1_doc},
660   {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, GetHold2_doc},
661   {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, SetHold2_doc},
662 //  {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, GetUseAllKeys_doc},
663 //  {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, SetUseAllKeys_doc},
664   {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, GetPressedKeys_doc},
665   {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, GetCurrentlyPressedKeys_doc},
666 //  {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, GetKeyEvents_doc},
667   {NULL,NULL} //Sentinel
668 };
669
670 PyObject*
671 SCA_KeyboardSensor::_getattr(char* attr)
672 {
673   _getattr_up(SCA_ISensor);
674 }
675