Name attributes added since 2.48a more consistently.
[blender.git] / source / gameengine / GameLogic / SCA_KeyboardSensor.cpp
index f13b1bcf4c991a0b801324ea7f54d6c87a100999..f8ee8ed8b414c23382108cedde31c8967a3d8ac1 100644 (file)
@@ -62,7 +62,7 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr,
        if (hotkey == SCA_IInputDevice::KX_ESCKEY)
                keybdmgr->GetInputDevice()->HookEscape();
 //     SetDrawColor(0xff0000ff);
-       m_val=0;
+       Init();
 }
 
 
@@ -71,14 +71,22 @@ SCA_KeyboardSensor::~SCA_KeyboardSensor()
 {
 }
 
-
+void SCA_KeyboardSensor::Init()
+{
+       // this function is used when the sensor is disconnected from all controllers
+       // by the state engine. It reinitializes the sensor as if it was just created.
+       // However, if the target key is pressed when the sensor is reactivated, it
+       // will not generated an event (see remark in Evaluate()).
+       m_val = (m_invert)?1:0;
+       m_reset = true;
+}
 
 CValue* SCA_KeyboardSensor::GetReplica()
 {
-       CValue* replica = new SCA_KeyboardSensor(*this);
+       SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this);
        // this will copy properties and so on...
-       CValue::AddDataToReplica(replica);
-
+       replica->ProcessReplica();
+       replica->Init();
        return replica;
 }
 
@@ -110,11 +118,15 @@ bool SCA_KeyboardSensor::TriggerOnAllKeys()
 
 
 
-bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
+bool SCA_KeyboardSensor::Evaluate()
 {
        bool result    = false;
-       SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+       bool reset     = m_reset && m_level;
+       bool qual          = true;
+       bool qual_change = false;
+       short int m_val_orig = m_val;
        
+       SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
        //      cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n";
 
        /* See if we need to do logging: togPropState exists and is
@@ -127,7 +139,7 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                LogKeystrokes();
        }
 
-
+       m_reset = false;
 
        /* Now see whether events must be bounced. */
        if (m_bAllKeys)
@@ -136,7 +148,7 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                bool justreleased = false;
                bool active = false;
 
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        switch (inevent.m_status) 
@@ -169,10 +181,10 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                                {
                                        if (m_val == 0)
                                        {
-                                               //see comment below
-                                               //m_val = 1;
-                                               //result = true;
-                                               ;
+                                               m_val = 1;
+                                               if (m_level) {
+                                                       result = true;
+                                               }
                                        }
                                } else
                                {
@@ -183,6 +195,9 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                                        }
                                }
                        }
+                       if (m_tap)
+                               // special case for tap mode: only generate event for new activation
+                               result = false;
                }
 
 
@@ -194,7 +209,43 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                        (SCA_IInputDevice::KX_EnumInputs) m_hotkey);
        
        //              cerr << "======= SCA_KeyboardSensor::Evaluate:: status: " << inevent.m_status << endl;
-
+               
+               
+               /* Check qualifier keys
+                * - see if the qualifiers we request are pressed - 'qual' true/false
+                * - see if the qualifiers we request changed their state - 'qual_change' true/false
+                */
+               if (m_qual > 0) {
+                       const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual);
+                       switch(qualevent.m_status) {
+                       case SCA_InputEvent::KX_NO_INPUTSTATUS:
+                               qual = false;
+                               break;
+                       case SCA_InputEvent::KX_JUSTRELEASED:
+                               qual_change = true;
+                               qual = false;
+                               break;
+                       case SCA_InputEvent::KX_JUSTACTIVATED:
+                               qual_change = true;
+                       }
+               }
+               if (m_qual2 > 0 && qual==true) {
+                       const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual2);
+                       /* copy of above */
+                       switch(qualevent.m_status) {
+                       case SCA_InputEvent::KX_NO_INPUTSTATUS:
+                               qual = false;
+                               break;
+                       case SCA_InputEvent::KX_JUSTRELEASED:
+                               qual_change = true;
+                               qual = false;
+                               break;
+                       case SCA_InputEvent::KX_JUSTACTIVATED:
+                               qual_change = true;
+                       }
+               }
+               /* done reading qualifiers */
+               
                if (inevent.m_status == SCA_InputEvent::KX_NO_INPUTSTATUS)
                {
                        if (m_val == 1)
@@ -222,22 +273,46 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                                        {
                                                if (m_val == 0)
                                                {
-                                                       //hmm, this abnormal situation may occur in the following cases:
-                                                       //- the key was pressed while the scene was suspended
-                                                       //- this is a new scene and the key is active from the start
-                                                       //In the second case, it's dangerous to activate the sensor
-                                                       //(think of a key to go to next scene)
-                                                       //What we really need is a edge/level flag in the key sensor
-                                                       //m_val = 1;
-                                                       //result = true;
-                                                       ;
+                                                       m_val = 1;
+                                                       if (m_level) 
+                                                       {
+                                                               result = true;
+                                                       }
                                                }
                                        }
                                }
                        }
                }
