[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24769] trunk/blender/source/gameengine: [ #19258] [patch] Adding drawing capabilities to BGE Python

Campbell Barton ideasman42 at gmail.com
Sun Nov 22 15:42:22 CET 2009


Revision: 24769
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24769
Author:   campbellbarton
Date:     2009-11-22 15:42:22 +0100 (Sun, 22 Nov 2009)

Log Message:
-----------
[#19258] [patch] Adding drawing capabilities to BGE Python
patch from Mitchell Stokes (moguri)

simple use case
 scene.post_draw = [pyOpenGLFunc]

this only needs to be set once, then the funcion runs each redraw.

note, this patch also changes how python scripts run (not modules): Dont clear the namespace after running a script, since functions still use the namespace, BGE API is now better when dealing with stale data.

made some changes to this patch.
- assigning a list didnt decrement the existing list.
- initialize as NULL rather then a blank list
- dont use string comparisons for the callbacks, pass the python list to use instead.
- dont check the list items are callable. python will display an error if they are not.
- use python list macros that dont do any type checking sine blender does this when assigning the list

---- from tracker, edited since an updated patch changes some things.
Here is a patch to be able to draw to the screen with BGE Python. This will be very handy for GUI stuff. This patch
works by having the user register a callback in the scene. Two options are available KX_Scene.pre_draw
and KX_Scene.post_draw. The difference between these is when Python draws to the screen (before or after the BGE).
Each can take a list of functions. Here is an example that draws a blue semi-transparent

Modified Paths:
--------------
    trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp
    trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.h

Modified: trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp	2009-11-22 14:19:03 UTC (rev 24768)
+++ trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp	2009-11-22 14:42:22 UTC (rev 24769)
@@ -465,7 +465,8 @@
 	{
 		/* clear after PyErrPrint - seems it can be using
 		 * something in this dictionary and crash? */
-		PyDict_Clear(excdict);
+		// This doesn't appear to be needed anymore
+		//PyDict_Clear(excdict);
 		Py_DECREF(excdict);
 	}	
 	

Modified: trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp	2009-11-22 14:19:03 UTC (rev 24768)
+++ trunk/blender/source/gameengine/Ketsji/KX_KetsjiEngine.cpp	2009-11-22 14:42:22 UTC (rev 24769)
@@ -1306,7 +1306,13 @@
 	m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
 	SG_SetActiveStage(SG_STAGE_RENDER);
 
+	// Run any pre-drawing python callbacks
+	scene->RunDrawingCallbacks(scene->GetPreDrawCB());
+
 	scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+
+	// Run any post-drawing python callbacks
+	scene->RunDrawingCallbacks(scene->GetPostDrawCB());
 	
 	if (scene->GetPhysicsEnvironment())
 		scene->GetPhysicsEnvironment()->debugDrawWorld();

Modified: trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp	2009-11-22 14:19:03 UTC (rev 24768)
+++ trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp	2009-11-22 14:42:22 UTC (rev 24769)
@@ -211,6 +211,8 @@
 	
 #ifndef DISABLE_PYTHON
 	m_attr_dict = PyDict_New(); /* new ref */
+	m_draw_call_pre = NULL;
+	m_draw_call_post = NULL;
 #endif
 }
 
@@ -264,6 +266,9 @@
 #ifndef DISABLE_PYTHON
 	PyDict_Clear(m_attr_dict);
 	Py_DECREF(m_attr_dict);
+
+	Py_XDECREF(m_draw_call_pre);
+	Py_XDECREF(m_draw_call_post);
 #endif
 }
 
@@ -401,6 +406,28 @@
 	return m_isclearingZbuffer;
 }
 
+void KX_Scene::RunDrawingCallbacks(PyObject* cb_list)
+{
+	int len;
+
+	if (cb_list && (len=PyList_GET_SIZE(cb_list)))
+	{
+		PyObject* func;
+		PyObject* ret;
+
+		// Iterate the list and run the callbacks
+		for (int pos=0; pos < len; pos++)
+		{
+			func= PyList_GET_ITEM(cb_list, pos);
+			ret= PyObject_CallObject(func, NULL);
+			if (ret==NULL) {
+				PyErr_Print();
+				PyErr_Clear();
+			}
+		}
+	}
+}
+
 void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer)
 {
 	m_isclearingZbuffer = isclearingZbuffer;
@@ -1997,7 +2024,62 @@
 	return PY_SET_ATTR_SUCCESS;
 }
 
+PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Scene* self = static_cast<KX_Scene*>(self_v);
 
+	if(self->m_draw_call_pre==NULL)
+		self->m_draw_call_pre= PyList_New(0);
+	else
+		Py_INCREF(self->m_draw_call_pre);
+	return self->m_draw_call_pre;
+}
+
+PyObject* KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+	KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+	if(self->m_draw_call_post==NULL)
+		self->m_draw_call_post= PyList_New(0);
+	else
+		Py_INCREF(self->m_draw_call_post);
+	return self->m_draw_call_post;
+}
+
+int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+	if (!PyList_CheckExact(value))
+	{
+		PyErr_SetString(PyExc_ValueError, "Expected a list");
+		return PY_SET_ATTR_FAIL;
+	}
+	Py_XDECREF(self->m_draw_call_pre);
+
+	Py_INCREF(value);
+	self->m_draw_call_pre = value;
+
+	return PY_SET_ATTR_SUCCESS;
+}
+
+int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+	KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+	if (!PyList_CheckExact(value))
+	{
+		PyErr_SetString(PyExc_ValueError, "Expected a list");
+		return PY_SET_ATTR_FAIL;
+	}
+	Py_XDECREF(self->m_draw_call_post);
+
+	Py_INCREF(value);
+	self->m_draw_call_post = value;
+
+	return PY_SET_ATTR_SUCCESS;
+}
+
 PyAttributeDef KX_Scene::Attributes[] = {
 	KX_PYATTRIBUTE_RO_FUNCTION("name",				KX_Scene, pyattr_get_name),
 	KX_PYATTRIBUTE_RO_FUNCTION("objects",			KX_Scene, pyattr_get_objects),
@@ -2005,6 +2087,8 @@
 	KX_PYATTRIBUTE_RO_FUNCTION("cameras",			KX_Scene, pyattr_get_cameras),
 	KX_PYATTRIBUTE_RO_FUNCTION("lights",			KX_Scene, pyattr_get_lights),
 	KX_PYATTRIBUTE_RW_FUNCTION("active_camera",		KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
+	KX_PYATTRIBUTE_RW_FUNCTION("pre_draw",			KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre),
+	KX_PYATTRIBUTE_RW_FUNCTION("post_draw",			KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post),
 	KX_PYATTRIBUTE_BOOL_RO("suspended",				KX_Scene, m_suspend),
 	KX_PYATTRIBUTE_BOOL_RO("activity_culling",		KX_Scene, m_activity_culling),
 	KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),

Modified: trunk/blender/source/gameengine/Ketsji/KX_Scene.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Scene.h	2009-11-22 14:19:03 UTC (rev 24768)
+++ trunk/blender/source/gameengine/Ketsji/KX_Scene.h	2009-11-22 14:42:22 UTC (rev 24769)
@@ -95,6 +95,8 @@
 
 #ifndef DISABLE_PYTHON
 	PyObject*	m_attr_dict;
+	PyObject*	m_draw_call_pre;
+	PyObject*	m_draw_call_post;
 #endif
 
 	struct CullingInfo {
@@ -102,7 +104,6 @@
 		CullingInfo(int layer) : m_layer(layer) {}
 	};
 
-
 protected:
 	RAS_BucketManager*	m_bucketmanager;
 	CListValue*			m_tempObjectList;
@@ -287,7 +288,13 @@
 	void RenderBuckets(const MT_Transform& cameratransform,
 						RAS_IRasterizer* rasty,
 						RAS_IRenderTools* rendertools);
+
 	/**
+	 * Run the registered python drawing functions.
+	 */
+	void RunDrawingCallbacks(PyObject* cb_list);
+
+	/**
 	 * Update all transforms according to the scenegraph.
 	 */
 	static bool KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene);
@@ -544,6 +551,10 @@
 	static PyObject*	pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static PyObject*	pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 	static int			pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+	static PyObject*	pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	static int			pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
 	virtual PyObject* py_repr(void) { return PyUnicode_FromString(GetName().ReadPtr()); }
 	
@@ -551,6 +562,8 @@
 	static PyMappingMethods	Mapping;
 	static PySequenceMethods	Sequence;
 
+	PyObject* GetPreDrawCB() { return m_draw_call_pre; };
+	PyObject* GetPostDrawCB() { return m_draw_call_post; };
 #endif
 
 	/**





More information about the Bf-blender-cvs mailing list