- Mathutils.Vector assignment wasnt working in the BGE's py api, was using getValue...
[blender.git] / source / gameengine / Ketsji / KX_PythonSeq.cpp
index 42b1850a45469bb819003b7a763104a4601c9fab..1098dc03b6293fea00ea50419ce176dcd0790f39 100644 (file)
@@ -20,7 +20,7 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
+ * The Original Code is: none of this file.
  *
  * Contributor(s): Campbell Barton
  *
@@ -52,16 +52,16 @@ PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type )
        PyObject_DEL( self );
 }
 
-static Py_ssize_t KX_PythonSeq_len( KX_PythonSeq * self )
+static Py_ssize_t KX_PythonSeq_len( PyObject * self )
 {
-       PyObjectPlus *self_plus= BGE_PROXY_REF(self->base);
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
         
        if(self_plus==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               PyErr_SetString(PyExc_SystemError, "len(seq): "BGE_PROXY_ERROR_MSG);
                return -1;
        }
        
-       switch(self->type) {
+       switch(((KX_PythonSeq *)self)->type) {
        case KX_PYGENSEQ_CONT_TYPE_SENSORS:
                return ((SCA_IController *)self_plus)->GetLinkedSensors().size();
        case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
@@ -79,16 +79,16 @@ static Py_ssize_t KX_PythonSeq_len( KX_PythonSeq * self )
        }
 }
 
-static PyObject *KX_PythonSeq_getIndex(KX_PythonSeq * self, int index)
+static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index)
 {
-       PyObjectPlus *self_plus= BGE_PROXY_REF(self->base);
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
         
        if(self_plus==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               PyErr_SetString(PyExc_SystemError, "val = seq[i]: "BGE_PROXY_ERROR_MSG);
                return NULL;
        }
        
-       switch(self->type) {
+       switch(((KX_PythonSeq *)self)->type) {
                case KX_PYGENSEQ_CONT_TYPE_SENSORS:
                {
                        vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
@@ -145,35 +145,20 @@ static PyObject *KX_PythonSeq_getIndex(KX_PythonSeq * self, int index)
        return NULL;
 }
 
-
-static PyObject * KX_PythonSeq_subscript(KX_PythonSeq * self, PyObject *key)
+static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, char *key)
 {
-       PyObjectPlus *self_plus= BGE_PROXY_REF(self->base);
-       char *name = NULL;
-       
-       if(self_plus==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
-               return NULL;
-       }
-       
-       if (PyInt_Check(key)) {
-               return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key ));
-       } else if ( PyString_Check(key) ) {
-               name = PyString_AsString( key );
-       } else {
-               PyErr_SetString( PyExc_TypeError, "expected a string or an index" );
-               return NULL;
-       }
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
        
-       switch(self->type) {
+       switch(((KX_PythonSeq *)self)->type) {
                case KX_PYGENSEQ_CONT_TYPE_SENSORS:
                {
                        vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
                        SCA_ISensor* sensor;
                        for (unsigned int index=0;index<linkedsensors.size();index++) {
                                sensor = linkedsensors[index];
-                               if (sensor->GetName() == name)
-                                       return sensor->GetProxy();
+                               if (sensor->GetName() == key)
+                                       return static_cast<PyObjectPlus *>(sensor);
+                               
                        }
                        break;
                }
@@ -183,8 +168,8 @@ static PyObject * KX_PythonSeq_subscript(KX_PythonSeq * self, PyObject *key)
                        SCA_IActuator* actuator;
                        for (unsigned int index=0;index<linkedactuators.size();index++) {
                                actuator = linkedactuators[index];
-                               if (actuator->GetName() == name)
-                                       return actuator->GetProxy();
+                               if (actuator->GetName() == key)
+                                       return static_cast<PyObjectPlus *>(actuator);
                        }
                        break;
                }
@@ -194,8 +179,8 @@ static PyObject * KX_PythonSeq_subscript(KX_PythonSeq * self, PyObject *key)
                        SCA_ISensor *sensor;
                        for (unsigned int index=0;index<linkedsensors.size();index++) {
                                sensor= linkedsensors[index];
-                               if (sensor->GetName() == name)
-                                       return sensor->GetProxy();
+                               if (sensor->GetName() == key)
+                                       return static_cast<PyObjectPlus *>(sensor);
                        }
                        break;
                }
@@ -205,8 +190,8 @@ static PyObject * KX_PythonSeq_subscript(KX_PythonSeq * self, PyObject *key)
                        SCA_IController *controller;
                        for (unsigned int index=0;index<linkedcontrollers.size();index++) {
                                controller= linkedcontrollers[index];
-                               if (controller->GetName() == name)
-                                       return controller->GetProxy();
+                               if (controller->GetName() == key)
+                                       return static_cast<PyObjectPlus *>(controller);
                        }
                        break;
                }
@@ -216,32 +201,114 @@ static PyObject * KX_PythonSeq_subscript(KX_PythonSeq * self, PyObject *key)
                        SCA_IActuator *actuator;
                        for (unsigned int index=0;index<linkedactuators.size();index++) {
                                actuator= linkedactuators[index];
-                               if (actuator->GetName() == name)
-                                       return actuator->GetProxy();
+                               if (actuator->GetName() == key)
+                                       return static_cast<PyObjectPlus *>(actuator);
                        }
                        break;
                }
        }
        
-       PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name);
        return NULL;
 }
 