+               
+               /* Modify the key state based on qual(s)
+                * Tested carefuly. dont touch unless your really sure.
+                * note, this will only change the results if key modifiers are set.
+                *
+                * When all modifiers and keys are positive
+                *  - pulse true
+                * 
+                * When ANY of the modifiers or main key become inactive,
+                *  - pulse false
+                */
+               if (qual==false) { /* one of the qualifiers are not pressed */
+                       if (m_val_orig && qual_change) { /* we were originally enabled, but a qualifier changed */
+                               result = true;
+                       } else {
+                               result = false;
+                       }
+                       m_val = 0; /* since one of the qualifiers is not on, set the state to false */
+               } else {                                                /* we done have any qualifiers or they are all pressed */
+                       if (m_val && qual_change) {     /* the main key state is true and our qualifier just changed */
+                               result = true;
+                       }
+               }
+               /* done with key quals */
+               
        }
-
+       
+       if (reset)
+               // force an event
+               result = true;
        return result;
 
 }
@@ -280,148 +355,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
        }
        
 }
-
-/**
- * Determine whether this character can be printed. We cannot use
- * the library functions here, because we need to test our own
- * keycodes. */
-bool SCA_KeyboardSensor::IsPrintable(int keyIndex)
-{
-       /* only print 
-        * - numerals: KX_ZEROKEY to KX_NINEKEY
-        * - alphas:   KX_AKEY to KX_ZKEY. 
-        * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
-        *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
-        *             KX_PAD2 to KX_PADPLUSKEY
-        * - delete and backspace: also printable in the sense that they modify 
-        *                         the string
-        * - retkey: should this be printable?
-        * - virgule: prints a space... don't know which key that's supposed
-        *   to be...
-        */
-       if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
-                 && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
-                || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
-                        && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
-                || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
-/*                      || (keyIndex == KX_RETKEY)  */
-                || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
-                || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
-                || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
-                        && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
-                || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
-                        && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
-                || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
-                        && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
-                || (keyIndex == SCA_IInputDevice::KX_DELKEY)
-                || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)                              
-               )
-       {
-               return true;
-       } else {
-               return false;
-       }
-}
-
-// this code looks ugly, please use an ordinary hashtable
-
-char SCA_KeyboardSensor::ToCharacter(int keyIndex, bool shifted)
-{
-       /* numerals */
-       if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
-                && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
-               if (shifted) {
-                       char numshift[] = ")!@#$%^&*(";
-                       return numshift[keyIndex - '0']; 
-               } else {
-                       return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
-               }
-       }
-       
-       /* letters... always lowercase... is that desirable? */
-       if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
-                && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
-               if (shifted) {
-                       return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
-               } else {
-                       return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
-               }
-       }
-       
-       if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
-               return ' ';
-       }
-       
-/*                      || (keyIndex == SCA_IInputDevice::KX_RETKEY)  */
-       
-       if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
-               return '*';
-       }
-       
-       if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
-               return '\t';
-       }
-       
-       /* comma to period */
-       char commatoperiod[] = ",-.";
-       char commatoperiodshifted[] = "<_>";
-       if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
-               if (shifted) {
-                       return commatoperiodshifted[0];
-               } else {
-                       return commatoperiod[0];
-               }
-       }
-       if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
-               if (shifted) {
-                       return commatoperiodshifted[1];
-               } else {
-                       return commatoperiod[1];
-               }
-       }
-       if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
-               if (shifted) {
-                       return commatoperiodshifted[2];
-               } else {
-                       return commatoperiod[2];
-               }
-       }
-       
-       /* semicolon to rightbracket */
-       char semicolontorightbracket[] = ";\'` /\\=[]";
-       char semicolontorightbracketshifted[] = ":\"~ \?|+{}";
-       if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
-               && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
-               if (shifted) {
-                       return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
-               } else {
-                       return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
-               }
-       }
-       
-       /* keypad2 to padplus */
-       char pad2topadplus[] = "246813579. 0- +";
-       if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
-               && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
-               return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
-       }
-
-       return '!';
-}
        
