Blender  V2.59
SCA_PythonController.cpp
Go to the documentation of this file.
00001 /*
00002  * Execute Python scripts
00003  *
00004  * $Id: SCA_PythonController.cpp 36999 2011-05-29 11:17:25Z campbellbarton $
00005  *
00006  * ***** BEGIN GPL LICENSE BLOCK *****
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00023  * All rights reserved.
00024  *
00025  * The Original Code is: all of this file.
00026  *
00027  * Contributor(s): none yet.
00028  *
00029  * ***** END GPL LICENSE BLOCK *****
00030  */
00031 
00037 #include <stddef.h>
00038 
00039 #include "SCA_PythonController.h"
00040 #include "SCA_LogicManager.h"
00041 #include "SCA_ISensor.h"
00042 #include "SCA_IActuator.h"
00043 #include "PyObjectPlus.h"
00044 
00045 #ifdef WITH_PYTHON
00046 #include "compile.h"
00047 #include "eval.h"
00048 #endif // WITH_PYTHON
00049 
00050 #include <algorithm>
00051 
00052 
00053 // initialize static member variables
00054 SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL;
00055 
00056 
00057 SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, int mode)
00058         : SCA_IController(gameobj),
00059 #ifdef WITH_PYTHON
00060         m_bytecode(NULL),
00061         m_function(NULL),
00062 #endif
00063         m_function_argc(0),
00064         m_bModified(true),
00065         m_debug(false),
00066         m_mode(mode)
00067 #ifdef WITH_PYTHON
00068         , m_pythondictionary(NULL)
00069 #endif
00070 
00071 {
00072         
00073 }
00074 
00075 /*
00076 //debugging
00077 CValue*         SCA_PythonController::AddRef()
00078 {
00079         //printf("AddRef refcount = %i\n",GetRefCount());
00080         return CValue::AddRef();
00081 }
00082 int                     SCA_PythonController::Release()
00083 {
00084         //printf("Release refcount = %i\n",GetRefCount());
00085         return CValue::Release();
00086 }
00087 */
00088 
00089 
00090 
00091 SCA_PythonController::~SCA_PythonController()
00092 {
00093 
00094 #ifdef WITH_PYTHON
00095         //printf("released python byte script\n");
00096         
00097         Py_XDECREF(m_bytecode);
00098         Py_XDECREF(m_function);
00099         
00100         if (m_pythondictionary) {
00101                 // break any circular references in the dictionary
00102                 PyDict_Clear(m_pythondictionary);
00103                 Py_DECREF(m_pythondictionary);
00104         }
00105 #endif
00106 }
00107 
00108 
00109 
00110 CValue* SCA_PythonController::GetReplica()
00111 {
00112         SCA_PythonController* replica = new SCA_PythonController(*this);
00113 
00114 #ifdef WITH_PYTHON
00115         /* why is this needed at all??? - m_bytecode is NULL'd below so this doesnt make sense
00116          * but removing it crashes blender (with YoFrankie). so leave in for now - Campbell */
00117         Py_XINCREF(replica->m_bytecode);
00118         
00119         Py_XINCREF(replica->m_function); // this is ok since its not set to NULL
00120         replica->m_bModified = replica->m_bytecode == NULL;
00121         
00122         // The replica->m_pythondictionary is stolen - replace with a copy.
00123         if (m_pythondictionary)
00124                 replica->m_pythondictionary = PyDict_Copy(m_pythondictionary);
00125                 
00126         /*
00127         // The other option is to incref the replica->m_pythondictionary -
00128         // the replica objects can then share data.
00129         if (m_pythondictionary)
00130                 Py_INCREF(replica->m_pythondictionary);
00131         */
00132 #endif
00133         
00134         // this will copy properties and so on...
00135         replica->ProcessReplica();
00136 
00137         return replica;
00138 }
00139 
00140 
00141 
00142 void SCA_PythonController::SetScriptText(const STR_String& text)
00143 { 
00144         m_scriptText = text;
00145         m_bModified = true;
00146 }
00147 
00148 
00149 
00150 void SCA_PythonController::SetScriptName(const STR_String& name)
00151 {
00152         m_scriptName = name;
00153 }
00154 
00155 
00156 #ifdef WITH_PYTHON
00157 void SCA_PythonController::SetNamespace(PyObject*       pythondictionary)
00158 {
00159         if (m_pythondictionary)
00160         {
00161                 PyDict_Clear(m_pythondictionary);
00162                 Py_DECREF(m_pythondictionary);
00163         }
00164         m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */
00165         
00166         /* Without __file__ set the sys.argv[0] is used for the filename
00167          * which ends up with lines from the blender binary being printed in the console */
00168         PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_FromString(m_scriptName.Ptr()));
00169         
00170 }
00171 #endif
00172 
00173 int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
00174 {
00175         if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != 
00176                 m_triggeredSensors.end())
00177                 return 1;
00178         return 0;
00179 }
00180 
00181 #ifdef WITH_PYTHON
00182 
00183 /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
00184 PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self)
00185 {
00186         if(m_sCurrentController==NULL)
00187         {
00188                 PyErr_SetString(PyExc_SystemError, "bge.logic.getCurrentController(), this function is being run outside the python controllers context, or blenders internal state is corrupt.");
00189                 return NULL;
00190         }
00191         return m_sCurrentController->GetProxy();
00192 }
00193 
00194 SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
00195 {
00196         // for safety, todo: only allow for registered actuators (pointertable)
00197         // we don't want to crash gameengine/blender by python scripts
00198         std::vector<SCA_IActuator*> lacts =  m_sCurrentController->GetLinkedActuators();
00199         std::vector<SCA_IActuator*>::iterator it;
00200         
00201         if (PyUnicode_Check(value)) {
00202                 /* get the actuator from the name */
00203                 char *name= _PyUnicode_AsString(value);
00204                 for(it = lacts.begin(); it!= lacts.end(); ++it) {
00205                         if( name == (*it)->GetName() ) {
00206                                 return *it;
00207                         }
00208                 }
00209         }
00210         else if (PyObject_TypeCheck(value, &SCA_IActuator::Type)) {
00211                 PyObjectPlus *value_plus= BGE_PROXY_REF(value);
00212                 for(it = lacts.begin(); it!= lacts.end(); ++it) {
00213                         if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) {
00214                                 return *it;
00215                         }
00216                 }
00217         }
00218         
00219         /* set the exception */
00220         PyObject *value_str = PyObject_Repr(value); /* new ref */
00221         PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", _PyUnicode_AsString(value_str));
00222         Py_DECREF(value_str);
00223         
00224         return NULL;
00225 }
00226 
00227 const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
00228 
00229 PyTypeObject SCA_PythonController::Type = {
00230         PyVarObject_HEAD_INIT(NULL, 0)
00231         "SCA_PythonController",
00232         sizeof(PyObjectPlus_Proxy),
00233         0,
00234         py_base_dealloc,
00235         0,
00236         0,
00237         0,
00238         0,
00239         py_base_repr,
00240         0,0,0,0,0,0,0,0,0,
00241         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00242         0,0,0,0,0,0,0,
00243         Methods,
00244         0,
00245         0,
00246         &SCA_IController::Type,
00247         0,0,0,0,0,0,
00248         py_base_new
00249 };
00250 
00251 PyMethodDef SCA_PythonController::Methods[] = {
00252         {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O},
00253         {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O},
00254         {NULL,NULL} //Sentinel
00255 };
00256 
00257 PyAttributeDef SCA_PythonController::Attributes[] = {
00258         KX_PYATTRIBUTE_RW_FUNCTION("script", SCA_PythonController, pyattr_get_script, pyattr_set_script),
00259         KX_PYATTRIBUTE_INT_RO("mode", SCA_PythonController, m_mode),
00260         { NULL }        //Sentinel
00261 };
00262 
00263 void SCA_PythonController::ErrorPrint(const char *error_msg)
00264 {
00265         printf("%s - object '%s', controller '%s':\n", error_msg, GetParent()->GetName().Ptr(), GetName().Ptr());
00266         PyErr_Print();
00267         
00268         /* Added in 2.48a, the last_traceback can reference Objects for example, increasing
00269          * their user count. Not to mention holding references to wrapped data.
00270          * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
00271          * has already dealocated the pointer */
00272         PySys_SetObject( (char *)"last_traceback", NULL);
00273         PyErr_Clear(); /* just to be sure */
00274 }
00275 
00276 bool SCA_PythonController::Compile()
00277 {       
00278         //printf("py script modified '%s'\n", m_scriptName.Ptr());
00279         m_bModified= false;
00280         
00281         // if a script already exists, decref it before replace the pointer to a new script
00282         if (m_bytecode) {
00283                 Py_DECREF(m_bytecode);
00284                 m_bytecode=NULL;
00285         }
00286         
00287         // recompile the scripttext into bytecode
00288         m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input);
00289         
00290         if (m_bytecode) {
00291                 return true;
00292         } else {
00293                 ErrorPrint("Python error compiling script");
00294                 return false;
00295         }
00296 }
00297 
00298 bool SCA_PythonController::Import()
00299 {
00300         //printf("py module modified '%s'\n", m_scriptName.Ptr());
00301         m_bModified= false;
00302 
00303         /* incase we re-import */
00304         Py_XDECREF(m_function);
00305         m_function= NULL;
00306         
00307         STR_String mod_path_str= m_scriptText; /* just for storage, use C style string access */
00308         char *mod_path= mod_path_str.Ptr();
00309         char *function_string;
00310 
00311         function_string= strrchr(mod_path, '.');
00312 
00313         if(function_string == NULL) {
00314                 printf("Python module name formatting error in object '%s', controller '%s':\n\texpected 'SomeModule.Func', got '%s'\n", GetParent()->GetName().Ptr(), GetName().Ptr(), m_scriptText.Ptr());
00315                 return false;
00316         }
00317 
00318         *function_string= '\0';
00319         function_string++;
00320 
00321         // Import the module and print an error if it's not found
00322         PyObject *mod = PyImport_ImportModule(mod_path);
00323 
00324         if (mod == NULL) {
00325                 ErrorPrint("Python module can't be imported");
00326                 return false;
00327         }
00328 
00329         if(m_debug)
00330                 mod = PyImport_ReloadModule(mod);
00331 
00332         if (mod == NULL) {
00333                 ErrorPrint("Python module can't be reloaded");
00334                 return false;
00335         }
00336 
00337         // Get the function object
00338         m_function = PyObject_GetAttrString(mod, function_string);
00339 
00340         // DECREF the module as we don't need it anymore
00341         Py_DECREF(mod);
00342 
00343         if(m_function==NULL) {
00344                 if(PyErr_Occurred())
00345                         ErrorPrint("Python controller found the module but could not access the function");
00346                 else
00347                         printf("Python module error in object '%s', controller '%s':\n '%s' module found but function missing\n", GetParent()->GetName().Ptr(), GetName().Ptr(), m_scriptText.Ptr());
00348                 return false;
00349         }
00350         
00351         if(!PyCallable_Check(m_function)) {
00352                 Py_DECREF(m_function);
00353                 m_function = NULL;
00354                 printf("Python module function error in object '%s', controller '%s':\n '%s' not callable\n", GetParent()->GetName().Ptr(), GetName().Ptr(), m_scriptText.Ptr());
00355                 return false;
00356         }
00357         
00358         m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */
00359         if (PyFunction_Check(m_function)) {
00360                 m_function_argc= ((PyCodeObject *)PyFunction_GET_CODE(m_function))->co_argcount;
00361         }
00362         
00363         if(m_function_argc > 1) {
00364                 Py_DECREF(m_function);
00365                 m_function = NULL;
00366                 printf("Python module function in object '%s', controller '%s':\n '%s' takes %d args, should be zero or 1 controller arg\n", GetParent()->GetName().Ptr(), GetName().Ptr(), m_scriptText.Ptr(), m_function_argc);
00367                 return false;
00368         }
00369         
00370         return true;
00371 }
00372 
00373 
00374 void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
00375 {
00376         m_sCurrentController = this;
00377         m_sCurrentLogicManager = logicmgr;
00378         
00379         PyObject *excdict=              NULL;
00380         PyObject* resultobj=    NULL;
00381         
00382         switch(m_mode) {
00383         case SCA_PYEXEC_SCRIPT:
00384         {
00385                 if (m_bModified)
00386                         if (Compile()==false) // sets m_bModified to false
00387                                 return;
00388                 if (!m_bytecode)
00389                         return;
00390                 
00391                 /*
00392                  * This part here with excdict is a temporary patch
00393                  * to avoid python/gameengine crashes when python
00394                  * inadvertently holds references to game objects
00395                  * in global variables.
00396                  * 
00397                  * The idea is always make a fresh dictionary, and
00398                  * destroy it right after it is used to make sure
00399                  * python won't hold any gameobject references.
00400                  * 
00401                  * Note that the PyDict_Clear _is_ necessary before
00402                  * the Py_DECREF() because it is possible for the
00403                  * variables inside the dictionary to hold references
00404                  * to the dictionary (ie. generate a cycle), so we
00405                  * break it by hand, then DECREF (which in this case
00406                  * should always ensure excdict is cleared).
00407                  */
00408 
00409                 excdict= PyDict_Copy(m_pythondictionary);
00410 
00411                 resultobj = PyEval_EvalCode((PyObject *)m_bytecode, excdict, excdict);
00412 
00413                 /* PyRun_SimpleString(m_scriptText.Ptr()); */
00414                 break;
00415         }
00416         case SCA_PYEXEC_MODULE:
00417         {
00418                 if (m_bModified || m_debug)
00419                         if (Import()==false) // sets m_bModified to false
00420                                 return;
00421                 if (!m_function)
00422                         return;
00423                 
00424                 PyObject *args= NULL;
00425                 
00426                 if(m_function_argc==1) {
00427                         args = PyTuple_New(1);
00428                         PyTuple_SET_ITEM(args, 0, GetProxy());
00429                 }
00430                 
00431                 resultobj = PyObject_CallObject(m_function, args);
00432                 Py_XDECREF(args);
00433                 break;
00434         }
00435         
00436         } /* end switch */
00437         
00438         
00439         
00440         /* Free the return value and print the error */
00441         if (resultobj)
00442                 Py_DECREF(resultobj);
00443         else
00444                 ErrorPrint("Python script error");
00445         
00446         if(excdict) /* Only for SCA_PYEXEC_SCRIPT types */
00447         {
00448                 /* clear after PyErrPrint - seems it can be using
00449                  * something in this dictionary and crash? */
00450                 // This doesn't appear to be needed anymore
00451                 //PyDict_Clear(excdict);
00452                 Py_DECREF(excdict);
00453         }       
00454         
00455         m_triggeredSensors.clear();
00456         m_sCurrentController = NULL;
00457 }
00458 
00459 PyObject* SCA_PythonController::PyActivate(PyObject *value)
00460 {
00461         if(m_sCurrentController != this) {
00462                 PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
00463                 return NULL;
00464         }
00465         
00466         SCA_IActuator* actu = LinkedActuatorFromPy(value);
00467         if(actu==NULL)
00468                 return NULL;
00469         
00470         m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, true);
00471         Py_RETURN_NONE;
00472 }
00473 
00474 PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
00475 {
00476         if(m_sCurrentController != this) {
00477                 PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
00478                 return NULL;
00479         }
00480         
00481         SCA_IActuator* actu = LinkedActuatorFromPy(value);
00482         if(actu==NULL)
00483                 return NULL;
00484         
00485         m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, false);
00486         Py_RETURN_NONE;
00487 }
00488 
00489 PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00490 {
00491         //SCA_PythonController* self= static_cast<SCA_PythonController*>(static_cast<SCA_IController*>(static_cast<SCA_ILogicBrick*>(static_cast<CValue*>(static_cast<PyObjectPlus*>(self_v)))));
00492         // static_cast<void *>(dynamic_cast<Derived *>(obj)) - static_cast<void *>(obj)
00493 
00494         SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
00495         return PyUnicode_FromString(self->m_scriptText);
00496 }
00497 
00498 
00499 
00500 int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00501 {
00502         SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
00503         
00504         char *scriptArg = _PyUnicode_AsString(value);
00505         
00506         if (scriptArg==NULL) {
00507                 PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text");
00508                 return PY_SET_ATTR_FAIL;
00509         }
00510 
00511         /* set scripttext sets m_bModified to true, 
00512                 so next time the script is needed, a reparse into byte code is done */
00513         self->SetScriptText(scriptArg);
00514                 
00515         return PY_SET_ATTR_SUCCESS;
00516 }
00517 
00518 #else // WITH_PYTHON
00519 
00520 void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
00521 {
00522         /* intentionally blank */
00523 }
00524 
00525 #endif // WITH_PYTHON
00526 
00527 /* eof */