2.5: Restored statistics in the info header.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 19 Aug 2009 12:35:40 +0000 (12:35 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 19 Aug 2009 12:35:40 +0000 (12:35 +0000)
Implementation:
* NC_SCENE or NC_OBJECT cause scene->stats to be cleared.
* NC_INFO is sent to tag info headers for redraw.
* In UI scene.statistics() creates scene->stats if it is
  NULLd, and then returns the string.

release/ui/space_info.py
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_info.h [new file with mode: 0644]
source/blender/editors/interface/interface_widgets.c
source/blender/editors/space_info/info_stats.c [new file with mode: 0644]
source/blender/editors/space_info/space_info.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_event_system.c

index 7703874..1a3f9a3 100644 (file)
@@ -8,7 +8,8 @@ class INFO_HT_header(bpy.types.Header):
                layout = self.layout
                
                st = context.space_data
-               rd = context.scene.render_data
+               scene = context.scene
+               rd = scene.render_data
 
                row = layout.row(align=True)
                row.template_header()
@@ -33,6 +34,8 @@ class INFO_HT_header(bpy.types.Header):
 
                layout.template_operator_search()
                layout.template_running_jobs()
+
+               layout.itemL(text=scene.statistics())
                        
 class INFO_MT_file(bpy.types.Menu):
        __space_type__ = "INFO"
index 2a8fd76..6dd362d 100644 (file)
@@ -155,6 +155,7 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
                scen->theDag= NULL;
                scen->obedit= NULL;
                scen->toolsettings= MEM_dupallocN(sce->toolsettings);
+               scen->stats= NULL;
 
                ts= scen->toolsettings;
                if(ts) {
@@ -299,6 +300,9 @@ void free_scene(Scene *sce)
                ntreeFreeTree(sce->nodetree);
                MEM_freeN(sce->nodetree);
        }
+
+       if(sce->stats)
+               MEM_freeN(sce->stats);
 }
 
 Scene *add_scene(char *name)
index 779a898..db811b2 100644 (file)
@@ -4134,6 +4134,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->theDag = NULL;
        sce->dagisvalid = 0;
        sce->obedit= NULL;
+       sce->stats= 0;
 
        memset(&sce->sound_handles, 0, sizeof(sce->sound_handles));
 
diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h
new file mode 100644 (file)
index 0000000..d09e174
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef ED_INFO_H
+#define ED_INFO_H
+
+/* info_stats.c */
+void ED_info_stats_clear(struct Scene *scene);
+char *ED_info_stats_string(struct Scene *scene);
+
+#endif /*  ED_INFO_H */
index a70fbab..48de234 100644 (file)
@@ -835,9 +835,11 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
 //     else transopts= ui_translate_buttons();
        
        /* cut string in 2 parts - only for menu entries */
