Fix #128346: Search results fail to display in the outliner

Regression in [0] caused the outliner not to draw at the clamped scroll
position. This meant searching in the outliner could show no results
even when results were found. It also meant deleting objects could show
nothing until the user manually forced the outliner to redraw.

Workaround the problem by detecting when outliner drawing changes the
scroll position and draw again. While inelegant this doesn't happen
often in practice.

Fixing without a second draw likely involves resolving the order of
initialization problem by separating bounds calculating from drawing.

[0]: a63ac425d0
This commit is contained in:
Campbell Barton
2024-10-16 13:48:50 +11:00
parent f5e660f5f0
commit 7ae7592899
3 changed files with 51 additions and 19 deletions

View File

@@ -4041,7 +4041,7 @@ static void outliner_update_viewable_area(ARegion *region,
* Draw contents of Outliner editor.
* \{ */
void draw_outliner(const bContext *C)
void draw_outliner(const bContext *C, bool do_rebuild)
{
Main *mainvar = CTX_data_main(C);
ARegion *region = CTX_wm_region(C);
@@ -4053,22 +4053,32 @@ void draw_outliner(const bContext *C)
TreeViewContext tvc;
outliner_viewcontext_init(C, &tvc);
outliner_build_tree(mainvar, tvc.scene, tvc.view_layer, space_outliner, region); /* Always. */
/* FIXME(@ideasman42): There is an order of initialization problem here between
* `v2d->cur` & `v2d->tot` where this function reads from `v2d->cur` for the scroll position
* but may reset the scroll position *without* drawing into the clamped position.
*
* The `on_scroll` argument is used for an optional second draw pass.
*
* See `USE_OUTLINER_DRAW_CLAMPS_SCROLL_HACK` & #128346 for a full description. */
/* If global sync select is dirty, flag other outliners. */
if (ED_outliner_select_sync_is_dirty(C)) {
ED_outliner_select_sync_flag_outliners(C);
}
if (do_rebuild) {
outliner_build_tree(mainvar, tvc.scene, tvc.view_layer, space_outliner, region); /* Always. */
/* Sync selection state from view layer. */
if (!ELEM(space_outliner->outlinevis,
SO_LIBRARIES,
SO_OVERRIDES_LIBRARY,
SO_DATA_API,
SO_ID_ORPHANS) &&
space_outliner->flag & SO_SYNC_SELECT)
{
outliner_sync_selection(C, space_outliner);
/* If global sync select is dirty, flag other outliners. */
if (ED_outliner_select_sync_is_dirty(C)) {
ED_outliner_select_sync_flag_outliners(C);
}
/* Sync selection state from view layer. */
if (!ELEM(space_outliner->outlinevis,
SO_LIBRARIES,
SO_OVERRIDES_LIBRARY,
SO_DATA_API,
SO_ID_ORPHANS) &&
space_outliner->flag & SO_SYNC_SELECT)
{
outliner_sync_selection(C, space_outliner);
}
}
/* Force display to pixel coords. */

View File

@@ -292,7 +292,10 @@ TreeTraversalAction outliner_collect_selected_objects(TreeElement *te, void *cus
/* `outliner_draw.cc` */
void draw_outliner(const bContext *C);
/**
* \param do_rebuild: When false, only the scroll position changed since last draw.
*/
void draw_outliner(const bContext *C, bool do_rebuild);
void outliner_tree_dimensions(SpaceOutliner *space_outliner, int *r_width, int *r_height);

View File

@@ -42,6 +42,14 @@
#include "outliner_intern.hh"
#include "tree/tree_display.hh"
/**
* Since 2.8x outliner drawing itself can change the scroll position of the outliner
* after drawing has completed. Failing to draw a second time can cause nothing to display.
* Making search seem to fail & deleting objects fail to scroll up to show remaining objects.
* See #128346 for details.
*/
#define USE_OUTLINER_DRAW_CLAMPS_SCROLL_HACK
namespace blender::ed::outliner {
SpaceOutliner_Runtime::SpaceOutliner_Runtime(const SpaceOutliner_Runtime & /*other*/)
@@ -80,10 +88,21 @@ static void outliner_main_region_draw(const bContext *C, ARegion *region)
{
View2D *v2d = &region->v2d;
/* clear */
UI_ThemeClearColor(TH_BACK);
#ifdef USE_OUTLINER_DRAW_CLAMPS_SCROLL_HACK
const rctf v2d_cur_prev = v2d->cur;
#endif
draw_outliner(C);
UI_ThemeClearColor(TH_BACK);
draw_outliner(C, true);
#ifdef USE_OUTLINER_DRAW_CLAMPS_SCROLL_HACK
/* This happens when scrolling is clamped & occasionally when resizing the area.
* In practice this isn't often which is important as that would hurt performance. */
if (!BLI_rctf_compare(&v2d->cur, &v2d_cur_prev, FLT_EPSILON)) {
UI_ThemeClearColor(TH_BACK);
draw_outliner(C, false);
}
#endif
/* reset view matrix */
UI_view2d_view_restore(C);