Commit: cd374baef3963f8cd5f4610a3069a45f798c52ad
Author: Julian Eisel
Date:   Sun Jul 3 22:36:49 2016 +0200
Branches: soc-2016-layer_manager
https://developer.blender.org/rBcd374baef3963f8cd5f4610a3069a45f798c52ad

Get layer drag & drop with layer groups to work

Still get some occasional crashes but have to investigate at another time.

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

M       source/blender/blenkernel/BKE_layer.h
M       source/blender/blenkernel/intern/layer.c
M       source/blender/editors/space_layers/layers_ops.c
M       source/blender/makesdna/DNA_scene_types.h

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

diff --git a/source/blender/blenkernel/BKE_layer.h 
b/source/blender/blenkernel/BKE_layer.h
index a1d362d..8564490 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -110,7 +110,7 @@ void BKE_layeritem_register(
         const eLayerTreeItem_Type type, const char *name);
 void BKE_layeritem_remove(LayerTreeItem *litem, const bool remove_children);
 
-void BKE_layeritem_move(LayerTreeItem *litem, const int newidx);
+void BKE_layeritem_move(LayerTreeItem *litem, const int newidx, const bool 
with_childs);
 void BKE_layeritem_group_assign(LayerTreeItem *group, LayerTreeItem *item);
 
 bool BKE_layeritem_iterate_childs(
diff --git a/source/blender/blenkernel/intern/layer.c 
b/source/blender/blenkernel/intern/layer.c
index 5cc8e49..8006432 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -32,12 +32,14 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "BKE_context.h"
 #include "BKE_idprop.h"
 #include "BKE_layer.h" /* own include */
 #include "BKE_object.h"
 
+#include "BLI_alloca.h"
 #include "BLI_listbase.h"
 #include "BLI_string.h"
 
@@ -275,41 +277,76 @@ void BKE_layeritem_remove(LayerTreeItem *litem, const 
bool remove_children)
        ltree->items_all = MEM_reallocN(ltree->items_all, 
sizeof(*ltree->items_all) * ltree->tot_items);
 }
 
-static bool layeritem_move_array(LayerTreeItem *litem, const int newidx)
+/* XXX newidx isn't always the index the items are inserted at. */
+static void layeritem_move_array(LayerTreeItem *litem, const int newidx, const 
int num_items)
 {
-       const bool is_higher = litem->index < newidx;
+       LayerTree *ltree = litem->tree;
+       const int oldidx = litem->index;
+       const bool is_higher = oldidx < newidx;
+       const int insertidx = is_higher ? newidx - num_items + 1 : newidx;
 
-       BLI_assert(litem->tree->tot_items > newidx);
+       BLI_assert(num_items > 0 && ltree->tot_items > (insertidx + num_items - 
1));
        /* Already where we want to move it to. */
-       if (litem->index == newidx)
-               return false;
+       if (oldidx == newidx)
+               return;
+
+       /* Save items to be moved */
+       LayerTreeItem **movechunk = &litem;
+       if (num_items > 1) {
+               movechunk = BLI_array_alloca(movechunk, num_items);
+//             memcpy(movechunk, ltree->items_all[oldidx], 
sizeof(*ltree->items_all) * num_items); XXX doesn't work
+               for (int i = 0; i < num_items; i++) {
+                       movechunk[i] = ltree->items_all[oldidx + i];
+               }
+       }
+       BLI_assert(movechunk[0] == litem);
 
-       for (int i = is_higher ? litem->index + 1 : litem->index - 1;
-            i < litem->tree->tot_items && i >= 0;
+       /* rearrange items to fill in gaps of items to be moved */
+       for (int i = is_higher ? oldidx + num_items : oldidx - 1;
+            i < ltree->tot_items && i >= 0;
             is_higher ? i++ : i--)
        {
-               const int iter_new_idx = i + (is_higher ? -1 : 1);
-               litem->tree->items_all[iter_new_idx] = 
litem->tree->items_all[i];
-               litem->tree->items_all[iter_new_idx]->index = iter_new_idx;
+               const int iter_new_idx = i + (is_higher ? -num_items : 
num_items);
+               ltree->items_all[iter_new_idx] = ltree->items_all[i];
+               ltree->items_all[iter_new_idx]->index = iter_new_idx;
                if (i == newidx) {
-                       litem->tree->items_all[i] = litem;
-                       litem->index = i;
                        break;
                }
        }
+       /* move items to new position starting at newidx */
+       for (int i = 0; i < num_items; i++) {
+               ltree->items_all[insertidx + i] = movechunk[i];
+               ltree->items_all[insertidx + i]->index = insertidx + i;
+       }
+       /* TODO can check using gtest */
+       BLI_assert(ltree->items_all[insertidx] == litem && litem->index == 
insertidx);
+}
 
-       return true;
+/**
+ * Helper to count all children (and grand-children etc.) of a layer item.
+ * \note Recursive.
+ */
+static unsigned int layeritem_childs_count(ListBase *childs)
+{
+       int i = 0;
+       for (LayerTreeItem *child = childs->first; child; child = child->next, 
i++) {
+               if (!BLI_listbase_is_empty(&child->childs)) {
+                       i += layeritem_childs_count(&child->childs);
+               }
+       }
+       return i;
 }
 
 /**
  * Move \a litem that's already in the layer tree to slot \a newidx.
  */
