[Bf-blender-cvs] [3c39c51d021] soc-2020-outliner: Outliner: Object drop initial implementation

Nathan Craddock noreply at git.blender.org
Thu Jul 9 21:42:35 CEST 2020


Commit: 3c39c51d0211210ea04c5e91a4d2f8181f1e5745
Author: Nathan Craddock
Date:   Thu Jul 9 13:40:58 2020 -0600
Branches: soc-2020-outliner
https://developer.blender.org/rB3c39c51d0211210ea04c5e91a4d2f8181f1e5745

Outliner: Object drop initial implementation

Allow reordering objects in the outliner. Works for multiple selection.
The code has a few places that could be cleaned up.

Also, an issue exists where it isn't always clear where to move the
objects to. This applies to any outliner drag+drop so that will be
handled separately.

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

M	source/blender/blenkernel/BKE_collection.h
M	source/blender/blenkernel/intern/collection.c
M	source/blender/editors/space_outliner/outliner_dragdrop.c

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

diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 4cf33640ebd..bdb9ca7afa7 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -97,6 +97,9 @@ void BKE_collection_object_move(struct Main *bmain,
                                 struct Collection *collection_dst,
                                 struct Collection *collection_src,
                                 struct Object *ob);
+void BKE_collection_object_move_after(struct Collection *collection,
+                                      struct Object *ob_relative,
+                                      struct Object *ob);
 
 bool BKE_scene_collections_object_remove(struct Main *bmain,
                                          struct Scene *scene,
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 7e22048379b..22c254684bb 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -1084,6 +1084,33 @@ void BKE_collection_object_move(
   }
 }
 
+/**
+ * Move object within a collection after specified object.
+ *
+ * For outliner drag & drop.
+ */
+void BKE_collection_object_move_after(Collection *collection, Object *ob_relative, Object *ob)
+{
+  if (ELEM(NULL, collection, ob_relative, ob)) {
+    return;
+  }
+
+  CollectionObject *relative = BLI_findptr(
+      &collection->gobject, ob_relative, offsetof(CollectionObject, ob));
+  if (!relative) {
+    return;
+  }
+  int index_to = BLI_findindex(&collection->gobject, relative);
+
+  CollectionObject *object = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
+  if (!object) {
+    return;
+  }
+  int index_from = BLI_findindex(&collection->gobject, object);
+
+  BLI_listbase_move_index(&collection->gobject, index_from, index_to);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index aa5842fafc5..9d70cc13286 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -66,6 +66,8 @@
 
 #include "outliner_intern.h"
 
+static Collection *collection_parent_from_ID(ID *id);
+
 /* ******************** Drop Data Functions *********************** */
 
 typedef struct OutlinerDropData {
@@ -297,11 +299,11 @@ static bool parent_drop_allowed(TreeElement *te, Object *potential_child)
 static bool parent_drop_poll(bContext *C,
                              wmDrag *drag,
                              const wmEvent *event,
-                             const char **UNUSED(r_tooltip))
+                             const char **r_tooltip)
 {
   SpaceOutliner *soops = CTX_wm_space_outliner(C);
 
-  bool changed = outliner_flag_set(&soops->tree, TSE_DRAG_ANY, false);
+  bool changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false);
   if (changed) {
     ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
   }
@@ -311,18 +313,39 @@ static bool parent_drop_poll(bContext *C,
     return false;
   }
 
-  TreeElement *te = outliner_drop_find(C, event);
+  TreeElementInsertType insert_type;
+  TreeElement *te = outliner_drop_insert_find(C, event, &insert_type);
   if (!te) {
     return false;
   }
+  TreeStoreElem *tselem = TREESTORE(te);
 
-  if (parent_drop_allowed(te, potential_child)) {
-    TREESTORE(te)->flag |= TSE_DRAG_INTO;
-    ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
-    return true;
+  if (soops->sort_method != SO_SORT_FREE || soops->outlinevis != SO_VIEW_LAYER) {
+    insert_type = TE_INSERT_INTO;
   }
 
-  return false;
+  if (!parent_drop_allowed(te, potential_child)) {
+    return false;
+  }
+
+  switch (insert_type) {
+    case TE_INSERT_BEFORE:
+      tselem->flag |= TSE_DRAG_BEFORE;
+      *r_tooltip = TIP_("Reorder object");
+      break;
+    case TE_INSERT_AFTER:
+      tselem->flag |= TSE_DRAG_AFTER;
+      *r_tooltip = TIP_("Reorder object");
+      break;
+    case TE_INSERT_INTO:
+      tselem->flag |= TSE_DRAG_INTO;
+      break;
+  }
+
+  TREESTORE(te)->flag |= TSE_DRAG_INTO;
+  ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
+
+  return true;
 }
 
 static void parent_drop_set_parents(bContext *C,
@@ -378,9 +401,51 @@ static void parent_drop_set_parents(bContext *C,
   }
 }
 
+static void parent_drop_move_objects(bContext *C, wmDragID *drag, TreeElement *te)
+{
+  Main *bmain = CTX_data_main(C);
+  SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+  Scene *scene = (Scene *)outliner_search_back(te, ID_SCE);
+  if (scene == NULL) {
+    scene = CTX_data_scene(C);
+  }
+
+  Object *ob_drop = (Object *)TREESTORE(te)->id;
+  Collection *collection_to = collection_parent_from_ID(&ob_drop->id);
+  while (te) {
+    te = te->parent;
+    if (outliner_is_collection_tree_element(te)) {
+      collection_to = outliner_collection_from_tree_element(te);
+      break;
+    }
+  }
+
+  for (wmDragID *drag_id = drag; drag_id; drag_id = drag_id->next) {
+    if (GS(drag_id->id->name) == ID_OB) {
+      Object *object = (Object *)drag_id->id;
+
+      /* Do nothing to linked data */
+      if (ID_IS_LINKED(object)) {
+        continue;
+      }
+
+      Collection *from = collection_parent_from_ID(drag_id->from_parent);
+      BKE_collection_object_move(bmain, scene, collection_to, from, object);
+      BKE_collection_object_move_after(collection_to, ob_drop, object);
+    }
+  }
+
+  DEG_relations_tag_update(bmain);
+  WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+  WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+  WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+}
+
 static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
-  TreeElement *te = outliner_drop_find(C, event);
+  TreeElementInsertType insert_type;
+  TreeElement *te = outliner_drop_insert_find(C, event, &insert_type);
   TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
 
   if (!(te && te->idcode == ID_OB && tselem->type == 0)) {
@@ -404,7 +469,17 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
   ListBase *lb = event->customdata;
   wmDrag *drag = lb->first;
 
-  parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT, event->alt);
+  SpaceOutliner *soops = CTX_wm_space_outliner(C);
+  if (soops->sort_method != SO_SORT_FREE || soops->outlinevis != SO_VIEW_LAYER) {
+    insert_type = TE_INSERT_INTO;
+  }
+
+  if (insert_type == TE_INSERT_INTO) {
+    parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT, event->alt);
+  }
+  else {
+    parent_drop_move_objects(C, drag->ids.first, te);
+  }
 
   return OPERATOR_FINISHED;
 }



More information about the Bf-blender-cvs mailing list