BGE: scene.pre_draw_setup[] callback
authorDalai Felinto <dfelinto@gmail.com>
Tue, 21 Apr 2015 20:36:18 +0000 (17:36 -0300)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 21 Apr 2015 20:41:23 +0000 (17:41 -0300)
This callback allows the user to change the camera data right before the
rendering calculations.

scene.pre_draw[] is not enough here, because if you want to change the
camera matrices (projection/modelview) the culling test is done before
that (after pre_draw_setup[] though).

Reviewers: moguri, campbellbarton

Differential Revision: https://developer.blender.org/D1251

Python sample code using this. The sample scene would need a default
camera (not used for rendering), a dummy camera ('Camera.VR'), and two
cameras ('Camera.Left', 'Camera.Right') that will be used for the actual
rendering.

```
import bge

def callback():
    scene = bge.logic.getCurrentScene()
    objects = scene.objects

    vr_camera = objects.get('Camera.VR')

    if bge.render.getStereoEye() ==  bge.render.LEFT_EYE:
        camera = objects.get('Camera.Left')
    else:
        camera = objects.get('Camera.Right')

    vr_camera.worldOrientation = camera.worldOrientation
    vr_camera.worldPosition =  camera.worldPosition

def init():
    scene = bge.logic.getCurrentScene()
    main_camera = scene.active_camera
    main_camera.useViewport = True

   scene.pre_draw_setup.append(callback)

    objects = scene.objects
    vr_camera = objects.get('Camera.VR')
    vr_camera.useViewport = True
    vr_camera.setViewport(
            0,
            0,
            bge.render.getWindowWidth(),
            bge.render.getWindowHeight() )
```

doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h

index a6135054058146c14a11417eda3e931dc678ba5b..f4846cd9265cc5d68c20e0a19e439306c9d3ee88 100644 (file)
@@ -125,6 +125,12 @@ base class --- :class:`PyObjectPlus`
 
       :type: list
 
+   .. attribute:: pre_draw_setup
+
+      A list of callables to be run before the drawing setup (i.e., before the model view and projection matrices are computed).
+
+      :type: list
+
    .. attribute:: gravity
 
       The scene gravity using the world x, y and z axis.
index f0b47684092d65056200b2bbdc41938ef8ecd5f2..40af9b4ca39dd0fe4d2abccf553c1d2c9b749945 100644 (file)
@@ -1108,6 +1108,10 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
 
        KX_SetActiveScene(scene);
 
+#ifdef WITH_PYTHON
+       scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB());
+#endif
+
        GetSceneViewport(scene, cam, area, viewport);
 
        // store the computed viewport in the scene
index a3e1d1562c9b64c4ef7db938395836cd4911956a..ca4d017fe8c23fd7c3282c95744615f732c04ea5 100644 (file)
@@ -238,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
        m_attr_dict = NULL;
        m_draw_call_pre = NULL;
        m_draw_call_post = NULL;
+       m_draw_setup_call_pre = NULL;
 #endif
 }
 
@@ -2399,6 +2400,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT
        return self->m_draw_call_post;
 }
 
+PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+       if (self->m_draw_setup_call_pre == NULL)
+               self->m_draw_setup_call_pre = PyList_New(0);
+
+       Py_INCREF(self->m_draw_setup_call_pre);
+       return self->m_draw_setup_call_pre;
+}
+
 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);
@@ -2433,6 +2445,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT
        return PY_SET_ATTR_SUCCESS;
 }
 
+int KX_Scene::pyattr_set_drawing_setup_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_setup_call_pre);
+       Py_INCREF(value);
+
+       self->m_draw_setup_call_pre = value;
+       return PY_SET_ATTR_SUCCESS;
+}
+
 PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2462,6 +2490,7 @@ PyAttributeDef KX_Scene::Attributes[] = {
        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_RW_FUNCTION("pre_draw_setup",    KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre),
        KX_PYATTRIBUTE_RW_FUNCTION("gravity",                   KX_Scene, pyattr_get_gravity, pyattr_set_gravity),
        KX_PYATTRIBUTE_BOOL_RO("suspended",                             KX_Scene, m_suspend),
        KX_PYATTRIBUTE_BOOL_RO("activity_culling",              KX_Scene, m_activity_culling),
index 93e764851a96dfc41a7e489622147717a97167ef..a5645ea6448b4845099abbeddaf1c7e7c636002b 100644 (file)
@@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
        PyObject*       m_attr_dict;
        PyObject*       m_draw_call_pre;
        PyObject*       m_draw_call_post;
+       PyObject*       m_draw_setup_call_pre;
 #endif
 
        struct CullingInfo {
@@ -631,6 +632,8 @@ public:
        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);
+       static PyObject*        pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static PyObject*        pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
@@ -647,6 +650,7 @@ public:
        
        PyObject *GetPreDrawCB() { return m_draw_call_pre; }
        PyObject *GetPostDrawCB() { return m_draw_call_post; }
+       PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; }
 #endif
 
        /**