Commit: b077de086e14291fe5f7cdf6d3564a8f1cfb9cb3
Author: Julian Eisel
Date:   Thu Aug 20 20:17:00 2020 +0200
Branches: master
https://developer.blender.org/rBb077de086e14291fe5f7cdf6d3564a8f1cfb9cb3

Outliner: Avoid rebuilding tree on selection/active changes

We can avoid the rather expensive outliner tree rebuilds and only redraw
if nothing but the selection or active item changes. This should give a
bit of speedup for heavy scenes.

For this to work I had to correct a few notifiers, some were only
sending selection/active change notifiers that actually did things like
adding objects. I also added a more precise notifier type for when the
active collection changes. At the notifier subtype/action level we're
not even close to running out of bits, so this should be fine.
Also had to correct a wrong notifier check (was using `&` rather than
`==`).

===================================================================

M       source/blender/editors/object/object_add.c
M       source/blender/editors/space_outliner/outliner_edit.c
M       source/blender/editors/space_outliner/outliner_intern.h
M       source/blender/editors/space_outliner/outliner_select.c
M       source/blender/editors/space_outliner/outliner_tools.c
M       source/blender/editors/space_outliner/outliner_tree.c
M       source/blender/editors/space_outliner/outliner_utils.c
M       source/blender/editors/space_outliner/space_outliner.c
M       source/blender/windowmanager/WM_types.h

===================================================================

diff --git a/source/blender/editors/object/object_add.c 
b/source/blender/editors/object/object_add.c
index 139900d0a4d..a59d8136f47 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1450,6 +1450,7 @@ static int collection_instance_add_exec(bContext *C, 
wmOperator *op)
     DEG_relations_tag_update(bmain);
     DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
     WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+    WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
 
     return OPERATOR_FINISHED;
   }
@@ -2783,6 +2784,7 @@ static int object_convert_exec(bContext *C, wmOperator 
*op)
   DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+  WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
 
   return OPERATOR_FINISHED;
 }
@@ -3003,6 +3005,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
   DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
 
   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+  WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
 
   return OPERATOR_FINISHED;
 }
@@ -3094,6 +3097,7 @@ static int object_add_named_exec(bContext *C, wmOperator 
*op)
   DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
   WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+  WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
   ED_outliner_select_sync_from_object_tag(C);
 
   return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_edit.c 
b/source/blender/editors/space_outliner/outliner_edit.c
index cd2fcd8e2cf..8567dd4da13 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -193,13 +193,7 @@ static int outliner_item_openclose_modal(bContext *C, 
wmOperator *op, const wmEv
       if (te->xs == data->x_location) {
         outliner_item_openclose(te, data->open, false);
 
-        /* Avoid rebuild if possible. */
-        if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) {
-          ED_region_tag_redraw(region);
-        }
-        else {
-          ED_region_tag_redraw_no_rebuild(region);
-        }
+        outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, 
region);
       }
     }
 
@@ -239,13 +233,7 @@ static int outliner_item_openclose_invoke(bContext *C, 
wmOperator *op, const wmE
                       (toggle_all && (outliner_flag_is_any_test(&te->subtree, 
TSE_CLOSED, 1)));
 
     outliner_item_openclose(te, open, toggle_all);
-    /* Avoid rebuild if possible. */
-    if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) {
-      ED_region_tag_redraw(region);
-    }
-    else {
-      ED_region_tag_redraw_no_rebuild(region);
-    }
+    outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
 
     /* Only toggle once for single click toggling */
     if (event->type == LEFTMOUSE) {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h 
b/source/blender/editors/space_outliner/outliner_intern.h
index 33dbbb274c0..9795bb73efe 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -237,7 +237,7 @@ void outliner_build_tree(struct Main *mainvar,
                          struct SpaceOutliner *space_outliner,
                          struct ARegion *region);
 
-bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem 
*tselem);
+bool outliner_mode_requires_always_rebuild(const struct SpaceOutliner 
*space_outliner);
 
 typedef struct IDsSelectedData {
   struct ListBase selected_array;
@@ -515,6 +515,8 @@ float outliner_restrict_columns_width(const struct 
SpaceOutliner *space_outliner
 TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag);
 bool outliner_is_element_visible(const TreeElement *te);
 void outliner_scroll_view(struct ARegion *region, int delta_y);
+void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct 
SpaceOutliner *space_outliner,
+                                                      struct ARegion *region);
 
 /* outliner_sync.c ---------------------------------------------- */
 
