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