Blender V2.61 - r43446
|
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