diff --git a/source/blender/editors/space_outliner/outliner_select.c 
b/source/blender/editors/space_outliner/outliner_select.c
index 1ac1b46f0d1..d720747e953 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -1000,7 +1000,9 @@ static eOLDrawState 
tree_element_active_master_collection(bContext *C,
     ViewLayer *view_layer = CTX_data_view_layer(C);
     LayerCollection *layer_collection = view_layer->layer_collections.first;
     BKE_layer_collection_activate(view_layer, layer_collection);
-    WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+    /* A very precise notifier - ND_LAYER alone is quite vague, we want to 
avoid unnecessary work
+     * when only the active collection changes. */
+    WM_main_add_notifier(NC_SCENE | ND_LAYER | NS_LAYER_COLLECTION | 
NA_ACTIVATED, NULL);
   }
 
   return OL_DRAWSEL_NONE;
@@ -1022,7 +1024,9 @@ static eOLDrawState 
tree_element_active_layer_collection(bContext *C,
     LayerCollection *layer_collection = te->directdata;
     ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, 
layer_collection);
     BKE_layer_collection_activate(view_layer, layer_collection);
-    WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+    /* A very precise notifier - ND_LAYER alone is quite vague, we want to 
avoid unnecessary work
+     * when only the active collection changes. */
+    WM_main_add_notifier(NC_SCENE | ND_LAYER | NS_LAYER_COLLECTION | 
NA_ACTIVATED, NULL);
   }
 
   return OL_DRAWSEL_NONE;
@@ -1507,7 +1511,7 @@ static int outliner_box_select_exec(bContext *C, 
wmOperator *op)
 
   DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-  ED_region_tag_redraw(region);
+  ED_region_tag_redraw_no_rebuild(region);
 
   ED_outliner_select_sync_from_outliner(C, space_outliner);
 
@@ -1729,7 +1733,7 @@ static int outliner_walk_select_invoke(bContext *C, 
wmOperator *op, const wmEven
   outliner_walk_scroll(region, active_te);
 
   ED_outliner_select_sync_from_outliner(C, space_outliner);
-  ED_region_tag_redraw(region);
+  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
 
   return OPERATOR_FINISHED;
 }
diff --git a/source/blender/editors/space_outliner/outliner_tools.c 
b/source/blender/editors/space_outliner/outliner_tools.c
index 4b037327038..2a13f9d6a66 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -1630,6 +1630,7 @@ static int outliner_delete_exec(bContext *C, wmOperator 
*op)
 
   DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+  WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
   ED_outliner_select_sync_from_object_tag(C);
 
   return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c 
b/source/blender/editors/space_outliner/outliner_tree.c
index 60058c82283..9e3cbabf283 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -244,14 +244,12 @@ static TreeElement *outliner_add_element(SpaceOutliner 
*space_outliner,
 /* -------------------------------------------------------- */
 
 /**
- * Check if an element type needs a full rebuild if the open/collapsed state 
changes.
- * These element types don't add children if collapsed.
- *
- * This current check isn't great really. A per element-type flag would be 
preferable.
+ * Check if a display mode needs a full rebuild if the open/collapsed state 
changes.
+ * Element types in these modes don't actually add children if collapsed, so 
the rebuild is needed.
  */
-bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem *tselem)
+bool outliner_mode_requires_always_rebuild(const SpaceOutliner *space_outliner)
 {
-  return ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_KEYMAP);
+  return ELEM(space_outliner->outlinevis, SO_DATA_API);
 }
 
 /* special handling of hierarchical non-lib data */
diff --git a/source/blender/editors/space_outliner/outliner_utils.c 
b/source/blender/editors/space_outliner/outliner_utils.c
index 1da44b5e51e..25dc7bc271e 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -37,6 +37,7 @@
 
 #include "ED_armature.h"
 #include "ED_outliner.h"
+#include "ED_screen.h"
 
 #include "UI_interface.h"
 #include "UI_view2d.h"
@@ -455,6 +456,23 @@ void outliner_scroll_view(ARegion *region, int delta_y)
   }
 }
 
+/**
+ * The outliner should generally use #ED_region_tag_redraw_no_rebuild() to 
avoid unnecessary tree
+ * rebuilds. If elements are open or closed, we may still have to rebuild.
+ * Upon changing the open/closed state, call this to avoid rebuilds if 
possible.
+ */
+void outliner_tag_redraw_avoid_rebuild_on_open_change(const SpaceOutliner 
*space_outliner,
+                                                      ARegion *region)
+{
+  /* Avoid rebuild if possible. */
+  if (outliner_mode_requires_always_rebuild(space_outliner)) {
+    ED_region_tag_redraw(region);
+  }
+  else {
+    ED_region_tag_redraw_no_rebuild(region);
+  }
+}
+
 /* Get base of object under cursor. Used for eyedropper tool */
 Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2])
 {
diff --git a/source/blender/editors/space_outliner/space_outliner.c 
b/source/blender/editors/space_outliner/space_outliner.c
index b14afed81dd..6854367d975 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -114,6 +114,8 @@ static void outliner_main_region_listener(wmWindow 
*UNUSED(win),
       switch (wmn->data) {
         case ND_OB_ACTIVE:
   

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to