[Bf-blender-cvs] [60a74015111] temp-soc-2019-outliner-sync: Outliner: Synced selection fixes

Nathan Craddock noreply at git.blender.org
Fri Aug 16 19:30:13 CEST 2019


Commit: 60a74015111884dc8d0877fe422497913f94fd03
Author: Nathan Craddock
Date:   Fri Aug 16 11:16:33 2019 -0600
Branches: temp-soc-2019-outliner-sync
https://developer.blender.org/rB60a74015111884dc8d0877fe422497913f94fd03

Outliner: Synced selection fixes

Fix outliner select on items linked between collections not
syncing.
Adds more control to from-outliner select syncing, to only sync
data within the current interaction mode.
Deselect all non-synced data on syncing to outliner.
Fix edit bone outliner syncing not tagging for updates

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

M	source/blender/editors/space_outliner/outliner_sync.c

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

diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
index 42068dfff1e..a8aeb7ea4e1 100644
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -30,6 +30,9 @@
 #include "DNA_sequence_types.h"
 #include "DNA_space_types.h"
 
+#include "BLI_compiler_compat.h"
+#include "BLI_ghash.h"
+
 #include "BKE_armature.h"
 #include "BKE_context.h"
 #include "BKE_layer.h"
@@ -112,15 +115,22 @@ typedef struct SyncSelectTypes {
   bool sequence;
 } SyncSelectTypes;
 
-/** Set which types of data to sync when syncing selection from the outliner. */
-static void outliner_sync_select_from_outliner_set_types(SpaceOutliner *soops,
+/**
+ * Set which types of data to sync when syncing selection from the outliner based on object
+ * interaction mode and outliner display mode
+ */
+static void outliner_sync_select_from_outliner_set_types(bContext *C,
+                                                         SpaceOutliner *soops,
                                                          SyncSelectTypes *sync_types)
 {
+  Object *obact = CTX_data_active_object(C);
+  Object *obedit = CTX_data_edit_object(C);
+
   const bool sequence_view = soops->outlinevis == SO_SEQUENCE;
 
-  sync_types->object = !sequence_view;
-  sync_types->edit_bone = !sequence_view;
-  sync_types->pose_bone = !sequence_view;
+  sync_types->object = !sequence_view && (obact && obact->mode == OB_MODE_OBJECT);
+  sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE);
+  sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE);
   sync_types->sequence = sequence_view;
 }
 
@@ -128,24 +138,77 @@ static void outliner_sync_select_from_outliner_set_types(SpaceOutliner *soops,
  * Current dirty flags and outliner display mode determine which type of syncing should occur.
  * This is to ensure sync flag data is not lost on sync in the wrong display mode.
  */
-static void outliner_sync_select_to_outliner_set_types(SpaceOutliner *soops,
+static void outliner_sync_select_to_outliner_set_types(const bContext *C,
+                                                       SpaceOutliner *soops,
                                                        SyncSelectTypes *sync_types)
 {
+  Object *obact = CTX_data_active_object(C);
+  Object *obedit = CTX_data_edit_object(C);
+
   const bool sequence_view = soops->outlinevis == SO_SEQUENCE;
 
-  sync_types->object = !sequence_view &&
+  sync_types->object = !sequence_view && (obact && obact->mode == OB_MODE_OBJECT) &&
                        (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_OBJECT);
-  sync_types->edit_bone = !sequence_view &&
+  sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE) &&
                           (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE);
-  sync_types->pose_bone = !sequence_view &&
+  sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE) &&
                           (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE);
   sync_types->sequence = sequence_view &&
                          (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE);
 }
 
