Blender  V2.93
info_stats.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "DNA_armature_types.h"
27 #include "DNA_collection_types.h"
28 #include "DNA_curve_types.h"
29 #include "DNA_gpencil_types.h"
30 #include "DNA_lattice_types.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meta_types.h"
33 #include "DNA_scene_types.h"
35 
36 #include "BLF_api.h"
37 
38 #include "BLI_listbase.h"
39 #include "BLI_math.h"
40 #include "BLI_string.h"
41 #include "BLI_utildefines.h"
42 
43 #include "BLT_translation.h"
44 
45 #include "BKE_armature.h"
46 #include "BKE_blender_version.h"
47 #include "BKE_context.h"
48 #include "BKE_curve.h"
49 #include "BKE_displist.h"
50 #include "BKE_editmesh.h"
51 #include "BKE_gpencil.h"
52 #include "BKE_key.h"
53 #include "BKE_layer.h"
54 #include "BKE_main.h"
55 #include "BKE_object.h"
56 #include "BKE_paint.h"
57 #include "BKE_particle.h"
58 #include "BKE_pbvh.h"
59 #include "BKE_scene.h"
60 #include "BKE_subdiv_ccg.h"
61 
62 #include "DEG_depsgraph_query.h"
63 
64 #include "ED_info.h"
65 
66 #include "UI_resources.h"
67 
68 #include "GPU_capabilities.h"
69 
70 #define MAX_INFO_NUM_LEN 16
71 
72 typedef struct SceneStats {
82 
83 typedef struct SceneStatsFmt {
84  /* Totals */
95 
96 static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats)
97 {
98  if (me_eval == NULL) {
99  return false;
100  }
101 
102  int totvert, totedge, totface, totloop;
103  if (me_eval->runtime.subdiv_ccg != NULL) {
104  const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
105  BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop);
106  }
107  else {
108  totvert = me_eval->totvert;
109  totedge = me_eval->totedge;
110  totface = me_eval->totpoly;
111  totloop = me_eval->totloop;
112  }
113 
114  stats->totvert += totvert;
115  stats->totedge += totedge;
116  stats->totface += totface;
117  stats->tottri += poly_to_tri_count(totface, totloop);
118 
119  if (is_selected) {
120  stats->totvertsel += totvert;
121  stats->totfacesel += totface;
122  }
123  return true;
124 }
125 
126 static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
127 {
128  if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) {
129  return;
130  }
131 
132  const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0;
133 
134  stats->totobj++;
135  if (is_selected) {
136  stats->totobjsel++;
137  }
138 
139  switch (ob->type) {
140  case OB_MESH: {
141  /* we assume evaluated mesh is already built, this strictly does stats now. */
142  Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
143  if (!BLI_gset_add(objects_gset, me_eval)) {
144  break;
145  }
146  stats_mesheval(me_eval, is_selected, stats);
147  break;
148  }
149  case OB_LAMP:
150  stats->totlamp++;
151  if (is_selected) {
152  stats->totlampsel++;
153  }
154  break;
155  case OB_SURF:
156  case OB_CURVE:
157  case OB_FONT: {
158  Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
159  if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) {
160  break;
161  }
162 
163  if (stats_mesheval(me_eval, is_selected, stats)) {
164  break;
165  }
166  ATTR_FALLTHROUGH; /* Fallthrough to displist. */
167  }
168  case OB_MBALL: {
169  int totv = 0, totf = 0, tottri = 0;
170 
171  if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
172  /* Note: We only get the same curve_cache for instances of the same curve/font/...
173  * For simple linked duplicated objects, each has its own dispList. */
174  if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) {
175  break;
176  }
177 
178  BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri);
179  }
180 
181  stats->totvert += totv;
182  stats->totface += totf;
183  stats->tottri += tottri;
184 
185  if (is_selected) {
186  stats->totvertsel += totv;
187  stats->totfacesel += totf;
188  }
189  break;
190  }
191  case OB_GPENCIL: {
192  if (is_selected) {
193  bGPdata *gpd = (bGPdata *)ob->data;
194  if (!BLI_gset_add(objects_gset, gpd)) {
195  break;
196  }
197  /* GPXX Review if we can move to other place when object change
198  * maybe to depsgraph evaluation
199  */
201 
202  stats->totgplayer += gpd->totlayer;
203  stats->totgpframe += gpd->totframe;
204  stats->totgpstroke += gpd->totstroke;
205  stats->totgppoint += gpd->totpoint;
206  }
207  break;
208  }
209  case OB_HAIR:
210  case OB_POINTCLOUD:
211  case OB_VOLUME: {
212  break;
213  }
214  }
215 }
216 
217 static void stats_object_edit(Object *obedit, SceneStats *stats)
218 {
219  if (obedit->type == OB_MESH) {
220  BMEditMesh *em = BKE_editmesh_from_object(obedit);
221 
222  stats->totvert += em->bm->totvert;
223  stats->totvertsel += em->bm->totvertsel;
224 
225  stats->totedge += em->bm->totedge;
226  stats->totedgesel += em->bm->totedgesel;
227 
228  stats->totface += em->bm->totface;
229  stats->totfacesel += em->bm->totfacesel;
230 
231  stats->tottri += em->tottri;
232  }
233  else if (obedit->type == OB_ARMATURE) {
234  /* Armature Edit */
235  bArmature *arm = obedit->data;
236  EditBone *ebo;
237 
238  for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
239  stats->totbone++;
240 
241  if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
242  stats->totvert--;
243  }
244 
245  if (ebo->flag & BONE_TIPSEL) {
246  stats->totvertsel++;
247  }
248  if (ebo->flag & BONE_ROOTSEL) {
249  stats->totvertsel++;
250  }
251 
252  if (ebo->flag & BONE_SELECTED) {
253  stats->totbonesel++;
254  }
255 
256  /* if this is a connected child and its parent is being moved, remove our root */
257  if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) && ebo->parent &&
258  (ebo->parent->flag & BONE_TIPSEL)) {
259  stats->totvertsel--;
260  }
261 
262  stats->totvert += 2;
263  }
264  }
265  else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { /* OB_FONT has no cu->editnurb */
266  /* Curve Edit */
267  Curve *cu = obedit->data;
268  Nurb *nu;
269  BezTriple *bezt;
270  BPoint *bp;
271  int a;
272  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
273 
274  for (nu = nurbs->first; nu; nu = nu->next) {
275  if (nu->type == CU_BEZIER) {
276  bezt = nu->bezt;
277  a = nu->pntsu;
278  while (a--) {
279  stats->totvert += 3;
280  if (bezt->f1 & SELECT) {
281  stats->totvertsel++;
282  }
283  if (bezt->f2 & SELECT) {
284  stats->totvertsel++;
285  }
286  if (bezt->f3 & SELECT) {
287  stats->totvertsel++;
288  }
289  bezt++;
290  }
291  }
292  else {
293  bp = nu->bp;
294  a = nu->pntsu * nu->pntsv;
295  while (a--) {
296  stats->totvert++;
297  if (bp->f1 & SELECT) {
298  stats->totvertsel++;
299  }
300  bp++;
301  }
302  }
303  }
304  }
305  else if (obedit->type == OB_MBALL) {
306  /* MetaBall Edit */
307  MetaBall *mball = obedit->data;
308  MetaElem *ml;
309 
310  for (ml = mball->editelems->first; ml; ml = ml->next) {
311  stats->totvert++;
312  if (ml->flag & SELECT) {
313  stats->totvertsel++;
314  }
315  }
316  }
317  else if (obedit->type == OB_LATTICE) {
318  /* Lattice Edit */
319  Lattice *lt = obedit->data;
320  Lattice *editlatt = lt->editlatt->latt;
321  BPoint *bp;
322  int a;
323 
324  bp = editlatt->def;
325 
326  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
327  while (a--) {
328  stats->totvert++;
329  if (bp->f1 & SELECT) {
330  stats->totvertsel++;
331  }
332  bp++;
333  }
334  }
335 }
336 
337 static void stats_object_pose(Object *ob, SceneStats *stats)
338 {
339  if (ob->pose) {
340  bArmature *arm = ob->data;
341  bPoseChannel *pchan;
342 
343  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
344  stats->totbone++;
345  if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
346  if (pchan->bone->layer & arm->layer) {
347  stats->totbonesel++;
348  }
349  }
350  }
351  }
352 }
353 
355 {
356  if (ob == NULL) {
357  return false;
358  }
359  const eObjectMode object_mode = ob->mode;
360  return ((object_mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->bm);
361 }
362 
363 static void stats_object_sculpt(Object *ob, SceneStats *stats)
364 {
365 
366  SculptSession *ss = ob->sculpt;
367 
368  if (ss == NULL || ss->pbvh == NULL) {
369  return;
370  }
371 
372  switch (BKE_pbvh_type(ss->pbvh)) {
373  case PBVH_FACES:
374  stats->totvertsculpt = ss->totvert;
375  stats->totfacesculpt = ss->totfaces;
376  break;
377  case PBVH_BMESH:
378  stats->totvertsculpt = ob->sculpt->bm->totvert;
379  stats->tottri = ob->sculpt->bm->totface;
380  break;
381  case PBVH_GRIDS:
384  break;
385  }
386 }
387 
388 /* Statistics displayed in info header. Called regularly on scene changes. */
389 static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
390 {
391  SceneStats stats = {0};
392  Object *ob = OBACT(view_layer);
393  Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
394 
395  if (obedit) {
396  /* Edit Mode */
397  FOREACH_OBJECT_BEGIN (view_layer, ob_iter) {
398  if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) {
399  if (ob_iter->mode == OB_MODE_EDIT) {
400  stats_object_edit(ob_iter, &stats);
401  stats.totobjsel++;
402  }
403  stats.totobj++;
404  }
405  }
407  }
408  else if (ob && (ob->mode & OB_MODE_POSE)) {
409  /* Pose Mode */
410  stats_object_pose(ob, &stats);
411  }
413  /* Dynamic topology. Do not count all vertices, dynamic topology stats are initialized later as
414  * part of sculpt stats. */
415  }
416  else {
417  /* Objects */
418  GSet *objects_gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
420  stats_object(ob_iter, &stats, objects_gset);
421  }
423  BLI_gset_free(objects_gset, NULL);
424  }
425 
426  if (ob && (ob->mode & OB_MODE_SCULPT)) {
427  /* Sculpt Mode. When dynamic topology is not enabled both sculpt stats and scene stats are
428  * collected. */
429  stats_object_sculpt(ob, &stats);
430  }
431 
432  if (!view_layer->stats) {
433  view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
434  }
435 
436  *(view_layer->stats) = stats;
437 }
438 
440 {
441  if (view_layer->stats) {
442  MEM_freeN(view_layer->stats);
443  view_layer->stats = NULL;
444  }
445 }
446 
447 static bool format_stats(Main *bmain,
448  Scene *scene,
449  ViewLayer *view_layer,
450  SceneStatsFmt *stats_fmt)
451 {
452  /* Create stats if they don't already exist. */
453  if (!view_layer->stats) {
454  /* Do not not access dependency graph if interface is marked as locked. */
455  wmWindowManager *wm = bmain->wm.first;
456  if (wm->is_interface_locked) {
457  return false;
458  }
459  Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
460  stats_update(depsgraph, view_layer);
461  }
462 
463  SceneStats *stats = view_layer->stats;
464 
465  /* Generate formatted numbers. */
466 #define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt->_id, stats->_id)
467 
468  SCENE_STATS_FMT_INT(totvert);
469  SCENE_STATS_FMT_INT(totvertsel);
470  SCENE_STATS_FMT_INT(totvertsculpt);
471 
472  SCENE_STATS_FMT_INT(totedge);
473  SCENE_STATS_FMT_INT(totedgesel);
474 
475  SCENE_STATS_FMT_INT(totface);
476  SCENE_STATS_FMT_INT(totfacesel);
477  SCENE_STATS_FMT_INT(totfacesculpt);
478 
479  SCENE_STATS_FMT_INT(totbone);
480  SCENE_STATS_FMT_INT(totbonesel);
481 
482  SCENE_STATS_FMT_INT(totobj);
483  SCENE_STATS_FMT_INT(totobjsel);
484 
485  SCENE_STATS_FMT_INT(totlamp);
486  SCENE_STATS_FMT_INT(totlampsel);
487 
488  SCENE_STATS_FMT_INT(tottri);
489 
490  SCENE_STATS_FMT_INT(totgplayer);
491  SCENE_STATS_FMT_INT(totgpframe);
492  SCENE_STATS_FMT_INT(totgpstroke);
493  SCENE_STATS_FMT_INT(totgppoint);
494 
495 #undef SCENE_STATS_FMT_INT
496  return true;
497 }
498 
499 static void get_stats_string(
500  char *info, int len, size_t *ofs, ViewLayer *view_layer, SceneStatsFmt *stats_fmt)
501 {
502  Object *ob = OBACT(view_layer);
503  Object *obedit = OBEDIT_FROM_OBACT(ob);
504  eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
505  LayerCollection *layer_collection = view_layer->active_collection;
506 
507  if (object_mode == OB_MODE_OBJECT) {
508  *ofs += BLI_snprintf(info + *ofs,
509  len - *ofs,
510  "%s | ",
511  BKE_collection_ui_name_get(layer_collection->collection));
512  }
513 
514  if (ob) {
515  *ofs += BLI_snprintf(info + *ofs, len - *ofs, "%s | ", ob->id.name + 2);
516  }
517 
518  if (obedit) {
519  if (BKE_keyblock_from_object(obedit)) {
520  *ofs += BLI_strncpy_rlen(info + *ofs, TIP_("(Key) "), len - *ofs);
521  }
522 
523  if (obedit->type == OB_MESH) {
524  *ofs += BLI_snprintf(info + *ofs,
525  len - *ofs,
526  TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
527  stats_fmt->totvertsel,
528  stats_fmt->totvert,
529  stats_fmt->totedgesel,
530  stats_fmt->totedge,
531  stats_fmt->totfacesel,
532  stats_fmt->totface,
533  stats_fmt->tottri);
534  }
535  else if (obedit->type == OB_ARMATURE) {
536  *ofs += BLI_snprintf(info + *ofs,
537  len - *ofs,
538  TIP_("Joints:%s/%s | Bones:%s/%s"),
539  stats_fmt->totvertsel,
540  stats_fmt->totvert,
541  stats_fmt->totbonesel,
542  stats_fmt->totbone);
543  }
544  else {
545  *ofs += BLI_snprintf(
546  info + *ofs, len - *ofs, TIP_("Verts:%s/%s"), stats_fmt->totvertsel, stats_fmt->totvert);
547  }
548  }
549  else if (ob && (object_mode & OB_MODE_POSE)) {
550  *ofs += BLI_snprintf(
551  info + *ofs, len - *ofs, TIP_("Bones:%s/%s"), stats_fmt->totbonesel, stats_fmt->totbone);
552  }
553  else if ((ob) && (ob->type == OB_GPENCIL)) {
554  *ofs += BLI_snprintf(info + *ofs,
555  len - *ofs,
556  TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s"),
557  stats_fmt->totgplayer,
558  stats_fmt->totgpframe,
559  stats_fmt->totgpstroke,
560  stats_fmt->totgppoint);
561  }
562  else if (ob && (object_mode & OB_MODE_SCULPT)) {
564  *ofs += BLI_snprintf(info + *ofs,
565  len - *ofs,
566  TIP_("Verts:%s | Tris:%s"),
567  stats_fmt->totvert,
568  stats_fmt->tottri);
569  }
570  else {
571  *ofs += BLI_snprintf(info + *ofs,
572  len - *ofs,
573  TIP_("Verts:%s/%s | Faces:%s/%s"),
574  stats_fmt->totvertsculpt,
575  stats_fmt->totvert,
576  stats_fmt->totfacesculpt,
577  stats_fmt->totface);
578  }
579  }
580  else {
581  *ofs += BLI_snprintf(info + *ofs,
582  len - *ofs,
583  TIP_("Verts:%s | Faces:%s | Tris:%s"),
584  stats_fmt->totvert,
585  stats_fmt->totface,
586  stats_fmt->tottri);
587  }
588 
589  *ofs += BLI_snprintf(
590  info + *ofs, len - *ofs, TIP_(" | Objects:%s/%s"), stats_fmt->totobjsel, stats_fmt->totobj);
591 }
592 
593 static const char *info_statusbar_string(Main *bmain,
594  Scene *scene,
595  ViewLayer *view_layer,
596  char statusbar_flag)
597 {
598  char formatted_mem[15];
599  size_t ofs = 0;
600  static char info[256];
601  int len = sizeof(info);
602 
603  info[0] = '\0';
604 
605  /* Scene statistics. */
606  if (statusbar_flag & STATUSBAR_SHOW_STATS) {
607  SceneStatsFmt stats_fmt;
608  if (format_stats(bmain, scene, view_layer, &stats_fmt)) {
609  get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt);
610  }
611  }
612 
613  /* Memory status. */
614  if (statusbar_flag & STATUSBAR_SHOW_MEMORY) {
615  if (info[0]) {
616  ofs += BLI_snprintf(info + ofs, len - ofs, " | ");
617  }
619  BLI_str_format_byte_unit(formatted_mem, mem_in_use, false);
620  ofs += BLI_snprintf(info + ofs, len, TIP_("Memory: %s"), formatted_mem);
621  }
622 
623  /* GPU VRAM status. */
624  if ((statusbar_flag & STATUSBAR_SHOW_VRAM) && (GPU_mem_stats_supported())) {
625  int gpu_free_mem_kb, gpu_tot_mem_kb;
626  GPU_mem_stats_get(&gpu_tot_mem_kb, &gpu_free_mem_kb);
627  float gpu_total_gb = gpu_tot_mem_kb / 1048576.0f;
628  float gpu_free_gb = gpu_free_mem_kb / 1048576.0f;
629  if (info[0]) {
630  ofs += BLI_snprintf(info + ofs, len - ofs, " | ");
631  }
632  if (gpu_free_mem_kb && gpu_tot_mem_kb) {
633  ofs += BLI_snprintf(info + ofs,
634  len - ofs,
635  TIP_("VRAM: %.1f/%.1f GiB"),
636  gpu_total_gb - gpu_free_gb,
637  gpu_total_gb);
638  }
639  else {
640  /* Can only show amount of GPU VRAM available. */
641  ofs += BLI_snprintf(info + ofs, len - ofs, TIP_("VRAM: %.1f GiB Free"), gpu_free_gb);
642  }
643  }
644 
645  /* Blender version. */
646  if (statusbar_flag & STATUSBAR_SHOW_VERSION) {
647  if (info[0]) {
648  ofs += BLI_snprintf(info + ofs, len - ofs, " | ");
649  }
650  ofs += BLI_snprintf(info + ofs, len - ofs, TIP_("%s"), BKE_blender_version_string());
651  }
652 
653  return info;
654 }
655 
656 const char *ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
657 {
658  return info_statusbar_string(bmain, scene, view_layer, U.statusbar_flag);
659 }
660 
661 const char *ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
662 {
663  const eUserpref_StatusBar_Flag statistics_status_bar_flag = STATUSBAR_SHOW_STATS |
666 
667  return info_statusbar_string(bmain, scene, view_layer, statistics_status_bar_flag);
668 }
669 
670 static void stats_row(int col1,
671  const char *key,
672  int col2,
673  const char *value1,
674  const char *value2,
675  int *y,
676  int height)
677 {
678  *y -= height;
679  BLF_draw_default(col1, *y, 0.0f, key, 128);
680  char values[128];
681  BLI_snprintf(values, sizeof(values), (value2) ? "%s / %s" : "%s", value1, value2);
682  BLF_draw_default(col2, *y, 0.0f, values, sizeof(values));
683 }
684 
686  Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height)
687 {
688  SceneStatsFmt stats_fmt;
689  if (!format_stats(bmain, scene, view_layer, &stats_fmt)) {
690  return;
691  }
692 
693  Object *ob = OBACT(view_layer);
694  Object *obedit = OBEDIT_FROM_OBACT(ob);
695  eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
696  const int font_id = BLF_default();
697 
698  UI_FontThemeColor(font_id, TH_TEXT_HI);
699  BLF_enable(font_id, BLF_SHADOW);
700  BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
701  BLF_shadow_offset(font_id, 1, -1);
702 
703  /* Translated labels for each stat row. */
704  enum {
705  OBJ,
706  VERTS,
707  EDGES,
708  FACES,
709  TRIS,
710  JOINTS,
711  BONES,
712  LAYERS,
713  FRAMES,
714  STROKES,
715  POINTS,
716  MAX_LABELS_COUNT
717  };
718  char labels[MAX_LABELS_COUNT][64];
719 
720  STRNCPY(labels[OBJ], IFACE_("Objects"));
721  STRNCPY(labels[VERTS], IFACE_("Vertices"));
722  STRNCPY(labels[EDGES], IFACE_("Edges"));
723  STRNCPY(labels[FACES], IFACE_("Faces"));
724  STRNCPY(labels[TRIS], IFACE_("Triangles"));
725  STRNCPY(labels[JOINTS], IFACE_("Joints"));
726  STRNCPY(labels[BONES], IFACE_("Bones"));
727  STRNCPY(labels[LAYERS], IFACE_("Layers"));
728  STRNCPY(labels[FRAMES], IFACE_("Frames"));
729  STRNCPY(labels[STROKES], IFACE_("Strokes"));
730  STRNCPY(labels[POINTS], IFACE_("Points"));
731 
732  int longest_label = 0;
733  int i;
734  for (i = 0; i < MAX_LABELS_COUNT; ++i) {
735  longest_label = max_ii(longest_label, BLF_width(font_id, labels[i], sizeof(labels[i])));
736  }
737 
738  int col1 = x;
739  int col2 = x + longest_label + (0.5f * U.widget_unit);
740 
741  /* Add some extra margin above this section. */
742  *y -= (0.6f * height);
743 
744  if (object_mode == OB_MODE_OBJECT) {
745  stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
746  }
747 
748  if (obedit) {
749  if (obedit->type == OB_MESH) {
750  stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
751  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
752  stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height);
753  stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height);
754  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
755  }
756  else if (obedit->type == OB_ARMATURE) {
757  stats_row(col1, labels[JOINTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
758  stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
759  }
760  else {
761  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
762  }
763  }
764  else if (ob && (object_mode & OB_MODE_POSE)) {
765  stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
766  }
767  else if ((ob) && (ob->type == OB_GPENCIL)) {
768  stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, NULL, y, height);
769  stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, NULL, y, height);
770  stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height);
771  stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height);
772  }
773  else if (ob && (object_mode & OB_MODE_SCULPT)) {
775  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, NULL, y, height);
776  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
777  }
778  else {
779  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, stats_fmt.totvert, y, height);
780  stats_row(col1, labels[FACES], col2, stats_fmt.totfacesculpt, stats_fmt.totface, y, height);
781  }
782  }
783  else {
784  stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
785  stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, NULL, y, height);
786  stats_row(col1, labels[FACES], col2, stats_fmt.totface, NULL, y, height);
787  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
788  }
789 
790  BLF_disable(font_id, BLF_SHADOW);
791 }
const char * BKE_blender_version_string(void)
Definition: blender.c:142
const char * BKE_collection_ui_name_get(struct Collection *collection)
Definition: collection.c:776
struct ListBase * BKE_curve_editNurbs_get(struct Curve *cu)
Definition: curve.c:437
display list (or rather multi purpose list) stuff.
void BKE_displist_count(const struct ListBase *lb, int *totvert, int *totface, int *tottri)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
void BKE_gpencil_stats_update(struct bGPdata *gpd)
Definition: gpencil.c:2412
struct KeyBlock * BKE_keyblock_from_object(struct Object *ob)
Definition: key.c:1902
#define FOREACH_OBJECT_END
Definition: BKE_layer.h:331
#define FOREACH_OBJECT_BEGIN(view_layer, _instance)
Definition: BKE_layer.h:324
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(struct Object *object)
Definition: object.c:4459
A BVH for high poly meshes.
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh)
Definition: pbvh.c:1718
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
Definition: pbvh.c:1712
@ PBVH_GRIDS
Definition: BKE_pbvh.h:211
@ PBVH_BMESH
Definition: BKE_pbvh.h:212
@ PBVH_FACES
Definition: BKE_pbvh.h:210
struct Depsgraph * BKE_scene_ensure_depsgraph(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer)
Definition: scene.c:3526
void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg, int *r_num_vertices, int *r_num_edges, int *r_num_faces, int *r_num_loops)
Definition: subdiv_ccg.c:1244
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL()
Definition: blf_default.c:71
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:723
int BLF_default(void)
Definition: blf_default.c:55
void BLF_shadow_offset(int fontid, int x, int y)
Definition: blf.c:841
void BLF_shadow(int fontid, int level, const float rgba[4]) ATTR_NONNULL(3)
Definition: blf.c:831
void BLF_disable(int fontid, int option)
Definition: blf.c:283
void BLF_enable(int fontid, int option)
Definition: blf.c:274
#define BLF_SHADOW
Definition: BLF_api.h:271
#define ATTR_FALLTHROUGH
struct GSet GSet
Definition: BLI_ghash.h:189
unsigned int BLI_ghashutil_ptrhash(const void *key)
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1125
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:1160
MINLINE int max_ii(int a, int b)
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) ATTR_NONNULL()
Definition: string.c:1206
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:187
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define ELEM(...)
#define TIP_(msgid)
#define IFACE_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(graph_, instance_)
#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TIPSEL
@ BONE_CONNECTED
Object groups, one object can be in many groups at once.
@ CU_BEZIER
@ BASE_VISIBLE_VIEWLAYER
@ BASE_SELECTED
eObjectMode
@ OB_MODE_EDIT
@ OB_MODE_SCULPT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_HAIR
@ OB_VOLUME
@ OB_CURVE
@ OB_GPENCIL
#define OBEDIT_FROM_VIEW_LAYER(view_layer)
#define OBEDIT_FROM_OBACT(ob)
#define OBACT(_view_layer)
eUserpref_StatusBar_Flag
@ STATUSBAR_SHOW_STATS
@ STATUSBAR_SHOW_MEMORY
@ STATUSBAR_SHOW_VRAM
@ STATUSBAR_SHOW_VERSION
void GPU_mem_stats_get(int *totalmem, int *freemem)
bool GPU_mem_stats_supported(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
@ TH_TEXT_HI
Definition: UI_resources.h:59
void UI_FontThemeColor(int fontid, int colorid)
Definition: resources.c:1156
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
Scene scene
const Depsgraph * depsgraph
static void stats_object_sculpt(Object *ob, SceneStats *stats)
Definition: info_stats.c:363
static void get_stats_string(char *info, int len, size_t *ofs, ViewLayer *view_layer, SceneStatsFmt *stats_fmt)
Definition: info_stats.c:499
#define SCENE_STATS_FMT_INT(_id)
#define MAX_INFO_NUM_LEN
Definition: info_stats.c:70
static void stats_row(int col1, const char *key, int col2, const char *value1, const char *value2, int *y, int height)
Definition: info_stats.c:670
static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
Definition: info_stats.c:389
const char * ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: info_stats.c:656
static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
Definition: info_stats.c:354
static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
Definition: info_stats.c:126
const char * ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: info_stats.c:661
static bool format_stats(Main *bmain, Scene *scene, ViewLayer *view_layer, SceneStatsFmt *stats_fmt)
Definition: info_stats.c:447
struct SceneStatsFmt SceneStatsFmt
static void stats_object_edit(Object *obedit, SceneStats *stats)
Definition: info_stats.c:217
void ED_info_stats_clear(ViewLayer *view_layer)
Definition: info_stats.c:439
struct SceneStats SceneStats
static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats)
Definition: info_stats.c:96
static void stats_object_pose(Object *ob, SceneStats *stats)
Definition: info_stats.c:337
static const char * info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer, char statusbar_flag)
Definition: info_stats.c:593
void ED_info_draw_stats(Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height)
Definition: info_stats.c:685
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_get_memory_in_use)(void)
Definition: mallocn.c:59
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static size_t mem_in_use
static unsigned a[3]
Definition: RandGen.cpp:92
_W64 unsigned int uintptr_t
Definition: stdint.h:122
unsigned __int64 uint64_t
Definition: stdint.h:93
struct BMesh * bm
Definition: BKE_editmesh.h:52
int totvert
Definition: bmesh_class.h:297
int totfacesel
Definition: bmesh_class.h:298
int totedge
Definition: bmesh_class.h:297
int totvertsel
Definition: bmesh_class.h:298
int totedgesel
Definition: bmesh_class.h:298
int totface
Definition: bmesh_class.h:297
uint8_t f1
ListBase disp
Definition: BKE_curve.h:49
struct EditBone * next
Definition: BKE_armature.h:49
struct EditBone * parent
Definition: BKE_armature.h:55
struct Lattice * latt
char name[66]
Definition: DNA_ID.h:283
struct EditLatt * editlatt
struct BPoint * def
struct Collection * collection
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase wm
Definition: BKE_main.h:175
struct SubdivCCG * subdiv_ccg
int totedge
int totvert
Mesh_Runtime runtime
int totpoly
int totloop
ListBase * editelems
struct MetaElem * next
short flag
struct Nurb * next
short type
BezTriple * bezt
BPoint * bp
struct CurveCache * curve_cache
short base_flag
struct bPose * pose
Object_Runtime runtime
struct SculptSession * sculpt
void * data
char totlampsel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:90
char totgplayer[MAX_INFO_NUM_LEN]
Definition: info_stats.c:92
char totobjsel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:89
char totface[MAX_INFO_NUM_LEN]
Definition: info_stats.c:86
char totvert[MAX_INFO_NUM_LEN]
Definition: info_stats.c:85
char totbone[MAX_INFO_NUM_LEN]
Definition: info_stats.c:88
char totgpstroke[MAX_INFO_NUM_LEN]
Definition: info_stats.c:93
char tottri[MAX_INFO_NUM_LEN]
Definition: info_stats.c:91
char totgpframe[MAX_INFO_NUM_LEN]
Definition: info_stats.c:92
char totvertsculpt[MAX_INFO_NUM_LEN]
Definition: info_stats.c:85
char totfacesculpt[MAX_INFO_NUM_LEN]
Definition: info_stats.c:87
char totlamp[MAX_INFO_NUM_LEN]
Definition: info_stats.c:90
char totfacesel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:86
char totedge[MAX_INFO_NUM_LEN]
Definition: info_stats.c:87
char totgppoint[MAX_INFO_NUM_LEN]
Definition: info_stats.c:93
char totobj[MAX_INFO_NUM_LEN]
Definition: info_stats.c:89
char totedgesel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:87
char totvertsel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:85
char totbonesel[MAX_INFO_NUM_LEN]
Definition: info_stats.c:88
uint64_t totfacesculpt
Definition: info_stats.c:75
uint64_t totfacesel
Definition: info_stats.c:75
uint64_t tottri
Definition: info_stats.c:79
uint64_t totedgesel
Definition: info_stats.c:74
uint64_t totvert
Definition: info_stats.c:73
uint64_t totbone
Definition: info_stats.c:76
uint64_t totgpframe
Definition: info_stats.c:80
uint64_t totvertsel
Definition: info_stats.c:73
uint64_t totlamp
Definition: info_stats.c:78
uint64_t totface
Definition: info_stats.c:75
uint64_t totgplayer
Definition: info_stats.c:80
uint64_t totvertsculpt
Definition: info_stats.c:73
uint64_t totgppoint
Definition: info_stats.c:80
uint64_t totlampsel
Definition: info_stats.c:78
uint64_t totobj
Definition: info_stats.c:77
uint64_t totgpstroke
Definition: info_stats.c:80
uint64_t totedge
Definition: info_stats.c:74
uint64_t totbonesel
Definition: info_stats.c:76
uint64_t totobjsel
Definition: info_stats.c:77
struct BMesh * bm
Definition: BKE_paint.h:493
struct PBVH * pbvh
Definition: BKE_paint.h:504
LayerCollection * active_collection
struct SceneStats * stats
unsigned int layer
ListBase * edbo
struct Bone * bone
struct bPoseChannel * next
ListBase chanbase
uint len