From dee32d0b3f409007f5a392668068b92c3810026a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 20 Apr 2009 09:13:59 +0000 Subject: [PATCH 1/5] BGE Python API - initialize pythons sys.argv in the blenderplayer - ignore all arguments after a single " - " in the blenderplayer (like in blender), so args can be passed to the game. - add a utility function PyOrientationTo() - to take a Py euler, quat or 3x3 matrix and convert into a C++ MT_Matrix3x3. - add utility function ConvertPythonToMesh to get a RAS_MeshObject from a KX_MeshProxy or a name. - Added error prefix arguments to ConvertPythonToGameObject, ConvertPythonToMesh and PyOrientationTo so the error messages can include what function they came from. - deprecated brick.getOwner() for the "owner" attribute. --- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 20 ++++- source/gameengine/GameLogic/SCA_ILogicBrick.h | 2 + .../GamePlayer/ghost/GPG_Application.cpp | 8 +- .../GamePlayer/ghost/GPG_Application.h | 6 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 13 ++- .../gameengine/Ketsji/KX_CameraActuator.cpp | 4 +- source/gameengine/Ketsji/KX_GameObject.cpp | 90 +++++-------------- source/gameengine/Ketsji/KX_GameObject.h | 2 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 55 ++++++++++++ source/gameengine/Ketsji/KX_MeshProxy.h | 3 + .../gameengine/Ketsji/KX_ParentActuator.cpp | 4 +- source/gameengine/Ketsji/KX_PyMath.cpp | 34 +++++++ source/gameengine/Ketsji/KX_PyMath.h | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 7 +- source/gameengine/Ketsji/KX_PythonInit.h | 2 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 4 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 41 +++------ source/gameengine/Ketsji/KX_Scene.cpp | 4 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 50 ++--------- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 4 +- .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 5 +- source/gameengine/PyDoc/KX_VehicleWrapper.py | 20 +++-- source/gameengine/PyDoc/SCA_ILogicBrick.py | 6 +- 23 files changed, 215 insertions(+), 171 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index b3045402c2c..3cd750ff63b 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -246,8 +246,8 @@ PyParentObject SCA_ILogicBrick::Parents[] = { PyMethodDef SCA_ILogicBrick::Methods[] = { + // --> Deprecated {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, - // --> Deprecated {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPyGetExecutePriority, METH_NOARGS}, {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS}, // <-- Deprecated @@ -255,6 +255,7 @@ PyMethodDef SCA_ILogicBrick::Methods[] = { }; PyAttributeDef SCA_ILogicBrick::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("owner", SCA_ILogicBrick, pyattr_get_owner), KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority), {NULL} //Sentinel }; @@ -291,6 +292,8 @@ int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value) PyObject* SCA_ILogicBrick::PyGetOwner() { + ShowDeprecationWarning("getOwner()", "the owner property"); + CValue* parent = GetParent(); if (parent) { @@ -327,6 +330,19 @@ PyObject* SCA_ILogicBrick::PyGetExecutePriority() } +/*Attribute functions */ +PyObject* SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ILogicBrick* self= static_cast(self_v); + CValue* parent = self->GetParent(); + + if (parent) + return parent->GetProxy(); + + Py_RETURN_NONE; +} + + /* Conversions for making life better. */ bool SCA_ILogicBrick::PyArgToBool(int boolArg) @@ -338,8 +354,6 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) } } - - PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg) { return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE); diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index c0ff0fd633f..e59d05ea051 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -90,6 +90,8 @@ public: KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetOwner); KX_PYMETHOD_VARARGS(SCA_ILogicBrick,SetExecutePriority); KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetExecutePriority); + + static PyObject* pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); // check that attribute is a property static int CheckProperty(void *self, const PyAttributeDef *attrdef); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 0ecbbea3af6..907ba99e63b 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -151,7 +151,7 @@ GPG_Application::~GPG_Application(void) -bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene) +bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene, int argc, char **argv) { bool result = false; @@ -163,6 +163,10 @@ bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene) m_startScene = scene; result = true; } + + /* Python needs these */ + m_argc= argc; + m_argv= argv; return result; } @@ -681,7 +685,7 @@ bool GPG_Application::startEngine(void) // some python things - PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest, m_maggie); + PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest, m_maggie, m_argc, m_argv); m_ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(m_rasterizer, m_canvas); PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 38408f919b4..845686f5770 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -58,7 +58,7 @@ public: GPG_Application(GHOST_ISystem* system); ~GPG_Application(void); - bool SetGameEngineData(struct Main* maggie, struct Scene* scene); + bool SetGameEngineData(struct Main* maggie, struct Scene* scene, int argc, char** argv); bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight, const bool stereoVisual, const int stereoMode); bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); @@ -154,5 +154,9 @@ protected: */ char* m_pyGlobalDictString; int m_pyGlobalDictString_Length; + + /* argc and argv need to be passed on to python */ + int m_argc; + char** m_argv; }; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index a41446ad88c..64e70ce37c3 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -206,6 +206,8 @@ void usage(const char* program) printf(" blender_material 0 Enable material settings\n"); printf(" ignore_deprecation_warnings 1 Ignore deprecation warnings\n"); printf("\n"); + printf(" - : all arguments after this are ignored, allowing python to access them from sys.argv\n"); + printf("\n"); printf("example: %s -w 320 200 10 10 -g noaudio c:\\loadtest.blend\n", program); printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } @@ -293,6 +295,7 @@ static BlendFileData *load_game_data(char *progname, char *filename = NULL, char int main(int argc, char** argv) { int i; + int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */ bool error = false; SYS_SystemHandle syshandle = SYS_GetSystem(); bool fullScreen = false; @@ -393,6 +396,12 @@ int main(int argc, char** argv) #endif if (argv[i][0] == '-') { + /* ignore all args after " - ", allow python to have own args */ + if (argv[i][1]=='\0') { + argc_py_clamped= i; + break; + } + switch (argv[i][1]) { case 'g': @@ -596,7 +605,7 @@ int main(int argc, char** argv) char pathname[FILE_MAXDIR + FILE_MAXFILE]; char *titlename; - get_filename(argc, argv, filename); + get_filename(argc_py_clamped, argv, filename); if(filename[0]) BLI_convertstringcwd(filename); @@ -691,7 +700,7 @@ int main(int argc, char** argv) } // GPG_Application app (system, maggie, startscenename); - app.SetGameEngineData(maggie, scene); + app.SetGameEngineData(maggie, scene, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */ BLI_strncpy(pathname, maggie->name, sizeof(pathname)); BLI_strncpy(G.sce, maggie->name, sizeof(G.sce)); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 6cc48856a94..355cdbb6263 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -462,7 +462,7 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* value) ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_CameraActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_ob != NULL) @@ -589,7 +589,7 @@ int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF KX_CameraActuator* self= static_cast(self_v); KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator")) return 1; // ConvertPythonToGameObject sets the error if (self->m_ob) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index af1dc7f67b2..bea0fcff2af 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1182,22 +1182,12 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args, PyObject* KX_GameObject::PyReplaceMesh(PyObject* value) { KX_Scene *scene = KX_GetActiveScene(); - char* meshname; - void* mesh_pt; - - meshname = PyString_AsString(value); - if (meshname==NULL) { - PyErr_SetString(PyExc_ValueError, "gameOb.replaceMesh(value): KX_GameObject, expected a mesh name"); - return NULL; - } - mesh_pt = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); + RAS_MeshObject* new_mesh; - if (mesh_pt==NULL) { - PyErr_SetString(PyExc_ValueError, "gameOb.replaceMesh(value): KX_GameObject, the mesh name given does not exist"); + if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject")) return NULL; - } - scene->ReplaceMesh(this, (class RAS_MeshObject*)mesh_pt); + scene->ReplaceMesh(this, new_mesh); Py_RETURN_NONE; } @@ -1568,49 +1558,15 @@ PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYAT int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_GameObject* self= static_cast(self_v); - if (!PySequence_Check(value)) { - PyErr_SetString(PyExc_AttributeError, "gameOb.orientation = [...]: KX_GameObject, expected a sequence"); - return 1; - } - + + /* if value is not a sequence PyOrientationTo makes an error */ MT_Matrix3x3 rot; + if (!PyOrientationTo(value, rot, "gameOb.orientation = sequence: KX_GameObject, ")) + return NULL; - if (PyMatTo(value, rot)) - { - self->NodeSetLocalOrientation(rot); - self->NodeUpdateGS(0.f); - return 0; - } - PyErr_Clear(); - - if (PySequence_Size(value) == 4) - { - MT_Quaternion qrot; - if (PyVecTo(value, qrot)) - { - rot.setRotation(qrot); - self->NodeSetLocalOrientation(rot); - self->NodeUpdateGS(0.f); - return 0; - } - return 1; - } - - if (PySequence_Size(value) == 3) - { - MT_Vector3 erot; - if (PyVecTo(value, erot)) - { - rot.setEuler(erot); - self->NodeSetLocalOrientation(rot); - self->NodeUpdateGS(0.f); - return 0; - } - return 1; - } - - PyErr_SetString(PyExc_AttributeError, "gameOb.orientation = [...]: KX_GameObject, could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); - return 1; + self->NodeSetLocalOrientation(rot); + self->NodeUpdateGS(0.f); + return 0; } PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -2127,7 +2083,7 @@ PyObject* KX_GameObject::PyGetParent() PyObject* KX_GameObject::PySetParent(PyObject* value) { KX_GameObject *obj; - if (!ConvertPythonToGameObject(value, &obj, false)) + if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject")) return NULL; this->SetParent(KX_GetActiveScene(), obj); @@ -2362,7 +2318,7 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, PyErr_Clear(); KX_GameObject *other; - if (ConvertPythonToGameObject(value, &other, false)) + if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject")) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition())); } @@ -2385,7 +2341,7 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo, PyErr_Clear(); KX_GameObject *other; - if (ConvertPythonToGameObject(value, &other, false)) + if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else @@ -2479,7 +2435,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_GameObject *other; PyErr_Clear(); - if (ConvertPythonToGameObject(pyarg, &other, false)) + if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else @@ -2555,7 +2511,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyErr_Clear(); - if (ConvertPythonToGameObject(pyto, &other, false)) + if (ConvertPythonToGameObject(pyto, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else @@ -2572,7 +2528,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyErr_Clear(); - if (ConvertPythonToGameObject(pyfrom, &other, false)) + if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */ { fromPoint = other->NodeGetWorldPosition(); } else @@ -2685,10 +2641,10 @@ void KX_GameObject::Relink(GEN_Map *map_parameter) } } -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok) +bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { - PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen"); + PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); *object = NULL; return false; } @@ -2699,7 +2655,7 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py if (py_none_ok) { return true; } else { - PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid"); + PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix); return false; } } @@ -2710,7 +2666,7 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py if (*object) { return true; } else { - PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject"); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value)); return false; } } @@ -2720,7 +2676,7 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py /* sets the error */ if (*object==NULL) { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); return false; } @@ -2730,9 +2686,9 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py *object = NULL; if (py_none_ok) { - PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None"); + PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix); } else { - PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string"); + PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix); } return false; diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 89517bd76ce..ec02dc17b75 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -61,7 +61,7 @@ class PHY_IPhysicsEnvironment; struct Object; /* utility conversion function */ -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok); +bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix); /** * KX_GameObject is the main class for dynamic objects. diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index e2c59ab4242..6be1da55ff8 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -304,3 +304,58 @@ PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBU KX_MeshProxy * self = static_cast (selfv); return PyInt_FromLong(self->m_meshobj->NumPolygons()); } + +/* a close copy of ConvertPythonToGameObject but for meshes */ +bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix) +{ + if (value==NULL) { + PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); + *object = NULL; + return false; + } + + if (value==Py_None) { + *object = NULL; + + if (py_none_ok) { + return true; + } else { + PyErr_Format(PyExc_TypeError, "%s, expected KX_MeshProxy or a KX_MeshProxy name, None is invalid", error_prefix); + return false; + } + } + + if (PyString_Check(value)) { + *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) )); + + if (*object) { + return true; + } else { + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value)); + return false; + } + } + + if (PyObject_TypeCheck(value, &KX_MeshProxy::Type)) { + KX_MeshProxy *kx_mesh = static_castBGE_PROXY_REF(value); + + /* sets the error */ + if (*object==NULL) { + PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + return false; + } + + *object = kx_mesh->GetMesh(); + return true; + } + + *object = NULL; + + if (py_none_ok) { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy, a string or None", error_prefix); + } else { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy or a string", error_prefix); + } + + return false; +} diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index dfc498801a7..aeecefc09e6 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -31,6 +31,9 @@ #include "SCA_IObject.h" +/* utility conversion function */ +bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix); + class KX_MeshProxy : public SCA_IObject { Py_Header; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 69c0a3cd510..0093cf5f313 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -192,7 +192,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE KX_ParentActuator* actuator = static_cast(self); KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_ParentActuator")) return 1; // ConvertPythonToGameObject sets the error if (actuator->m_ob != NULL) @@ -226,7 +226,7 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* value) { ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_ParentActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_ob != NULL) diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index cceb7a12446..0093a72808e 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -44,6 +44,7 @@ #include "ListValue.h" #include "KX_Python.h" +#include "KX_PyMath.h" bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) { @@ -74,6 +75,39 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) return false; } +bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix) +{ + MT_Matrix3x3 rot; + int size= PySequence_Size(pyval); + + if (size == 4) + { + MT_Quaternion qrot; + if (PyVecTo(pyval, qrot)) + { + rot.setRotation(qrot); + return true; + } + } + else if (size == 3) { + /* 3x3 matrix or euler */ + MT_Vector3 erot; + if (PyVecTo(pyval, erot)) + { + rot.setEuler(erot); + return true; + } + PyErr_Clear(); + + if (PyMatTo(pyval, rot)) + { + return true; + } + } + + PyErr_Format(PyExc_TypeError, "%s, could not set the orientation from a 3x3 matrix, quaternion or euler sequence", error_prefix); + return false; +} PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 4a64063aaa1..00f7c5cad93 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -145,6 +145,8 @@ bool PyVecTo(PyObject* pyval, T& vec) return false; } +bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix); + /** * Converts an MT_Matrix4x4 to a python object. */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 097d20fe0e5..9649e50a98b 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1357,14 +1357,17 @@ void setSandbox(TPythonSecurityLevel level) /** * Python is not initialised. */ -PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) { STR_String pname = progname; Py_SetProgramName(pname.Ptr()); Py_NoSiteFlag=1; Py_FrozenFlag=1; Py_Initialize(); - + + if(argv) /* browser plugins dont currently set this */ + PySys_SetArgv(argc, argv); + //importBlenderModules() setSandbox(level); diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 97d23fe391c..11360197b95 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -43,7 +43,7 @@ extern bool gUseVisibilityTemp; PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); -PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie); +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie, int argc, char** argv); PyObject* initMathutils(); PyObject* initBGL(); PyObject* initVideoTexture(void); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index f1c7b757579..56d94a8d226 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -231,7 +231,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT KX_SCA_AddObjectActuator* actuator = static_cast(self); KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator")) return 1; // ConvertPythonToGameObject sets the error if (actuator->m_OriginalObject != NULL) @@ -277,7 +277,7 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* value) ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_SCA_AddObjectActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_OriginalObject != NULL) diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 53067e94cd8..38f8d581d55 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -116,22 +116,12 @@ PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct K int KX_SCA_ReplaceMeshActuator::pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_SCA_ReplaceMeshActuator* actuator = static_cast(self); - if (value == Py_None) { - actuator->m_mesh = NULL; - } else if (PyString_Check(value)) { - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(PyString_AsString(value))); - if (mesh==NULL) { - PyErr_SetString(PyExc_ValueError, "actuator.mesh = string: Replace Mesh Actuator, mesh name given does not exist"); - return 1; - } - actuator->m_mesh= (class RAS_MeshObject*)mesh; - } else if PyObject_TypeCheck(value, &KX_MeshProxy::Type) { - KX_MeshProxy* proxy = (KX_MeshProxy*)value; - actuator->m_mesh= proxy->GetMesh(); - } else { - PyErr_SetString(PyExc_ValueError, "actuator.mesh = value: Replace Mesh Actuator, expected the mesh name, a KX_MeshProxy or None"); + RAS_MeshObject* new_mesh; + + if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator")) return 1; - } + + actuator->m_mesh = new_mesh; return 0; } @@ -144,23 +134,12 @@ const char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* value) { ShowDeprecationWarning("setMesh()", "the mesh property"); - if (value == Py_None) { - m_mesh = NULL; - } else { - char* meshname = PyString_AsString(value); - if (!meshname) { - PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None"); - return NULL; - } - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); - - if (mesh==NULL) { - PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); - return NULL; - } - m_mesh= (class RAS_MeshObject*)mesh; - } + RAS_MeshObject* new_mesh; + if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator")) + return NULL; + + m_mesh = new_mesh; Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 0e1572da679..aa7bd65f240 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1747,8 +1747,8 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) return NULL; - if (!ConvertPythonToGameObject(pyob, &ob, false) - || !ConvertPythonToGameObject(pyother, &other, false)) + if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) return NULL; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index b9edd7436df..412be497c5a 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -540,50 +540,16 @@ int KX_SoundActuator::pyattr_set_orientation(void *self, const struct KX_PYATTRI MT_Matrix3x3 rot; KX_SoundActuator * actuator = static_cast (self); - if (!PySequence_Check(value)) { - PyErr_SetString(PyExc_AttributeError, "value = actuator.orientation: KX_SoundActuator, expected a sequence"); - return 1; - } - + /* if value is not a sequence PyOrientationTo makes an error */ + if (!PyOrientationTo(value, rot, "actuator.orientation = value: KX_SoundActuator")) + return NULL; + if (!actuator->m_soundObject) return 0; /* Since not having m_soundObject didn't do anything in the old version, - * it probably should be kept that way */ - - if (PyMatTo(value, rot)) - { - actuator->m_soundObject->SetOrientation(rot); - return 0; - } - PyErr_Clear(); - - - if (PySequence_Size(value) == 4) - { - MT_Quaternion qrot; - if (PyVecTo(value, qrot)) - { - rot.setRotation(qrot); - actuator->m_soundObject->SetOrientation(rot); - return 0; - } - return 1; - } - - if (PySequence_Size(value) == 3) - { - MT_Vector3 erot; - if (PyVecTo(value, erot)) - { - rot.setEuler(erot); - actuator->m_soundObject->SetOrientation(rot); - return 0; - } - return 1; - } - - PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); - return 1; - + * it probably should be kept that way */ + + actuator->m_soundObject->SetOrientation(rot); + return 0; } // Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index c89d88389c4..fbf43de6cf4 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -489,7 +489,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT KX_TrackToActuator* actuator = static_cast(self); KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_TrackToActuator")) return 1; // ConvertPythonToGameObject sets the error if (actuator->m_object != NULL) @@ -525,7 +525,7 @@ PyObject* KX_TrackToActuator::PySetObject(PyObject* value) ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_TrackToActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_object != NULL) diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index f77c135e994..1a6fb196db5 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -47,14 +47,15 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args) if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) { KX_GameObject *gameOb; - if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false)) + if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)")) return NULL; if (gameOb->GetSGNode()) { PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - + + /* TODO - no error checking here! - bad juju */ MT_Vector3 attachPos,attachDir,attachAxle; PyVecTo(pylistPos,attachPos); PyVecTo(pylistDir,attachDir); diff --git a/source/gameengine/PyDoc/KX_VehicleWrapper.py b/source/gameengine/PyDoc/KX_VehicleWrapper.py index 68240e15622..087aa167475 100644 --- a/source/gameengine/PyDoc/KX_VehicleWrapper.py +++ b/source/gameengine/PyDoc/KX_VehicleWrapper.py @@ -5,15 +5,23 @@ class KX_VehicleWrapper: # (PyObjectPlus) All placeholders have a __ prefix """ - def __addWheel(val): + def addWheel(wheel, attachPos, attachDir, axleDir, suspensionRestLength, wheelRadius, hasSteering): + """ TODO - Description - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description + @param wheel: The object to use as a wheel. + @type wheel: L{KX_GameObject} or a KX_GameObject name + @param attachPos: The position that this wheel will attach to. + @type attachPos: vector of 3 floats + @param attachDir: The direction this wheel points. + @type attachDir: vector of 3 floats + @param axleDir: The direction of this wheels axle. + @type axleDir: vector of 3 floats + @param suspensionRestLength: TODO - Description + @type suspensionRestLength: float + @param wheelRadius: The size of the wheel. + @type wheelRadius: float """ def __applyBraking(val): diff --git a/source/gameengine/PyDoc/SCA_ILogicBrick.py b/source/gameengine/PyDoc/SCA_ILogicBrick.py index 18cb900f28d..4688ba12bb6 100644 --- a/source/gameengine/PyDoc/SCA_ILogicBrick.py +++ b/source/gameengine/PyDoc/SCA_ILogicBrick.py @@ -8,13 +8,17 @@ class SCA_ILogicBrick: @ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first). @type executePriority: int + @ivar owner: The game object this logic brick is attached to (read only). + @type owner: L{KX_GameObject} or None in exceptional cases. """ def getOwner(): """ Gets the game object associated with this logic brick. - @rtype: L{KX_GameObject} + Deprecated: Use the "owner" property instead. + + @rtype: L{KX_GameObject} """ #--The following methods are deprecated-- From d76a6f5231c015c35123d22e1f5c3ffcdfbf9bbd Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 20 Apr 2009 13:18:54 +0000 Subject: [PATCH 2/5] Booleans: Fix for "no faces" error, reported by alxarch, thanks! --- source/blender/src/booleanops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c index 948797014a4..c5b97e475a9 100644 --- a/source/blender/src/booleanops.c +++ b/source/blender/src/booleanops.c @@ -537,7 +537,7 @@ int NewBooleanMesh(Base *base, Base *base_select, int int_op_type) /* put some checks in for nice user feedback */ if (dm == NULL || dm_select == NULL) return 0; - if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0; + if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) { MEM_freeN(mat); return -1; From 449e9a454d5cc160014f25077bfdf7cd04a411c4 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 20 Apr 2009 18:23:46 +0000 Subject: [PATCH 3/5] Bugfix 18558 In OSX, using spin/extrude etc. buttons, with more than 1 3d window open, should turn cursor in a Question Mark to indicate you have to tell which window to use (yes weak, but that's 2.4x!). OSX didn't support that type of cursor, so no hint happened. Now uses the 'hand' icon for osx... no nicer one is there afaik. --- source/blender/src/ghostwinlay.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/src/ghostwinlay.c b/source/blender/src/ghostwinlay.c index 9388ac93543..794ba0cf6e0 100644 --- a/source/blender/src/ghostwinlay.c +++ b/source/blender/src/ghostwinlay.c @@ -212,7 +212,12 @@ static GHOST_TStandardCursor convert_cursor(int curs) { case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow; case CURSOR_WAIT: return GHOST_kStandardCursorWait; case CURSOR_EDIT: return GHOST_kStandardCursorCrosshair; - case CURSOR_HELP: return GHOST_kStandardCursorHelp; + case CURSOR_HELP: +#ifdef __APPLE__ + return GHOST_kStandardCursorLeftRight; +#else + return GHOST_kStandardCursorHelp; +#endif case CURSOR_X_MOVE: return GHOST_kStandardCursorLeftRight; case CURSOR_Y_MOVE: return GHOST_kStandardCursorUpDown; case CURSOR_PENCIL: return GHOST_kStandardCursorPencil; From 6afaab654d6d9df31f6cb01e8e2c834ae79927fb Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 20 Apr 2009 18:31:48 +0000 Subject: [PATCH 4/5] Bugfix for [#18554] Time + Scale Node Crash --- source/blender/nodes/intern/CMP_nodes/CMP_scale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_scale.c b/source/blender/nodes/intern/CMP_nodes/CMP_scale.c index cc6f9249495..ee3607c11f6 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_scale.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_scale.c @@ -65,8 +65,8 @@ static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, b newx = cbuf->x * (rd->size / 100.0f); newy = cbuf->y * (rd->size / 100.0f); } else { /* CMP_SCALE_ABSOLUTE */ - newx= (int)in[1]->vec[0]; - newy= (int)in[2]->vec[0]; + newx= MAX2((int)in[1]->vec[0], 1); + newy= MAX2((int)in[2]->vec[0], 1); } newx= MIN2(newx, CMP_SCALE_MAX); newy= MIN2(newy, CMP_SCALE_MAX); From 2d0d06f642b661b084657c05ebb0c664f998a937 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 20 Apr 2009 21:20:33 +0000 Subject: [PATCH 5/5] BGE VideoTexture: fix bug with VideoTexture.materialID() since recent commit. --- source/gameengine/VideoTexture/BlendType.h | 6 ++++-- source/gameengine/VideoTexture/Texture.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h index ac3ed8812a6..8b243c43912 100644 --- a/source/gameengine/VideoTexture/BlendType.h +++ b/source/gameengine/VideoTexture/BlendType.h @@ -25,6 +25,7 @@ http://www.gnu.org/copyleft/lesser.txt. /// class allows check type of blender python object and access its contained object +/// MUST ONLY BE USED FOR KX classes that are descendent of PyObjectPlus template class BlendType { public: @@ -48,8 +49,9 @@ public: // if pointer to type is set and don't match to type of provided object, return NULL else if (obj->ob_type != m_objType) return NULL; - // return pointer to object - return (PyObj*)obj; + // return pointer to object, this class can only be used for KX object => + // the Py object is actually a proxy + return (PyObj*)BGE_PROXY_REF(obj); } /// parse arguments to get object diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 66c67023e38..fa941f9260e 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -163,7 +163,8 @@ void Texture_dealloc (Texture * self) // release renderer Py_XDECREF(self->m_source); // close texture - Texture_close(self); + PyObject* ret = Texture_close(self); + Py_DECREF(ret); // release scaled image buffer delete [] self->m_scaledImg; // release object