[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16105] trunk/blender/source/gameengine: Python API get/setObject update for Actuators.

Campbell Barton ideasman42 at gmail.com
Thu Aug 14 10:59:24 CEST 2008


Revision: 16105
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16105
Author:   campbellbarton
Date:     2008-08-14 10:58:25 +0200 (Thu, 14 Aug 2008)

Log Message:
-----------
Python API get/setObject update for Actuators. (SetParent, AddObject, Camera and TrackTo)
* bugfix for BGE python api - SetParent actuator getObject would segfault if the object was not set.
* Added utility function ConvertPythonToGameObject() that can take a GameObject, string or None and set the game object from this since it was being done in a number of places.
* allow setObject(None), since no object is valid for actuators, Python should be able to set this.
* added optional argument for getObject() so it returns the KX_GameObject rather then its name, would prefer this be default but it could break existing games.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Converter/KX_ConvertActuators.cpp
    trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
    trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.cpp
    trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.h
    trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp
    trunk/blender/source/gameengine/Ketsji/KX_GameObject.h
    trunk/blender/source/gameengine/Ketsji/KX_ParentActuator.cpp
    trunk/blender/source/gameengine/Ketsji/KX_ParentActuator.h
    trunk/blender/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
    trunk/blender/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
    trunk/blender/source/gameengine/Ketsji/KX_TrackToActuator.cpp
    trunk/blender/source/gameengine/Ketsji/KX_TrackToActuator.h
    trunk/blender/source/gameengine/PyDoc/KX_CameraActuator.py
    trunk/blender/source/gameengine/PyDoc/KX_ParentActuator.py
    trunk/blender/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
    trunk/blender/source/gameengine/PyDoc/KX_TrackToActuator.py

Modified: trunk/blender/source/gameengine/Converter/KX_ConvertActuators.cpp
===================================================================
--- trunk/blender/source/gameengine/Converter/KX_ConvertActuators.cpp	2008-08-14 06:42:52 UTC (rev 16104)
+++ trunk/blender/source/gameengine/Converter/KX_ConvertActuators.cpp	2008-08-14 08:58:25 UTC (rev 16105)
@@ -540,9 +540,16 @@
 						// does the 'original' for replication exists, and 
 						// is it in a non-active layer ?
 						SCA_IObject* originalval = NULL;
-						if (editobact->ob && !(editobact->ob->lay & activeLayerBitInfo))
-							originalval = converter->FindGameObject(editobact->ob);
-						
+						if (editobact->ob)
+						{
+							if (editobact->ob->lay & activeLayerBitInfo)
+							{
+								fprintf(stderr, "Warning, object \"%s\" from AddObject actuator \"%s\" is not in a hidden layer.\n", objectname.Ptr(), uniquename.Ptr());
+							}
+							else {
+								originalval = converter->FindGameObject(editobact->ob);
+							}
+						}
 						MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]),
 							KX_BLENDERTRUNC(editobact->linVelocity[1]),
 							KX_BLENDERTRUNC(editobact->linVelocity[2]));

Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.h	2008-08-14 06:42:52 UTC (rev 16104)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.h	2008-08-14 08:58:25 UTC (rev 16105)
@@ -121,6 +121,13 @@
 	}; \
     static char method_name##_doc[]; \
 
+#define KX_PYMETHOD_DOC_VARARGS(class_name, method_name)			\
+	PyObject* Py##method_name(PyObject* self, PyObject* args); \
+	static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
+		return ((class_name*) self)->Py##method_name(self, args);		\
+	}; \
+    static char method_name##_doc[]; \
+
 #define KX_PYMETHOD_DOC_O(class_name, method_name)			\
 	PyObject* Py##method_name(PyObject* self, PyObject* value); \
 	static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \

Modified: trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.cpp	2008-08-14 06:42:52 UTC (rev 16104)
+++ trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.cpp	2008-08-14 08:58:25 UTC (rev 16105)
@@ -395,8 +395,8 @@
 };
 
 PyMethodDef KX_CameraActuator::Methods[] = {
-	{"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_VARARGS,	SetObject_doc},
-	{"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_NOARGS,	GetObject_doc},
+	{"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O,	SetObject_doc},
+	{"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS,	GetObject_doc},
 	{"setMin"	,(PyCFunction) KX_CameraActuator::sPySetMin,	METH_VARARGS,	SetMin_doc},
 	{"getMin"	,(PyCFunction) KX_CameraActuator::sPyGetMin,	METH_NOARGS,	GetMin_doc},
 	{"setMax"	,(PyCFunction) KX_CameraActuator::sPySetMax,	METH_VARARGS,	SetMax_doc},
@@ -413,50 +413,43 @@
 }
 /* get obj  ---------------------------------------------------------- */
 char KX_CameraActuator::GetObject_doc[] = 
-"getObject\n"
+"getObject(name_only = 1)\n"
+"name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
 "\tReturns the object this sensor reacts to.\n";
-PyObject* KX_CameraActuator::PyGetObject(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args)
 {
-	return PyString_FromString(m_ob->GetName());
+	int ret_name_only = 1;
+	if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
+		return NULL;
+	
+	if (!m_ob)
+		Py_RETURN_NONE;
+	
+	if (ret_name_only)
+		return PyString_FromString(m_ob->GetName());
+	else
+		return m_ob->AddRef();
 }
 /* set obj  ---------------------------------------------------------- */
 char KX_CameraActuator::SetObject_doc[] = 
-"setObject\n"
+"setObject(object)\n"
+"\t- object: KX_GameObject, string or None\n"
 "\tSets the object this sensor reacts to.\n";
-PyObject* KX_CameraActuator::PySetObject(PyObject* self, 
-										PyObject* args, 
-										PyObject* kwds)
+PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value)
 {
-    
-	PyObject* gameobj;
-	if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
-	{
-		if (m_ob)
-			m_ob->UnregisterActuator(this);
-		m_ob = (SCA_IObject*)gameobj;
-		if (m_ob)
-			m_ob->RegisterActuator(this);
-		Py_Return;
-	}
-	PyErr_Clear();
+	KX_GameObject *gameobj;
 	
-	char* objectname;
-	if (PyArg_ParseTuple(args, "s", &objectname))
-	{
-		SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
-		if(object)
-		{
-			if (m_ob != NULL)
-				m_ob->UnregisterActuator(this);
-			m_ob = object;
-			m_ob->RegisterActuator(this);
-			Py_Return;
-		}
-	}
+	if (!ConvertPythonToGameObject(value, &gameobj, true))
+		return NULL; // ConvertPythonToGameObject sets the error
 	
-	return NULL;
+	if (m_ob != NULL)
+		m_ob->UnregisterActuator(this);	
+
+	m_ob = (SCA_IObject*)gameobj;
+	if (m_ob)
+		m_ob->RegisterActuator(this);
+	
+	Py_RETURN_NONE;
 }
 
 /* get min  ---------------------------------------------------------- */

Modified: trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.h	2008-08-14 06:42:52 UTC (rev 16104)
+++ trunk/blender/source/gameengine/Ketsji/KX_CameraActuator.h	2008-08-14 08:58:25 UTC (rev 16105)
@@ -123,9 +123,9 @@
 	virtual PyObject* _getattr(const STR_String& attr);
 	
 	/* set object to look at */
-	KX_PYMETHOD_DOC(KX_CameraActuator,SetObject);
+	KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject);
 	/* get current object  */
-	KX_PYMETHOD_DOC(KX_CameraActuator,GetObject);
+	KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,GetObject);
 	KX_PYMETHOD_DOC(KX_CameraActuator,SetMin);
 	KX_PYMETHOD_DOC(KX_CameraActuator,GetMin);
 	KX_PYMETHOD_DOC(KX_CameraActuator,SetMax);

Modified: trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp	2008-08-14 06:42:52 UTC (rev 16104)
+++ trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp	2008-08-14 08:58:25 UTC (rev 16105)
@@ -1551,9 +1551,9 @@
 	PyErr_Clear();
 	
 	PyObject *pyother;
-	if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
+	KX_GameObject *other;
+	if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
 	{
-		KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
 		return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
 	}
 	
@@ -1574,11 +1574,12 @@
 	if (!PyVecArgTo(args, toPoint))
 	{
 		PyErr_Clear();
-		if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
+		
+		KX_GameObject *other;
+		if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
 		{
-			KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
 			toPoint = other->NodeGetWorldPosition();
-		}else
+		} else
 		{
 			PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
 			return NULL;
@@ -1648,12 +1649,15 @@
 	{
 		KX_GameObject *other;
 		PyErr_Clear();
-		if (!PyType_IsSubtype(pyarg->ob_type, &KX_GameObject::Type)) {
+		
+		if (ConvertPythonToGameObject(pyarg, &other, false))
+		{
+			toPoint = other->NodeGetWorldPosition();
+		} else
+		{
 			PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
 			return NULL;
 		}
-		other = static_cast<KX_GameObject*>(pyarg);
-		toPoint = other->NodeGetWorldPosition();
 	}
 	MT_Point3 fromPoint = NodeGetWorldPosition();
 	if (dist != 0.0f)
@@ -1712,12 +1716,15 @@
 	if (!PyVecTo(pyto, toPoint))
 	{
 		PyErr_Clear();
-		if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type)) {
+		
+		if (ConvertPythonToGameObject(pyto, &other, false))
+		{
+			toPoint = other->NodeGetWorldPosition();
+		} else
+		{
 			PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
 			return NULL;
 		}
-		other = static_cast<KX_GameObject*>(pyto);
-		toPoint = other->NodeGetWorldPosition();
 	}
 	if (!pyfrom || pyfrom == Py_None)
 	{
@@ -1726,12 +1733,15 @@
 	else if (!PyVecTo(pyfrom, fromPoint))
 	{
 		PyErr_Clear();
-		if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type)) {
+		
+		if (ConvertPythonToGameObject(pyfrom, &other, false))
+		{
+			fromPoint = other->NodeGetWorldPosition();
+		} else
+		{
 			PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
 			return NULL;
 		}
-		other = static_cast<KX_GameObject*>(pyfrom);
-		fromPoint = other->NodeGetWorldPosition();
 	}
 	
 	if (dist != 0.0f) {
@@ -1798,3 +1808,49 @@
 	}
 }
 
+bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok)
+{
+	if (value==NULL) {
+		PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen");
+		*object = NULL;
+		return false;
+	}
+		
+	if (value==Py_None) {
+		*object = NULL;
+		
+		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");
+			return false;
+		}
+		return (py_none_ok ? true : false);
+	}
+	
+	if (PyString_Check(value)) {
+		*object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
+		
+		if (*object) {
+			return true;
+		} else {
+			PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject");
+			return false;
+		}
+	}
+	
+	if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
+		*object = static_cast<KX_GameObject*>(value);
+		return true;
+	}
+	
+	*object = NULL;
+	
+	if (py_none_ok) {
+		PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None");
+	} else {
+		PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string");
+	}
+	
+	return false;
+}

Modified: trunk/blender/source/gameengine/Ketsji/KX_GameObject.h
===================================================================

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list