[Bf-blender-cvs] [20ae943bf41] soc-2019-outliner: Outliner: Redo synced selection dirty outliner implementation

Nathan Craddock noreply at git.blender.org
Tue Jun 25 04:23:36 CEST 2019


Commit: 20ae943bf4133d2188cb9443636b5fe2a1ec9ae5
Author: Nathan Craddock
Date:   Mon Jun 24 20:16:18 2019 -0600
Branches: soc-2019-outliner
https://developer.blender.org/rB20ae943bf4133d2188cb9443636b5fe2a1ec9ae5

Outliner: Redo synced selection dirty outliner implementation

The previous implementation assumed each selection type was identical
and synced each outliner with the 3D view. This had flaws because
hidden objects can be selected in the outliner, and it would be impossible
to know whether or not to keep them selected when syncing. To work around
that and other cases, this implementation does two things:

1. After any 3D view selection, sync selection flags with an outliner.
After syncing, a clean outliner is stored. Then the other outliners
are marked as dirty, to be synced from the clean outliner.

2. After an outliner select, that outliner is set as clean and the
other outliners are marked as dirty to be synced from.

More work is needed to support all outliner selection operations,
as well as properly supporting extending selections from the 3D
view. However, the underlying code for selection syncing should now
support the edge cases that the other implementation failed to
support.

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

M	source/blender/blenkernel/BKE_main.h
M	source/blender/editors/object/object_select.c
M	source/blender/editors/space_outliner/outliner_draw.c
M	source/blender/editors/space_outliner/outliner_intern.h
M	source/blender/editors/space_outliner/outliner_select.c
M	source/blender/windowmanager/intern/wm_event_system.c

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

diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 18e36fd788f..415a9aecd5d 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -81,7 +81,10 @@ typedef struct Main {
   char recovered;                  /* indicate the main->name (file) is the recovered one */
   /** All current ID's exist in the last memfile undo step. */
   char is_memfile_undo_written;
-  char is_sync_select_dirty;
+
+  /* Flag to indicate if a sync is to extend or replace the outliner selection */
+  char sync_select_dirty_flag;
+  struct SpaceOutliner *clean_outliner; /* to store the clean outliner to be synced from */
 
   BlendThumbnail *blen_thumb;
 
@@ -133,6 +136,13 @@ typedef struct Main {
   struct MainLock *lock;
 } Main;
 
+/* Main->sync_select_dirty_flag */
+enum {
+  SYNC_SELECT_NONE = 0,
+  SYNC_SELECT_REPLACE = 1,
+  SYNC_SELECT_EXTEND = 2,
+};
+
 struct Main *BKE_main_new(void);
 void BKE_main_free(struct Main *mainvar);
 
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index c297514710e..d2d8a7680e2 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -119,7 +119,7 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
   }
 
   /* Using globals to sync selection for now */
