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