From 7ae759289960748ee91cc5257d3ab53016841534 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Oct 2024 13:48:50 +1100 Subject: [PATCH] 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]: a63ac425d07533e602d285df4e1a13e8ec64c4cf --- .../editors/space_outliner/outliner_draw.cc | 40 ++++++++++++------- .../editors/space_outliner/outliner_intern.hh | 5 ++- .../editors/space_outliner/space_outliner.cc | 25 ++++++++++-- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 2b1f1b604d2..3a4c3d90648 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -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. */ diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index 7a4be5ca2c1..f15b570ec08 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -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); diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index 6d419182d2c..69a4f6652fd 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -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 = ®ion->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);