/* When no longer needed, duplilist should be freed with Object.free_duplilist */ static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings) { bool for_render = (settings == DAG_EVAL_RENDER); EvaluationContext eval_ctx; DEG_evaluation_context_init(&eval_ctx, settings); if (!(ob->transflag & OB_DUPLI)) { BKE_report(reports, RPT_ERROR, "Object does not have duplis"); return; } /* free duplilist if a user forgets to */ if (ob->duplilist) { BKE_report(reports, RPT_WARNING, "Object.dupli_list has not been freed"); free_object_duplilist(ob->duplilist); ob->duplilist = NULL; } if (for_render) dupli_render_particle_set(sce, ob, 0, 1); ob->duplilist = object_duplilist(&eval_ctx, sce, ob); if (for_render) dupli_render_particle_set(sce, ob, 0, 0); /* ob->duplilist should now be freed with Object.free_duplilist */ }
static void rna_Object_free_duplilist(Object *ob) { if (ob->duplilist) { free_object_duplilist(ob->duplilist); ob->duplilist = NULL; } }
/* When no longer needed, duplilist should be freed with Object.free_duplilist */ void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce) { if (!(ob->transflag & OB_DUPLI)) { BKE_report(reports, RPT_ERROR, "Object does not have duplis"); return; } /* free duplilist if a user forgets to */ if (ob->duplilist) { BKE_reportf(reports, RPT_WARNING, "Object.dupli_list has not been freed"); free_object_duplilist(ob->duplilist); ob->duplilist= NULL; } if(G.rendering) dupli_render_particle_set(sce, ob, 0, 1); ob->duplilist= object_duplilist(sce, ob); if(G.rendering) dupli_render_particle_set(sce, ob, 0, 0); /* ob->duplilist should now be freed with Object.free_duplilist */ }
static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip) { short code = 1; char dt; short dtx; if (vc->obedit && vc->obedit->type == OB_MBALL) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); } else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { /* if not drawing sketch, draw bones */ if (!BDR_drawSketchNames(vc)) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); } } else { Base *base; v3d->xray = true; /* otherwise it postpones drawing */ for (base = scene->base.first; base; base = base->next) { if (base->lay & v3d->lay) { if ((base->object->restrictflag & OB_RESTRICT_SELECT) || (use_obedit_skip && (scene->obedit->data == base->object->data))) { base->selcol = 0; } else { base->selcol = code; if (GPU_select_load_id(code)) { draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { ListBase *lb; DupliObject *dob; Base tbase; tbase.flag = OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { float omat[4][4]; tbase.object = dob->ob; copy_m4_m4(omat, dob->ob->obmat); copy_m4_m4(dob->ob->obmat, dob->mat); /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR); tbase.object->dt = dt; tbase.object->dtx = dtx; copy_m4_m4(dob->ob->obmat, omat); } free_object_duplilist(lb); } } code++; } } } v3d->xray = false; /* restore */ } }
/* used by metaballs * doesnt return the original duplicated object, only dupli's */ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob) { static ListBase *duplilist = NULL; static DupliObject *dupob; static int fase = F_START, in_next_object = 0; int run_again = 1; /* init */ if (val == 0) { fase = F_START; dupob = NULL; /* XXX particle systems with metas+dupligroups call this recursively */ /* see bug #18725 */ if (in_next_object) { printf("ERROR: Metaball generation called recursively, not supported\n"); return F_ERROR; } } else { in_next_object = 1; /* run_again is set when a duplilist has been ended */ while (run_again) { run_again = 0; /* the first base */ if (fase == F_START) { *base = (*scene)->base.first; if (*base) { *ob = (*base)->object; fase = F_SCENE; } else { /* exception: empty scene */ while ((*scene)->set) { (*scene) = (*scene)->set; if ((*scene)->base.first) { *base = (*scene)->base.first; *ob = (*base)->object; fase = F_SCENE; break; } } } } else { if (*base && fase != F_DUPLI) { *base = (*base)->next; if (*base) *ob = (*base)->object; else { if (fase == F_SCENE) { /* (*scene) is finished, now do the set */ while ((*scene)->set) { (*scene) = (*scene)->set; if ((*scene)->base.first) { *base = (*scene)->base.first; *ob = (*base)->object; break; } } } } } } if (*base == NULL) fase = F_START; else { if (fase != F_DUPLI) { if ( (*base)->object->transflag & OB_DUPLI) { /* groups cannot be duplicated for mballs yet, * this enters eternal loop because of * makeDispListMBall getting called inside of group_duplilist */ if ((*base)->object->dup_group == NULL) { duplilist = object_duplilist((*scene), (*base)->object, FALSE); dupob = duplilist->first; if (!dupob) free_object_duplilist(duplilist); } } } /* handle dupli's */ if (dupob) { copy_m4_m4(dupob->ob->obmat, dupob->mat); (*base)->flag |= OB_FROMDUPLI; *ob = dupob->ob; fase = F_DUPLI; dupob = dupob->next; } else if (fase == F_DUPLI) { fase = F_SCENE; (*base)->flag &= ~OB_FROMDUPLI; for (dupob = duplilist->first; dupob; dupob = dupob->next) { copy_m4_m4(dupob->ob->obmat, dupob->omat); } free_object_duplilist(duplilist); duplilist = NULL; run_again = 1; } } } } #if 0 if (ob && *ob) { printf("Scene: '%s', '%s'\n", (*scene)->id.name + 2, (*ob)->id.name + 2); } #endif /* reset recursion test */ in_next_object = 0; return fase; }
/* Warning: be sure to account for a negative return value * This is an error, "Too many objects in select buffer" * and no action should be taken (can crash blender) if this happens */ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, rcti *input) { Scene *scene= vc->scene; View3D *v3d= vc->v3d; ARegion *ar= vc->ar; rctf rect; short code, hits; char dt, dtx; G.f |= G_PICKSEL; /* case not a border select */ if(input->xmin==input->xmax) { rect.xmin= input->xmin-12; // seems to be default value for bones only now rect.xmax= input->xmin+12; rect.ymin= input->ymin-12; rect.ymax= input->ymin+12; } else { rect.xmin= input->xmin; rect.xmax= input->xmax; rect.ymin= input->ymin; rect.ymax= input->ymax; } setwinmatrixview3d(ar, v3d, &rect); mult_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); if(v3d->drawtype > OB_WIRE) { v3d->zbuf= TRUE; glEnable(GL_DEPTH_TEST); } if(vc->rv3d->rflag & RV3D_CLIPPING) view3d_set_clipping(vc->rv3d); glSelectBuffer( bufsize, (GLuint *)buffer); glRenderMode(GL_SELECT); glInitNames(); /* these two calls whatfor? It doesnt work otherwise */ glPushName(-1); code= 1; if(vc->obedit && vc->obedit->type==OB_MBALL) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); } else if((vc->obedit && vc->obedit->type==OB_ARMATURE)) { /* if not drawing sketch, draw bones */ if(!BDR_drawSketchNames(vc)) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); } } else { Base *base; v3d->xray= TRUE; // otherwise it postpones drawing for(base= scene->base.first; base; base= base->next) { if(base->lay & v3d->lay) { if (base->object->restrictflag & OB_RESTRICT_SELECT) base->selcol= 0; else { base->selcol= code; glLoadName(code); draw_object(scene, ar, v3d, base, DRAW_PICKING|DRAW_CONSTCOLOR); /* we draw group-duplicators for selection too */ if((base->object->transflag & OB_DUPLI) && base->object->dup_group) { ListBase *lb; DupliObject *dob; Base tbase; tbase.flag= OB_FROMDUPLI; lb= object_duplilist(scene, base->object); for(dob= lb->first; dob; dob= dob->next) { tbase.object= dob->ob; copy_m4_m4(dob->ob->obmat, dob->mat); /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt); dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; draw_object(scene, ar, v3d, &tbase, DRAW_PICKING|DRAW_CONSTCOLOR); tbase.object->dt= dt; tbase.object->dtx= dtx; copy_m4_m4(dob->ob->obmat, dob->omat); } free_object_duplilist(lb); } code++; } } } v3d->xray= FALSE; // restore } glPopName(); /* see above (pushname) */ hits= glRenderMode(GL_RENDER); G.f &= ~G_PICKSEL; setwinmatrixview3d(ar, v3d, NULL); mult_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); if(v3d->drawtype > OB_WIRE) { v3d->zbuf= 0; glDisable(GL_DEPTH_TEST); } // XXX persp(PERSP_WIN); if(vc->rv3d->rflag & RV3D_CLIPPING) view3d_clr_clipping(); if(hits<0) printf("Too many objects in select buffer\n"); // XXX make error message return hits; }
/* used by metaballs * doesn't return the original duplicated object, only dupli's */ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob) { int run_again = 1; /* init */ if (val == 0) { iter->fase = F_START; iter->dupob = NULL; iter->duplilist = NULL; } else { /* run_again is set when a duplilist has been ended */ while (run_again) { run_again = 0; /* the first base */ if (iter->fase == F_START) { *base = (*scene)->base.first; if (*base) { *ob = (*base)->object; iter->fase = F_SCENE; } else { /* exception: empty scene */ while ((*scene)->set) { (*scene) = (*scene)->set; if ((*scene)->base.first) { *base = (*scene)->base.first; *ob = (*base)->object; iter->fase = F_SCENE; break; } } } } else { if (*base && iter->fase != F_DUPLI) { *base = (*base)->next; if (*base) { *ob = (*base)->object; } else { if (iter->fase == F_SCENE) { /* (*scene) is finished, now do the set */ while ((*scene)->set) { (*scene) = (*scene)->set; if ((*scene)->base.first) { *base = (*scene)->base.first; *ob = (*base)->object; break; } } } } } } if (*base == NULL) { iter->fase = F_START; } else { if (iter->fase != F_DUPLI) { if ( (*base)->object->transflag & OB_DUPLI) { /* groups cannot be duplicated for mballs yet, * this enters eternal loop because of * makeDispListMBall getting called inside of group_duplilist */ if ((*base)->object->dup_group == NULL) { iter->duplilist = object_duplilist_ex(eval_ctx, (*scene), (*base)->object, false); iter->dupob = iter->duplilist->first; if (!iter->dupob) free_object_duplilist(iter->duplilist); } } } /* handle dupli's */ if (iter->dupob) { copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat); (*base)->flag |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->fase = F_DUPLI; iter->dupob = iter->dupob->next; } else if (iter->fase == F_DUPLI) { iter->fase = F_SCENE; (*base)->flag &= ~OB_FROMDUPLI; for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) { copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->omat); } free_object_duplilist(iter->duplilist); iter->duplilist = NULL; run_again = 1; } } } } #if 0 if (ob && *ob) { printf("Scene: '%s', '%s'\n", (*scene)->id.name + 2, (*ob)->id.name + 2); } #endif return iter->fase; }