From 033a63f8580227582a9695ebdd78ac0b4322e867 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 5 Apr 2009 14:01:49 +0000 Subject: BGE Bugfixes (mostly in the py api) KX_PolygonMaterial and KX_BlenderMaterial - Added a print function (would raise a python error on printing) * Crashes * KX_GameObject SetParent - Disallowed setting a parent to its self, caused a recursion crash. KX_MeshProxy "materials" attribute was segfaulting because of my recent change - I was wrong, you do need to check material types (no idea why since they are both PyObject * at the base) KX_VisibilityActuator - Wasn't initialized with PyType_Ready() making it crash on access (own fault) * Crashes because of missing NULL checks * KX_PolygonMaterial's "gl_texture" attribute wasnt checking for a valid m_tface KX_GameObject - added checks for GetPhysicsController() KX_RayCast::RayTest - didnt check for a valid physics_environment KX_SceneActuator's getCamera python function wasnt checking if there was a camera. --- source/gameengine/Ketsji/KX_BlenderMaterial.h | 1 + source/gameengine/Ketsji/KX_GameObject.cpp | 33 ++++++++++++---- source/gameengine/Ketsji/KX_MeshProxy.cpp | 51 ++++++++++++++++--------- source/gameengine/Ketsji/KX_PolygonMaterial.cpp | 7 +++- source/gameengine/Ketsji/KX_PolygonMaterial.h | 3 +- source/gameengine/Ketsji/KX_PythonInitTypes.cpp | 2 + source/gameengine/Ketsji/KX_RayCast.cpp | 3 ++ source/gameengine/Ketsji/KX_SceneActuator.cpp | 7 +++- source/gameengine/PyDoc/KX_GameObject.py | 2 + 9 files changed, 81 insertions(+), 28 deletions(-) (limited to 'source') diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 2d9dc8fd022..48d4730ab07 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -84,6 +84,7 @@ public: // -------------------------------- virtual PyObject* py_getattro(PyObject *attr); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); } KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 6f4aa2bc71a..a788b12b121 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -73,6 +73,8 @@ typedef unsigned long uint_ptr; #include "KX_SG_NodeRelationships.h" +static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0); + KX_GameObject::KX_GameObject( void* sgReplicationInfo, SG_Callbacks callbacks, @@ -943,7 +945,7 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const } -static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0); + const MT_Point3& KX_GameObject::NodeGetWorldPosition() const { // check on valid node in case a python controller holds a reference to a deleted object @@ -964,7 +966,8 @@ void KX_GameObject::Resume(void) { if (m_suspended) { SCA_IObject::Resume(); - GetPhysicsController()->RestoreDynamics(); + if(GetPhysicsController()) + GetPhysicsController()->RestoreDynamics(); m_suspended = false; } @@ -975,7 +978,8 @@ void KX_GameObject::Suspend() if ((!m_ignore_activity_culling) && (!m_suspended)) { SCA_IObject::Suspend(); - GetPhysicsController()->SuspendDynamics(); + if(GetPhysicsController()) + GetPhysicsController()->SuspendDynamics(); m_suspended = true; } } @@ -1717,7 +1721,7 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) PyObject* KX_GameObject::PyGetMass(PyObject* self) { ShowDeprecationWarning("getMass()", "the mass property"); - return PyFloat_FromDouble(GetPhysicsController()->GetMass()); + return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f); } @@ -1725,14 +1729,24 @@ PyObject* KX_GameObject::PyGetMass(PyObject* self) PyObject* KX_GameObject::PyGetReactionForce(PyObject* self) { // only can get the velocity if we have a physics object connected to us... - return PyObjectFrom(GetPhysicsController()->getReactionForce()); + + // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce + /* + if (GetPhysicsController()) + return PyObjectFrom(GetPhysicsController()->getReactionForce()); + return PyObjectFrom(dummy_point); + */ + + return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); + } PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self) { - GetPhysicsController()->setRigidBody(true); + if(GetPhysicsController()) + GetPhysicsController()->setRigidBody(true); Py_RETURN_NONE; } @@ -1741,7 +1755,8 @@ PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self) PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self) { - GetPhysicsController()->setRigidBody(false); + if(GetPhysicsController()) + GetPhysicsController()->setRigidBody(false); Py_RETURN_NONE; } @@ -1763,6 +1778,10 @@ PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value) PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type"); return NULL; } + if (self==value) { + PyErr_SetString(PyExc_ValueError, "cannot set the object to be its own parent!"); + return NULL; + } // The object we want to set as parent CValue *m_ob = (CValue*)value; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 4a4c98603e3..d9b1cc6df23 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -190,24 +190,24 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, PyObject* args, PyObject* kwds) { - int matid= -1; - int length = -1; + int matid= 0; + int length = 0; - if (PyArg_ParseTuple(args,"i",&matid)) + if (!PyArg_ParseTuple(args,"i",&matid)) + return NULL; + + + RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); /* can be NULL*/ + + if (mmat) { - RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial(); - if (mat) length = m_meshobj->NumVertices(mat); } - else { - return NULL; - } - + return PyInt_FromLong(length); - } @@ -244,15 +244,21 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, if (!PyArg_ParseTuple(args,"i",&polyindex)) return NULL; + + if (polyindex<0 || polyindex >= m_meshobj->NumPolygons()) + { + PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); + return NULL; + } + RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); if (polygon) { polyob = new KX_PolyProxy(m_meshobj, polygon); } - else - { - PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); + else { + PyErr_SetString(PyExc_AttributeError, "polygon is NULL, unknown reason"); } return polyob; } @@ -275,11 +281,22 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ list::iterator mit= self->m_meshobj->GetFirstMaterial(); - /* Can be a KX_PolygonMaterial or KX_BlenderMaterial, since both are cast to a PyObject * we dont need to care */ + for(i=0; im_bucket->GetPolyMaterial(); - PyList_SET_ITEM(materials, i, py_mat); - Py_INCREF(py_mat); + RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); + + /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */ + if(polymat->GetFlag() & RAS_BLENDERMAT) + { + KX_BlenderMaterial *mat = static_cast(polymat); + PyList_SET_ITEM(materials, i, mat); + Py_INCREF(mat); + } + else { + KX_PolygonMaterial *mat = static_cast(polymat); + PyList_SET_ITEM(materials, i, mat); + Py_INCREF(mat); + } } return materials; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index c5bddd6d166..3975189a9c2 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -333,8 +333,11 @@ PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUT PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolygonMaterial* self= static_cast(self_v); - Image *ima = self->m_tface->tpage; - return PyInt_FromLong(ima ? ima->bindcode:0); + int bindcode= 0; + if (self->m_tface && self->m_tface->tpage) + bindcode= self->m_tface->tpage->bindcode; + + return PyInt_FromLong(bindcode); } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 1e8ce5c3367..9865a66e836 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -33,6 +33,7 @@ #include "RAS_MaterialBucket.h" #include "RAS_IRasterizer.h" +#include "DNA_ID.h" struct MTFace; struct Material; @@ -117,7 +118,7 @@ public: virtual PyObject* py_getattro(PyObject *attr); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); - + virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index e2ff4ced122..8eeed5d853b 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -80,6 +80,7 @@ #include "KX_SCA_DynamicActuator.h" #include "KX_SoundActuator.h" #include "KX_TouchSensor.h" +#include "KX_VisibilityActuator.h" #include "SCA_PropertySensor.h" #include "SCA_PythonController.h" #include "SCA_RandomActuator.h" @@ -177,6 +178,7 @@ void initPyTypes(void) PyType_Ready(&KX_TrackToActuator::Type); PyType_Ready(&KX_VehicleWrapper::Type); PyType_Ready(&KX_VertexProxy::Type); + PyType_Ready(&KX_VisibilityActuator::Type); PyType_Ready(&PyObjectPlus::Type); PyType_Ready(&SCA_2DFilterActuator::Type); PyType_Ready(&SCA_ANDController::Type); diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 974d4b992a6..8c7612bf663 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -56,12 +56,15 @@ void KX_RayCast::reportHit(PHY_RayCastResult* result) bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback) { + if(physics_environment==NULL) return false; /* prevents crashing in some cases */ + // Loops over all physics objects between frompoint and topoint, // calling callback.RayHit for each one. // // callback.RayHit should return true to stop looking, or false to continue. // // returns true if an object was found, false if not. + MT_Point3 frompoint(_frompoint); const MT_Vector3 todir( (topoint - frompoint).safe_normalized() ); MT_Point3 prevpoint(_frompoint+todir*(-1.f)); diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 40a2ff2ef66..f158eb29dd7 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -468,6 +468,11 @@ PyObject* KX_SceneActuator::PyGetCamera(PyObject* self, PyObject* kwds) { ShowDeprecationWarning("getCamera()", "the camera property"); - return PyString_FromString(m_camera->GetName()); + if (m_camera) { + PyString_FromString(m_camera->GetName()); + } + else { + Py_RETURN_NONE; + } } /* eof */ diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 88c3a55280e..97e53ffacaa 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -270,6 +270,8 @@ class KX_GameObject: # (SCA_IObject) The reaction force is the force applied to this object over the last simulation timestep. This also includes impulses, eg from collisions. + (B{This is not implimented for bullet physics at the moment}) + @rtype: list [fx, fy, fz] @return: the reaction force of this object. """ -- cgit v1.2.3