-/**
- * Tests whether this is a delete key.
- */    
-bool SCA_KeyboardSensor::IsDelete(int keyIndex)
-{
-       if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
-                || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * Tests whether shift is pressed
  */    
@@ -456,7 +390,7 @@ void SCA_KeyboardSensor::LogKeystrokes(void)
                int index = 0;
                /* Check on all keys whether they were pushed. This does not
          * untangle the ordering, so don't type too fast :) */
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
@@ -473,55 +407,31 @@ void SCA_KeyboardSensor::LogKeystrokes(void)
 
 
 /* ------------------------------------------------------------------------- */
-/* Python functions : specific                                               */
+/* Python Functions                                                   */
 /* ------------------------------------------------------------------------- */
 
-
-PyObject* SCA_KeyboardSensor::PySetAllMode(PyObject* self, 
-                              PyObject* args, 
-                              PyObject* kwds)
-{
-       bool allkeys;
-
-       if (!PyArg_ParseTuple(args, "i", &allkeys))
-       {
-         return NULL;
-       }
-       
-       m_bAllKeys = allkeys;
-       Py_Return
-}
-
-
-
-PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, 
-                                      PyObject* args, 
-                                      PyObject* kwds)
-{
-//     printf("sPyIsPositive\n");
-    return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
-}
-
-
+//Deprecated ----->
 /** 1. GetKey : check which key this sensor looks at */
-char SCA_KeyboardSensor::GetKey_doc[] = 
+const char SCA_KeyboardSensor::GetKey_doc[] = 
 "getKey()\n"
 "\tReturn the code of the key this sensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetKey()
 {
+       ShowDeprecationWarning("getKey()", "the key property");
        return PyInt_FromLong(m_hotkey);
 }
 
 /** 2. SetKey: change the key to look at */
-char SCA_KeyboardSensor::SetKey_doc[] = 
+const char SCA_KeyboardSensor::SetKey_doc[] = 
 "setKey(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetKey(PyObject* args)
 {
+       ShowDeprecationWarning("setKey()", "the key property");
        int keyCode;
        
-       if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+       if(!PyArg_ParseTuple(args, "i:setKey", &keyCode)) {
                return NULL;
        }
 
@@ -529,29 +439,31 @@ PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject*
        /* anything. It's up to the user to provide a sensible number.           */
        m_hotkey = keyCode;
 
-       Py_Return;
+       Py_RETURN_NONE;
 }
 
 /** 3. GetHold1 : set the first bucky bit */
-char SCA_KeyboardSensor::GetHold1_doc[] = 
+const char SCA_KeyboardSensor::GetHold1_doc[] = 
 "getHold1()\n"
 "\tReturn the code of the first key modifier to the key this \n"
 "\tsensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetHold1()
 {
+       ShowDeprecationWarning("getHold1()", "the hold1 property");
        return PyInt_FromLong(m_qual);
 }
 
 /** 4. SetHold1: change the first bucky bit */
-char SCA_KeyboardSensor::SetHold1_doc[] = 
+const char SCA_KeyboardSensor::SetHold1_doc[] = 
 "setHold1(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the first modifier to the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* args)
 {
+       ShowDeprecationWarning("setHold1()", "the hold1 property");
        int keyCode;
 
-       if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+       if(!PyArg_ParseTuple(args, "i:setHold1", &keyCode)) {
                return NULL;
        }
        
@@ -559,29 +471,31 @@ PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObjec
        /* anything. It's up to the user to provide a sensible number.           */
        m_qual = keyCode;
 
-       Py_Return;
+       Py_RETURN_NONE;
 }
        
 /** 5. GetHold2 : get the second bucky bit */
-char SCA_KeyboardSensor::GetHold2_doc[] = 
+const char SCA_KeyboardSensor::GetHold2_doc[] = 
 "getHold2()\n"
 "\tReturn the code of the second key modifier to the key this \n"
 "\tsensor is listening to.\n" ;
-PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetHold2()
 {
+       ShowDeprecationWarning("getHold2()", "the hold2 property");
        return PyInt_FromLong(m_qual2);
 }
 
 /** 6. SetHold2: change the second bucky bit */
-char SCA_KeyboardSensor::SetHold2_doc[] = 
+const char SCA_KeyboardSensor::SetHold2_doc[] = 
 "setHold2(keycode)\n"
 "\t- keycode: any code from GameKeys\n"
 "\tSet the first modifier to the key this sensor should listen to.\n" ;
-PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* args)
 {
+       ShowDeprecationWarning("setHold2()", "the hold2 property");
        int keyCode;
 
-       if(!PyArg_ParseTuple(args, "i", &keyCode)) {
+       if(!PyArg_ParseTuple(args, "i:setHold2", &keyCode)) {
                return NULL;
        }
        
@@ -589,16 +503,18 @@ PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObjec
        /* anything. It's up to the user to provide a sensible number.           */
        m_qual2 = keyCode;
 
-       Py_Return;
+       Py_RETURN_NONE;
 }
 
        
-char SCA_KeyboardSensor::GetPressedKeys_doc[] = 
+const char SCA_KeyboardSensor::GetPressedKeys_doc[] = 
 "getPressedKeys()\n"
 "\tGet a list of pressed keys that have either been pressed, or just released this frame.\n" ;
 
-PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetPressedKeys()
 {
+       ShowDeprecationWarning("getPressedKeys()", "events");
+
        SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
 
        int num = inputdev->GetNumJustEvents();
@@ -609,37 +525,38 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P
                
                int index = 0;
                
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if ((inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
                                || (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED))
                        {
-                               if (index < num)
-                               {
-                                       PyObject* keypair = PyList_New(2);
-                                       PyList_SetItem(keypair,0,PyInt_FromLong(i));
-                                       PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
-                                       PyList_SetItem(resultlist,index,keypair);
-                                       index++;
-                               }
+                               PyObject* keypair = PyList_New(2);
+                               PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+                               PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+                               PyList_SET_ITEM(resultlist,index,keypair);
+                               index++;
+                               
+                               if (index >= num) /* should not happen */
+                                       break; 
                        }
-               }       
-               if (index>0) return resultlist;
+               }
        }
        
-       Py_Return;
+       return resultlist;
 }
 
 
 
-char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] = 
+const char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] = 
 "getCurrentlyPressedKeys()\n"
 "\tGet a list of keys that are currently pressed.\n" ;
 
-PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys()
 {
-SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+       ShowDeprecationWarning("getCurrentlyPressedKeys()", "events");
+
+       SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
 
        int num = inputdev->GetNumActiveEvents();
        PyObject* resultlist = PyList_New(num);
@@ -648,51 +565,77 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
        {
                int index = 0;
                
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if ( (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
                                 || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED))
                        {
-                               if (index < num)
-                               {
-                                       PyObject* keypair = PyList_New(2);
-                                       PyList_SetItem(keypair,0,PyInt_FromLong(i));
-                                       PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status));
-                                       PyList_SetItem(resultlist,index,keypair);
-                                       index++;
-                               }
+                               PyObject* keypair = PyList_New(2);
+                               PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+                               PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+                               PyList_SET_ITEM(resultlist,index,keypair);
+                               index++;
+                               
+                               if (index >= num) /* should never happen */
+                                       break;
                        }
                }
-
-               /* why?*/
-               if (index > 0) return resultlist;
        }
 
-       Py_Return;
+       return resultlist;
+}
+
+//<---- Deprecated
+
+KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus,
+"getKeyStatus(keycode)\n"
+"\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n")
+{
+       if (!PyInt_Check(value)) {
+               PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int");
+               return NULL;
+       }
+       
+       int keycode = PyInt_AsLong(value);
+       
+       if ((keycode < SCA_IInputDevice::KX_BEGINKEY)
+               || (keycode > SCA_IInputDevice::KX_ENDKEY)){
+               PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!");
+               return NULL;
+       }
+       
+       SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
+       const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode);
+       return PyInt_FromLong(inevent.m_status);
 }
 
 /* ------------------------------------------------------------------------- */
-/* Python functions : integration hooks                                      */
+/* Python Integration Hooks                                           */
 /* ------------------------------------------------------------------------- */
 
 PyTypeObject SCA_KeyboardSensor::Type = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,
+#if (PY_VERSION_HEX >= 0x02060000)
+       PyVarObject_HEAD_INIT(NULL, 0)
+#else
+       /* python 2.5 and below */
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+#endif
        "SCA_KeyboardSensor",
-       sizeof(SCA_KeyboardSensor),
+       sizeof(PyObjectPlus_Proxy),
        0,
-       PyDestructor,
+       py_base_dealloc,
        0,
