|
Blender
V2.59
|
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