|
Blender
V2.59
|
00001 /* 00002 * $Id: KX_PythonSeq.cpp 35211 2011-02-27 03:59:17Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: none of this file. 00024 * 00025 * Contributor(s): Campbell Barton 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * Readonly sequence wrapper for lookups on logic bricks 00029 */ 00030 00036 #ifdef WITH_PYTHON 00037 00038 #include "KX_PythonSeq.h" 00039 #include "KX_GameObject.h" 00040 #include "BL_ArmatureObject.h" 00041 #include "SCA_ISensor.h" 00042 #include "SCA_IController.h" 00043 #include "SCA_IActuator.h" 00044 00045 00046 PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type ) 00047 { 00048 KX_PythonSeq *seq = PyObject_GC_New(KX_PythonSeq, &KX_PythonSeq_Type); 00049 seq->base = base; 00050 Py_INCREF(base); /* so we can always access to check if its valid */ 00051 seq->type = type; 00052 seq->iter = -1; /* init */ 00053 return (PyObject *)seq; 00054 } 00055 00056 static int KX_PythonSeq_traverse(KX_PythonSeq *self, visitproc visit, void *arg) 00057 { 00058 Py_VISIT(self->base); 00059 return 0; 00060 } 00061 00062 static int KX_PythonSeq_clear(KX_PythonSeq *self) 00063 { 00064 Py_CLEAR(self->base); 00065 return 0; 00066 } 00067 00068 static void KX_PythonSeq_dealloc(KX_PythonSeq * self) 00069 { 00070 KX_PythonSeq_clear(self); 00071 PyObject_GC_Del(self); 00072 } 00073 00074 static Py_ssize_t KX_PythonSeq_len( PyObject * self ) 00075 { 00076 PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); 00077 00078 if(self_plus==NULL) { 00079 PyErr_SetString(PyExc_SystemError, "len(seq): "BGE_PROXY_ERROR_MSG); 00080 return -1; 00081 } 00082 00083 switch(((KX_PythonSeq *)self)->type) { 00084 case KX_PYGENSEQ_CONT_TYPE_SENSORS: 00085 return ((SCA_IController *)self_plus)->GetLinkedSensors().size(); 00086 case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: 00087 return ((SCA_IController *)self_plus)->GetLinkedActuators().size(); 00088 case KX_PYGENSEQ_OB_TYPE_SENSORS: 00089 return ((KX_GameObject *)self_plus)->GetSensors().size(); 00090 case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: 00091 return ((KX_GameObject *)self_plus)->GetControllers().size(); 00092 case KX_PYGENSEQ_OB_TYPE_ACTUATORS: 00093 return ((KX_GameObject *)self_plus)->GetActuators().size(); 00094 case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS: 00095 return ((BL_ArmatureObject *)self_plus)->GetConstraintNumber(); 00096 case KX_PYGENSEQ_OB_TYPE_CHANNELS: 00097 return ((BL_ArmatureObject *)self_plus)->GetChannelNumber(); 00098 default: 00099 /* Should never happen */ 00100 PyErr_SetString(PyExc_SystemError, "invalid type, internal error"); 00101 return -1; 00102 } 00103 } 00104 00105 static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) 00106 { 00107 PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); 00108 00109 if(self_plus==NULL) { 00110 PyErr_SetString(PyExc_SystemError, "val = seq[i]: "BGE_PROXY_ERROR_MSG); 00111 return NULL; 00112 } 00113 00114 switch(((KX_PythonSeq *)self)->type) { 00115 case KX_PYGENSEQ_CONT_TYPE_SENSORS: 00116 { 00117 vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); 00118 if(index<0) index += linkedsensors.size(); 00119 if(index<0 || index>= linkedsensors.size()) { 00120 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00121 return NULL; 00122 } 00123 return linkedsensors[index]->GetProxy(); 00124 } 00125 case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: 00126 { 00127 vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); 00128 if(index<0) index += linkedactuators.size(); 00129 if(index<0 || index>= linkedactuators.size()) { 00130 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00131 return NULL; 00132 } 00133 return linkedactuators[index]->GetProxy(); 00134 } 00135 case KX_PYGENSEQ_OB_TYPE_SENSORS: 00136 { 00137 SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); 00138 if(index<0) index += linkedsensors.size(); 00139 if(index<0 || index>= linkedsensors.size()) { 00140 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00141 return NULL; 00142 } 00143 return linkedsensors[index]->GetProxy(); 00144 } 00145 case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: 00146 { 00147 SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); 00148 if(index<0) index += linkedcontrollers.size(); 00149 if(index<0 || index>= linkedcontrollers.size()) { 00150 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00151 return NULL; 00152 } 00153 return linkedcontrollers[index]->GetProxy(); 00154 } 00155 case KX_PYGENSEQ_OB_TYPE_ACTUATORS: 00156 { 00157 SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); 00158 if(index<0) index += linkedactuators.size(); 00159 if(index<0 || index>= linkedactuators.size()) { 00160 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00161 return NULL; 00162 } 00163 return linkedactuators[index]->GetProxy(); 00164 } 00165 case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS: 00166 { 00167 int nb_constraint = ((BL_ArmatureObject *)self_plus)->GetConstraintNumber(); 00168 if(index<0) 00169 index += nb_constraint; 00170 if(index<0 || index>= nb_constraint) { 00171 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00172 return NULL; 00173 } 00174 return ((BL_ArmatureObject *)self_plus)->GetConstraint(index)->GetProxy(); 00175 } 00176 case KX_PYGENSEQ_OB_TYPE_CHANNELS: 00177 { 00178 int nb_channel = ((BL_ArmatureObject *)self_plus)->GetChannelNumber(); 00179 if(index<0) 00180 index += nb_channel; 00181 if(index<0 || index>= nb_channel) { 00182 PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); 00183 return NULL; 00184 } 00185 return ((BL_ArmatureObject *)self_plus)->GetChannel(index)->GetProxy(); 00186 } 00187 00188 } 00189 00190 PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug"); 00191 return NULL; 00192 } 00193 00194 static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, char *key) 00195 { 00196 PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); 00197 00198 switch(((KX_PythonSeq *)self)->type) { 00199 case KX_PYGENSEQ_CONT_TYPE_SENSORS: 00200 { 00201 vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); 00202 SCA_ISensor* sensor; 00203 for (unsigned int index=0;index<linkedsensors.size();index++) { 00204 sensor = linkedsensors[index]; 00205 if (sensor->GetName() == key) 00206 return static_cast<PyObjectPlus *>(sensor); 00207 00208 } 00209 break; 00210 } 00211 case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: 00212 { 00213 vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); 00214 SCA_IActuator* actuator; 00215 for (unsigned int index=0;index<linkedactuators.size();index++) { 00216 actuator = linkedactuators[index]; 00217 if (actuator->GetName() == key) 00218 return static_cast<PyObjectPlus *>(actuator); 00219 } 00220 break; 00221 } 00222 case KX_PYGENSEQ_OB_TYPE_SENSORS: 00223 { 00224 SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); 00225 SCA_ISensor *sensor; 00226 for (unsigned int index=0;index<linkedsensors.size();index++) { 00227 sensor= linkedsensors[index]; 00228 if (sensor->GetName() == key) 00229 return static_cast<PyObjectPlus *>(sensor); 00230 } 00231 break; 00232 } 00233 case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: 00234 { 00235 SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); 00236 SCA_IController *controller; 00237 for (unsigned int index=0;index<linkedcontrollers.size();index++) { 00238 controller= linkedcontrollers[index]; 00239 if (controller->GetName() == key) 00240 return static_cast<PyObjectPlus *>(controller); 00241 } 00242 break; 00243 } 00244 case KX_PYGENSEQ_OB_TYPE_ACTUATORS: 00245 { 00246 SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); 00247 SCA_IActuator *actuator; 00248 for (unsigned int index=0;index<linkedactuators.size();index++) { 00249 actuator= linkedactuators[index]; 00250 if (actuator->GetName() == key) 00251 return static_cast<PyObjectPlus *>(actuator); 00252 } 00253 break; 00254 } 00255 case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS: 00256 { 00257 return ((BL_ArmatureObject*)self_plus)->GetConstraint(key); 00258 } 00259 case KX_PYGENSEQ_OB_TYPE_CHANNELS: 00260 { 00261 return ((BL_ArmatureObject*)self_plus)->GetChannel(key); 00262 } 00263 } 00264 00265 return NULL; 00266 } 00267 00268 00269 static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) 00270 { 00271 PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); 00272 00273 if(self_plus==NULL) { 00274 PyErr_SetString(PyExc_SystemError, "val = seq[key], KX_PythonSeq: "BGE_PROXY_ERROR_MSG); 00275 return NULL; 00276 } 00277 00278 if (PyLong_Check(key)) { 00279 return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key )); 00280 } 00281 else if ( PyUnicode_Check(key) ) { 00282 char *name = _PyUnicode_AsString(key); 00283 PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name); 00284 00285 if(ret) { 00286 return ret->GetProxy(); 00287 } else { 00288 PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name); 00289 return NULL; 00290 } 00291 } 00292 else { 00293 PyErr_SetString( PyExc_TypeError, "expected a string or an index" ); 00294 return NULL; 00295 } 00296 } 00297 00298 00299 static int KX_PythonSeq_contains(PyObject *self, PyObject *key) 00300 { 00301 PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); 00302 00303 if(self_plus==NULL) { 00304 PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG); 00305 return -1; 00306 } 00307 if(!PyUnicode_Check(key)) { 00308 PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string"); 00309 return -1; 00310 } 00311 00312 if(KX_PythonSeq_subscript__internal(self, _PyUnicode_AsString(key))) 00313 return 1; 00314 00315 return 0; 00316 } 00317 00318 /* Matches python dict.get(key, [default]) */ 00319 PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args) 00320 { 00321 char *key; 00322 PyObject* def = Py_None; 00323 PyObjectPlus* ret_plus; 00324 00325 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) 00326 return NULL; 00327 00328 if((ret_plus = KX_PythonSeq_subscript__internal(self, key))) 00329 return ret_plus->GetProxy(); 00330 00331 Py_INCREF(def); 00332 return def; 00333 } 00334 00335 PySequenceMethods KX_PythonSeq_as_sequence = { 00336 NULL, /* Cant set the len otherwise it can evaluate as false */ 00337 NULL, /* sq_concat */ 00338 NULL, /* sq_repeat */ 00339 NULL, /* sq_item */ 00340 NULL, /* sq_slice */ 00341 NULL, /* sq_ass_item */ 00342 NULL, /* sq_ass_slice */ 00343 (objobjproc)KX_PythonSeq_contains, /* sq_contains */ 00344 (binaryfunc) NULL, /* sq_inplace_concat */ 00345 (ssizeargfunc) NULL, /* sq_inplace_repeat */ 00346 }; 00347 00348 static PyMappingMethods KX_PythonSeq_as_mapping = { 00349 KX_PythonSeq_len, /* mp_length */ 00350 KX_PythonSeq_subscript, /* mp_subscript */ 00351 0, /* mp_ass_subscript */ 00352 }; 00353 00354 PyMethodDef KX_PythonSeq_methods[] = { 00355 // dict style access for props 00356 {"get",(PyCFunction) KX_PythonSeq_get, METH_VARARGS}, 00357 {NULL,NULL} //Sentinel 00358 }; 00359 00360 /* 00361 * Initialize the interator index 00362 */ 00363 00364 static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self) 00365 { 00366 if(BGE_PROXY_REF(self->base)==NULL) { 00367 PyErr_SetString(PyExc_SystemError, "for i in seq: "BGE_PROXY_ERROR_MSG); 00368 return NULL; 00369 } 00370 00371 /* create a new iterator if were already using this one */ 00372 if (self->iter == -1) { 00373 self->iter = 0; 00374 Py_INCREF(self); 00375 return (PyObject *)self; 00376 } else { 00377 return KX_PythonSeq_CreatePyObject(self->base, self->type); 00378 } 00379 } 00380 00381 00382 /* 00383 * Return next KX_PythonSeq iter. 00384 */ 00385 00386 static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self) 00387 { 00388 PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter); 00389 00390 self->iter++; 00391 if( object==NULL ) { 00392 self->iter= -1; /* for reuse */ 00393 PyErr_SetString(PyExc_StopIteration, "iterator at end"); 00394 } 00395 return object; /* can be NULL for end of iterator */ 00396 } 00397 00398 00399 static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) 00400 { 00401 return ( a->type == b->type && a->base == b->base) ? 0 : -1; 00402 } 00403 00404 static PyObject *KX_PythonSeq_richcmp(PyObject *a, PyObject *b, int op) 00405 { 00406 PyObject *res; 00407 int ok= -1; /* zero is true */ 00408 00409 if(BPy_KX_PythonSeq_Check(a) && BPy_KX_PythonSeq_Check(b)) 00410 ok= KX_PythonSeq_compare((KX_PythonSeq *)a, (KX_PythonSeq *)b); 00411 00412 switch (op) { 00413 case Py_NE: 00414 ok = !ok; /* pass through */ 00415 case Py_EQ: 00416 res = ok ? Py_False : Py_True; 00417 break; 00418 00419 case Py_LT: 00420 case Py_LE: 00421 case Py_GT: 00422 case Py_GE: 00423 res = Py_NotImplemented; 00424 break; 00425 default: 00426 PyErr_BadArgument(); 00427 return NULL; 00428 } 00429 00430 Py_INCREF(res); 00431 return res; 00432 } 00433 00434 00435 /* 00436 * repr function 00437 * convert to a list and get its string value 00438 */ 00439 static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self ) 00440 { 00441 PyObject *list = PySequence_List((PyObject *)self); 00442 PyObject *repr = PyObject_Repr(list); 00443 Py_DECREF(list); 00444 return repr; 00445 } 00446 00447 00448 /*****************************************************************************/ 00449 /* Python KX_PythonSeq_Type structure definition: */ 00450 /*****************************************************************************/ 00451 PyTypeObject KX_PythonSeq_Type = { 00452 PyVarObject_HEAD_INIT(NULL, 0) 00453 /* For printing, in format "<module>.<name>" */ 00454 "KX_PythonSeq", /* char *tp_name; */ 00455 sizeof( KX_PythonSeq ), /* int tp_basicsize; */ 00456 0, /* tp_itemsize; For allocation */ 00457 00458 /* Methods to implement standard operations */ 00459 00460 ( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */ 00461 NULL, /* printfunc tp_print; */ 00462 NULL, /* getattrfunc tp_getattr; */ 00463 NULL, /* setattrfunc tp_setattr; */ 00464 NULL, /* cmpfunc tp_compare; */ 00465 ( reprfunc ) KX_PythonSeq_repr, /* reprfunc tp_repr; */ 00466 00467 /* Method suites for standard classes */ 00468 00469 NULL, /* PyNumberMethods *tp_as_number; */ 00470 &KX_PythonSeq_as_sequence, /* PySequenceMethods *tp_as_sequence; */ 00471 &KX_PythonSeq_as_mapping, /* PyMappingMethods *tp_as_mapping; */ 00472 00473 /* More standard operations (here for binary compatibility) */ 00474 00475 NULL, /* hashfunc tp_hash; */ 00476 NULL, /* ternaryfunc tp_call; */ 00477 NULL, /* reprfunc tp_str; */ 00478 NULL, /* getattrofunc tp_getattro; */ 00479 NULL, /* setattrofunc tp_setattro; */ 00480 00481 /* Functions to access object as input/output buffer */ 00482 NULL, /* PyBufferProcs *tp_as_buffer; */ 00483 00484 /*** Flags to define presence of optional/expanded features ***/ 00485 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ 00486 00487 NULL, /* char *tp_doc; Documentation string */ 00488 /*** Assigned meaning in release 2.0 ***/ 00489 /* call function for all accessible objects */ 00490 (traverseproc)KX_PythonSeq_traverse, /* traverseproc tp_traverse; */ 00491 00492 /* delete references to contained objects */ 00493 (inquiry)KX_PythonSeq_clear, /* inquiry tp_clear; */ 00494 00495 /*** Assigned meaning in release 2.1 ***/ 00496 /*** rich comparisons ***/ 00497 (richcmpfunc)KX_PythonSeq_richcmp, /* richcmpfunc tp_richcompare; */ 00498 00499 /*** weak reference enabler ***/ 00500 0, /* long tp_weaklistoffset; */ 00501 00502 /*** Added in release 2.2 ***/ 00503 /* Iterators */ 00504 ( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */ 00505 ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */ 00506 00507 /*** Attribute descriptor and subclassing stuff ***/ 00508 KX_PythonSeq_methods, /* struct PyMethodDef *tp_methods; */ 00509 NULL, /* struct PyMemberDef *tp_members; */ 00510 NULL, /* struct PyGetSetDef *tp_getset; */ 00511 NULL, /* struct _typeobject *tp_base; */ 00512 NULL, /* PyObject *tp_dict; */ 00513 NULL, /* descrgetfunc tp_descr_get; */ 00514 NULL, /* descrsetfunc tp_descr_set; */ 00515 0, /* long tp_dictoffset; */ 00516 NULL, /* initproc tp_init; */ 00517 NULL, /* allocfunc tp_alloc; */ 00518 NULL, /* newfunc tp_new; */ 00519 /* Low-level free-memory routine */ 00520 NULL, /* freefunc tp_free; */ 00521 /* For PyObject_IS_GC */ 00522 NULL, /* inquiry tp_is_gc; */ 00523 NULL, /* PyObject *tp_bases; */ 00524 /* method resolution order */ 00525 NULL, /* PyObject *tp_mro; */ 00526 NULL, /* PyObject *tp_cache; */ 00527 NULL, /* PyObject *tp_subclasses; */ 00528 NULL, /* PyObject *tp_weaklist; */ 00529 NULL 00530 }; 00531 00532 #endif // WITH_PYTHON