-       if(ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS)==0) {
-               cpoin= strchr(but->drawstr, '|');
-               if(cpoin) *cpoin= 0;            
+       if((but->block->flag & UI_BLOCK_LOOP)) {
+               if(ELEM5(but->type, SLI, NUM, TEX, NUMSLI, NUMABS)==0) {
+                       cpoin= strchr(but->drawstr, '|');
+                       if(cpoin) *cpoin= 0;            
+               }
        }
        
        glColor3ubv((unsigned char*)wcol->text);
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
new file mode 100644 (file)
index 0000000..2d14fbc
--- /dev/null
@@ -0,0 +1,434 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_anim.h"
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_particle.h"
+#include "BKE_utildefines.h"
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+
+#include "BLI_editVert.h"
+
+typedef struct SceneStats {
+       int totvert, totvertsel;
+       int totedge, totedgesel;
+       int totface, totfacesel;
+       int totbone, totbonesel;
+       int totobj, totobjsel;
+       int totmesh, totlamp, totcurve;
+
+       char infostr[512];
+} SceneStats;
+
+static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
+{
+       switch(ob->type) {
+       case OB_MESH: {
+               /* we assume derivedmesh is already built, this strictly does stats now. */
+               DerivedMesh *dm= ob->derivedFinal;
+               int totvert, totedge, totface;
+
+               stats->totmesh +=totob;
+
+               if(dm) {
+                       totvert = dm->getNumVerts(dm);
+                       totedge = dm->getNumEdges(dm);
+                       totface = dm->getNumFaces(dm);
+
+                       stats->totvert += totvert*totob;
+                       stats->totedge += totedge*totob;
+                       stats->totface += totface*totob;
+
+                       if(sel) {
+                               stats->totvertsel += totvert;
+                               stats->totfacesel += totface;
+                       }
+               }
+               break;
+       }
+       case OB_LAMP:
+               stats->totlamp += totob;
+               break;
+       case OB_SURF:
+       case OB_CURVE:
+       case OB_FONT: {
+               Curve *cu= ob->data;
+               int tot= 0, totf= 0;
+
+               stats->totcurve += totob;
+
+               if(cu->disp.first)
+                       count_displist(&cu->disp, &tot, &totf);
+
+               tot *= totob;
+               totf *= totob;
+
+               stats->totvert+= tot;
+               stats->totface+= totf;
+
+               if(sel) {
+                       stats->totvertsel += tot;
+                       stats->totfacesel += totf;
+               }
+               break;
+       }
+       case OB_MBALL: {
+               int tot= 0, totf= 0;
+
+               count_displist(&ob->disp, &tot, &totf);
+
+               tot *= totob;
+               totf *= totob;
+
+               stats->totvert += tot;
+               stats->totface += totf;
+
+               if(sel) {
+                       stats->totvertsel += tot;
+                       stats->totfacesel += totf;
+               }
+               break;
+       }
+       }
+}
+
+static void stats_object_edit(Object *obedit, SceneStats *stats)
+{
+       if(obedit->type==OB_MESH) {
+               /* Mesh Edit */
+               EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
+               EditVert *eve;
+               EditEdge *eed;
+               EditFace *efa;
+               
+               for(eve= em->verts.first; eve; eve=eve->next) {
+                       stats->totvert++;
+                       if(eve->f & SELECT) stats->totvertsel++;
+               }
+               for(eed= em->edges.first; eed; eed=eed->next) {
+                       stats->totedge++;
+                       if(eed->f & SELECT) stats->totedgesel++;
+               }
+               for(efa= em->faces.first; efa; efa=efa->next) {
+                       stats->totface++;
+                       if(efa->f & SELECT) stats->totfacesel++;
+               }
+               
+               EM_validate_selections(em);
+       }
+       else if(obedit->type==OB_ARMATURE){
+               /* Armature Edit */
+               bArmature *arm= obedit->data;
+               EditBone *ebo;
+
+               for(ebo=arm->edbo->first; ebo; ebo=ebo->next){
+                       stats->totbone++;
+                       
+                       if((ebo->flag & BONE_CONNECTED) && ebo->parent)
+                               stats->totvert--;
+                       
+                       if(ebo->flag & BONE_TIPSEL)
+                               stats->totvertsel++;
+                       if(ebo->flag & BONE_ROOTSEL)
+                               stats->totvertsel++;
+                       
+                       if(ebo->flag & BONE_SELECTED) stats->totbonesel++;
+
+                       /* if this is a connected child and it's parent is being moved, remove our root */
+                       if((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL))
+                               stats->totvertsel--;
+
+                       stats->totvert+=2;
+               }
+       }
+       else if ELEM3(obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
+               /* Curve Edit */
+               Curve *cu= obedit->data;
+               Nurb *nu;
+               BezTriple *bezt;
+               BPoint *bp;
+               int a;
+
+               for(nu=cu->editnurb->first; nu; nu=nu->next) {
+                       if((nu->type & 7)==CU_BEZIER) {
+                               bezt= nu->bezt;
+                               a= nu->pntsu;
+                               while(a--) {
+                                       stats->totvert+=3;
+                                       if(bezt->f1) stats->totvertsel++;
+                                       if(bezt->f2) stats->totvertsel++;
+                                       if(bezt->f3) stats->totvertsel++;
+                                       bezt++;
+                               }
+                       }
+                       else {
+                               bp= nu->bp;
+                               a= nu->pntsu*nu->pntsv;
+                               while(a--) {
+                                       stats->totvert++;
+                                       if(bp->f1 & SELECT) stats->totvertsel++;
+                                       bp++;
+                               }
+                       }
+               }
+       }
+       else if(obedit->type==OB_MBALL) {
+               /* MetaBall Edit */
+               MetaBall *mball= obedit->data;
+               MetaElem *ml;
+               
+               for(ml= mball->editelems->first; ml; ml=ml->next) {
+                       stats->totvert++;
+                       if(ml->flag & SELECT) stats->totvertsel++;
+               }
+       }
+       else if(obedit->type==OB_LATTICE) {
+               /* Lattice Edit */
+               Lattice *lt= obedit->data;
+               Lattice *editlatt= lt->editlatt;
+               BPoint *bp;
+               int a;
+
+               bp= editlatt->def;
+               
+               a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
+               while(a--) {
+                       stats->totvert++;
+                       if(bp->f1 & SELECT) stats->totvertsel++;
+                       bp++;
+               }
+       }
+}
+
+static void stats_object_pose(Object *ob, SceneStats *stats)
+{
+       if(ob->pose) {
+               bArmature *arm= ob->data;
+               bPoseChannel *pchan;
+
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       stats->totbone++;
+                       if(pchan->bone && (pchan->bone->flag & BONE_SELECTED))
+                               if(pchan->bone->layer & arm->layer)
+                                       stats->totbonesel++;
+               }
+       }
+}
+
+static void stats_object_paint(Object *ob, SceneStats *stats)
+{
+       if(ob->type == OB_MESH) {
+               Mesh *me= ob->data;
+
+               stats->totface= me->totface;
+               stats->totvert= me->totvert;
+       }
+}
+
+static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
+{
+       if(base->flag & SELECT) stats->totobjsel++;
+
+       if(ob->transflag & OB_DUPLIPARTS) {
+               /* Dupli Particles */
+               ParticleSystem *psys;
+               ParticleSettings *part;
+
+               for(psys=ob->particlesystem.first; psys; psys=psys->next){
+                       part=psys->part;
+
+                       if(part->draw_as==PART_DRAW_OB && part->dup_ob){
+                               int tot=count_particles(psys);
+                               stats_object(part->dup_ob, 0, tot, stats);
+                       }
+                       else if(part->draw_as==PART_DRAW_GR && part->dup_group){
+                               GroupObject *go;
+                               int tot, totgroup=0, cur=0;
+                               
+                               for(go= part->dup_group->gobject.first; go; go=go->next)
+                                       totgroup++;
+
+                               for(go= part->dup_group->gobject.first; go; go=go->next) {
+                                       tot=count_particles_mod(psys,totgroup,cur);
+                                       stats_object(go->ob, 0, tot, stats);
+                                       cur++;
+                               }
+                       }
+               }
+               
+               stats_object(ob, base->flag & SELECT, 1, stats);
+               stats->totobj++;
+       }
+       else if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
+               /* Dupli Verts/Faces */
+               int tot= count_duplilist(ob->parent);
+               stats->totobj+=tot;
+               stats_object(ob, base->flag & SELECT, tot, stats);
+       }
+       else if(ob->transflag & OB_DUPLIFRAMES) {
+               /* Dupli Frames */
+               int tot= count_duplilist(ob);
+               stats->totobj+=tot;
+               stats_object(ob, base->flag & SELECT, tot, stats);
+       }
+       else if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
+               /* Dupli Group */
+               int tot= count_duplilist(ob);
+               stats->totobj+=tot;
+               stats_object(ob, base->flag & SELECT, tot, stats);
+       }
+       else {
+               /* No Dupli */
+               stats_object(ob, base->flag & SELECT, 1, stats);
+               stats->totobj++;
+       }
+}
+
+/* Statistics displayed in info header. Called regularly on scene changes. */
+static void stats_update(Scene *scene)
+{
+       SceneStats stats;
+       Object *ob= (scene->basact)? scene->basact->object: NULL;
+       Base *base;
+       
+       memset(&stats, 0, sizeof(stats));
+
+       if(scene->obedit) {
+               /* Edit Mode */
+               stats_object_edit(scene->obedit, &stats);
+       }
+       else if(ob && (ob->mode & OB_MODE_POSE)) {
+               /* Pose Mode */
+               stats_object_pose(ob, &stats);
+       }
+       else if(ob && (ob->flag & (OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))) {
+               /* Sculpt and Paint Mode */
+               stats_object_paint(ob, &stats);
+       }
+       else {
+               /* Objects */
+               for(base= scene->base.first; base; base=base->next)
+                       if(scene->lay & base->lay)
+                               stats_dupli_object(base, base->object, &stats);
+       }
+
+       if(!scene->stats)
+               scene->stats= MEM_mallocN(sizeof(SceneStats), "SceneStats");
+
+       *(scene->stats)= stats;
+}
+
+static void stats_string(Scene *scene)
+{
+       SceneStats *stats= scene->stats;
+       Object *ob= (scene->basact)? scene->basact->object: NULL;
+       uintptr_t mem_in_use, mmap_in_use;
+       char memstr[64];
+       char *s;
+
+       mem_in_use= MEM_get_memory_in_use();
+       mmap_in_use= MEM_get_mapped_memory_in_use();
+
+       /* get memory statistics */
+       s= memstr + sprintf(memstr, " | Mem:%.2fM", ((mem_in_use-mmap_in_use)>>10)/1024.0);
+       if(mmap_in_use)
+               sprintf(s, " (%.2fM)", ((mmap_in_use)>>10)/1024.0);
+
+       s= stats->infostr;
+
+       if(scene->obedit) {
+               if(ob_get_keyblock(scene->obedit))
+                       s+= sprintf(s, "(Key) ");
+
+               if(scene->obedit->type==OB_MESH) {
+                       if(scene->toolsettings->selectmode & SCE_SELECT_VERTEX)
+                               s+= sprintf(s, "Ve:%d-%d | Ed:%d-%d | Fa:%d-%d",
+                                               stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface);
+                       else if(scene->toolsettings->selectmode & SCE_SELECT_EDGE)
+                               s+= sprintf(s, "Ed:%d-%d | Fa:%d-%d",
+                                               stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface);
+                       else
+                               s+= sprintf(s, "Fa:%d-%d", stats->totfacesel, stats->totface);
+               }
+               else if(scene->obedit->type==OB_ARMATURE) {
+                       s+= sprintf(s, "Ve:%d-%d | Bo:%d-%d", stats->totvertsel, stats->totvert, stats->totbonesel, stats->totbone);
+               }
+               else {
+                       s+= sprintf(s, "Ve:%d-%d", stats->totvertsel, stats->totvert);
+               }
+
+               strcat(s, memstr);
+       }
+       else if(ob && (ob->mode & OB_MODE_POSE)) {
+               s += sprintf(s, "Bo:%d-%d %s",
+                                       stats->totbonesel, stats->totbone, memstr);
+       }
+       else {
+               s += sprintf(s, "Ve:%d | Fa:%d | Ob:%d-%d | La:%d%s",
+                       stats->totvert, stats->totface, stats->totobj, stats->totobjsel, stats->totlamp, memstr);
+       }
+
+       if(ob)
+               sprintf(s, " | %s", ob->id.name+2);
+}
+
+void ED_info_stats_clear(Scene *scene)
+{
+       if(scene->stats) {
+               MEM_freeN(scene->stats);
+               scene->stats= NULL;
+       }
+}
+
+char *ED_info_stats_string(Scene *scene)
+{
+       if(!scene->stats)
+               stats_update(scene);
+       stats_string(scene);
+
+       return scene->stats->infostr;
+}
+
index fe5bbf0..b6f9cbe 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id:
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -58,6 +58,7 @@
 #include "UI_view2d.h"
 
 #include "ED_markers.h"
