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