Revision: 15628
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15628
Author:   ben2610
Date:     2008-07-18 21:56:56 +0200 (Fri, 18 Jul 2008)

Log Message:
-----------
BGE patch: support for partial hierarchy in dupligroup instantiation; removal 
of links that point to inactive objects during group instantiation.

This situation corresponds to a group containing only a portion
of a parent hierarchy (the Apricot team needed that to avoid
logic duplication). The BGE will instantiate only the
children that are in the group so that it follows the 3D view
more closely.
As a result, the logic links to the objects in the portion of the
hierarchy that was not replicated will point to inactive objects
(if the groups are stored in inactive layers as they should be). 
To keep the logic system consistent, these links are automatically
removed.
This last part of the patch is a general fix that could go in
2.47 but as this situation does not normally occurs in pre-2.47
games, it is not needed.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.h
    trunk/blender/source/gameengine/SceneGraph/SG_IObject.cpp
    trunk/blender/source/gameengine/SceneGraph/SG_IObject.h
    trunk/blender/source/gameengine/SceneGraph/SG_Node.cpp
    trunk/blender/source/gameengine/SceneGraph/SG_Node.h

Modified: trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp 2008-07-18 19:54:15 UTC 
(rev 15627)
+++ trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp 2008-07-18 19:56:56 UTC 
(rev 15628)
@@ -431,6 +431,11 @@
 
 KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class 
CValue* gameobj)
 {
+       // for group duplication, limit the duplication of the hierarchy to the
+       // objects that are part of the group. 
+       if (!IsObjectInGroup(gameobj))
+               return NULL;
+       
        KX_GameObject* orgobj = (KX_GameObject*)gameobj;
        KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica();
        m_map_gameobject_to_replica.insert(orgobj, newobj);
@@ -545,7 +550,9 @@
                        if (!newsensorobj)
                        {
                                // no, then the sensor points outside the 
hierachy, keep it the same
-                               m_logicmgr->RegisterToSensor(cont,oldsensor);
+                               if (m_objectlist->SearchValue(oldsensorobj))
+                                       // only replicate links that points to 
active objects
+                                       
m_logicmgr->RegisterToSensor(cont,oldsensor);
                        }
                        else
                        {
@@ -583,7 +590,9 @@
                        if (!newactuatorobj)
                        {
                                // no, then the sensor points outside the 
hierachy, keep it the same
-                               
m_logicmgr->RegisterToActuator(cont,oldactuator);
+                               if (m_objectlist->SearchValue(oldactuatorobj))
+                                       // only replicate links that points to 
active objects
+                                       
m_logicmgr->RegisterToActuator(cont,oldactuator);
                        }
                        else
                        {
@@ -615,6 +624,7 @@
 {
        KX_GameObject* groupobj = (KX_GameObject*) obj;
        KX_GameObject* replica;
+       KX_GameObject* gameobj;
        Object* blgroupobj = groupobj->GetBlenderObject();
        Group* group;
        GroupObject *go;
@@ -628,6 +638,10 @@
        m_logicHierarchicalGameObjects.clear();
        m_map_gameobject_to_replica.clear();
        m_ueberExecutionPriority++;
+       // for groups will do something special: 
+       // we will force the creation of objects to those in the group only
+       // Again, this is match what Blender is doing (it doesn't care of 
parent relationship)
+       m_groupGameObjects.clear();
 
        group = blgroupobj->dup_group;
        for(go=(GroupObject*)group->gobject.first; go; 
go=(GroupObject*)go->next) 
@@ -636,13 +650,25 @@
                if (blgroupobj == blenderobj)
                        // this check is also in group_duplilist()
                        continue;
-               KX_GameObject* gameobj = 
m_sceneConverter->FindGameObject(blenderobj);
+               gameobj = m_sceneConverter->FindGameObject(blenderobj);
                if (gameobj == NULL) 
                {
                        // this object has not been converted!!!
                        // Should not happen as dupli group are created 
automatically 
                        continue;
                }
+               if (blenderobj->lay & group->layer==0)
+               {
+                       // object is not visible in the 3D view, will not be 
instantiated
+                       continue;
+               }
+               m_groupGameObjects.insert(gameobj);
+       }
+
+       set<CValue*>::iterator oit;
+       for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); 
oit++)
+       {
+               gameobj = (KX_GameObject*)(*oit);
                if (gameobj->GetParent() != NULL)
                {
                        // this object is not a top parent. Either it is the 
child of another
@@ -651,11 +677,6 @@
                        // is inconsistent, skip it anyway
                        continue;
                }
-               if (blenderobj->lay & group->layer==0)
-               {
-                       // object is not visible in the 3D view, will not be 
instantiated
-                       continue;
-               }
                replica = (KX_GameObject*) AddNodeReplicaObject(NULL,gameobj);
                // add to 'rootparent' list (this is the list of top hierarchy 
objects, updated each frame)
                m_parentlist->Add(replica->AddRef());
@@ -668,7 +689,8 @@
                {
                        SG_Node* orgnode = (*childit);
                        SG_Node* childreplicanode = orgnode->GetSGReplica();
-                       replica->GetSGNode()->AddChild(childreplicanode);
+                       if (childreplicanode)
+                               
replica->GetSGNode()->AddChild(childreplicanode);
                }
                // don't replicate logic now: we assume that the objects in the 
group can have
                // logic relationship, even outside parent relationship
@@ -745,6 +767,7 @@
 
        m_logicHierarchicalGameObjects.clear();
        m_map_gameobject_to_replica.clear();
+       m_groupGameObjects.clear();
 
        // todo: place a timebomb in the object, for temporarily objects :)
        // lifespan of zero means 'this object lives forever'