-  G_MAIN->is_sync_select_dirty = true;
+  G_MAIN->sync_select_dirty_flag = SYNC_SELECT_REPLACE;
 }
 
 /**
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 252a7061bc5..10244f61ba4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -45,6 +45,7 @@
 #include "BKE_context.h"
 #include "BKE_deform.h"
 #include "BKE_fcurve.h"
+#include "BKE_global.h"
 #include "BKE_gpencil.h"
 #include "BKE_idcode.h"
 #include "BKE_layer.h"
@@ -3538,6 +3539,107 @@ static void outliner_update_viewable_area(ARegion *ar,
   UI_view2d_totRect_set(&ar->v2d, sizex, sizey);
 }
 
+void outliners_mark_dirty(const bContext *C, SpaceOutliner *soops)
+{
+  Main *bmain = CTX_data_main(C);
+  for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+    for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+      for (SpaceLink *space = sa->spacedata.first; space; space = space->next) {
+        if (space->spacetype == SPACE_OUTLINER) {
+          SpaceOutliner *soutliner = (SpaceOutliner *)space;
+
+          /* Mark selection state as dirty */
+          if (soutliner != soops) {
+            soutliner->flag |= SO_IS_DIRTY;
+          }
+        }
+      }
+    }
+  }
+}
+
+/* Sync selection flags with other outliner */
+static void outliner_sync_selection_with_outliner(SpaceOutliner *soops, ListBase *tree)
+{
+  for (TreeElement *te = tree->first; te; te = te->next) {
+    TreeStoreElem *tselem = TREESTORE(te);
+
+    TreeElement *ten = outliner_find_id(soops, &soops->tree, tselem->id);
+    if (ten) {
+      TreeStoreElem *this_tselem = TREESTORE(ten);
+      /* If is selected in other outliner */
+      if (tselem->flag & TSE_SELECTED) {
+
+        this_tselem->flag |= TSE_SELECTED;
+      }
+      else {
+        this_tselem->flag &= ~TSE_SELECTED;
+      }
+    }
+
+    outliner_sync_selection_with_outliner(soops, &te->subtree);
+  }
+}
+
+/* Sync selection flags from active view layer */
+static void outliner_sync_selection_from_view_layer(ViewLayer *view_layer, ListBase *tree)
+{
+  for (TreeElement *te = tree->first; te; te = te->next) {
+    TreeStoreElem *tselem = TREESTORE(te);
+    if (tselem->type == 0) {
+      if (te->idcode == ID_OB) {
+        Object *ob = (Object *)tselem->id;
+        Base *base = (te->directdata) ? (Base *)te->directdata :
+                                        BKE_view_layer_base_find(view_layer, ob);
+        const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
+
+        if (G_MAIN->sync_select_dirty_flag == SYNC_SELECT_EXTEND) {
+          puts("extend mode");
+        }
+
+        if (base && G_MAIN->sync_select_dirty_flag != SYNC_SELECT_EXTEND) {
+          if (is_selected) {
+            tselem->flag |= TSE_SELECTED;
+          }
+          else if (G_MAIN->sync_select_dirty_flag != SYNC_SELECT_EXTEND) {
+            tselem->flag &= ~TSE_SELECTED;
+          }
+        }
+      }
+    }
+
+    outliner_sync_selection_from_view_layer(view_layer, &te->subtree);
+  }
+}
+
+static void outliner_sync_selection(const bContext *C, SpaceOutliner *soops)
+{
+  /* Sync from clean outliner */
+  if (soops->flag & SO_IS_DIRTY) {
+    puts("\tSyncing from clean outliner");
+    if (G_MAIN->clean_outliner) {
+      outliner_sync_selection_with_outliner(soops, &G_MAIN->clean_outliner->tree);
+    }
+
+    soops->flag &= ~SO_IS_DIRTY;
+  }
+  /* Sync from view layer */
+  else if (G_MAIN->sync_select_dirty_flag != SYNC_SELECT_NONE) {
+    printf("View3D select... Syncing from view layer... ");
+
+    ViewLayer *view_layer = CTX_data_view_layer(C);
+
+    outliner_sync_selection_from_view_layer(view_layer, &soops->tree);
+
+    /* Mark other outliners as dirty */
+    outliners_mark_dirty(C, soops);
+
+    G_MAIN->clean_outliner = soops;
+    G_MAIN->sync_select_dirty_flag = SYNC_SELECT_NONE;
+    printf("set clean outliner\n");
+  }
+}
+
 /* ****************************************************** */
 /* Main Entrypoint - Draw contents of Outliner editor */
 
@@ -3554,10 +3656,9 @@ void draw_outliner(const bContext *C)
 
   outliner_build_tree(mainvar, scene, view_layer, soops, ar);  // always
 
