Blender V2.61 - r43446
|
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