remove python2.x support
[blender.git] / source / gameengine / GameLogic / SCA_PythonController.cpp
1 /**
2  * Execute Python scripts
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "SCA_PythonController.h"
33 #include "SCA_LogicManager.h"
34 #include "SCA_ISensor.h"
35 #include "SCA_IActuator.h"
36 #include "PyObjectPlus.h"
37 #include "compile.h"
38 #include "eval.h"
39 #include <algorithm>
40
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 // initialize static member variables
47 SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL;
48
49
50 SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, int mode)
51         : SCA_IController(gameobj),
52         m_bytecode(NULL),
53         m_function(NULL),
54         m_function_argc(0),
55         m_bModified(true),
56         m_debug(false),
57         m_mode(mode),
58         m_pythondictionary(NULL)
59 {
60         
61 }
62
63 /*
64 //debugging
65 CValue*         SCA_PythonController::AddRef()
66 {
67         //printf("AddRef refcount = %i\n",GetRefCount());
68         return CValue::AddRef();
69 }
70 int                     SCA_PythonController::Release()
71 {
72         //printf("Release refcount = %i\n",GetRefCount());
73         return CValue::Release();
74 }
75 */
76
77
78
79 SCA_PythonController::~SCA_PythonController()
80 {
81         //printf("released python byte script\n");
82         
83         Py_XDECREF(m_bytecode);
84         Py_XDECREF(m_function);
85         
86         if (m_pythondictionary) {
87                 // break any circular references in the dictionary
88                 PyDict_Clear(m_pythondictionary);
89                 Py_DECREF(m_pythondictionary);
90         }
91 }
92
93
94
95 CValue* SCA_PythonController::GetReplica()
96 {
97         SCA_PythonController* replica = new SCA_PythonController(*this);
98         
99         /* why is this needed at all??? - m_bytecode is NULL'd below so this doesnt make sense
100          * but removing it crashes blender (with YoFrankie). so leave in for now - Campbell */
101         Py_XINCREF(replica->m_bytecode);
102         
103         Py_XINCREF(replica->m_function); // this is ok since its not set to NULL
104         replica->m_bModified = replica->m_bytecode == NULL;
105         
106         // The replica->m_pythondictionary is stolen - replace with a copy.
107         if (m_pythondictionary)
108                 replica->m_pythondictionary = PyDict_Copy(m_pythondictionary);
109                 
110         /*
111         // The other option is to incref the replica->m_pythondictionary -
112         // the replica objects can then share data.
113         if (m_pythondictionary)
114                 Py_INCREF(replica->m_pythondictionary);
115         */
116         
117         // this will copy properties and so on...
118         replica->ProcessReplica();
119
120         return replica;
121 }
122
123
124
125 void SCA_PythonController::SetScriptText(const STR_String& text)
126
127         m_scriptText = text;
128         m_bModified = true;
129 }
130
131
132
133 void SCA_PythonController::SetScriptName(const STR_String& name)
134 {
135         m_scriptName = name;
136 }
137
138
139
140 void SCA_PythonController::SetDictionary(PyObject*      pythondictionary)
141 {
142         if (m_pythondictionary)
143         {
144                 PyDict_Clear(m_pythondictionary);
145                 Py_DECREF(m_pythondictionary);
146         }
147         m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */
148         
149         /* Without __file__ set the sys.argv[0] is used for the filename
150          * which ends up with lines from the blender binary being printed in the console */
151         PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_FromString(m_scriptName.Ptr()));
152         
153 }
154
155 int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
156 {
157         if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != 
158                 m_triggeredSensors.end())
159                 return 1;
160         return 0;
161 }
162
163 /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
164 PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self)
165 {
166         if(m_sCurrentController==NULL)
167         {
168                 PyErr_SetString(PyExc_SystemError, "GameLogic.getCurrentController(), this function is being run outside the python controllers context, or blenders internal state is corrupt.");
169                 return NULL;
170         }
171         return m_sCurrentController->GetProxy();
172 }
173
174 SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value)
175 {
176         // for safety, todo: only allow for registered actuators (pointertable)
177         // we don't want to crash gameengine/blender by python scripts
178         std::vector<SCA_IActuator*> lacts =  m_sCurrentController->GetLinkedActuators();
179         std::vector<SCA_IActuator*>::iterator it;
180         
181         if (PyUnicode_Check(value)) {
182                 /* get the actuator from the name */
183                 char *name= _PyUnicode_AsString(value);
184                 for(it = lacts.begin(); it!= lacts.end(); ++it) {
185                         if( name == (*it)->GetName() ) {
186                                 return *it;
187                         }
188                 }
189         }
190         else if (PyObject_TypeCheck(value, &SCA_IActuator::Type)) {
191                 PyObjectPlus *value_plus= BGE_PROXY_REF(value);
192                 for(it = lacts.begin(); it!= lacts.end(); ++it) {
193                         if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) {
194                                 return *it;
195                         }
196                 }
197         }
198         
199         /* set the exception */
200         PyObject *value_str = PyObject_Repr(value); /* new ref */
201         PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", _PyUnicode_AsString(value_str));
202         Py_DECREF(value_str);
203         
204         return false;
205 }
206
207 /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */
208 PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* args)
209 {
210         ShowDeprecationWarning("GameLogic.addActiveActuator(act, bool)", "controller.activate(act) or controller.deactivate(act)");
211         
212         PyObject* ob1;
213         int activate;
214         if (!PyArg_ParseTuple(args, "Oi:addActiveActuator", &ob1,&activate))
215                 return NULL;
216         
217         SCA_IActuator* actu = LinkedActuatorFromPy(ob1);
218         if(actu==NULL)
219                 return NULL;
220         
221         bool boolval = (activate!=0);
222         m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval);
223         Py_RETURN_NONE;
224 }
225
226 const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
227 const char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)";
228
229 PyTypeObject SCA_PythonController::Type = {
230         PyVarObject_HEAD_INIT(NULL, 0)
231         "SCA_PythonController",
232         sizeof(PyObjectPlus_Proxy),
233         0,
234         py_base_dealloc,
235         0,
236         0,
237         0,
238         0,
239         py_base_repr,
240         0,0,0,0,0,0,0,0,0,
241         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
242         0,0,0,0,0,0,0,
243         Methods,
244         0,
245         0,
246         &SCA_IController::Type,
247         0,0,0,0,0,0,
248         py_base_new
249 };
250
251 PyMethodDef SCA_PythonController::Methods[] = {
252         {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O},
253         {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O},
254         
255         //Deprecated functions ------>
256         {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O},
257         {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS},
258         //<----- Deprecated
259         {NULL,NULL} //Sentinel
260 };
261
262 PyAttributeDef SCA_PythonController::Attributes[] = {
263         KX_PYATTRIBUTE_RW_FUNCTION("script", SCA_PythonController, pyattr_get_script, pyattr_set_script),
264         KX_PYATTRIBUTE_INT_RO("mode", SCA_PythonController, m_mode),
265         { NULL }        //Sentinel
266 };
267
268 void SCA_PythonController::ErrorPrint(const char *error_msg)
269 {
270         // didn't compile, so instead of compile, complain
271         // something is wrong, tell the user what went wrong
272         printf("%s - controller \"%s\":\n", error_msg, GetName().Ptr());
273         //PyRun_SimpleString(m_scriptText.Ptr());
274         PyErr_Print();
275         
276         /* Added in 2.48a, the last_traceback can reference Objects for example, increasing
277          * their user count. Not to mention holding references to wrapped data.
278          * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
279          * has alredy dealocated the pointer */
280         PySys_SetObject( (char *)"last_traceback", NULL);
281         PyErr_Clear(); /* just to be sure */
282 }
283
284 bool SCA_PythonController::Compile()
285 {       
286         //printf("py script modified '%s'\n", m_scriptName.Ptr());
287         m_bModified= false;
288         
289         // if a script already exists, decref it before replace the pointer to a new script
290         if (m_bytecode) {
291                 Py_DECREF(m_bytecode);
292                 m_bytecode=NULL;
293         }
294         
295         // recompile the scripttext into bytecode
296         m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input);
297         
298         if (m_bytecode) {
299                 return true;
300         } else {
301                 ErrorPrint("Python error compiling script");
302                 return false;
303         }
304 }
305
306 bool SCA_PythonController::Import()
307 {
308         //printf("py module modified '%s'\n", m_scriptName.Ptr());
309         m_bModified= false;
310         
311         /* incase we re-import */
312         Py_XDECREF(m_function);
313         m_function= NULL;
314         
315         vector<STR_String> py_function_path = m_scriptText.Explode('.');
316         
317         if(py_function_path.size() < 2) {
318                 printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"\n", GetName().Ptr(), m_scriptText.Ptr());
319                 return false;
320         }
321         
322         PyObject *mod = PyImport_ImportModule((char *)py_function_path[0].Ptr());
323         /* Dont reload yet, do this within the loop so packages reload too */
324         
325         if(mod==NULL) {
326                 ErrorPrint("Python module not found");
327                 return false;
328         }
329         /* 'mod' will be DECREF'd as 'base' 
330          * 'm_function' will be left holding a reference that the controller owns */
331         
332         PyObject *base= mod;
333         
334         for(unsigned int i=1; i < py_function_path.size(); i++) {
335                 if(m_debug && PyModule_Check(base)) { /* base could be a class */
336                         Py_DECREF(base); /* getting a new one so dont hold a ref to the old one */
337                         base= PyImport_ReloadModule(base);
338                         if (base==NULL) {
339                                 m_function= NULL;
340                                 break;
341                         }
342                 }
343                 
344                 m_function = PyObject_GetAttrString(base, py_function_path[i].Ptr());
345                 Py_DECREF(base);
346                 base = m_function; /* for the next loop if there is on */
347                 
348                 if(m_function==NULL) {
349                         break;
350                 }
351         }
352         
353         if(m_function==NULL) {
354                 if(PyErr_Occurred())
355                         ErrorPrint("Python controller found the module but could not access the function");
356                 else
357                         printf("Python module error \"%s\":\n \"%s\" module found but function missing\n", GetName().Ptr(), m_scriptText.Ptr());
358                 return false;
359         }
360         
361         if(!PyCallable_Check(m_function)) {
362                 Py_DECREF(m_function);
363                 printf("Python module function error \"%s\":\n \"%s\" not callable\n", GetName().Ptr(), m_scriptText.Ptr());
364                 return false;
365         }
366         
367         m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */
368         if (PyFunction_Check(m_function)) {
369                 PyObject *py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(m_function), "co_argcount");
370                 if(py_arg_count) {
371                         m_function_argc = PyLong_AsLong(py_arg_count);
372                         Py_DECREF(py_arg_count);
373                 }
374                 else {
375                         PyErr_Clear(); /* unlikely to fail but just incase */
376                 }
377         }
378         
379         if(m_function_argc > 1) {
380                 Py_DECREF(m_function);
381                 printf("Python module function has \"%s\":\n \"%s\" takes %d args, should be zero or 1 controller arg\n", GetName().Ptr(), m_scriptText.Ptr(), m_function_argc);
382                 return false;
383         }
384         
385         return true;
386 }
387
388 void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
389 {
390         m_sCurrentController = this;
391         m_sCurrentLogicManager = logicmgr;
392         
393         PyObject *excdict=              NULL;
394         PyObject* resultobj=    NULL;
395         
396         switch(m_mode) {
397         case SCA_PYEXEC_SCRIPT:
398         {
399                 if (m_bModified)
400                         if (Compile()==false) // sets m_bModified to false
401                                 return;
402                 if (!m_bytecode)
403                         return;
404                 
405                 /*
406                  * This part here with excdict is a temporary patch
407                  * to avoid python/gameengine crashes when python
408                  * inadvertently holds references to game objects
409                  * in global variables.
410                  * 
411                  * The idea is always make a fresh dictionary, and
412                  * destroy it right after it is used to make sure
413                  * python won't hold any gameobject references.
414                  * 
415                  * Note that the PyDict_Clear _is_ necessary before
416                  * the Py_DECREF() because it is possible for the
417                  * variables inside the dictionary to hold references
418                  * to the dictionary (ie. generate a cycle), so we
419                  * break it by hand, then DECREF (which in this case
420                  * should always ensure excdict is cleared).
421                  */
422
423                 excdict= PyDict_Copy(m_pythondictionary);
424                 resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, excdict, excdict);
425                 /* PyRun_SimpleString(m_scriptText.Ptr()); */
426                 break;
427         }
428         case SCA_PYEXEC_MODULE:
429         {
430                 if (m_bModified || m_debug)
431                         if (Import()==false) // sets m_bModified to false
432                                 return;
433                 if (!m_function)
434                         return;
435                 
436                 PyObject *args= NULL;
437                 
438                 if(m_function_argc==1) {
439                         args = PyTuple_New(1);
440                         PyTuple_SET_ITEM(args, 0, GetProxy());
441                 }
442                 
443                 resultobj = PyObject_CallObject(m_function, args);
444                 Py_XDECREF(args);
445                 break;
446         }
447         
448         } /* end switch */
449         
450         
451         
452         /* Free the return value and print the error */
453         if (resultobj)
454         {
455                 Py_DECREF(resultobj);
456         }
457         else
458         {
459                 // something is wrong, tell the user what went wrong
460                 printf("Python script error from controller \"%s\":\n", GetName().Ptr());
461                 PyErr_Print();
462                 
463                 /* Added in 2.48a, the last_traceback can reference Objects for example, increasing
464                  * their user count. Not to mention holding references to wrapped data.
465                  * This is especially bad when the PyObject for the wrapped data is free'd, after blender 
466                  * has alredy dealocated the pointer */
467                 PySys_SetObject( (char *)"last_traceback", NULL);
468                 PyErr_Clear(); /* just to be sure */
469         }
470         
471         if(excdict) /* Only for SCA_PYEXEC_SCRIPT types */
472         {
473                 /* clear after PyErrPrint - seems it can be using
474                  * something in this dictionary and crash? */
475                 PyDict_Clear(excdict);
476                 Py_DECREF(excdict);
477         }       
478         
479         m_triggeredSensors.clear();
480         m_sCurrentController = NULL;
481 }
482
483 PyObject* SCA_PythonController::PyActivate(PyObject *value)
484 {
485         if(m_sCurrentController != this) {
486                 PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
487                 return NULL;
488         }
489         
490         SCA_IActuator* actu = LinkedActuatorFromPy(value);
491         if(actu==NULL)
492                 return NULL;
493         
494         m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, true);
495         Py_RETURN_NONE;
496 }
497
498 PyObject* SCA_PythonController::PyDeActivate(PyObject *value)
499 {
500         if(m_sCurrentController != this) {
501                 PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller");
502                 return NULL;
503         }
504         
505         SCA_IActuator* actu = LinkedActuatorFromPy(value);
506         if(actu==NULL)
507                 return NULL;
508         
509         m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, false);
510         Py_RETURN_NONE;
511 }
512
513 /* 1. getScript */
514 PyObject* SCA_PythonController::PyGetScript()
515 {
516         ShowDeprecationWarning("getScript()", "the script property");
517         return PyUnicode_FromString(m_scriptText);
518 }
519
520 /* 2. setScript */
521 PyObject* SCA_PythonController::PySetScript(PyObject* value)
522 {
523         char *scriptArg = _PyUnicode_AsString(value);
524         
525         ShowDeprecationWarning("setScript()", "the script property");
526         
527         if (scriptArg==NULL) {
528                 PyErr_SetString(PyExc_TypeError, "expected a string (script name)");
529                 return NULL;
530         }
531         
532         /* set scripttext sets m_bModified to true, 
533                 so next time the script is needed, a reparse into byte code is done */
534
535         this->SetScriptText(scriptArg);
536         
537         Py_RETURN_NONE;
538 }
539
540 PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
541 {
542         //SCA_PythonController* self= static_cast<SCA_PythonController*>(static_cast<SCA_IController*>(static_cast<SCA_ILogicBrick*>(static_cast<CValue*>(static_cast<PyObjectPlus*>(self_v)))));
543         // static_cast<void *>(dynamic_cast<Derived *>(obj)) - static_cast<void *>(obj)
544
545         SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
546         return PyUnicode_FromString(self->m_scriptText);
547 }
548
549
550
551 int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
552 {
553         SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v);
554         
555         char *scriptArg = _PyUnicode_AsString(value);
556         
557         if (scriptArg==NULL) {
558                 PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text");
559                 return PY_SET_ATTR_FAIL;
560         }
561
562         /* set scripttext sets m_bModified to true, 
563                 so next time the script is needed, a reparse into byte code is done */
564         self->SetScriptText(scriptArg);
565                 
566         return PY_SET_ATTR_SUCCESS;
567 }
568
569
570 /* eof */