-  /* Get selection state from view layer if dirty */
-  if ((soops->flag & SO_IS_DIRTY) && (soops->flag & SO_SYNC_SELECTION)) {
-    do_outliner_selection_sync(C, false);
-    soops->flag &= ~SO_IS_DIRTY;
+  /* Sync selection state from view layer or clean outliner if needed */
+  if (soops->flag & SO_SYNC_SELECTION) {
+    outliner_sync_selection(C, soops);
   }
 
   /* force display to pixel coords */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 0a5bde74a72..debf2934a92 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -261,7 +261,7 @@ void outliner_object_mode_toggle(struct bContext *C,
                                  ViewLayer *view_layer,
                                  Base *base);
 
-void do_outliner_selection_sync(const struct bContext *C, bool to_view_layer);
+void outliners_mark_dirty(const struct bContext *C, struct SpaceOutliner *soops);
 
 /* outliner_edit.c ---------------------------------------------- */
 typedef void (*outliner_operation_cb)(struct bContext *C,
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 7396d458939..7235d92a6c8 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -41,6 +41,7 @@
 #include "BKE_armature.h"
 #include "BKE_collection.h"
 #include "BKE_context.h"
+#include "BKE_global.h"
 #include "BKE_gpencil.h"
 #include "BKE_layer.h"
 #include "BKE_main.h"
@@ -72,6 +73,15 @@
 
 #include "outliner_intern.h"
 
+/* Set clean outliner and mark other outliners for syncing */
+static void outliner_select_sync(const bContext *C, SpaceOutliner *soops)
+{
+  puts("Outliner select... Mark other outliners as dirty for syncing");
+  G_MAIN->sync_select_dirty_flag = SYNC_SELECT_NONE;
+  G_MAIN->clean_outliner = soops;
+  outliners_mark_dirty(C, soops);
+}
+
 /* Get base of object under cursor (for eyedropper) */
 Base *ED_outliner_give_base_under_cursor(struct bContext *C, const int mval[2])
 {
@@ -1335,81 +1345,6 @@ void outliner_item_do_activate_from_tree_element(
       C, scene, view_layer, soops, te, tselem, extend, recursive);
 }
 
-static void do_outliner_selection_sync_recursive(SpaceOutliner *soops,
-                                                 ViewLayer *view_layer,
-                                                 ListBase *tree,
-                                                 bool to_view_layer)
-{
-  TreeElement *te;
-
-  for (te = tree->first; te; te = te->next) {
-    if (te->idcode == ID_OB) {
-      TreeStoreElem *tselem = TREESTORE(te);
-      Object *ob = (Object *)tselem->id;
-
-      Base *base = (te->directdata) ? (Base *)te->directdata :
-                                      BKE_view_layer_base_find(view_layer, ob);
-
-      if (to_view_layer) {
-        const bool is_selected = (tselem->flag & TSE_SELECTED) != 0;
-
-        if (is_selected) {
-          base->flag |= BASE_SELECTED;
-        }
-        else {
-          base->flag &= ~BASE_SELECTED;
-        }
-      }
-      else {
-        const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
-
-        if (is_selected) {
-          tselem->flag |= TSE_SELECTED;
-        }
-      }
-    }
-
-    if (&te->subtree) {
-      do_outliner_selection_sync_recursive(soops, view_layer, &te->subtree, to_view_layer);
-    }
-  }
-}
-
-void do_outliner_selection_sync(const bContext *C, bool to_view_layer)
-{
-  Scene *scene = CTX_data_scene(C);
-  ViewLayer *view_layer = CTX_data_view_layer(C);
-  SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
-  if (!to_view_layer) {
-    outliner_flag_set(&soops->tree, TSE_SELECTED, false);
-  }
-  do_outliner_selection_sync_recursive(soops, view_layer, &soops->tree, to_view_layer);
-
-  if (to_view_layer) {
-    /* Mark other outliners as dirty */
-    if (to_view_layer) {
-      Main *bmain = CTX_data_main(C);
-      for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
-        for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
-          for (SpaceLink *space = sa->spacedata.first; space; space = space->next) {
-            if (space->spacetype == SPACE_OUTLINER) {
-              SpaceOutliner *soutliner = (SpaceOutliner *)space;
-
-              /* Mark selection state as dirty */
-              soutliner->flag |= SO_IS_DIRTY;
-      

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list