diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-11-22 17:42:22 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-11-22 17:42:22 +0300 |
commit | c36f78dd41b8d2c714b2a94c43eabe928afea26a (patch) | |
tree | 48856d51a20eb4024f142e1fb68a9d345a291aeb /source/gameengine/Ketsji/KX_Scene.cpp | |
parent | f4a0c9239ff21a75a336ed3f496dd88d3997d28e (diff) |
[#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
Diffstat (limited to 'source/gameengine/Ketsji/KX_Scene.cpp')
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 655c8eedaae..c018dcd387f 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -211,6 +211,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, #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 @@ KX_Scene::~KX_Scene() #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 @@ bool KX_Scene::IsClearingZBuffer() 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,6 +2024,61 @@ int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *a 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), @@ -2005,6 +2087,8 @@ PyAttributeDef KX_Scene::Attributes[] = { 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), |