forked from bartvdbraak/blender
[#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
This commit is contained in:
parent
f4a0c9239f
commit
c36f78dd41
@ -465,7 +465,8 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -1306,7 +1306,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
|
||||
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();
|
||||
|
@ -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),
|
||||
|
@ -95,6 +95,8 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
PyObject* m_attr_dict;
|
||||
PyObject* m_draw_call_pre;
|
||||
PyObject* m_draw_call_post;
|
||||
#endif
|
||||
|
||||
struct CullingInfo {
|
||||
@ -102,7 +104,6 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
|
||||
CullingInfo(int layer) : m_layer(layer) {}
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
RAS_BucketManager* m_bucketmanager;
|
||||
CListValue* m_tempObjectList;
|
||||
@ -287,6 +288,12 @@ public:
|
||||
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.
|
||||
*/
|
||||
@ -544,6 +551,10 @@ public:
|
||||
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 @@ public:
|
||||
static PyMappingMethods Mapping;
|
||||
static PySequenceMethods Sequence;
|
||||
|
||||
PyObject* GetPreDrawCB() { return m_draw_call_pre; };
|
||||
PyObject* GetPostDrawCB() { return m_draw_call_post; };
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user