-       __getattr,
-       __setattr,
-       0, //&MyPyCompare,
-       __repr,
-       0, //&cvalue_as_number,
        0,
        0,
        0,
-       0
+       py_base_repr,
+       0,0,0,0,0,0,
+       py_base_getattro,
+       py_base_setattro,
+       0,0,0,0,0,0,0,0,0,
+       Methods
 };
 
 PyParentObject SCA_KeyboardSensor::Parents[] = {
@@ -704,23 +647,213 @@ PyParentObject SCA_KeyboardSensor::Parents[] = {
 };
 
 PyMethodDef SCA_KeyboardSensor::Methods[] = {
-  {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, GetKey_doc},
-  {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, SetKey_doc},
-  {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, GetHold1_doc},
-  {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, SetHold1_doc},
-  {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, GetHold2_doc},
-  {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, SetHold2_doc},
-//  {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, GetUseAllKeys_doc},
-//  {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, SetUseAllKeys_doc},
-  {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, GetPressedKeys_doc},
-  {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, GetCurrentlyPressedKeys_doc},
-//  {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, GetKeyEvents_doc},
-  {NULL,NULL} //Sentinel
+       //Deprecated functions ------>
+       {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_NOARGS, (PY_METHODCHAR)GetKey_doc},
+       {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc},
+       {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_NOARGS, (PY_METHODCHAR)GetHold1_doc},
+       {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc},
+       {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_NOARGS, (PY_METHODCHAR)GetHold2_doc},
+       {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc},
+       {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_NOARGS, (PY_METHODCHAR)GetPressedKeys_doc},
+       {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_NOARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc},
+       //<----- Deprecated
+       KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus),
+       {NULL,NULL} //Sentinel
 };
 
-PyObject*
-SCA_KeyboardSensor::_getattr(const STR_String& attr)
+PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
+       KX_PYATTRIBUTE_RO_FUNCTION("events", SCA_KeyboardSensor, pyattr_get_events),
+       KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys),
+       KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey),
+       KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual),
+       KX_PYATTRIBUTE_SHORT_RW("hold2",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual2),
+       KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,false,SCA_KeyboardSensor,m_toggleprop),
+       KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,false,SCA_KeyboardSensor,m_targetprop),
+       { NULL }        //Sentinel
+};
+
+PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr)
+{
+  py_getattro_up(SCA_ISensor);
+}
+
+PyObject* SCA_KeyboardSensor::py_getattro_dict() {
+       py_getattro_dict_up(SCA_ISensor);
+}
+
+int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value)
 {
-  _getattr_up(SCA_ISensor);
+       py_setattro_up(SCA_ISensor);
 }
 