@@ -778,7 +801,8 @@
        {
                SG_Node* orgnode = (*childit);
                SG_Node* childreplicanode = orgnode->GetSGReplica();
-               replica->GetSGNode()->AddChild(childreplicanode);
+               if (childreplicanode)
+                       replica->GetSGNode()->AddChild(childreplicanode);
        }
 
        //      relink any pointers as necessary, sort of a temporary solution

Modified: trunk/blender/source/gameengine/Ketsji/KX_Scene.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Scene.h   2008-07-18 19:54:15 UTC 
(rev 15627)
+++ trunk/blender/source/gameengine/Ketsji/KX_Scene.h   2008-07-18 19:56:56 UTC 
(rev 15628)
@@ -216,6 +216,16 @@
         */
        std::vector<KX_GameObject*>     m_logicHierarchicalGameObjects;
        
+       /**
+        * This temporary variable will contain the list of 
+        * object that can be added during group instantiation.
+        * objects outside this list will not be added (can 
+        * happen with children that are outside the group).
+        * Used in AddReplicaObject. If the list is empty, it
+        * means don't care.
+        */
+       std::set<CValue*>       m_groupGameObjects;
+       
        /** 
         * Pointer to system variable passed in in constructor
         * only used in constructor so we do not need to keep it
@@ -292,6 +302,11 @@
         */
        void UpdateParents(double curtime);
        void DupliGroupRecurse(CValue* gameobj, int level);
+       bool IsObjectInGroup(CValue* gameobj)
+       { 
+               return (m_groupGameObjects.empty() || 
+                               m_groupGameObjects.find(gameobj) != 
m_groupGameObjects.end());
+       }
        SCA_IObject* AddReplicaObject(CValue* gameobj,
                                                                  CValue* 
locationobj,
                                                                  int 
lifespan=0);

Modified: trunk/blender/source/gameengine/SceneGraph/SG_IObject.cpp
===================================================================
--- trunk/blender/source/gameengine/SceneGraph/SG_IObject.cpp   2008-07-18 
19:54:15 UTC (rev 15627)
+++ trunk/blender/source/gameengine/SceneGraph/SG_IObject.cpp   2008-07-18 
19:56:56 UTC (rev 15628)
@@ -104,7 +104,7 @@
 }
 
 
-       void
+       bool
 SG_IObject::
 ActivateReplicationCallback(
        SG_IObject *replica
@@ -112,8 +112,10 @@
        if (m_callbacks.m_replicafunc)
        {
                // Call client provided replication func
-               
m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo);
+               if 
(m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
+                       return false;
        }
+       return true;
 };     
 
        void

Modified: trunk/blender/source/gameengine/SceneGraph/SG_IObject.h
===================================================================
--- trunk/blender/source/gameengine/SceneGraph/SG_IObject.h     2008-07-18 
19:54:15 UTC (rev 15627)
+++ trunk/blender/source/gameengine/SceneGraph/SG_IObject.h     2008-07-18 
19:56:56 UTC (rev 15628)
@@ -202,7 +202,7 @@
 
 protected :
 
-               void
+               bool
        ActivateReplicationCallback(
                SG_IObject *replica
        );

Modified: trunk/blender/source/gameengine/SceneGraph/SG_Node.cpp
===================================================================
--- trunk/blender/source/gameengine/SceneGraph/SG_Node.cpp      2008-07-18 
19:54:15 UTC (rev 15627)
+++ trunk/blender/source/gameengine/SceneGraph/SG_Node.cpp      2008-07-18 
19:56:56 UTC (rev 15628)
@@ -68,7 +68,7 @@
        SG_Node* replica = new SG_Node(*this);
        if (replica == NULL) return NULL;
 
-       ProcessSGReplica(replica);
+       ProcessSGReplica(&replica);
        
        return replica;
 }
@@ -76,25 +76,42 @@
        void 
 SG_Node::
 ProcessSGReplica(
-       SG_Node* replica
+       SG_Node** replica
 ){
        // Apply the replication call back function.
-       ActivateReplicationCallback(replica);
+       if (!ActivateReplicationCallback(*replica)) 
+       {
+               delete (*replica);
+               *replica = NULL;
+               return;
+       }
 
        // clear the replica node of it's parent.
-       static_cast<SG_Node*>(replica)->m_SGparent = NULL;
+       static_cast<SG_Node*>(*replica)->m_SGparent = NULL;
 
        if (m_children.begin() != m_children.end())
        {
                // if this node has children, the replica has too, so clear and 
clone children
-               replica->ClearSGChildren();
+               (*replica)->ClearSGChildren();
        
                NodeList::iterator childit;
                for (childit = 
m_children.begin();childit!=m_children.end();++childit)
                {
-                       replica->AddChild((*childit)->GetSGReplica());
+                       SG_Node* childnode = (*childit)->GetSGReplica();
+                       if (childnode)
+                               (*replica)->AddChild(childnode);
                }
        }
+       // Nodes without children and without client object are
+       // not worth to keep, they will just take up CPU
+       // This can happen in partial replication of hierarchy
+       // during group duplication.
+       if ((*replica)->m_children.empty() && 
+               (*replica)->GetSGClientObject() == NULL)
+       {
+               delete (*replica);
+               *replica = NULL;
+       }
 }
 
 

Modified: trunk/blender/source/gameengine/SceneGraph/SG_Node.h
===================================================================
--- trunk/blender/source/gameengine/SceneGraph/SG_Node.h        2008-07-18 
19:54:15 UTC (rev 15627)
+++ trunk/blender/source/gameengine/SceneGraph/SG_Node.h        2008-07-18 
19:56:56 UTC (rev 15628)
@@ -205,7 +205,7 @@
 
                void            
        ProcessSGReplica(
-               SG_Node* replica
+               SG_Node** replica
        );
 
        /**


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to