-void BKE_layeritem_move(LayerTreeItem *litem, const int newidx)
+void BKE_layeritem_move(LayerTreeItem *litem, const int newidx, const bool 
with_childs)
 {
-       /* move in array (return if failed) */
-       if (!layeritem_move_array(litem, newidx)) {
+       const int tot_childs = with_childs ? 
layeritem_childs_count(&litem->childs) : 0;
+
+       /* Already where we want to move it to. */
+       if (litem->index == newidx)
                return;
-       }
 
        /* move in listbase */
        BLI_remlink(litem->parent ? &litem->parent->childs : 
&litem->tree->items, litem);
@@ -321,6 +358,9 @@ void BKE_layeritem_move(LayerTreeItem *litem, const int 
newidx)
                LayerTreeItem *moved = litem->tree->items_all[newidx + 1];
                BLI_insertlinkbefore(moved->parent ? &moved->parent->childs : 
&litem->tree->items, moved, litem);
        }
+
+       /* move in array (return if failed) */
+       layeritem_move_array(litem, newidx, tot_childs + 1);
 }
 
 /**
@@ -339,7 +379,7 @@ void BKE_layeritem_group_assign(LayerTreeItem *group, 
LayerTreeItem *item)
        BLI_addtail(&group->childs, item);
        /* move in array */
        /* XXX we could/should limit iterations to one in case multiple 
elmenents are assigned to a group */
-       layeritem_move_array(item, (item->prev ? item->prev->index : 
item->parent->index) + 1);
+       layeritem_move_array(item, (item->prev ? item->prev->index : 
item->parent->index) + 1, 1);
 }
 
 /**
diff --git a/source/blender/editors/space_layers/layers_ops.c 
b/source/blender/editors/space_layers/layers_ops.c
index 891d3e3..5e6cdcb 100644
--- a/source/blender/editors/space_layers/layers_ops.c
+++ b/source/blender/editors/space_layers/layers_ops.c
@@ -86,6 +86,7 @@ typedef struct {
        int init_mval_y;
        bool is_dragging;
        bool is_cancel;
+       bool needs_reopen;
 
        /* anim data */
        wmTimer *anim_timer;
@@ -254,7 +255,8 @@ static int layer_group_add_invoke(bContext *C, wmOperator 
*UNUSED(op), const wmE
                LayerTile *tile = BLI_ghash_lookup(slayer->tiles, litem);
                if (tile->flag & LAYERTILE_SELECTED) {
                        if (is_first) {
-                               BKE_layeritem_move(new_group, litem->index);
+                               
BLI_assert(BLI_listbase_is_empty(&new_group->childs));
+                               BKE_layeritem_move(new_group, litem->index, 
false);
                                is_first = false;
                        }
                        BKE_layeritem_group_assign(new_group, litem);
@@ -438,8 +440,11 @@ static int layer_drag_modal(bContext *C, wmOperator *op, 
const wmEvent *event)
                        case LAYERDRAG_CONFIRM:
                                ldrag->is_dragging = false;
                                layer_drag_drop_anim_start(C, ldrag, event);
+                               if (ldrag->needs_reopen) {
+                                       ldrag->dragged.tile->flag &= 
~LAYERTILE_CLOSED;
+                               }
                                /* apply new position before animation is done 
*/
-                               BKE_layeritem_move(ldrag->dragged.tile->litem, 
ldrag->insert_idx);
+                               BKE_layeritem_move(ldrag->dragged.tile->litem, 
ldrag->insert_idx, true);
                                if (ldrag->insert_idx != 
ldrag->dragged.tile->litem->index) {
                                        WM_event_add_notifier(C, NC_SCENE | 
ND_LAYER, NULL);
                                }
@@ -481,6 +486,10 @@ static int layer_drag_invoke(bContext *C, wmOperator *op, 
const wmEvent *event)
 
        op->customdata = ldrag;
        tile->flag |= LAYERTILE_FLOATING;
+       if (!BLI_listbase_is_empty(&tile->litem->childs) && !(tile->flag & 
LAYERTILE_CLOSED)) {
+               tile->flag |= LAYERTILE_CLOSED;
+               ldrag->needs_reopen = true;
+       }
 
        WM_event_add_modal_handler(C, op);
 
diff --git a/source/blender/makesdna/DNA_scene_types.h 
b/source/blender/makesdna/DNA_scene_types.h
index 6248baf..9f0280f 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -89,7 +89,10 @@ typedef struct LayerTree {
        /* LayerTreeItem - Only items of the first level in the hierarchy, 
these may have children then.
         * TODO check if worth using array instead */
        ListBase items;
-       /* Array of all layer tree items, including all childs. Using array in 
hope it speeds up iterations. */
+       /* Array of all layer tree items, including all childs. Using array in 
hope it speeds up iterations.
+        * NOTE: We currently assume that all children (or grand-children, etc) 
are placed after their parent, even though
+        * it's quite easy to break it. It could be supported but might lower 
performance a bit (maybe uber-picky).
+        * XXX Check if this can be made safer */
        struct LayerTreeItem **items_all;
 } LayerTree;
 
@@ -105,7 +108,7 @@ typedef struct LayerTreeItem {
        int index, pad; /* index of the item - stored to avoid loockups */
        char name[64];  /* MAX_NAME */
 
-       struct LayerTree *tree; /* pointer back to layer tree - TODO check if 
needed */
+       LayerTree *tree; /* pointer back to layer tree - TODO check if needed */
        struct LayerTreeItem *parent; /* the group this item belongs to */
        ListBase childs; /* LayerTreeItem */

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

Reply via email to