Blender V2.61 - r43446

group.c

Go to the documentation of this file.
00001 /* 
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <math.h>
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "DNA_group_types.h"
00041 #include "DNA_material_types.h"
00042 #include "DNA_object_types.h"
00043 #include "DNA_nla_types.h"
00044 #include "DNA_scene_types.h"
00045 #include "DNA_particle_types.h"
00046 
00047 #include "BLI_blenlib.h"
00048 #include "BLI_utildefines.h"
00049 
00050 
00051 #include "BKE_global.h"
00052 #include "BKE_group.h"
00053 #include "BKE_library.h"
00054 #include "BKE_main.h"
00055 #include "BKE_object.h"
00056 #include "BKE_scene.h" /* object_in_scene */
00057 
00058 static void free_group_object(GroupObject *go)
00059 {
00060     MEM_freeN(go);
00061 }
00062 
00063 
00064 void free_group_objects(Group *group)
00065 {
00066     /* don't free group itself */
00067     GroupObject *go;
00068     
00069     while(group->gobject.first) {
00070         go= group->gobject.first;
00071         BLI_remlink(&group->gobject, go);
00072         free_group_object(go);
00073     }
00074 }
00075 
00076 void unlink_group(Group *group)
00077 {
00078     Main *bmain= G.main;
00079     Material *ma;
00080     Object *ob;
00081     Scene *sce;
00082     SceneRenderLayer *srl;
00083     ParticleSystem *psys;
00084     
00085     for(ma= bmain->mat.first; ma; ma= ma->id.next) {
00086         if(ma->group==group)
00087             ma->group= NULL;
00088     }
00089     for(ma= bmain->mat.first; ma; ma= ma->id.next) {
00090         if(ma->group==group)
00091             ma->group= NULL;
00092     }
00093     for (sce= bmain->scene.first; sce; sce= sce->id.next) {
00094         Base *base= sce->base.first;
00095         
00096         /* ensure objects are not in this group */
00097         for(; base; base= base->next) {
00098             if(rem_from_group(group, base->object, sce, base) && find_group(base->object, NULL)==NULL) {
00099                 base->object->flag &= ~OB_FROMGROUP;
00100                 base->flag &= ~OB_FROMGROUP;
00101             }
00102         }           
00103         
00104         for(srl= sce->r.layers.first; srl; srl= srl->next) {
00105             if (srl->light_override==group)
00106                 srl->light_override= NULL;
00107         }
00108     }
00109     
00110     for(ob= bmain->object.first; ob; ob= ob->id.next) {
00111         
00112         if(ob->dup_group==group) {
00113             ob->dup_group= NULL;
00114 #if 0       /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
00115             {
00116                 bActionStrip *strip;
00117                 /* duplicator strips use a group object, we remove it */
00118                 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
00119                     if(strip->object)
00120                         strip->object= NULL;
00121                 }
00122             }
00123 #endif
00124         }
00125         
00126         for(psys=ob->particlesystem.first; psys; psys=psys->next){
00127             if(psys->part->dup_group==group)
00128                 psys->part->dup_group= NULL;
00129 #if 0       /* not used anymore, only keps for readfile.c, no need to account for this */
00130             if(psys->part->eff_group==group)
00131                 psys->part->eff_group= NULL;
00132 #endif
00133         }
00134     }
00135     
00136     /* group stays in library, but no members */
00137     free_group_objects(group);
00138     group->id.us= 0;
00139 }
00140 
00141 Group *add_group(const char *name)
00142 {
00143     Group *group;
00144     
00145     group = alloc_libblock(&G.main->group, ID_GR, name);
00146     group->layer= (1<<20)-1;
00147     return group;
00148 }
00149 
00150 Group *copy_group(Group *group)
00151 {
00152     Group *groupn;
00153 
00154     groupn= MEM_dupallocN(group);
00155     BLI_duplicatelist(&groupn->gobject, &group->gobject);
00156 
00157     return groupn;
00158 }
00159 
00160 /* external */
00161 static int add_to_group_internal(Group *group, Object *ob)
00162 {
00163     GroupObject *go;
00164     
00165     if(group==NULL || ob==NULL) return 0;
00166     
00167     /* check if the object has been added already */
00168     for(go= group->gobject.first; go; go= go->next) {
00169         if(go->ob==ob) return 0;
00170     }
00171     
00172     go= MEM_callocN(sizeof(GroupObject), "groupobject");
00173     BLI_addtail( &group->gobject, go);
00174     
00175     go->ob= ob;
00176     
00177     return 1;
00178 }
00179 
00180 int add_to_group(Group *group, Object *object, Scene *scene, Base *base)
00181 {
00182     if(add_to_group_internal(group, object)) {
00183         if((object->flag & OB_FROMGROUP)==0) {
00184 
00185             if(scene && base==NULL)
00186                 base= object_in_scene(object, scene);
00187 
00188             object->flag |= OB_FROMGROUP;
00189 
00190             if(base)
00191                 base->flag |= OB_FROMGROUP;
00192         }
00193         return 1;
00194     }
00195     else {
00196         return 0;
00197     }
00198 }
00199 
00200 /* also used for ob==NULL */
00201 static int rem_from_group_internal(Group *group, Object *ob)
00202 {
00203     GroupObject *go, *gon;
00204     int removed = 0;
00205     if(group==NULL) return 0;
00206     
00207     go= group->gobject.first;
00208     while(go) {
00209         gon= go->next;
00210         if(go->ob==ob) {
00211             BLI_remlink(&group->gobject, go);
00212             free_group_object(go);
00213             removed = 1;
00214             /* should break here since an object being in a group twice cant happen? */
00215         }
00216         go= gon;
00217     }
00218     return removed;
00219 }
00220 
00221 int rem_from_group(Group *group, Object *object, Scene *scene, Base *base)
00222 {
00223     if(rem_from_group_internal(group, object)) {
00224         /* object can be NULL */
00225         if(object && find_group(object, NULL) == NULL) {
00226             if(scene && base==NULL)
00227                 base= object_in_scene(object, scene);
00228 
00229             object->flag &= ~OB_FROMGROUP;
00230 
00231             if(base)
00232                 base->flag &= ~OB_FROMGROUP;
00233         }
00234         return 1;
00235     }
00236     else {
00237         return 0;
00238     }
00239 }
00240 
00241 int object_in_group(Object *ob, Group *group)
00242 {
00243     GroupObject *go;
00244     
00245     if(group==NULL || ob==NULL) return 0;
00246     
00247     for(go= group->gobject.first; go; go= go->next) {
00248         if(go->ob==ob) 
00249             return 1;
00250     }
00251     return 0;
00252 }
00253 
00254 Group *find_group(Object *ob, Group *group)
00255 {
00256     if (group)
00257         group= group->id.next;
00258     else
00259         group= G.main->group.first;
00260     
00261     while(group) {
00262         if(object_in_group(ob, group))
00263             return group;
00264         group= group->id.next;
00265     }
00266     return NULL;
00267 }
00268 
00269 void group_tag_recalc(Group *group)
00270 {
00271     GroupObject *go;
00272     
00273     if(group==NULL) return;
00274     
00275     for(go= group->gobject.first; go; go= go->next) {
00276         if(go->ob) 
00277             go->ob->recalc= go->recalc;
00278     }
00279 }
00280 
00281 int group_is_animated(Object *UNUSED(parent), Group *group)
00282 {
00283     GroupObject *go;
00284 
00285 #if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
00286     if(parent->nlastrips.first)
00287         return 1;
00288 #endif
00289 
00290     for(go= group->gobject.first; go; go= go->next)
00291         if(go->ob && go->ob->proxy)
00292             return 1;
00293 
00294     return 0;
00295 }
00296 
00297 #if 0 // add back when timeoffset & animsys work again
00298 /* only replaces object strips or action when parent nla instructs it */
00299 /* keep checking nla.c though, in case internal structure of strip changes */
00300 static void group_replaces_nla(Object *parent, Object *target, char mode)
00301 {
00302     static ListBase nlastrips={NULL, NULL};
00303     static bAction *action= NULL;
00304     static int done= 0;
00305     bActionStrip *strip, *nstrip;
00306     
00307     if(mode=='s') {
00308         
00309         for(strip= parent->nlastrips.first; strip; strip= strip->next) {
00310             if(strip->object==target) {
00311                 if(done==0) {
00312                     /* clear nla & action from object */
00313                     nlastrips= target->nlastrips;
00314                     target->nlastrips.first= target->nlastrips.last= NULL;
00315                     action= target->action;
00316                     target->action= NULL;
00317                     target->nlaflag |= OB_NLA_OVERRIDE;
00318                     done= 1;
00319                 }
00320                 nstrip= MEM_dupallocN(strip);
00321                 BLI_addtail(&target->nlastrips, nstrip);
00322             }
00323         }
00324     }
00325     else if(mode=='e') {
00326         if(done) {
00327             BLI_freelistN(&target->nlastrips);
00328             target->nlastrips= nlastrips;
00329             target->action= action;
00330             
00331             nlastrips.first= nlastrips.last= NULL;  /* not needed, but yah... :) */
00332             action= NULL;
00333             done= 0;
00334         }
00335     }
00336 }
00337 #endif
00338 
00339 /* puts all group members in local timing system, after this call
00340 you can draw everything, leaves tags in objects to signal it needs further updating */
00341 
00342 /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
00343 void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group)
00344 {
00345     GroupObject *go;
00346     
00347 #if 0 /* warning, isnt clearing the recalc flag on the object which causes it to run all the time,
00348        * not just on frame change.
00349        * This isnt working because the animation data is only re-evalyated on frame change so commenting for now
00350        * but when its enabled at some point it will need to be changed so as not to update so much - campbell */
00351 
00352     /* if animated group... */
00353     if(parent->nlastrips.first) {
00354         int cfrao;
00355         
00356         /* switch to local time */
00357         cfrao= scene->r.cfra;
00358         
00359         /* we need a DAG per group... */
00360         for(go= group->gobject.first; go; go= go->next) {
00361             if(go->ob && go->recalc) {
00362                 go->ob->recalc= go->recalc;
00363                 
00364                 group_replaces_nla(parent, go->ob, 's');
00365                 object_handle_update(scene, go->ob);
00366                 group_replaces_nla(parent, go->ob, 'e');
00367                 
00368                 /* leave recalc tags in case group members are in normal scene */
00369                 go->ob->recalc= go->recalc;
00370             }
00371         }
00372         
00373         /* restore */
00374         scene->r.cfra= cfrao;
00375     }
00376     else
00377 #endif
00378     {
00379         /* only do existing tags, as set by regular depsgraph */
00380         for(go= group->gobject.first; go; go= go->next) {
00381             if(go->ob) {
00382                 if(go->ob->recalc) {
00383                     object_handle_update(scene, go->ob);
00384                 }
00385             }
00386         }
00387     }
00388 }
00389 
00390 #if 0
00391 Object *group_get_member_with_action(Group *group, bAction *act)
00392 {
00393     GroupObject *go;
00394     
00395     if(group==NULL || act==NULL) return NULL;
00396     
00397     for(go= group->gobject.first; go; go= go->next) {
00398         if(go->ob) {
00399             if(go->ob->action==act)
00400                 return go->ob;
00401             if(go->ob->nlastrips.first) {
00402                 bActionStrip *strip;
00403                 
00404                 for(strip= go->ob->nlastrips.first; strip; strip= strip->next) {
00405                     if(strip->act==act)
00406                         return go->ob;
00407                 }
00408             }
00409         }
00410     }
00411     return NULL;
00412 }
00413 
00414 /* if group has NLA, we try to map the used objects in NLA to group members */
00415 /* this assuming that object has received a new group link */
00416 void group_relink_nla_objects(Object *ob)
00417 {
00418     Group *group;
00419     GroupObject *go;
00420     bActionStrip *strip;
00421     
00422     if(ob==NULL || ob->dup_group==NULL) return;
00423     group= ob->dup_group;
00424     
00425     for(strip= ob->nlastrips.first; strip; strip= strip->next) {
00426         if(strip->object) {
00427             for(go= group->gobject.first; go; go= go->next) {
00428                 if(go->ob) {
00429                     if(strcmp(go->ob->id.name, strip->object->id.name)==0)
00430                         break;
00431                 }
00432             }
00433             if(go)
00434                 strip->object= go->ob;
00435             else
00436                 strip->object= NULL;
00437         }
00438             
00439     }
00440 }
00441 
00442 #endif