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