Fix random crashes in the outliner, especially with bigger scenes.
The outliner can redraw quicker without rebuilding the tree, for example when just moving the mouse and highlighting different items. The way this worked is that the outliner would be tagged to avoid rebuilding, however if another operation that does require rebuilding happens in the meantime we could go out of sync and crash.
This commit is contained in:
parent
8021ac986a
commit
3f20105622
|
@ -74,6 +74,7 @@ void ED_region_init(struct bContext *C, struct ARegion *ar);
|
|||
void ED_region_tag_redraw(struct ARegion *ar);
|
||||
void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct);
|
||||
void ED_region_tag_redraw_overlay(struct ARegion *ar);
|
||||
void ED_region_tag_redraw_no_rebuild(struct ARegion *ar);
|
||||
void ED_region_tag_refresh_ui(struct ARegion *ar);
|
||||
void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
|
||||
void ED_region_panels(
|
||||
|
|
|
@ -169,18 +169,19 @@ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float
|
|||
/* validate that view is in valid configuration after this operation */
|
||||
UI_view2d_curRect_validate(v2d);
|
||||
|
||||
/* request updates to be done... */
|
||||
ED_region_tag_redraw(vpd->ar);
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
|
||||
|
||||
/* exceptions */
|
||||
if (vpd->sa->spacetype == SPACE_OUTLINER) {
|
||||
/* don't rebuild full tree, since we're just changing our view */
|
||||
SpaceOops *soops = vpd->sa->spacedata.first;
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
ED_region_tag_redraw_no_rebuild(vpd->ar);
|
||||
}
|
||||
else {
|
||||
ED_region_tag_redraw(vpd->ar);
|
||||
}
|
||||
|
||||
/* request updates to be done... */
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
|
||||
}
|
||||
|
||||
static void view_pan_apply(bContext *C, wmOperator *op)
|
||||
|
|
|
@ -550,7 +550,7 @@ void ED_region_tag_redraw(ARegion *ar)
|
|||
* but python scripts can cause this to happen indirectly */
|
||||
if (ar && !(ar->do_draw & RGN_DRAWING)) {
|
||||
/* zero region means full region redraw */
|
||||
ar->do_draw &= ~RGN_DRAW_PARTIAL;
|
||||
ar->do_draw &= ~(RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD);
|
||||
ar->do_draw |= RGN_DRAW;
|
||||
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
|
||||
}
|
||||
|
@ -562,6 +562,15 @@ void ED_region_tag_redraw_overlay(ARegion *ar)
|
|||
ar->do_draw_overlay = RGN_DRAW;
|
||||
}
|
||||
|
||||
void ED_region_tag_redraw_no_rebuild(ARegion *ar)
|
||||
{
|
||||
if (ar && !(ar->do_draw & (RGN_DRAWING | RGN_DRAW))) {
|
||||
ar->do_draw &= ~RGN_DRAW_PARTIAL;
|
||||
ar->do_draw |= RGN_DRAW_NO_REBUILD;
|
||||
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
|
||||
}
|
||||
}
|
||||
|
||||
void ED_region_tag_refresh_ui(ARegion *ar)
|
||||
{
|
||||
if (ar) {
|
||||
|
@ -572,7 +581,7 @@ void ED_region_tag_refresh_ui(ARegion *ar)
|
|||
void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
|
||||
{
|
||||
if (ar && !(ar->do_draw & RGN_DRAWING)) {
|
||||
if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_PARTIAL))) {
|
||||
if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD | RGN_DRAW_PARTIAL))) {
|
||||
/* no redraw set yet, set partial region */
|
||||
ar->do_draw |= RGN_DRAW_PARTIAL;
|
||||
ar->drawrct = *rct;
|
||||
|
@ -583,7 +592,7 @@ void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct)
|
|||
BLI_rcti_union(&ar->drawrct, rct);
|
||||
}
|
||||
else {
|
||||
BLI_assert((ar->do_draw & RGN_DRAW) != 0);
|
||||
BLI_assert((ar->do_draw & (RGN_DRAW | RGN_DRAW_NO_REBUILD)) != 0);
|
||||
/* Else, full redraw is already requested, nothing to do here. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -782,7 +782,6 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
/* TODO(sergey): Use proper flag for tagging here. */
|
||||
DEG_id_tag_update(&scene->id, 0);
|
||||
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -1987,7 +1987,4 @@ void draw_outliner(const bContext *C)
|
|||
|
||||
UI_block_end(C, block);
|
||||
UI_block_draw(C, block);
|
||||
|
||||
/* clear flag that allows quick redraws */
|
||||
soops->storeflag &= ~SO_TREESTORE_REDRAW;
|
||||
}
|
||||
|
|
|
@ -172,8 +172,7 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
|
||||
ED_region_tag_redraw(ar);
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
}
|
||||
|
||||
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
|
||||
|
@ -903,10 +902,8 @@ static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
else
|
||||
outliner_set_flag(&soops->tree, TSE_SELECTED, 1);
|
||||
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
||||
ED_region_tag_redraw(ar);
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -1027,11 +1024,9 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
xdelta = (int)(te->xs - v2d->cur.xmin);
|
||||
v2d->cur.xmin += xdelta;
|
||||
v2d->cur.xmax += xdelta;
|
||||
|
||||
so->storeflag |= SO_TREESTORE_REDRAW;
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -1187,7 +1182,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so
|
|||
soops->search_flags = flags;
|
||||
|
||||
/* redraw */
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -271,11 +271,13 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
|
|||
break;
|
||||
}
|
||||
|
||||
if (skip_rebuild) {
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
|
||||
}
|
||||
if (redraw) {
|
||||
ED_region_tag_redraw(ar);
|
||||
if (skip_rebuild) {
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
}
|
||||
else {
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -389,8 +391,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE
|
|||
/* unset highlighted tree element, dragged one will be highlighted instead */
|
||||
outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
|
||||
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
|
||||
ED_region_tag_redraw(ar);
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
|
|
|
@ -995,12 +995,13 @@ int outliner_item_do_activate_from_cursor(
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
if (!rebuild_tree) {
|
||||
/* only needs to redraw, no rebuild */
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
if (rebuild_tree) {
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
else {
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
}
|
||||
ED_undo_push(C, "Outliner selection change");
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -2034,9 +2034,10 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
|
|||
outliner_set_flag(&soops->tree, TSE_SELECTED, 0);
|
||||
|
||||
tselem->flag |= TSE_SELECTED;
|
||||
/* redraw, same as outliner_select function */
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
ED_region_tag_redraw(ar);
|
||||
|
||||
/* Only redraw, don't rebuild here because TreeElement pointers will
|
||||
* become invalid and operations will crash. */
|
||||
ED_region_tag_redraw_no_rebuild(ar);
|
||||
}
|
||||
|
||||
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
|
||||
|
|
|
@ -1705,8 +1705,6 @@ static void outliner_restore_scrolling_position(SpaceOops *soops, ARegion *ar, O
|
|||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
soops->storeflag |= SO_TREESTORE_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2070,8 +2068,9 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
|
|||
BKE_outliner_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
|
||||
}
|
||||
|
||||
if (soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
|
||||
if (ar->flag & RGN_DRAW_NO_REBUILD) {
|
||||
return;
|
||||
}
|
||||
|
||||
OutlinerTreeElementFocus focus;
|
||||
outliner_store_scrolling_position(soops, ar, &focus);
|
||||
|
|
|
@ -468,5 +468,6 @@ enum {
|
|||
#define RGN_DRAW_PARTIAL 2
|
||||
#define RGN_DRAWING 4
|
||||
#define RGN_DRAW_REFRESH_UI 8 /* re-create uiBlock's where possible */
|
||||
#define RGN_DRAW_NO_REBUILD 16
|
||||
#endif
|
||||
|
||||
|
|
|
@ -349,8 +349,7 @@ typedef enum eSpaceOutliner_Mode {
|
|||
typedef enum eSpaceOutliner_StoreFlag {
|
||||
/* cleanup tree */
|
||||
SO_TREESTORE_CLEANUP = (1 << 0),
|
||||
/* if set, it allows redraws. gets set for some allqueue events */
|
||||
SO_TREESTORE_REDRAW = (1 << 1),
|
||||
/* SO_TREESTORE_REDRAW = (1 << 1), */ /* Deprecated */
|
||||
/* rebuild the tree, similar to cleanup,
|
||||
* but defer a call to BKE_outliner_treehash_rebuild_from_treestore instead */
|
||||
SO_TREESTORE_REBUILD = (1 << 2),
|
||||
|
|
Loading…
Reference in New Issue