+
+PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       SCA_KeyboardSensor* self= static_cast<SCA_KeyboardSensor*>(self_v);
+       
+       SCA_IInputDevice* inputdev = self->m_pKeyboardMgr->GetInputDevice();
+
+       PyObject* resultlist = PyList_New(0);
+       
+       for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
+       {
+               const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
+               if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
+               {
+                       PyObject* keypair = PyList_New(2);
+                       PyList_SET_ITEM(keypair,0,PyInt_FromLong(i));
+                       PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status));
+                       PyList_Append(resultlist,keypair);
+               }
+       }       
+       return resultlist;
+}
+
+
+/* Accessed from python */
+
+// this code looks ugly, please use an ordinary hashtable
+
+char ToCharacter(int keyIndex, bool shifted)
+{
+       /* numerals */
+       if ( (keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
+                && (keyIndex <= SCA_IInputDevice::KX_NINEKEY) ) {
+               if (shifted) {
+                       char numshift[] = ")!@#$%^&*(";
+                       return numshift[keyIndex - '0']; 
+               } else {
+                       return keyIndex - SCA_IInputDevice::KX_ZEROKEY + '0'; 
+               }
+       }
+       
+       /* letters... always lowercase... is that desirable? */
+       if ( (keyIndex >= SCA_IInputDevice::KX_AKEY) 
+                && (keyIndex <= SCA_IInputDevice::KX_ZKEY) ) {
+               if (shifted) {
+                       return keyIndex - SCA_IInputDevice::KX_AKEY + 'A'; 
+               } else {
+                       return keyIndex - SCA_IInputDevice::KX_AKEY + 'a'; 
+               }
+       }
+       
+       if (keyIndex == SCA_IInputDevice::KX_SPACEKEY) {
+               return ' ';
+       }
+       if (keyIndex == SCA_IInputDevice::KX_RETKEY || keyIndex == SCA_IInputDevice::KX_PADENTER) {
+               return '\n';
+       }
+       
+       
+       if (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) {
+               return '*';
+       }
+       
+       if (keyIndex == SCA_IInputDevice::KX_TABKEY) {
+               return '\t';
+       }
+       
+       /* comma to period */
+       char commatoperiod[] = ",-.";
+       char commatoperiodshifted[] = "<_>";
+       if (keyIndex == SCA_IInputDevice::KX_COMMAKEY) {
+               if (shifted) {
+                       return commatoperiodshifted[0];
+               } else {
+                       return commatoperiod[0];
+               }
+       }
+       if (keyIndex == SCA_IInputDevice::KX_MINUSKEY) {
+               if (shifted) {
+                       return commatoperiodshifted[1];
+               } else {
+                       return commatoperiod[1];
+               }
+       }
+       if (keyIndex == SCA_IInputDevice::KX_PERIODKEY) {
+               if (shifted) {
+                       return commatoperiodshifted[2];
+               } else {
+                       return commatoperiod[2];
+               }
+       }
+       
+       /* semicolon to rightbracket */
+       char semicolontorightbracket[] = ";\'`/\\=[]";
+       char semicolontorightbracketshifted[] = ":\"~\?|+{}";
+       if ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
+               && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) {
+               if (shifted) {
+                       return semicolontorightbracketshifted[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+               } else {
+                       return semicolontorightbracket[keyIndex - SCA_IInputDevice::KX_SEMICOLONKEY];
+               }
+       }
+       
+       /* keypad2 to padplus */
+       char pad2topadplus[] = "246813579. 0- +";
+       if ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
+               && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) { 
+               return pad2topadplus[keyIndex - SCA_IInputDevice::KX_PAD2];
+       }
+
+       return '!';
+}
+
+
+
+/**
+ * Determine whether this character can be printed. We cannot use
+ * the library functions here, because we need to test our own
+ * keycodes. */
+bool IsPrintable(int keyIndex)
+{
+       /* only print 
+        * - numerals: KX_ZEROKEY to KX_NINEKEY
+        * - alphas:   KX_AKEY to KX_ZKEY. 
+        * - specials: KX_RETKEY, KX_PADASTERKEY, KX_PADCOMMAKEY to KX_PERIODKEY,
+        *             KX_TABKEY , KX_SEMICOLONKEY to KX_RIGHTBRACKETKEY, 
+        *             KX_PAD2 to KX_PADPLUSKEY
+        * - delete and backspace: also printable in the sense that they modify 
+        *                         the string
+        * - retkey: should this be printable?
+        * - virgule: prints a space... don't know which key that's supposed
+        *   to be...
+        */
+       if ( ((keyIndex >= SCA_IInputDevice::KX_ZEROKEY) 
+                 && (keyIndex <= SCA_IInputDevice::KX_NINEKEY))
+                || ((keyIndex >= SCA_IInputDevice::KX_AKEY) 
+                        && (keyIndex <= SCA_IInputDevice::KX_ZKEY)) 
+                || (keyIndex == SCA_IInputDevice::KX_SPACEKEY) 
+                || (keyIndex == SCA_IInputDevice::KX_RETKEY)
+                || (keyIndex == SCA_IInputDevice::KX_PADENTER)
+                || (keyIndex == SCA_IInputDevice::KX_PADASTERKEY) 
+                || (keyIndex == SCA_IInputDevice::KX_TABKEY) 
+                || ((keyIndex >= SCA_IInputDevice::KX_COMMAKEY) 
+                        && (keyIndex <= SCA_IInputDevice::KX_PERIODKEY)) 
+                || ((keyIndex >= SCA_IInputDevice::KX_SEMICOLONKEY) 
+                        && (keyIndex <= SCA_IInputDevice::KX_RIGHTBRACKETKEY)) 
+                || ((keyIndex >= SCA_IInputDevice::KX_PAD2) 
+                        && (keyIndex <= SCA_IInputDevice::KX_PADPLUSKEY)) 
+                || (keyIndex == SCA_IInputDevice::KX_DELKEY)
+                || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY)
+               )
+       {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+/**
+ * Tests whether this is a delete key.
+ */    
+bool IsDelete(int keyIndex)
+{
+       if ( (keyIndex == SCA_IInputDevice::KX_DELKEY)
+                || (keyIndex == SCA_IInputDevice::KX_BACKSPACEKEY) ) {
+               return true;
+       } else {
+               return false;
+       }
+}