Blender  V3.3
info_stats.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cstdio>
8 #include <cstring>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_armature_types.h"
13 #include "DNA_collection_types.h"
14 #include "DNA_curve_types.h"
15 #include "DNA_gpencil_types.h"
16 #include "DNA_lattice_types.h"
17 #include "DNA_mesh_types.h"
18 #include "DNA_meta_types.h"
19 #include "DNA_scene_types.h"
20 #include "DNA_space_types.h"
22 
23 #include "BLF_api.h"
24 
25 #include "BLI_listbase.h"
26 #include "BLI_math.h"
27 #include "BLI_string.h"
28 #include "BLI_utildefines.h"
29 
30 #include "BLT_translation.h"
31 
32 #include "BKE_action.h"
33 #include "BKE_armature.h"
34 #include "BKE_blender_version.h"
35 #include "BKE_context.h"
36 #include "BKE_curve.h"
37 #include "BKE_displist.h"
38 #include "BKE_editmesh.h"
39 #include "BKE_gpencil.h"
40 #include "BKE_key.h"
41 #include "BKE_layer.h"
42 #include "BKE_main.h"
43 #include "BKE_object.h"
44 #include "BKE_paint.h"
45 #include "BKE_particle.h"
46 #include "BKE_pbvh.h"
47 #include "BKE_scene.h"
48 #include "BKE_subdiv_ccg.h"
49 #include "BKE_subdiv_modifier.h"
50 
51 #include "DEG_depsgraph_query.h"
52 
53 #include "ED_info.h"
54 
55 #include "WM_api.h"
56 
57 #include "UI_resources.h"
58 
59 #include "GPU_capabilities.h"
60 
62 
63 #define MAX_INFO_NUM_LEN 16
64 
65 struct SceneStats {
74 };
75 
76 struct SceneStatsFmt {
77  /* Totals */
87 };
88 
89 static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats)
90 {
91  if (me_eval == nullptr) {
92  return false;
93  }
94 
95  int totvert, totedge, totface, totloop;
96 
97  const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
98  const SubsurfRuntimeData *subsurf_runtime_data = me_eval->runtime.subsurf_runtime_data;
99 
100  if (subdiv_ccg != nullptr) {
101  BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop);
102  }
103  else if (subsurf_runtime_data && subsurf_runtime_data->resolution != 0) {
104  totvert = subsurf_runtime_data->stats_totvert;
105  totedge = subsurf_runtime_data->stats_totedge;
106  totface = subsurf_runtime_data->stats_totpoly;
107  totloop = subsurf_runtime_data->stats_totloop;
108  }
109  else {
110  totvert = me_eval->totvert;
111  totedge = me_eval->totedge;
112  totface = me_eval->totpoly;
113  totloop = me_eval->totloop;
114  }
115 
116  stats->totvert += totvert;
117  stats->totedge += totedge;
118  stats->totface += totface;
119  stats->tottri += poly_to_tri_count(totface, totloop);
120 
121  if (is_selected) {
122  stats->totvertsel += totvert;
123  stats->totfacesel += totface;
124  }
125  return true;
126 }
127 
128 static void stats_object(Object *ob,
129  const View3D *v3d_local,
130  SceneStats *stats,
131  GSet *objects_gset)
132 {
133  if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) {
134  return;
135  }
136 
137  if (v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob)) {
138  return;
139  }
140 
141  const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0;
142 
143  stats->totobj++;
144  if (is_selected) {
145  stats->totobjsel++;
146  }
147 
148  switch (ob->type) {
149  case OB_MESH: {
150  /* we assume evaluated mesh is already built, this strictly does stats now. */
151  const Mesh *me_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob);
152  if (!BLI_gset_add(objects_gset, (void *)me_eval)) {
153  break;
154  }
155  stats_mesheval(me_eval, is_selected, stats);
156  break;
157  }
158  case OB_LAMP:
159  stats->totlamp++;
160  if (is_selected) {
161  stats->totlampsel++;
162  }
163  break;
164  case OB_SURF:
165  case OB_CURVES_LEGACY:
166  case OB_FONT: {
167  const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
168  if ((me_eval != nullptr) && !BLI_gset_add(objects_gset, (void *)me_eval)) {
169  break;
170  }
171 
172  if (stats_mesheval(me_eval, is_selected, stats)) {
173  break;
174  }
175  ATTR_FALLTHROUGH; /* Fall-through to displist. */
176  }
177  case OB_MBALL: {
178  int totv = 0, totf = 0, tottri = 0;
179 
180  if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
181  /* NOTE: We only get the same curve_cache for instances of the same curve/font/...
182  * For simple linked duplicated objects, each has its own dispList. */
183  if (!BLI_gset_add(objects_gset, ob->runtime.curve_cache)) {
184  break;
185  }
186 
187  BKE_displist_count(&ob->runtime.curve_cache->disp, &totv, &totf, &tottri);
188  }
189 
190  stats->totvert += totv;
191  stats->totface += totf;
192  stats->tottri += tottri;
193 
194  if (is_selected) {
195  stats->totvertsel += totv;
196  stats->totfacesel += totf;
197  }
198  break;
199  }
200  case OB_GPENCIL: {
201  if (is_selected) {
202  bGPdata *gpd = (bGPdata *)ob->data;
203  if (!BLI_gset_add(objects_gset, gpd)) {
204  break;
205  }
206  /* GPXX Review if we can move to other place when object change
207  * maybe to depsgraph evaluation
208  */
210 
211  stats->totgplayer += gpd->totlayer;
212  stats->totgpframe += gpd->totframe;
213  stats->totgpstroke += gpd->totstroke;
214  stats->totgppoint += gpd->totpoint;
215  }
216  break;
217  }
218  case OB_CURVES:
219  case OB_POINTCLOUD:
220  case OB_VOLUME: {
221  break;
222  }
223  }
224 }
225 
226 static void stats_object_edit(Object *obedit, SceneStats *stats)
227 {
228  if (obedit->type == OB_MESH) {
229  BMEditMesh *em = BKE_editmesh_from_object(obedit);
230 
231  stats->totvert += em->bm->totvert;
232  stats->totvertsel += em->bm->totvertsel;
233 
234  stats->totedge += em->bm->totedge;
235  stats->totedgesel += em->bm->totedgesel;
236 
237  stats->totface += em->bm->totface;
238  stats->totfacesel += em->bm->totfacesel;
239 
240  stats->tottri += em->tottri;
241  }
242  else if (obedit->type == OB_ARMATURE) {
243  /* Armature Edit */
244  bArmature *arm = static_cast<bArmature *>(obedit->data);
245 
246  LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
247  stats->totbone++;
248 
249  if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
250  stats->totvert--;
251  }
252 
253  if (ebo->flag & BONE_TIPSEL) {
254  stats->totvertsel++;
255  }
256  if (ebo->flag & BONE_ROOTSEL) {
257  stats->totvertsel++;
258  }
259 
260  if (ebo->flag & BONE_SELECTED) {
261  stats->totbonesel++;
262  }
263 
264  /* if this is a connected child and its parent is being moved, remove our root */
265  if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) && ebo->parent &&
266  (ebo->parent->flag & BONE_TIPSEL)) {
267  stats->totvertsel--;
268  }
269 
270  stats->totvert += 2;
271  }
272  }
273  else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) { /* OB_FONT has no cu->editnurb */
274  /* Curve Edit */
275  Curve *cu = static_cast<Curve *>(obedit->data);
276  BezTriple *bezt;
277  BPoint *bp;
278  int a;
279  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
280 
281  LISTBASE_FOREACH (Nurb *, nu, nurbs) {
282  if (nu->type == CU_BEZIER) {
283  bezt = nu->bezt;
284  a = nu->pntsu;
285  while (a--) {
286  stats->totvert += 3;
287  if (bezt->f1 & SELECT) {
288  stats->totvertsel++;
289  }
290  if (bezt->f2 & SELECT) {
291  stats->totvertsel++;
292  }
293  if (bezt->f3 & SELECT) {
294  stats->totvertsel++;
295  }
296  bezt++;
297  }
298  }
299  else {
300  bp = nu->bp;
301  a = nu->pntsu * nu->pntsv;
302  while (a--) {
303  stats->totvert++;
304  if (bp->f1 & SELECT) {
305  stats->totvertsel++;
306  }
307  bp++;
308  }
309  }
310  }
311  }
312  else if (obedit->type == OB_MBALL) {
313  /* MetaBall Edit */
314  MetaBall *mball = static_cast<MetaBall *>(obedit->data);
315 
316  LISTBASE_FOREACH (MetaElem *, ml, mball->editelems) {
317  stats->totvert++;
318  if (ml->flag & SELECT) {
319  stats->totvertsel++;
320  }
321  }
322  }
323  else if (obedit->type == OB_LATTICE) {
324  /* Lattice Edit */
325  Lattice *lt = static_cast<Lattice *>(obedit->data);
326  Lattice *editlatt = lt->editlatt->latt;
327  BPoint *bp;
328  int a;
329 
330  bp = editlatt->def;
331 
332  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
333  while (a--) {
334  stats->totvert++;
335  if (bp->f1 & SELECT) {
336  stats->totvertsel++;
337  }
338  bp++;
339  }
340  }
341 }
342 
343 static void stats_object_pose(const Object *ob, SceneStats *stats)
344 {
345  if (ob->pose) {
346  bArmature *arm = static_cast<bArmature *>(ob->data);
347 
348  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
349  stats->totbone++;
350  if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
351  if (BKE_pose_is_layer_visible(arm, pchan)) {
352  stats->totbonesel++;
353  }
354  }
355  }
356  }
357 }
358 
360 {
362  return (ob->sculpt && ob->sculpt->bm);
363 }
364 
365 static void stats_object_sculpt(const Object *ob, SceneStats *stats)
366 {
367 
368  SculptSession *ss = ob->sculpt;
369 
370  if (ss == nullptr || ss->pbvh == nullptr) {
371  return;
372  }
373 
374  switch (BKE_pbvh_type(ss->pbvh)) {
375  case PBVH_FACES:
376  stats->totvertsculpt = ss->totvert;
377  stats->totfacesculpt = ss->totfaces;
378  break;
379  case PBVH_BMESH:
380  stats->totvertsculpt = ob->sculpt->bm->totvert;
381  stats->tottri = ob->sculpt->bm->totface;
382  break;
383  case PBVH_GRIDS:
386  break;
387  }
388 }
389 
390 /* Statistics displayed in info header. Called regularly on scene changes. */
392  ViewLayer *view_layer,
393  View3D *v3d_local,
394  SceneStats *stats)
395 {
396  const Object *ob = OBACT(view_layer);
397  const Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
398 
399  memset(stats, 0x0, sizeof(*stats));
400 
401  if (obedit) {
402  /* Edit Mode. */
403  FOREACH_OBJECT_BEGIN (view_layer, ob_iter) {
404  if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) {
405  if (ob_iter->mode & OB_MODE_EDIT) {
406  stats_object_edit(ob_iter, stats);
407  stats->totobjsel++;
408  }
409  else {
410  /* Skip hidden objects in local view that are not in edit-mode,
411  * an exception for edit-mode, in most other modes these would be considered hidden. */
412  if ((v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob_iter))) {
413  continue;
414  }
415  }
416  stats->totobj++;
417  }
418  }
420  }
421  else if (ob && (ob->mode & OB_MODE_POSE)) {
422  /* Pose Mode. */
423  FOREACH_OBJECT_BEGIN (view_layer, ob_iter) {
424  if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) {
425  if (ob_iter->mode & OB_MODE_POSE) {
426  stats_object_pose(ob_iter, stats);
427  stats->totobjsel++;
428  }
429  else {
430  /* See comment for edit-mode. */
431  if ((v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob_iter))) {
432  continue;
433  }
434  }
435  stats->totobj++;
436  }
437  }
439  }
440  else if (ob && (ob->mode & OB_MODE_SCULPT)) {
441  /* Sculpt Mode. */
443  /* Dynamic topology. Do not count all vertices,
444  * dynamic topology stats are initialized later as part of sculpt stats. */
445  }
446  else {
447  /* When dynamic topology is not enabled both sculpt stats and scene stats are collected. */
448  stats_object_sculpt(ob, stats);
449  }
450  }
451  else {
452  /* Objects. */
453  GSet *objects_gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
455  stats_object(ob_iter, v3d_local, stats, objects_gset);
456  }
458  BLI_gset_free(objects_gset, nullptr);
459  }
460 }
461 
463 {
464  MEM_SAFE_FREE(view_layer->stats);
465 
466  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
467  ViewLayer *view_layer_test = WM_window_get_active_view_layer(win);
468  if (view_layer != view_layer_test) {
469  continue;
470  }
471  const bScreen *screen = WM_window_get_active_screen(win);
472  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
473  if (area->spacetype == SPACE_VIEW3D) {
474  View3D *v3d = (View3D *)area->spacedata.first;
475  if (v3d->localvd) {
477  }
478  }
479  }
480  }
481 }
482 
483 static bool format_stats(
484  Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, SceneStatsFmt *stats_fmt)
485 {
486  /* Create stats if they don't already exist. */
487  SceneStats **stats_p = (v3d_local) ? &v3d_local->runtime.local_stats : &view_layer->stats;
488  if (*stats_p == nullptr) {
489  /* Don't access dependency graph if interface is marked as locked. */
490  wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
491  if (wm->is_interface_locked) {
492  return false;
493  }
494  Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
495  *stats_p = (SceneStats *)MEM_mallocN(sizeof(SceneStats), __func__);
496  stats_update(depsgraph, view_layer, v3d_local, *stats_p);
497  }
498 
499  SceneStats *stats = *stats_p;
500 
501  /* Generate formatted numbers. */
502 #define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt->_id, stats->_id)
503 
504  SCENE_STATS_FMT_INT(totvert);
505  SCENE_STATS_FMT_INT(totvertsel);
506  SCENE_STATS_FMT_INT(totvertsculpt);
507 
508  SCENE_STATS_FMT_INT(totedge);
509  SCENE_STATS_FMT_INT(totedgesel);
510 
511  SCENE_STATS_FMT_INT(totface);
512  SCENE_STATS_FMT_INT(totfacesel);
513  SCENE_STATS_FMT_INT(totfacesculpt);
514 
515  SCENE_STATS_FMT_INT(totbone);
516  SCENE_STATS_FMT_INT(totbonesel);
517 
518  SCENE_STATS_FMT_INT(totobj);
519  SCENE_STATS_FMT_INT(totobjsel);
520 
521  SCENE_STATS_FMT_INT(totlamp);
522  SCENE_STATS_FMT_INT(totlampsel);
523 
524  SCENE_STATS_FMT_INT(tottri);
525 
526  SCENE_STATS_FMT_INT(totgplayer);
527  SCENE_STATS_FMT_INT(totgpframe);
528  SCENE_STATS_FMT_INT(totgpstroke);
529  SCENE_STATS_FMT_INT(totgppoint);
530 
531 #undef SCENE_STATS_FMT_INT
532  return true;
533 }
534 
535 static void get_stats_string(
536  char *info, int len, size_t *ofs, ViewLayer *view_layer, SceneStatsFmt *stats_fmt)
537 {
538  Object *ob = OBACT(view_layer);
539  Object *obedit = OBEDIT_FROM_OBACT(ob);
540  eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT;
541  LayerCollection *layer_collection = view_layer->active_collection;
542 
543  if (object_mode == OB_MODE_OBJECT) {
544  *ofs += BLI_snprintf_rlen(info + *ofs,
545  len - *ofs,
546  "%s | ",
547  BKE_collection_ui_name_get(layer_collection->collection));
548  }
549 
550  if (ob) {
551  *ofs += BLI_snprintf_rlen(info + *ofs, len - *ofs, "%s | ", ob->id.name + 2);
552  }
553 
554  if (obedit) {
555  if (BKE_keyblock_from_object(obedit)) {
556  *ofs += BLI_strncpy_rlen(info + *ofs, TIP_("(Key) "), len - *ofs);
557  }
558 
559  if (obedit->type == OB_MESH) {
560  *ofs += BLI_snprintf_rlen(info + *ofs,
561  len - *ofs,
562  TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
563  stats_fmt->totvertsel,
564  stats_fmt->totvert,
565  stats_fmt->totedgesel,
566  stats_fmt->totedge,
567  stats_fmt->totfacesel,
568  stats_fmt->totface,
569  stats_fmt->tottri);
570  }
571  else if (obedit->type == OB_ARMATURE) {
572  *ofs += BLI_snprintf_rlen(info + *ofs,
573  len - *ofs,
574  TIP_("Joints:%s/%s | Bones:%s/%s"),
575  stats_fmt->totvertsel,
576  stats_fmt->totvert,
577  stats_fmt->totbonesel,
578  stats_fmt->totbone);
579  }
580  else {
581  *ofs += BLI_snprintf_rlen(
582  info + *ofs, len - *ofs, TIP_("Verts:%s/%s"), stats_fmt->totvertsel, stats_fmt->totvert);
583  }
584  }
585  else if (ob && (object_mode & OB_MODE_POSE)) {
586  *ofs += BLI_snprintf_rlen(
587  info + *ofs, len - *ofs, TIP_("Bones:%s/%s"), stats_fmt->totbonesel, stats_fmt->totbone);
588  }
589  else if ((ob) && (ob->type == OB_GPENCIL)) {
590  *ofs += BLI_snprintf_rlen(info + *ofs,
591  len - *ofs,
592  TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s"),
593  stats_fmt->totgplayer,
594  stats_fmt->totgpframe,
595  stats_fmt->totgpstroke,
596  stats_fmt->totgppoint);
597  }
598  else if (ob && (object_mode & OB_MODE_SCULPT)) {
600  *ofs += BLI_snprintf_rlen(info + *ofs,
601  len - *ofs,
602  TIP_("Verts:%s | Tris:%s"),
603  stats_fmt->totvert,
604  stats_fmt->tottri);
605  }
606  else {
607  *ofs += BLI_snprintf_rlen(info + *ofs,
608  len - *ofs,
609  TIP_("Verts:%s/%s | Faces:%s/%s"),
610  stats_fmt->totvertsculpt,
611  stats_fmt->totvert,
612  stats_fmt->totfacesculpt,
613  stats_fmt->totface);
614  }
615  }
616  else {
617  *ofs += BLI_snprintf_rlen(info + *ofs,
618  len - *ofs,
619  TIP_("Verts:%s | Faces:%s | Tris:%s"),
620  stats_fmt->totvert,
621  stats_fmt->totface,
622  stats_fmt->tottri);
623  }
624 
625  *ofs += BLI_snprintf_rlen(
626  info + *ofs, len - *ofs, TIP_(" | Objects:%s/%s"), stats_fmt->totobjsel, stats_fmt->totobj);
627 }
628 
630  Scene *scene,
631  ViewLayer *view_layer,
632  const char statusbar_flag)
633 {
634  char formatted_mem[15];
635  size_t ofs = 0;
636  static char info[256];
637  int len = sizeof(info);
638 
639  info[0] = '\0';
640 
641  /* Scene statistics. */
642  if (statusbar_flag & STATUSBAR_SHOW_STATS) {
643  SceneStatsFmt stats_fmt;
644  if (format_stats(bmain, scene, view_layer, nullptr, &stats_fmt)) {
645  get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt);
646  }
647  }
648 
649  /* Memory status. */
650  if (statusbar_flag & STATUSBAR_SHOW_MEMORY) {
651  if (info[0]) {
652  ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | ");
653  }
655  BLI_str_format_byte_unit(formatted_mem, mem_in_use, false);
656  ofs += BLI_snprintf_rlen(info + ofs, len, TIP_("Memory: %s"), formatted_mem);
657  }
658 
659  /* GPU VRAM status. */
660  if ((statusbar_flag & STATUSBAR_SHOW_VRAM) && (GPU_mem_stats_supported())) {
661  int gpu_free_mem_kb, gpu_tot_mem_kb;
662  GPU_mem_stats_get(&gpu_tot_mem_kb, &gpu_free_mem_kb);
663  float gpu_total_gb = gpu_tot_mem_kb / 1048576.0f;
664  float gpu_free_gb = gpu_free_mem_kb / 1048576.0f;
665  if (info[0]) {
666  ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | ");
667  }
668  if (gpu_free_mem_kb && gpu_tot_mem_kb) {
669  ofs += BLI_snprintf_rlen(info + ofs,
670  len - ofs,
671  TIP_("VRAM: %.1f/%.1f GiB"),
672  gpu_total_gb - gpu_free_gb,
673  gpu_total_gb);
674  }
675  else {
676  /* Can only show amount of GPU VRAM available. */
677  ofs += BLI_snprintf_rlen(info + ofs, len - ofs, TIP_("VRAM: %.1f GiB Free"), gpu_free_gb);
678  }
679  }
680 
681  /* Blender version. */
682  if (statusbar_flag & STATUSBAR_SHOW_VERSION) {
683  if (info[0]) {
684  ofs += BLI_snprintf_rlen(info + ofs, len - ofs, " | ");
685  }
686  ofs += BLI_snprintf_rlen(info + ofs, len - ofs, TIP_("%s"), BKE_blender_version_string());
687  }
688 
689  return info;
690 }
691 
692 const char *ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
693 {
694  return ED_info_statusbar_string_ex(bmain, scene, view_layer, U.statusbar_flag);
695 }
696 
697 const char *ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
698 {
699  const eUserpref_StatusBar_Flag statistics_status_bar_flag = STATUSBAR_SHOW_STATS |
702 
703  return ED_info_statusbar_string_ex(bmain, scene, view_layer, statistics_status_bar_flag);
704 }
705 
706 static void stats_row(int col1,
707  const char *key,
708  int col2,
709  const char *value1,
710  const char *value2,
711  int *y,
712  int height)
713 {
714  *y -= height;
715  BLF_draw_default(col1, *y, 0.0f, key, 128);
716  char values[128];
717  BLI_snprintf(values, sizeof(values), (value2) ? "%s / %s" : "%s", value1, value2);
718  BLF_draw_default(col2, *y, 0.0f, values, sizeof(values));
719 }
720 
722  Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, int x, int *y, int height)
723 {
724  BLI_assert(v3d_local == nullptr || v3d_local->localvd != nullptr);
725  SceneStatsFmt stats_fmt;
726  if (!format_stats(bmain, scene, view_layer, v3d_local, &stats_fmt)) {
727  return;
728  }
729 
730  Object *ob = OBACT(view_layer);
731  Object *obedit = OBEDIT_FROM_OBACT(ob);
732  eObjectMode object_mode = ob ? (eObjectMode)ob->mode : OB_MODE_OBJECT;
733  const int font_id = BLF_set_default();
734 
735  UI_FontThemeColor(font_id, TH_TEXT_HI);
736  BLF_enable(font_id, BLF_SHADOW);
737  const float shadow_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
738  BLF_shadow(font_id, 5, shadow_color);
739  BLF_shadow_offset(font_id, 1, -1);
740 
741  /* Translated labels for each stat row. */
742  enum {
743  OBJ,
744  VERTS,
745  EDGES,
746  FACES,
747  TRIS,
748  JOINTS,
749  BONES,
750  LAYERS,
751  FRAMES,
752  STROKES,
753  POINTS,
754  LIGHTS,
755  MAX_LABELS_COUNT
756  };
757  char labels[MAX_LABELS_COUNT][64];
758 
759  STRNCPY(labels[OBJ], IFACE_("Objects"));
760  STRNCPY(labels[VERTS], IFACE_("Vertices"));
761  STRNCPY(labels[EDGES], IFACE_("Edges"));
762  STRNCPY(labels[FACES], IFACE_("Faces"));
763  STRNCPY(labels[TRIS], IFACE_("Triangles"));
764  STRNCPY(labels[JOINTS], IFACE_("Joints"));
765  STRNCPY(labels[BONES], IFACE_("Bones"));
766  STRNCPY(labels[LAYERS], IFACE_("Layers"));
767  STRNCPY(labels[FRAMES], IFACE_("Frames"));
768  STRNCPY(labels[STROKES], IFACE_("Strokes"));
769  STRNCPY(labels[POINTS], IFACE_("Points"));
770  STRNCPY(labels[LIGHTS], IFACE_("Lights"));
771 
772  int longest_label = 0;
773  int i;
774  for (i = 0; i < MAX_LABELS_COUNT; ++i) {
775  longest_label = max_ii(longest_label, BLF_width(font_id, labels[i], sizeof(labels[i])));
776  }
777 
778  int col1 = x;
779  int col2 = x + longest_label + (0.5f * U.widget_unit);
780 
781  /* Add some extra margin above this section. */
782  *y -= (0.6f * height);
783 
784  if (object_mode == OB_MODE_OBJECT) {
785  stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
786  }
787 
788  if (obedit) {
789  stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
790  if (obedit->type == OB_MESH) {
791  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
792  stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height);
793  stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height);
794  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
795  }
796  else if (obedit->type == OB_ARMATURE) {
797  stats_row(col1, labels[JOINTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
798  stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
799  }
800  else {
801  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height);
802  }
803  }
804  else if (ob && (object_mode & OB_MODE_POSE)) {
805  stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height);
806  stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height);
807  }
808  else if ((ob) && (ob->type == OB_GPENCIL)) {
809  stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, nullptr, y, height);
810  stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, nullptr, y, height);
811  stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, nullptr, y, height);
812  stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, nullptr, y, height);
813  }
814  else if (ob && (object_mode & OB_MODE_SCULPT)) {
816  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, nullptr, y, height);
817  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
818  }
819  else {
820  stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, stats_fmt.totvert, y, height);
821  stats_row(col1, labels[FACES], col2, stats_fmt.totfacesculpt, stats_fmt.totface, y, height);
822  }
823  }
824  else if ((ob) && (ob->type == OB_LAMP)) {
825  stats_row(col1, labels[LIGHTS], col2, stats_fmt.totlampsel, stats_fmt.totlamp, y, height);
826  }
827  else {
828  stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, nullptr, y, height);
829  stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, nullptr, y, height);
830  stats_row(col1, labels[FACES], col2, stats_fmt.totface, nullptr, y, height);
831  stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, nullptr, y, height);
832  }
833 
834  BLF_disable(font_id, BLF_SHADOW);
835 }
Blender kernel action and pose functionality.
bool BKE_pose_is_layer_visible(const struct bArmature *arm, const struct bPoseChannel *pchan)
const char * BKE_blender_version_string(void)
Definition: blender.c:124
const char * BKE_collection_ui_name_get(struct Collection *collection)
Definition: collection.c:736
struct ListBase * BKE_curve_editNurbs_get(struct Curve *cu)
Definition: curve.cc:426
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:58
void BKE_gpencil_stats_update(struct bGPdata *gpd)
Definition: gpencil.c:2180
struct KeyBlock * BKE_keyblock_from_object(struct Object *ob)
Definition: key.c:1890
#define FOREACH_OBJECT_END
Definition: BKE_layer.h:430
#define FOREACH_OBJECT_BEGIN(view_layer, _instance)
Definition: BKE_layer.h:423
bool BKE_object_is_visible_in_viewport(const struct View3D *v3d, const struct Object *ob)
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
struct Mesh * BKE_object_get_evaluated_mesh_no_subsurf(const struct Object *object)
A BVH for high poly meshes.
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh)
Definition: pbvh.c:1855
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
Definition: pbvh.c:1849
@ PBVH_GRIDS
Definition: BKE_pbvh.h:235
@ PBVH_BMESH
Definition: BKE_pbvh.h:236
@ PBVH_FACES
Definition: BKE_pbvh.h:234
struct Depsgraph * BKE_scene_ensure_depsgraph(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer)
Definition: scene.cc:3456
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:1352
@ BLF_SHADOW
Definition: BLF_api.h:336
void BLF_shadow_offset(int fontid, int x, int y)
Definition: blf.c:806
void BLF_shadow(int fontid, int level, const float rgba[4]) ATTR_NONNULL(3)
Definition: blf.c:796
void BLF_disable(int fontid, int option)
Definition: blf.c:279
float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:688
void BLF_enable(int fontid, int option)
Definition: blf.c:270
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL()
Definition: blf_default.c:59
int BLF_set_default(void)
Definition: blf_default.c:50
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
struct GSet GSet
Definition: BLI_ghash.h:340
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:947
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int max_ii(int a, int b)
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:120
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) ATTR_NONNULL()
Definition: string.c:1132
#define ENUM_OPERATORS(_type, _max)
#define ELEM(...)
#define TIP_(msgid)
#define IFACE_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
#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_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_GPENCIL
#define OBEDIT_FROM_VIEW_LAYER(view_layer)
#define OBEDIT_FROM_OBACT(ob)
#define OBACT(_view_layer)
@ SPACE_VIEW3D
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.
#define MEM_SAFE_FREE(v)
@ TH_TEXT_HI
Definition: UI_resources.h:43
void UI_FontThemeColor(int fontid, int colorid)
Definition: resources.c:1134
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
Scene scene
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
static void get_stats_string(char *info, int len, size_t *ofs, ViewLayer *view_layer, SceneStatsFmt *stats_fmt)
Definition: info_stats.cc:535
#define SCENE_STATS_FMT_INT(_id)
#define MAX_INFO_NUM_LEN
Definition: info_stats.cc:63
static void stats_row(int col1, const char *key, int col2, const char *value1, const char *value2, int *y, int height)
Definition: info_stats.cc:706
static void stats_object_sculpt(const Object *ob, SceneStats *stats)
Definition: info_stats.cc:365
void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer)
Definition: info_stats.cc:462
const char * ED_info_statusbar_string_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, const char statusbar_flag)
Definition: info_stats.cc:629
static void stats_object_pose(const Object *ob, SceneStats *stats)
Definition: info_stats.cc:343
const char * ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: info_stats.cc:692
static void stats_object(Object *ob, const View3D *v3d_local, SceneStats *stats, GSet *objects_gset)
Definition: info_stats.cc:128
static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer, View3D *v3d_local, SceneStats *stats)
Definition: info_stats.cc:391
const char * ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: info_stats.cc:697
static bool format_stats(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, SceneStatsFmt *stats_fmt)
Definition: info_stats.cc:483
static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *stats)
Definition: info_stats.cc:89
static void stats_object_edit(Object *obedit, SceneStats *stats)
Definition: info_stats.cc:226
static bool stats_is_object_dynamic_topology_sculpt(const Object *ob)
Definition: info_stats.cc:359
void ED_info_draw_stats(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, int x, int *y, int height)
Definition: info_stats.cc:721
size_t(* MEM_get_memory_in_use)(void)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static size_t mem_in_use
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
_W64 unsigned int uintptr_t
Definition: stdint.h:119
unsigned __int64 uint64_t
Definition: stdint.h:90
struct BMesh * bm
Definition: BKE_editmesh.h:40
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
uint8_t f3
uint8_t f1
uint8_t f2
ListBase disp
Definition: BKE_curve.h:33
struct Lattice * latt
char name[66]
Definition: DNA_ID.h:378
struct EditLatt * editlatt
struct BPoint * def
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
struct SubsurfRuntimeData * subsurf_runtime_data
struct SubdivCCG * subdiv_ccg
int totedge
int totvert
Mesh_Runtime runtime
int totpoly
int totloop
ListBase * editelems
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.cc:83
char totgplayer[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:85
char totobjsel[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:82
char totface[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:79
char totvert[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:78
char totbone[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:81
char totgpstroke[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:86
char tottri[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:84
char totgpframe[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:85
char totvertsculpt[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:78
char totfacesculpt[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:80
char totlamp[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:83
char totfacesel[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:79
char totedge[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:80
char totgppoint[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:86
char totobj[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:82
char totedgesel[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:80
char totvertsel[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:78
char totbonesel[MAX_INFO_NUM_LEN]
Definition: info_stats.cc:81
uint64_t totfacesculpt
Definition: info_stats.cc:68
uint64_t totfacesel
Definition: info_stats.cc:68
uint64_t tottri
Definition: info_stats.cc:72
uint64_t totedgesel
Definition: info_stats.cc:67
uint64_t totvert
Definition: info_stats.cc:66
uint64_t totbone
Definition: info_stats.cc:69
uint64_t totgpframe
Definition: info_stats.cc:73
uint64_t totvertsel
Definition: info_stats.cc:66
uint64_t totlamp
Definition: info_stats.cc:71
uint64_t totface
Definition: info_stats.cc:68
uint64_t totgplayer
Definition: info_stats.cc:73
uint64_t totvertsculpt
Definition: info_stats.cc:66
uint64_t totgppoint
Definition: info_stats.cc:73
uint64_t totlampsel
Definition: info_stats.cc:71
uint64_t totobj
Definition: info_stats.cc:70
uint64_t totgpstroke
Definition: info_stats.cc:73
uint64_t totedge
Definition: info_stats.cc:67
uint64_t totbonesel
Definition: info_stats.cc:69
uint64_t totobjsel
Definition: info_stats.cc:70
struct BMesh * bm
Definition: BKE_paint.h:539
struct PBVH * pbvh
Definition: BKE_paint.h:550
struct SceneStats * local_stats
View3D_Runtime runtime
struct View3D * localvd
LayerCollection * active_collection
struct SceneStats * stats
ListBase * edbo
ListBase chanbase
ListBase areabase
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2300
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2217