BGE PyController module type.

- Added support for any number of attributes, this means packages are supported automatically.
 so as well as "myModule.myFunc" you can do "myPackage.myModule.myFunc", nested packages work too.
- pass the controller to the python function as an argument for functions that take 1 arg, this check is only done at startup so it wont slow things down.

added support for
This commit is contained in:
2009-05-02 15:09:06 +00:00
parent 41f42099ac
commit 40fc1d2af7
2 changed files with 50 additions and 13 deletions

View File

@@ -53,6 +53,7 @@ SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj,
: SCA_IController(gameobj, T),
m_bytecode(NULL),
m_function(NULL),
m_function_argc(0),
m_bModified(true),
m_debug(false),
m_mode(mode),
@@ -325,14 +326,14 @@ bool SCA_PythonController::Import()
Py_XDECREF(m_function);
m_function= NULL;
vector<STR_String> module_func = m_scriptText.Explode('.');
vector<STR_String> py_function_path = m_scriptText.Explode('.');
if(module_func.size() != 2 || module_func[0].Length()==0 || module_func[1].Length()==0) {
printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"", GetName().Ptr(), m_scriptText.Ptr());
if(py_function_path.size() < 2) {
printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"\n", GetName().Ptr(), m_scriptText.Ptr());
return false;
}
PyObject *mod = PyImport_ImportModule((char *)module_func[0].Ptr());
PyObject *mod = PyImport_ImportModule((char *)py_function_path[0].Ptr());
if(mod && m_debug) {
Py_DECREF(mod); /* getting a new one so dont hold a ref to the old one */
mod= PyImport_ReloadModule(mod);
@@ -342,24 +343,50 @@ bool SCA_PythonController::Import()
ErrorPrint("Python module not found");
return false;
}
Py_DECREF(mod); /* will be added to sys.modules so no need to keep a ref */
/* 'mod' will be DECREF'd as 'base'
* 'm_function' will be left holding a reference that the controller owns */
PyObject *base= mod;
PyObject *dict= PyModule_GetDict(mod);
m_function= PyDict_GetItemString(dict, module_func[1]); /* borrow */
for(unsigned int i=1; i < py_function_path.size(); i++) {
m_function = PyObject_GetAttrString(base, py_function_path[i].Ptr());
Py_DECREF(base);
base = m_function; /* for the next loop if there is on */
if(m_function==NULL) {
PyErr_Clear(); /* print our own error below */
break;
}
}
if(m_function==NULL) {
printf("Python module error \"%s\":\n \"%s\" module fount but function missing\n", GetName().Ptr(), m_scriptText.Ptr());
printf("Python module error \"%s\":\n \"%s\" module found but function missing\n", GetName().Ptr(), m_scriptText.Ptr());
return false;
}
if(!PyCallable_Check(m_function)) {
printf("Python module function error \"%s\":\n \"%s\" not callable", GetName().Ptr(), m_scriptText.Ptr());
Py_DECREF(m_function);
printf("Python module function error \"%s\":\n \"%s\" not callable\n", GetName().Ptr(), m_scriptText.Ptr());
return false;
}
Py_INCREF(m_function);
Py_INCREF(mod);
m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */
if (PyFunction_Check(m_function)) {
PyObject *py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(m_function), "co_argcount");
if(py_arg_count) {
m_function_argc = PyLong_AsLong(py_arg_count);
Py_DECREF(py_arg_count);
}
else {
PyErr_Clear(); /* unlikely to fail but just incase */
}
}
if(m_function_argc > 1) {
Py_DECREF(m_function);
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);
return false;
}
return true;
}
@@ -412,7 +439,15 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
if (!m_function)
return;
resultobj = PyObject_CallObject(m_function, NULL);
PyObject *args= NULL;
if(m_function_argc==1) {
args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, GetProxy());
}
resultobj = PyObject_CallObject(m_function, args);
Py_XDECREF(args);
break;
}
@@ -428,7 +463,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
else
{
// something is wrong, tell the user what went wrong
printf("Python script error from controller \"%s\": \n", GetName().Ptr());
printf("Python script error from controller \"%s\":\n", GetName().Ptr());
PyErr_Print();
/* Added in 2.48a, the last_traceback can reference Objects for example, increasing