2.5: Restored statistics in the info header.

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.
This commit is contained in:
Brecht Van Lommel 2009-08-19 12:35:40 +00:00
parent c3041ae7cd
commit aace6ef551
11 changed files with 503 additions and 8 deletions

View 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"

View 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)

View 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));

View File

@ -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 */

View 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);

View File

@ -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;
}

View 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;
}
}

View 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;

View 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);

View 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

View 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 */