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