BGE set visible actuator, option to set visibility recursively to make managing visib...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 5 Sep 2008 16:22:14 +0000 (16:22 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 5 Sep 2008 16:22:14 +0000 (16:22 +0000)
BGE Python api's ob.setVisible() also takes an optional recursive arg thats off by default

source/blender/makesdna/DNA_actuator_types.h
source/blender/src/buttons_logic.c
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_VisibilityActuator.cpp
source/gameengine/Ketsji/KX_VisibilityActuator.h

index d08cf42..ca0ad06 100644 (file)
@@ -193,7 +193,8 @@ typedef struct bGameActuator {
 } bGameActuator;
 
 typedef struct bVisibilityActuator {
-       /** bit 0: Is this object visible? */
+       /** bit 0: Is this object visible? 
+        ** bit 1: Apply recursively  */
        int flag;
 } bVisibilityActuator;
 
@@ -448,6 +449,7 @@ typedef struct FreeCamera {
 /* visibilityact->flag */
 /* Set means the object will become invisible */
 #define ACT_VISIBILITY_INVISIBLE       (1 << 0)
+#define ACT_VISIBILITY_RECURSIVE       (1 << 1)
 
 /* twodfilter->type */
 #define ACT_2DFILTER_ENABLED                   -2
index 9c66b78..df76534 100644 (file)
@@ -2350,7 +2350,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                
                visAct = act->data;
 
-               str= "Visibility %t|Visible %x0|Invisible %x1";
+               str= "Visibility %t|Visible %x0|Invisible %x1|Visible Recursive %x2|Invisible Recursive %x3";
 
                uiDefButI(block, MENU, B_REDR, str,
                          xco + 10, yco - 24, width - 20, 19, &visAct->flag,
index 321fc32..3142f76 100644 (file)
@@ -962,10 +962,9 @@ void BL_ConvertActuators(char* maggiename,
                        bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data;
                        KX_VisibilityActuator * tmp_vis_act = NULL;
                        bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0);
+                       bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0);
 
-                       tmp_vis_act = 
-                               new KX_VisibilityActuator(gameobj,
-                                                         !v);
+                       tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive);
                        
                        baseact = tmp_vis_act;
                }
index bec5d18..204eed9 100644 (file)
@@ -364,15 +364,36 @@ void KX_GameObject::AddMeshUser()
        for (size_t i=0;i<m_meshes.size();i++)
                m_meshes[i]->AddMeshUser(this);
        
-       UpdateBuckets();
+       UpdateBuckets(false);
 }
 
-void KX_GameObject::UpdateBuckets()
+static void UpdateBuckets_recursive(SG_Node* node)
+{
+       NodeList& children = node->GetSGChildren();
+
+       for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+       {
+               SG_Node* childnode = (*childit);
+               KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+               if (clientgameobj != NULL) // This is a GameObject
+                       clientgameobj->UpdateBuckets(0);
+               
+               // if the childobj is NULL then this may be an inverse parent link
+               // so a non recursive search should still look down this node.
+               UpdateBuckets_recursive(childnode);
+       }
+}
+
+void KX_GameObject::UpdateBuckets( bool recursive )
 {
        double* fl = GetOpenGLMatrix();
 
        for (size_t i=0;i<m_meshes.size();i++)
                m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
+       
+       if (recursive) {
+               UpdateBuckets_recursive(m_pSGNode);
+       }
 }
 
 void KX_GameObject::RemoveMeshes()
@@ -502,12 +523,33 @@ KX_GameObject::GetVisible(
        return m_bVisible;
 }
 
+static void setVisible_recursive(SG_Node* node, bool v)
+{
+       NodeList& children = node->GetSGChildren();
+
+       for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+       {
+               SG_Node* childnode = (*childit);
+               KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+               if (clientgameobj != NULL) // This is a GameObject
+                       clientgameobj->SetVisible(v, 0);
+               
+               // if the childobj is NULL then this may be an inverse parent link
+               // so a non recursive search should still look down this node.
+               setVisible_recursive(childnode, v);
+       }
+}
+
+
 void
 KX_GameObject::SetVisible(
-       bool v
+       bool v,
+       bool recursive
        )
 {
        m_bVisible = v;
+       if (recursive)
+               setVisible_recursive(m_pSGNode, v);
 }
 
 bool
