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);