UI - LOCAL View3D overlay stats

This patch improves the 3DView statistics overlay to show LOCAL stats
while in local view. This means the stats can vary between 3DViews and
the statusbar when views are in local view, but this gives a much more
accurate count of the objects, and their components, that you are
directly working with rather than just scene values.

Differential Revision: https://developer.blender.org/D8883

Reviewed by Campbell Barton
This commit is contained in:
Harley Acheson 2021-06-15 19:01:53 -07:00
parent 4891da8ae2
commit c8e331f450
7 changed files with 93 additions and 22 deletions

View File

@ -27,9 +27,10 @@ extern "C" {
#endif
struct Main;
struct wmWindowManager;
/* info_stats.c */
void ED_info_stats_clear(struct ViewLayer *view_layer);
void ED_info_stats_clear(struct wmWindowManager *wm, struct ViewLayer *view_layer);
const char *ED_info_statusbar_string(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
@ -41,6 +42,7 @@ const char *ED_info_statistics_string(struct Main *bmain,
void ED_info_draw_stats(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct View3D *v3d_local,
int x,
int *y,
int height);

View File

@ -31,6 +31,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "BLF_api.h"
@ -63,6 +64,8 @@
#include "ED_info.h"
#include "WM_api.h"
#include "UI_resources.h"
#include "GPU_capabilities.h"
@ -123,12 +126,19 @@ static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats)
return true;
}
static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
static void stats_object(Object *ob,
const View3D *v3d_local,
SceneStats *stats,
GSet *objects_gset)
{
if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) {
return;
}
if (v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob)) {
return;
}
const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0;
stats->totobj++;
@ -386,7 +396,7 @@ static void stats_object_sculpt(Object *ob, SceneStats *stats)
}
/* Statistics displayed in info header. Called regularly on scene changes. */
static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer, View3D *v3d_local)
{
SceneStats stats = {0};
Object *ob = OBACT(view_layer);
@ -400,6 +410,13 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
stats_object_edit(ob_iter, &stats);
stats.totobjsel++;
}
else {
/* Skip hidden objects in local view that are not in edit-mode,
* an exception for edit-mode, in other modes these would be considered hidden. */
if ((v3d_local && !BKE_object_is_visible_in_viewport(v3d_local, ob_iter))) {
continue;
}
}
stats.totobj++;
}
}
@ -417,7 +434,7 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
/* Objects */
GSet *objects_gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob_iter) {
stats_object(ob_iter, &stats, objects_gset);
stats_object(ob_iter, v3d_local, &stats, objects_gset);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
BLI_gset_free(objects_gset, NULL);
@ -429,38 +446,61 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
stats_object_sculpt(ob, &stats);
}
if (!view_layer->stats) {
view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
if (v3d_local) {
BLI_assert(v3d_local->localvd != NULL);
if (v3d_local->runtime.local_stats == NULL) {
v3d_local->runtime.local_stats = MEM_mallocN(sizeof(SceneStats), "LocalStats");
}
*v3d_local->runtime.local_stats = stats;
}
else {
if (!view_layer->stats) {
view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
}
*view_layer->stats = stats;
}
*(view_layer->stats) = stats;
}
void ED_info_stats_clear(ViewLayer *view_layer)
void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer)
{
if (view_layer->stats) {
MEM_freeN(view_layer->stats);
view_layer->stats = NULL;
}
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
ViewLayer *view_layer_test = WM_window_get_active_view_layer(win);
if (view_layer != view_layer_test) {
continue;
}
const bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype == SPACE_VIEW3D) {
View3D *v3d = area->spacedata.first;
if (v3d->localvd) {
MEM_SAFE_FREE(v3d->runtime.local_stats);
}
}
}
}
}
static bool format_stats(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
SceneStatsFmt *stats_fmt)
static bool format_stats(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, SceneStatsFmt *stats_fmt)
{
/* Create stats if they don't already exist. */
if (!view_layer->stats) {
SceneStats **stats_p = (v3d_local) ? &v3d_local->runtime.local_stats : &view_layer->stats;
if (*stats_p == NULL) {
/* Do not not access dependency graph if interface is marked as locked. */
wmWindowManager *wm = bmain->wm.first;
if (wm->is_interface_locked) {
return false;
}
Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
stats_update(depsgraph, view_layer);
stats_update(depsgraph, view_layer, v3d_local);
}
SceneStats *stats = view_layer->stats;
SceneStats *stats = *stats_p;
/* Generate formatted numbers. */
#define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt->_id, stats->_id)
@ -605,7 +645,7 @@ static const char *info_statusbar_string(Main *bmain,
/* Scene statistics. */
if (statusbar_flag & STATUSBAR_SHOW_STATS) {
SceneStatsFmt stats_fmt;
if (format_stats(bmain, scene, view_layer, &stats_fmt)) {
if (format_stats(bmain, scene, view_layer, NULL, &stats_fmt)) {
get_stats_string(info + ofs, len, &ofs, view_layer, &stats_fmt);
}
}
@ -682,11 +722,17 @@ static void stats_row(int col1,
BLF_draw_default(col2, *y, 0.0f, values, sizeof(values));
}
/**
* \param v3d_local: Pass this argument to calculate view-port local statistics.
* Note that this must only be used for local-view, otherwise report specific statistics
* will be written into the global scene statistics giving incorrect results.
*/
void ED_info_draw_stats(
Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height)
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d_local, int x, int *y, int height)
{
BLI_assert(v3d_local == NULL || v3d_local->localvd != NULL);
SceneStatsFmt stats_fmt;
if (!format_stats(bmain, scene, view_layer, &stats_fmt)) {
if (!format_stats(bmain, scene, view_layer, v3d_local, &stats_fmt)) {
return;
}

View File

@ -331,6 +331,8 @@ static void view3d_free(SpaceLink *sl)
MEM_freeN(vd->localvd);
}
MEM_SAFE_FREE(vd->runtime.local_stats);
if (vd->runtime.properties_storage) {
MEM_freeN(vd->runtime.properties_storage);
}
@ -346,6 +348,18 @@ static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
static void view3d_exit(wmWindowManager *UNUSED(wm), ScrArea *area)
{
BLI_assert(area->spacetype == SPACE_VIEW3D);
View3D *v3d = area->spacedata.first;
/* Happens when freeing. */
if (v3d == NULL) {
return;
}
MEM_SAFE_FREE(v3d->runtime.local_stats);
}
static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
View3D *v3do = (View3D *)sl;
@ -1581,7 +1595,7 @@ static void space_view3d_listener(const wmSpaceTypeListenerParams *params)
}
}
static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
static void space_view3d_refresh(const bContext *C, ScrArea *area)
{
Scene *scene = CTX_data_scene(C);
LightCache *lcache = scene->eevee.light_cache_data;
@ -1590,6 +1604,9 @@ static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO;
view3d_lightcache_update((bContext *)C);
}
View3D *v3d = (View3D *)area->spacedata.first;
MEM_SAFE_FREE(v3d->runtime.local_stats);
}
const char *view3d_context_dir[] = {
@ -1697,6 +1714,7 @@ void ED_spacetype_view3d(void)
st->create = view3d_create;
st->free = view3d_free;
st->init = view3d_init;
st->exit = view3d_exit;
st->listener = space_view3d_listener;
st->refresh = space_view3d_refresh;
st->duplicate = view3d_duplicate;

View File

@ -1537,7 +1537,9 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
}
if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) {
ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
View3D *v3d_local = v3d->localvd ? v3d : NULL;
ED_info_draw_stats(
bmain, scene, view_layer, v3d_local, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
}
BLF_batch_draw_end();

View File

@ -1393,6 +1393,7 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
MEM_freeN(v3d->localvd);
v3d->localvd = NULL;
MEM_SAFE_FREE(v3d->runtime.local_stats);
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {

View File

@ -258,6 +258,8 @@ typedef struct View3D_Runtime {
int flag;
char _pad1[4];
/* Only used for overlay stats while in localview. */
struct SceneStats *local_stats;
} View3D_Runtime;
/** 3D ViewPort Struct. */

View File

@ -520,7 +520,7 @@ void wm_event_do_notifiers(bContext *C)
if (clear_info_stats) {
/* Only do once since adding notifiers is slow when there are many. */
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_info_stats_clear(view_layer);
ED_info_stats_clear(wm, view_layer);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}