+
+static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
+{
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+       
+       if(self_plus==NULL) {
+               PyErr_SetString(PyExc_SystemError, "val = seq[key], KX_PythonSeq: "BGE_PROXY_ERROR_MSG);
+               return NULL;
+       }
+       
+       if (PyLong_Check(key)) {
+               return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key ));
+       }
+       else if ( PyUnicode_Check(key) ) {
+               char *name = _PyUnicode_AsString(key);
+               PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name);
+               
+               if(ret) {
+                       return ret->GetProxy();
+               } else {
+                       PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name);
+                       return NULL;
+               }
+       }
+       else {
+               PyErr_SetString( PyExc_TypeError, "expected a string or an index" );
+               return NULL;
+       }
+}
+
+
+static int KX_PythonSeq_contains(PyObject *self, PyObject *key)
+{
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+       
+       if(self_plus==NULL) {
+               PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG);
+               return -1;
+       }
+       if(!PyUnicode_Check(key)) {
+               PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string");
+               return -1;
+       }
+       
+       if(KX_PythonSeq_subscript__internal(self, _PyUnicode_AsString(key)))
+               return 1;
+       
+       return 0;
+}
+
+/* Matches python dict.get(key, [default]) */
+PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args)
+{
+       char *key;
+       PyObject* def = Py_None;
+       PyObjectPlus* ret_plus;
+
+       if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
+               return NULL;
+       
+       if((ret_plus = KX_PythonSeq_subscript__internal(self, key)))
+               return ret_plus->GetProxy();
+       
+       Py_INCREF(def);
+       return def;
+}
+
+PySequenceMethods KX_PythonSeq_as_sequence = {
+       NULL,           /* Cant set the len otherwise it can evaluate as false */
+       NULL,           /* sq_concat */
+       NULL,           /* sq_repeat */
+       NULL,           /* sq_item */
+       NULL,           /* sq_slice */
+       NULL,           /* sq_ass_item */
+       NULL,           /* sq_ass_slice */
+       (objobjproc)KX_PythonSeq_contains,      /* sq_contains */
+};
+
 static PyMappingMethods KX_PythonSeq_as_mapping = {
-       ( inquiry ) KX_PythonSeq_len,   /* mp_length */
-       ( binaryfunc ) KX_PythonSeq_subscript,  /* mp_subscript */
+       KX_PythonSeq_len,       /* mp_length */
+       KX_PythonSeq_subscript, /* mp_subscript */
        0,      /* mp_ass_subscript */
 };
 
+PyMethodDef KX_PythonSeq_methods[] = {
+       // dict style access for props
+       {"get",(PyCFunction) KX_PythonSeq_get, METH_VARARGS},
+       {NULL,NULL} //Sentinel
+};
 
 /*
  * Initialize the interator index
  */
 
-static PyObject *KX_PythonSeq_getIter( KX_PythonSeq * self )
+static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self)
 {
        if(BGE_PROXY_REF(self->base)==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               PyErr_SetString(PyExc_SystemError, "for i in seq: "BGE_PROXY_ERROR_MSG);
                return NULL;
        }
        
@@ -260,9 +327,9 @@ static PyObject *KX_PythonSeq_getIter( KX_PythonSeq * self )
  * Return next KX_PythonSeq iter.
  */
  
-static PyObject *KX_PythonSeq_nextIter( KX_PythonSeq * self )
+static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self)
 {
-       PyObject *object = KX_PythonSeq_getIndex(self, self->iter);
+       PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter);
        
        self->iter++;
        if( object==NULL ) {
@@ -295,13 +362,7 @@ static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self )
 /* Python KX_PythonSeq_Type structure definition:                               */
 /*****************************************************************************/
 PyTypeObject KX_PythonSeq_Type = {
-#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
        /*  For printing, in format "<module>.<name>" */
        "KX_PythonSeq",           /* char *tp_name; */
        sizeof( KX_PythonSeq ),       /* int tp_basicsize; */
@@ -313,13 +374,14 @@ PyTypeObject KX_PythonSeq_Type = {
        NULL,                       /* printfunc tp_print; */
        NULL,                       /* getattrfunc tp_getattr; */
        NULL,                       /* setattrfunc tp_setattr; */
-       ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */
+       /* TODO, richcmp */
+       NULL, /* ( cmpfunc ) KX_PythonSeq_compare, // cmpfunc tp_compare; */
        ( reprfunc ) KX_PythonSeq_repr,   /* reprfunc tp_repr; */
 
        /* Method suites for standard classes */
 
        NULL,                       /* PyNumberMethods *tp_as_number; */
-       NULL,       /* PySequenceMethods *tp_as_sequence; */
+       &KX_PythonSeq_as_sequence,          /* PySequenceMethods *tp_as_sequence; */
        &KX_PythonSeq_as_mapping,                       /* PyMappingMethods *tp_as_mapping; */
 
        /* More standard operations (here for binary compatibility) */
@@ -357,7 +419,7 @@ PyTypeObject KX_PythonSeq_Type = {
        ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */
 
   /*** Attribute descriptor and subclassing stuff ***/
-       NULL,       /* struct PyMethodDef *tp_methods; */
+       KX_PythonSeq_methods,       /* struct PyMethodDef *tp_methods; */
        NULL,                       /* struct PyMemberDef *tp_members; */
        NULL,       /* struct PyGetSetDef *tp_getset; */
        NULL,                       /* struct _typeobject *tp_base; */