+#include "ED_object.h"
 
 #include "info_intern.h"       // own include
 
@@ -166,6 +167,9 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn)
                        if(wmn->data==ND_RENDER_RESULT)
                                ED_region_tag_redraw(ar);
                        break;
+               case NC_INFO:
+                       ED_region_tag_redraw(ar);
+                       break;
        }
        
 }
index 4a3d555..f1a77d7 100644 (file)
@@ -47,6 +47,7 @@ struct Text;
 struct bNodeTree;
 struct AnimData;
 struct Editing;
+struct SceneStats;
 
 typedef struct Base {
        struct Base *next, *prev;
@@ -717,7 +718,6 @@ typedef struct Scene {
 
        /* Units */
        struct UnitSettings unit;
-
 } Scene;
 
 
index 8879691..0301932 100644 (file)
@@ -62,6 +62,7 @@ EnumPropertyItem prop_mode_items[] ={
 
 #include "BLI_threads.h"
 
+#include "ED_info.h"
 #include "ED_node.h"
 
 #include "RE_pipeline.h"
@@ -1823,6 +1824,7 @@ void RNA_def_scene(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
+       FunctionRNA *func;
        
        /* Struct definition */
        srna= RNA_def_struct(brna, "Scene", "ID");
@@ -1982,6 +1984,11 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_pointer_sdna(prop, NULL, "gm");
        RNA_def_property_struct_type(prop, "SceneGameData");
        RNA_def_property_ui_text(prop, "Game Data", "");
+
+       /* Statistics */
+       func= RNA_def_function(srna, "statistics", "ED_info_stats_string");
+       prop= RNA_def_string(func, "statistics", "", 0, "Statistics", "");
+       RNA_def_function_return(func, prop);
        
        rna_def_tool_settings(brna);
        rna_def_unit_settings(brna);
index 00e9f6a..b717df8 100644 (file)
@@ -134,6 +134,7 @@ typedef struct wmNotifier {
 #define NC_ANIMATION           (15<<24)
 #define NC_CONSOLE                     (16<<24)
 #define NC_NODE                                (17<<24)
+#define NC_INFO                                (18<<24)
 
 /* data type, 256 entries is enough, it can overlap */
 #define NOTE_DATA                      0x00FF0000
index f0d9f8c..6c34ed6 100644 (file)
@@ -52,6 +52,7 @@
 #include "BKE_pointcache.h"
 
 #include "ED_fileselect.h"
+#include "ED_info.h"
 #include "ED_screen.h"
 #include "ED_space_api.h"
 #include "ED_util.h"
@@ -129,7 +130,7 @@ static wmNotifier *wm_notifier_next(wmWindowManager *wm)
 void wm_event_do_notifiers(bContext *C)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
-       wmNotifier *note;
+       wmNotifier *note, *next;
        wmWindow *win;
        
        if(wm==NULL)
@@ -141,7 +142,9 @@ void wm_event_do_notifiers(bContext *C)
                
                CTX_wm_window_set(C, win);
                
-               for(note= wm->queue.first; note; note= note->next) {
+               for(note= wm->queue.first; note; note= next) {
+                       next= note->next;
+
                        if(note->category==NC_WM) {
                                if( ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) {
                                        wm->file_saved= 1;
@@ -174,6 +177,10 @@ void wm_event_do_notifiers(bContext *C)
                                                do_anim= 1;
                                }
                        }
+                       if(note->category == NC_SCENE || note->category == NC_OBJECT) {
+                               ED_info_stats_clear(CTX_data_scene(C));
+                               WM_event_add_notifier(C, NC_INFO, NULL);
+                       }
                }
                if(do_anim) {
                        /* depsgraph gets called, might send more notifiers */