@@ -880,7 +922,7 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
        {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
        {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
-       {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O},
+       {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
        {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
        {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
        {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
@@ -1036,8 +1078,8 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)      // _setattr
                int val = PyInt_AsLong(value);
                if (attr == "visible")
                {
-                       SetVisible(val != 0);
-                       UpdateBuckets();
+                       SetVisible(val != 0, false);
+                       UpdateBuckets(false);
                        return 0;
                }
        }
@@ -1198,17 +1240,14 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
        return NULL;
 }
 
-PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
 {
-       int visible = PyInt_AsLong(value);
-       
-       if (visible==-1 && PyErr_Occurred()) {
-               PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
+       int visible, recursive = 0;
+       if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive))
                return NULL;
-       }
        
-       SetVisible(visible != 0);
-       UpdateBuckets();
+       SetVisible(visible ? true:false, recursive ? true:false);
+       UpdateBuckets(recursive ? true:false);
        Py_RETURN_NONE;
        
 }
index 9dcf652..98b3f3b 100644 (file)
@@ -566,6 +566,7 @@ public:
         */
                void                                            
        UpdateBuckets(
+               bool recursive
        );
 
        /**
@@ -640,7 +641,8 @@ public:
         */
                void
        SetVisible(
-               bool b
+               bool b,
+               bool recursive
        );
 
        /**
@@ -762,7 +764,7 @@ public:
        KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation);
        KX_PYMETHOD_O(KX_GameObject,SetOrientation);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible);
-       KX_PYMETHOD_O(KX_GameObject,SetVisible);
+       KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible);
        KX_PYMETHOD_NOARGS(KX_GameObject,GetState);
        KX_PYMETHOD_O(KX_GameObject,SetState);
        KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
index 2ad0412..72875bb 100644 (file)
@@ -1235,7 +1235,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi
                        }
 
                        gameobj->SetCulled(!visible);
-                       gameobj->UpdateBuckets();
+                       gameobj->UpdateBuckets(false);
                }
        }
        if (node->Left())
@@ -1253,7 +1253,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
        // Shadow lamp layers
        if(layer && !(gameobj->GetLayer() & layer)) {
                gameobj->SetCulled(true);
-               gameobj->UpdateBuckets();
+               gameobj->UpdateBuckets(false);
                return;
        }
 
@@ -1300,10 +1300,10 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
                // Visibility/ non-visibility are marked
                // elsewhere now.
                gameobj->SetCulled(false);
-               gameobj->UpdateBuckets();
+               gameobj->UpdateBuckets(false);
        } else {
                gameobj->SetCulled(true);
-               gameobj->UpdateBuckets();
+               gameobj->UpdateBuckets(false);
        }
 }
 
index 5a0cadc..60ea6ac 100644 (file)
 KX_VisibilityActuator::KX_VisibilityActuator(
        SCA_IObject* gameobj,
        bool visible,
+       bool recursive,
        PyTypeObject* T
        ) 
        : SCA_IActuator(gameobj,T),
-         m_visible(visible)
+         m_visible(visible),
+         m_recursive(recursive)
 {
        // intentionally empty
 }
@@ -75,8 +77,8 @@ KX_VisibilityActuator::Update()
 
        KX_GameObject *obj = (KX_GameObject*) GetParent();
        
-       obj->SetVisible(m_visible);
-       obj->UpdateBuckets();
+       obj->SetVisible(m_visible, m_recursive);
+       obj->UpdateBuckets(m_recursive);
 
        return true;
 }
index 9b47530..d1b85ab 100644 (file)
@@ -39,12 +39,14 @@ class KX_VisibilityActuator : public SCA_IActuator
 
        /** Make visible? */
        bool m_visible;
+       bool m_recursive;
 
  public:
        
        KX_VisibilityActuator(
                SCA_IObject* gameobj,
                bool visible,
+               bool recursive,
                PyTypeObject* T=&Type
                );