Blender V2.61 - r43446

info_stats.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Blender Foundation
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <stdio.h>
00029 #include <string.h>
00030 
00031 #include "MEM_guardedalloc.h"
00032 
00033 #include "DNA_armature_types.h"
00034 #include "DNA_curve_types.h"
00035 #include "DNA_group_types.h"
00036 #include "DNA_lattice_types.h"
00037 #include "DNA_meta_types.h"
00038 #include "DNA_scene_types.h"
00039 
00040 #include "BLI_utildefines.h"
00041 
00042 #include "BKE_anim.h"
00043 #include "BKE_blender.h"
00044 #include "BKE_curve.h"
00045 #include "BKE_displist.h"
00046 #include "BKE_DerivedMesh.h"
00047 #include "BKE_key.h"
00048 #include "BKE_mesh.h"
00049 #include "BKE_particle.h"
00050 
00051 #include "ED_info.h"
00052 #include "ED_armature.h"
00053 #include "ED_mesh.h"
00054 
00055 #include "BLI_editVert.h"
00056 
00057 typedef struct SceneStats {
00058     int totvert, totvertsel;
00059     int totedge, totedgesel;
00060     int totface, totfacesel;
00061     int totbone, totbonesel;
00062     int totobj, totobjsel;
00063     int totmesh, totlamp, totcurve;
00064 
00065     char infostr[512];
00066 } SceneStats;
00067 
00068 static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
00069 {
00070     switch(ob->type) {
00071     case OB_MESH: {
00072         /* we assume derivedmesh is already built, this strictly does stats now. */
00073         DerivedMesh *dm= ob->derivedFinal;
00074         int totvert, totedge, totface;
00075 
00076         stats->totmesh +=totob;
00077 
00078         if(dm) {
00079             totvert = dm->getNumVerts(dm);
00080             totedge = dm->getNumEdges(dm);
00081             totface = dm->getNumFaces(dm);
00082 
00083             stats->totvert += totvert*totob;
00084             stats->totedge += totedge*totob;
00085             stats->totface += totface*totob;
00086 
00087             if(sel) {
00088                 stats->totvertsel += totvert;
00089                 stats->totfacesel += totface;
00090             }
00091         }
00092         break;
00093     }
00094     case OB_LAMP:
00095         stats->totlamp += totob;
00096         break;
00097     case OB_SURF:
00098     case OB_CURVE:
00099     case OB_FONT: {
00100         int tot= 0, totf= 0;
00101 
00102         stats->totcurve += totob;
00103 
00104         if(ob->disp.first)
00105             count_displist(&ob->disp, &tot, &totf);
00106 
00107         tot *= totob;
00108         totf *= totob;
00109 
00110         stats->totvert+= tot;
00111         stats->totface+= totf;
00112 
00113         if(sel) {
00114             stats->totvertsel += tot;
00115             stats->totfacesel += totf;
00116         }
00117         break;
00118     }
00119     case OB_MBALL: {
00120         int tot= 0, totf= 0;
00121 
00122         count_displist(&ob->disp, &tot, &totf);
00123 
00124         tot *= totob;
00125         totf *= totob;
00126 
00127         stats->totvert += tot;
00128         stats->totface += totf;
00129 
00130         if(sel) {
00131             stats->totvertsel += tot;
00132             stats->totfacesel += totf;
00133         }
00134         break;
00135     }
00136     }
00137 }
00138 
00139 static void stats_object_edit(Object *obedit, SceneStats *stats)
00140 {
00141     if(obedit->type==OB_MESH) {
00142         /* Mesh Edit */
00143         EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
00144         EditVert *eve;
00145         EditEdge *eed;
00146         EditFace *efa;
00147         
00148         for(eve= em->verts.first; eve; eve=eve->next) {
00149             stats->totvert++;
00150             if(eve->f & SELECT) stats->totvertsel++;
00151         }
00152         for(eed= em->edges.first; eed; eed=eed->next) {
00153             stats->totedge++;
00154             if(eed->f & SELECT) stats->totedgesel++;
00155         }
00156         for(efa= em->faces.first; efa; efa=efa->next) {
00157             stats->totface++;
00158             if(efa->f & SELECT) stats->totfacesel++;
00159         }
00160         
00161         EM_validate_selections(em);
00162     }
00163     else if(obedit->type==OB_ARMATURE){
00164         /* Armature Edit */
00165         bArmature *arm= obedit->data;
00166         EditBone *ebo;
00167 
00168         for(ebo=arm->edbo->first; ebo; ebo=ebo->next){
00169             stats->totbone++;
00170             
00171             if((ebo->flag & BONE_CONNECTED) && ebo->parent)
00172                 stats->totvert--;
00173             
00174             if(ebo->flag & BONE_TIPSEL)
00175                 stats->totvertsel++;
00176             if(ebo->flag & BONE_ROOTSEL)
00177                 stats->totvertsel++;
00178             
00179             if(ebo->flag & BONE_SELECTED) stats->totbonesel++;
00180 
00181             /* if this is a connected child and it's parent is being moved, remove our root */
00182             if((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL))
00183                 stats->totvertsel--;
00184 
00185             stats->totvert+=2;
00186         }
00187     }
00188     else if ELEM(obedit->type, OB_CURVE, OB_SURF) { /* OB_FONT has no cu->editnurb */
00189         /* Curve Edit */
00190         Curve *cu= obedit->data;
00191         Nurb *nu;
00192         BezTriple *bezt;
00193         BPoint *bp;
00194         int a;
00195         ListBase *nurbs= curve_editnurbs(cu);
00196 
00197         for(nu=nurbs->first; nu; nu=nu->next) {
00198             if(nu->type == CU_BEZIER) {
00199                 bezt= nu->bezt;
00200                 a= nu->pntsu;
00201                 while(a--) {
00202                     stats->totvert+=3;
00203                     if(bezt->f1) stats->totvertsel++;
00204                     if(bezt->f2) stats->totvertsel++;
00205                     if(bezt->f3) stats->totvertsel++;
00206                     bezt++;
00207                 }
00208             }
00209             else {
00210                 bp= nu->bp;
00211                 a= nu->pntsu*nu->pntsv;
00212                 while(a--) {
00213                     stats->totvert++;
00214                     if(bp->f1 & SELECT) stats->totvertsel++;
00215                     bp++;
00216                 }
00217             }
00218         }
00219     }
00220     else if(obedit->type==OB_MBALL) {
00221         /* MetaBall Edit */
00222         MetaBall *mball= obedit->data;
00223         MetaElem *ml;
00224         
00225         for(ml= mball->editelems->first; ml; ml=ml->next) {
00226             stats->totvert++;
00227             if(ml->flag & SELECT) stats->totvertsel++;
00228         }
00229     }
00230     else if(obedit->type==OB_LATTICE) {
00231         /* Lattice Edit */
00232         Lattice *lt= obedit->data;
00233         Lattice *editlatt= lt->editlatt->latt;
00234         BPoint *bp;
00235         int a;
00236 
00237         bp= editlatt->def;
00238         
00239         a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
00240         while(a--) {
00241             stats->totvert++;
00242             if(bp->f1 & SELECT) stats->totvertsel++;
00243             bp++;
00244         }
00245     }
00246 }
00247 
00248 static void stats_object_pose(Object *ob, SceneStats *stats)
00249 {
00250     if(ob->pose) {
00251         bArmature *arm= ob->data;
00252         bPoseChannel *pchan;
00253 
00254         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
00255             stats->totbone++;
00256             if(pchan->bone && (pchan->bone->flag & BONE_SELECTED))
00257                 if(pchan->bone->layer & arm->layer)
00258                     stats->totbonesel++;
00259         }
00260     }
00261 }
00262 
00263 static void stats_object_paint(Object *ob, SceneStats *stats)
00264 {
00265     if(ob->type == OB_MESH) {
00266         Mesh *me= ob->data;
00267 
00268         stats->totface= me->totface;
00269         stats->totvert= me->totvert;
00270     }
00271 }
00272 
00273 static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
00274 {
00275     if(base->flag & SELECT) stats->totobjsel++;
00276 
00277     if(ob->transflag & OB_DUPLIPARTS) {
00278         /* Dupli Particles */
00279         ParticleSystem *psys;
00280         ParticleSettings *part;
00281 
00282         for(psys=ob->particlesystem.first; psys; psys=psys->next){
00283             part=psys->part;
00284 
00285             if(part->draw_as==PART_DRAW_OB && part->dup_ob){
00286                 int tot=count_particles(psys);
00287                 stats_object(part->dup_ob, 0, tot, stats);
00288             }
00289             else if(part->draw_as==PART_DRAW_GR && part->dup_group){
00290                 GroupObject *go;
00291                 int tot, totgroup=0, cur=0;
00292                 
00293                 for(go= part->dup_group->gobject.first; go; go=go->next)
00294                     totgroup++;
00295 
00296                 for(go= part->dup_group->gobject.first; go; go=go->next) {
00297                     tot=count_particles_mod(psys,totgroup,cur);
00298                     stats_object(go->ob, 0, tot, stats);
00299                     cur++;
00300                 }
00301             }
00302         }
00303         
00304         stats_object(ob, base->flag & SELECT, 1, stats);
00305         stats->totobj++;
00306     }
00307     else if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
00308         /* Dupli Verts/Faces */
00309         int tot= count_duplilist(ob->parent);
00310         stats->totobj+=tot;
00311         stats_object(ob, base->flag & SELECT, tot, stats);
00312     }
00313     else if(ob->transflag & OB_DUPLIFRAMES) {
00314         /* Dupli Frames */
00315         int tot= count_duplilist(ob);
00316         stats->totobj+=tot;
00317         stats_object(ob, base->flag & SELECT, tot, stats);
00318     }
00319     else if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
00320         /* Dupli Group */
00321         int tot= count_duplilist(ob);
00322         stats->totobj+=tot;
00323         stats_object(ob, base->flag & SELECT, tot, stats);
00324     }
00325     else {
00326         /* No Dupli */
00327         stats_object(ob, base->flag & SELECT, 1, stats);
00328         stats->totobj++;
00329     }
00330 }
00331 
00332 /* Statistics displayed in info header. Called regularly on scene changes. */
00333 static void stats_update(Scene *scene)
00334 {
00335     SceneStats stats= {0};
00336     Object *ob= (scene->basact)? scene->basact->object: NULL;
00337     Base *base;
00338     
00339     if(scene->obedit) {
00340         /* Edit Mode */
00341         stats_object_edit(scene->obedit, &stats);
00342     }
00343     else if(ob && (ob->mode & OB_MODE_POSE)) {
00344         /* Pose Mode */
00345         stats_object_pose(ob, &stats);
00346     }
00347     else if(ob && (ob->flag & OB_MODE_ALL_PAINT)) {
00348         /* Sculpt and Paint Mode */
00349         stats_object_paint(ob, &stats);
00350     }
00351     else {
00352         /* Objects */
00353         for(base= scene->base.first; base; base=base->next)
00354             if(scene->lay & base->lay)
00355                 stats_dupli_object(base, base->object, &stats);
00356     }
00357 
00358     if(!scene->stats)
00359         scene->stats= MEM_callocN(sizeof(SceneStats), "SceneStats");
00360 
00361     *(scene->stats)= stats;
00362 }
00363 
00364 static void stats_string(Scene *scene)
00365 {
00366     SceneStats *stats= scene->stats;
00367     Object *ob= (scene->basact)? scene->basact->object: NULL;
00368     uintptr_t mem_in_use, mmap_in_use;
00369     char memstr[64];
00370     char *s;
00371 
00372     mem_in_use= MEM_get_memory_in_use();
00373     mmap_in_use= MEM_get_mapped_memory_in_use();
00374 
00375     /* get memory statistics */
00376     s= memstr + sprintf(memstr, " | Mem:%.2fM", (double)((mem_in_use-mmap_in_use)>>10)/1024.0);
00377     if(mmap_in_use)
00378         sprintf(s, " (%.2fM)", (double)((mmap_in_use)>>10)/1024.0);
00379 
00380     s= stats->infostr;
00381     
00382     s+= sprintf(s, "%s | ", versionstr);
00383 
00384     if(scene->obedit) {
00385         if(ob_get_keyblock(scene->obedit))
00386             s+= sprintf(s, "(Key) ");
00387 
00388         if(scene->obedit->type==OB_MESH) {
00389             if(scene->toolsettings->selectmode & SCE_SELECT_VERTEX)
00390                 s+= sprintf(s, "Ve:%d-%d | Ed:%d-%d | Fa:%d-%d",
00391                         stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface);
00392             else if(scene->toolsettings->selectmode & SCE_SELECT_EDGE)
00393                 s+= sprintf(s, "Ed:%d-%d | Fa:%d-%d",
00394                         stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface);
00395             else
00396                 s+= sprintf(s, "Fa:%d-%d", stats->totfacesel, stats->totface);
00397         }
00398         else if(scene->obedit->type==OB_ARMATURE) {
00399             s+= sprintf(s, "Ve:%d-%d | Bo:%d-%d", stats->totvertsel, stats->totvert, stats->totbonesel, stats->totbone);
00400         }
00401         else {
00402             s+= sprintf(s, "Ve:%d-%d", stats->totvertsel, stats->totvert);
00403         }
00404 
00405         strcat(s, memstr);
00406     }
00407     else if(ob && (ob->mode & OB_MODE_POSE)) {
00408         s += sprintf(s, "Bo:%d-%d %s",
00409                     stats->totbonesel, stats->totbone, memstr);
00410     }
00411     else {
00412         s += sprintf(s, "Ve:%d | Fa:%d | Ob:%d-%d | La:%d%s",
00413             stats->totvert, stats->totface, stats->totobjsel, stats->totobj, stats->totlamp, memstr);
00414     }
00415 
00416     if(ob)
00417         sprintf(s, " | %s", ob->id.name+2);
00418 }
00419 
00420 void ED_info_stats_clear(Scene *scene)
00421 {
00422     if(scene->stats) {
00423         MEM_freeN(scene->stats);
00424         scene->stats= NULL;
00425     }
00426 }
00427 
00428 const char *ED_info_stats_string(Scene *scene)
00429 {
00430     if(!scene->stats)
00431         stats_update(scene);
00432     stats_string(scene);
00433 
00434     return scene->stats->infostr;
00435 }
00436