+/**
+ * Stores items selected from a sync from the outliner. Prevents syncing the selection
+ * state of the last instance of an object linked in multiple collections.
+ */
+typedef struct SelectedItems {
+  GSet *objects;
+  GSet *edit_bones;
+  GSet *pose_bones;
+} SelectedItems;
+
+static void selected_items_init(SelectedItems *selected_items)
+{
+  selected_items->objects = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+  selected_items->edit_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+  selected_items->pose_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+}
+
+static void selected_items_free(SelectedItems *selected_items)
+{
+  BLI_gset_free(selected_items->objects, NULL);
+  BLI_gset_free(selected_items->edit_bones, NULL);
+  BLI_gset_free(selected_items->pose_bones, NULL);
+}
+
+/* Check if an instance of this object been selected by the sync */
+static bool is_object_selected(GSet *selected_objects, Base *base)
+{
+  return BLI_gset_haskey(selected_objects, base);
+}
+
+/* Check if an instance of this edit bone been selected by the sync */
+static bool is_edit_bone_selected(GSet *selected_ebones, EditBone *ebone)
+{
+  return BLI_gset_haskey(selected_ebones, ebone);
+}
+
+/* Check if an instance of this pose bone been selected by the sync */
+static bool is_pose_bone_selected(GSet *selected_pbones, bPoseChannel *pchan)
+{
+  return BLI_gset_haskey(selected_pbones, pchan);
+}
+
+/* Add element's data to selected item set */
+static void add_selected_item(GSet *selected, void *data)
+{
+  BLI_gset_add(selected, data);
+}
+
 static void outliner_select_sync_to_object(ViewLayer *view_layer,
                                            TreeElement *te,
-                                           TreeStoreElem *tselem)
+                                           TreeStoreElem *tselem,
+                                           GSet *selected_objects)
 {
   Object *ob = (Object *)tselem->id;
   Base *base = (te->directdata) ? (Base *)te->directdata :
@@ -154,29 +217,47 @@ static void outliner_select_sync_to_object(ViewLayer *view_layer,
   if (base && (base->flag & BASE_SELECTABLE)) {
     if (tselem->flag & TSE_SELECTED) {
       ED_object_base_select(base, BA_SELECT);
+
+      add_selected_item(selected_objects, base);
     }
-    else {
+    else if (!is_object_selected(selected_objects, base)) {
       ED_object_base_select(base, BA_DESELECT);
     }
   }
 }
 
-static void outliner_select_sync_to_edit_bone(TreeElement *te, TreeStoreElem *tselem)
+static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer,
+                                              TreeElement *te,
+                                              TreeStoreElem *tselem,
+                                              GSet *selected_ebones)
 {
   bArmature *arm = (bArmature *)tselem->id;
   EditBone *ebone = (EditBone *)te->directdata;
 
+  short bone_flag = ebone->flag;
+
   if (EBONE_SELECTABLE(arm, ebone)) {
     if (tselem->flag & TSE_SELECTED) {
       ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+
+      add_selected_item(selected_ebones, ebone);
     }
-    else {
+    else if (!is_edit_bone_selected(selected_ebones, ebone)) {
       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
     }
   }
+
+  /* Tag if selection changed */
+  if (bone_flag != ebone->flag) {
+    Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+    DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+    WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, obedit);
+  }
 }
 
-static void outliner_select_sync_to_pose_bone(TreeElement *te, TreeStoreElem *tselem)
+static void outliner_select_sync_to_pose_bone(TreeElement *te,
+                                              TreeStoreElem *tselem,
+                                              GSet *selected_pbones)
 {
   Object *ob = (Object *)tselem->id;
   bArmature *arm = ob->data;
@@ -187,8 +268,10 @@ static void outliner_select_sync_to_pose_bone(TreeElement *te, TreeStoreElem *ts
   if (PBONE_SELECTABLE(arm, pchan->bone)) {
     if (tselem->flag & TSE_SELECTED) {
       pchan->bone->flag |= BONE_SELECTED;
+
+      add_selected_item(selected_pbones, pchan);
     }
-    else {
+    else if (!is_pose_bone_selected(selected_pbones, pchan)) {
       pchan->bone->flag &= ~BONE_SELECTED;
     }
   }
@@ -220,7 +303,8 @@ static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem
 static void outliner_sync_selection_from_outliner(Scene *scene,
                                                   ViewLayer *view_layer,
                                                   ListBase *tree,
-                                                  const SyncSelectTypes *sync_types)
+                                                  const SyncSelectTypes *sync_types,
+                                                  SelectedItems *selected_items)
 {
 
   for (TreeElement *te = tree->first; te; te = te->next) {
@@ -228,17 +312,17 @@ static void outliner_sync_selection_from_outliner(Scene *scene,
 
     if (tselem->type == 0 && te->idcode == ID_OB) {
       if (sync_types->object) {
-        outliner_select_sync_to_object(view_layer, te, tselem);
+        outliner_select_sync_to_object(view_layer, te, tselem, selected_items->objects);
       }
     }
     else if (tselem->type == TSE_EBONE) {
       if (sync_types->edit_bone) {
-        outliner_select_sync_to_edit_bone(te, tselem);
+        outliner_select_sync_to_edit_bone(view_layer, te, tselem, selected_items->edit_bones);
       }
     }
     else if (tselem->type == TSE_POSE_CHANNEL) {
       if (sync_types->pose_bone) {
-        outliner_select_sync_to_pose_bone(te, tselem);
+        outliner_select_sync_to_pose_bone(te, tselem, selected_items->pose_bones);
       }
     }
     else if (tselem->type == TSE_SEQUENCE) {
@@ -247,7 +331,8 @@ static void outliner_sync_selection_from_outliner(Scene *scene,
       }
     }
 
-    outliner_sync_selection_from_outliner(scene, view_layer, &te->subtree, sync_types);
+    outliner_sync_selection_from_outliner(
+        scene, view_layer, &te->subtree, sync_types, selected_items);
   }
 }
 
@@ -263,29 +348,28 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops)
   ViewLayer *view_layer = CTX_data_view_layer(C);
 
   SyncSelectTypes sync_types;
-  outliner_sync_select_from_outliner_set_types(soops, &sync_types);
+  outliner_sync_select_from_outliner_set_types(C, soops, &sync_types);
+
+  /* To store elements that have been selected to prevent linked object sync errors */
+  SelectedItems selected_items;
+
+  selected_items_init(&selected_items);
 
-  outliner_sync_selection_from_outliner(scene, view_layer, &soops->tree, &sync_types);
+  outliner_sync_selection_from_outliner(
+      scene, view_layer, &soops->tree, &sync_types, &selected_items);
 
-  /* Set globa

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list