BGE set visible actuator, option to set visibility recursively to make managing visibility for collections of objects a lot easier.

BGE Python api's ob.setVisible() also takes an optional recursive arg thats off by default
This commit is contained in:
Campbell Barton 2008-09-05 16:22:14 +00:00
parent 2e653838c0
commit 5eab0da633
8 changed files with 74 additions and 28 deletions

@ -193,7 +193,8 @@ typedef struct bGameActuator {
} bGameActuator; } bGameActuator;
typedef struct bVisibilityActuator { typedef struct bVisibilityActuator {
/** bit 0: Is this object visible? */ /** bit 0: Is this object visible?
** bit 1: Apply recursively */
int flag; int flag;
} bVisibilityActuator; } bVisibilityActuator;
@ -448,6 +449,7 @@ typedef struct FreeCamera {
/* visibilityact->flag */ /* visibilityact->flag */
/* Set means the object will become invisible */ /* Set means the object will become invisible */
#define ACT_VISIBILITY_INVISIBLE (1 << 0) #define ACT_VISIBILITY_INVISIBLE (1 << 0)
#define ACT_VISIBILITY_RECURSIVE (1 << 1)
/* twodfilter->type */ /* twodfilter->type */
#define ACT_2DFILTER_ENABLED -2 #define ACT_2DFILTER_ENABLED -2

@ -2350,7 +2350,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
visAct = act->data; 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, uiDefButI(block, MENU, B_REDR, str,
xco + 10, yco - 24, width - 20, 19, &visAct->flag, xco + 10, yco - 24, width - 20, 19, &visAct->flag,

@ -962,10 +962,9 @@ void BL_ConvertActuators(char* maggiename,
bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data; bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data;
KX_VisibilityActuator * tmp_vis_act = NULL; KX_VisibilityActuator * tmp_vis_act = NULL;
bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0); bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0);
bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0);
tmp_vis_act = tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive);
new KX_VisibilityActuator(gameobj,
!v);
baseact = tmp_vis_act; baseact = tmp_vis_act;
} }

@ -364,15 +364,36 @@ void KX_GameObject::AddMeshUser()
for (size_t i=0;i<m_meshes.size();i++) for (size_t i=0;i<m_meshes.size();i++)
m_meshes[i]->AddMeshUser(this); 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(); double* fl = GetOpenGLMatrix();
for (size_t i=0;i<m_meshes.size();i++) for (size_t i=0;i<m_meshes.size();i++)
m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
if (recursive) {
UpdateBuckets_recursive(m_pSGNode);
}
} }
void KX_GameObject::RemoveMeshes() void KX_GameObject::RemoveMeshes()
@ -502,12 +523,33 @@ KX_GameObject::GetVisible(
return m_bVisible; 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 void
KX_GameObject::SetVisible( KX_GameObject::SetVisible(
bool v bool v,
bool recursive
) )
{ {
m_bVisible = v; m_bVisible = v;
if (recursive)
setVisible_recursive(m_pSGNode, v);
} }
bool bool
@ -880,7 +922,7 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
{"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
{"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, {"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}, {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
{"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
{"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"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); int val = PyInt_AsLong(value);
if (attr == "visible") if (attr == "visible")
{ {
SetVisible(val != 0); SetVisible(val != 0, false);
UpdateBuckets(); UpdateBuckets(false);
return 0; return 0;
} }
} }
@ -1198,17 +1240,14 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value) PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
{ {
int visible = PyInt_AsLong(value); int visible, recursive = 0;
if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive))
if (visible==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
return NULL; return NULL;
}
SetVisible(visible != 0); SetVisible(visible ? true:false, recursive ? true:false);
UpdateBuckets(); UpdateBuckets(recursive ? true:false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }

@ -566,6 +566,7 @@ public:
*/ */
void void
UpdateBuckets( UpdateBuckets(
bool recursive
); );
/** /**
@ -640,7 +641,8 @@ public:
*/ */
void void
SetVisible( SetVisible(
bool b bool b,
bool recursive
); );
/** /**
@ -762,7 +764,7 @@ public:
KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation);
KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_O(KX_GameObject,SetOrientation);
KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); 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_NOARGS(KX_GameObject,GetState);
KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_O(KX_GameObject,SetState);
KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);

@ -1235,7 +1235,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi
} }
gameobj->SetCulled(!visible); gameobj->SetCulled(!visible);
gameobj->UpdateBuckets(); gameobj->UpdateBuckets(false);
} }
} }
if (node->Left()) if (node->Left())
@ -1253,7 +1253,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
// Shadow lamp layers // Shadow lamp layers
if(layer && !(gameobj->GetLayer() & layer)) { if(layer && !(gameobj->GetLayer() & layer)) {
gameobj->SetCulled(true); gameobj->SetCulled(true);
gameobj->UpdateBuckets(); gameobj->UpdateBuckets(false);
return; return;
} }
@ -1300,10 +1300,10 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
// Visibility/ non-visibility are marked // Visibility/ non-visibility are marked
// elsewhere now. // elsewhere now.
gameobj->SetCulled(false); gameobj->SetCulled(false);
gameobj->UpdateBuckets(); gameobj->UpdateBuckets(false);
} else { } else {
gameobj->SetCulled(true); gameobj->SetCulled(true);
gameobj->UpdateBuckets(); gameobj->UpdateBuckets(false);
} }
} }

@ -38,10 +38,12 @@
KX_VisibilityActuator::KX_VisibilityActuator( KX_VisibilityActuator::KX_VisibilityActuator(
SCA_IObject* gameobj, SCA_IObject* gameobj,
bool visible, bool visible,
bool recursive,
PyTypeObject* T PyTypeObject* T
) )
: SCA_IActuator(gameobj,T), : SCA_IActuator(gameobj,T),
m_visible(visible) m_visible(visible),
m_recursive(recursive)
{ {
// intentionally empty // intentionally empty
} }
@ -75,8 +77,8 @@ KX_VisibilityActuator::Update()
KX_GameObject *obj = (KX_GameObject*) GetParent(); KX_GameObject *obj = (KX_GameObject*) GetParent();
obj->SetVisible(m_visible); obj->SetVisible(m_visible, m_recursive);
obj->UpdateBuckets(); obj->UpdateBuckets(m_recursive);
return true; return true;
} }

@ -39,12 +39,14 @@ class KX_VisibilityActuator : public SCA_IActuator
/** Make visible? */ /** Make visible? */
bool m_visible; bool m_visible;
bool m_recursive;
public: public:
KX_VisibilityActuator( KX_VisibilityActuator(
SCA_IObject* gameobj, SCA_IObject* gameobj,
bool visible, bool visible,
bool recursive,
PyTypeObject* T=&Type PyTypeObject* T=&Type
); );