diff options
Diffstat (limited to 'source/gameengine/GameLogic/SCA_PythonController.cpp')
-rw-r--r-- | source/gameengine/GameLogic/SCA_PythonController.cpp | 198 |
1 files changed, 138 insertions, 60 deletions
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index e879481a444..c75e36acab2 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -157,8 +157,40 @@ static const char* sPyGetCurrentController__doc__; PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self) { - m_sCurrentController->AddRef(); - return m_sCurrentController; + return m_sCurrentController->AddRef(); +} + +SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) +{ + // for safety, todo: only allow for registered actuators (pointertable) + // we don't want to crash gameengine/blender by python scripts + std::vector<SCA_IActuator*> lacts = m_sCurrentController->GetLinkedActuators(); + std::vector<SCA_IActuator*>::iterator it; + + if (PyString_Check(value)) { + /* get the actuator from the name */ + char *name= PyString_AsString(value); + for(it = lacts.begin(); it!= lacts.end(); it++) { + if( name == (*it)->GetName() ) { + return *it; + } + } + } + else { + /* Expecting an actuator type */ + for(it = lacts.begin(); it!= lacts.end(); it++) { + if( static_cast<SCA_IActuator*>(value) == (*it) ) { + return *it; + } + } + } + + /* set the exception */ + PyObject *value_str = PyObject_Repr(value); /* new ref */ + PyErr_Format(PyExc_ValueError, "'%s' not in this controllers actuator list", PyString_AsString(value_str)); + Py_DECREF(value_str); + + return false; } #if 0 @@ -175,26 +207,14 @@ PyObject* SCA_PythonController::sPyAddActiveActuator( int activate; if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate)) return NULL; - - // for safety, todo: only allow for registered actuators (pointertable) - // we don't want to crash gameengine/blender by python scripts - std::vector<SCA_IActuator*> lacts = m_sCurrentController->GetLinkedActuators(); - std::vector<SCA_IActuator*>::iterator it; - bool found = false; - CValue* act = (CValue*)ob1; - - for(it = lacts.begin(); it!= lacts.end(); it++) { - if( static_cast<SCA_IActuator*>(act) == (*it) ) { - found=true; - break; - } - } - if(found){ - CValue* boolval = new CBoolValue(activate!=0); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)act,boolval); - boolval->Release(); - } + SCA_IActuator* actu = LinkedActuatorFromPy(ob1); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(activate!=0); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval); + boolval->Release(); Py_RETURN_NONE; } @@ -229,18 +249,61 @@ PyParentObject SCA_PythonController::Parents[] = { NULL }; PyMethodDef SCA_PythonController::Methods[] = { + {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, + {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, + {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc}, {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, - {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, //Deprecated functions ------> + {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, //<----- Deprecated {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_PythonController::Attributes[] = { + { NULL } //Sentinel +}; + +bool SCA_PythonController::Compile() +{ + //printf("py script modified '%s'\n", m_scriptName.Ptr()); + + // if a script already exists, decref it before replace the pointer to a new script + if (m_bytecode) + { + Py_DECREF(m_bytecode); + m_bytecode=NULL; + } + // recompile the scripttext into bytecode + m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); + m_bModified=false; + + if (m_bytecode) + { + + return true; + } + else { + // didn't compile, so instead of compile, complain + // something is wrong, tell the user what went wrong + printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); + //PyRun_SimpleString(m_scriptText.Ptr()); + PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( (char *)"last_traceback", Py_None); + PyErr_Clear(); /* just to be sure */ + + return false; + } +} void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) { @@ -249,33 +312,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) if (m_bModified) { - // if a script already exists, decref it before replace the pointer to a new script - if (m_bytecode) - { - Py_DECREF(m_bytecode); - m_bytecode=NULL; - } - // recompile the scripttext into bytecode - m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); - if (!m_bytecode) - { - // didn't compile, so instead of compile, complain - // something is wrong, tell the user what went wrong - printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); - //PyRun_SimpleString(m_scriptText.Ptr()); - PyErr_Print(); - - /* Added in 2.48a, the last_traceback can reference Objects for example, increasing - * their user count. Not to mention holding references to wrapped data. - * This is especially bad when the PyObject for the wrapped data is free'd, after blender - * has alredy dealocated the pointer */ - PySys_SetObject( "last_traceback", Py_None); - PyErr_Clear(); /* just to be sure */ - + if (Compile()==false) // sets m_bModified to false return; - } - m_bModified=false; } + if (!m_bytecode) { + return; + } + /* * This part here with excdict is a temporary patch @@ -313,7 +356,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * their user count. Not to mention holding references to wrapped data. * This is especially bad when the PyObject for the wrapped data is free'd, after blender * has alredy dealocated the pointer */ - PySys_SetObject( "last_traceback", Py_None); + PySys_SetObject( (char *)"last_traceback", Py_None); PyErr_Clear(); /* just to be sure */ //PyRun_SimpleString(m_scriptText.Ptr()); @@ -329,30 +372,63 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) -PyObject* SCA_PythonController::_getattr(const STR_String& attr) +PyObject* SCA_PythonController::_getattr(const char *attr) { - if (attr == "script") { - return PyString_FromString(m_scriptText); - } - if (attr == "state") { + if (!strcmp(attr,"state")) { return PyInt_FromLong(m_statemask); } + if (!strcmp(attr,"script")) { + return PyString_FromString(m_scriptText); + } _getattr_up(SCA_IController); } -int SCA_PythonController::_setattr(const STR_String& attr, PyObject *value) +int SCA_PythonController::_setattr(const char *attr, PyObject *value) { - if (attr == "script") { - PyErr_SetString(PyExc_AttributeError, "script is read only, use setScript() to update the script"); + if (!strcmp(attr,"state")) { + PyErr_SetString(PyExc_AttributeError, "state is read only"); return 1; } - if (attr == "state") { - PyErr_SetString(PyExc_AttributeError, "state is read only"); + if (!strcmp(attr,"script")) { + char *scriptArg = PyString_AsString(value); + + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); + return -1; + } + + /* set scripttext sets m_bModified to true, + so next time the script is needed, a reparse into byte code is done */ + this->SetScriptText(scriptArg); + return 1; } return SCA_IController::_setattr(attr, value); } +PyObject* SCA_PythonController::PyActivate(PyObject* self, PyObject *value) +{ + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(true); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); + boolval->Release(); + Py_RETURN_NONE; +} + +PyObject* SCA_PythonController::PyDeActivate(PyObject* self, PyObject *value) +{ + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(false); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); + boolval->Release(); + Py_RETURN_NONE; +} PyObject* SCA_PythonController::PyGetActuators(PyObject* self) { @@ -410,8 +486,7 @@ SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value) for (unsigned int index=0;index<m_linkedactuators.size();index++) { SCA_IActuator* actua = m_linkedactuators[index]; - STR_String realname = actua->GetName(); - if (realname == scriptArg) + if (actua->GetName() == scriptArg) { return actua->AddRef(); } @@ -448,6 +523,9 @@ PyObject* SCA_PythonController::PyGetScript(PyObject* self) PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value) { char *scriptArg = PyString_AsString(value); + + ShowDeprecationWarning("setScript()", "the script property"); + if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); return NULL; |