Commit: 030d228ca46b19b80d35ffd2ab986e4c6e54d55f
Author: Julian Eisel
Date:   Wed May 25 14:58:22 2016 +0200
Branches: soc-2016-layer_manager
https://developer.blender.org/rB030d228ca46b19b80d35ffd2ab986e4c6e54d55f

More layer selection methods

Now supports shift, ctrl+shift and a-key selection.

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

M       source/blender/editors/space_layers/layers_intern.h
M       source/blender/editors/space_layers/layers_ops.c
M       source/blender/editors/space_layers/layers_util.c
M       source/blender/editors/space_layers/space_layers.c
M       source/blender/makesdna/DNA_space_types.h

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

diff --git a/source/blender/editors/space_layers/layers_intern.h 
b/source/blender/editors/space_layers/layers_intern.h
index f3c505b..fe5ccb2 100644
--- a/source/blender/editors/space_layers/layers_intern.h
+++ b/source/blender/editors/space_layers/layers_intern.h
@@ -49,7 +49,9 @@ void layers_tiles_draw(const struct bContext *C, struct 
ARegion *ar);
 
 /* layers_util.c */
 LayerTile *layers_tile_add(struct SpaceLayers *slayer, struct LayerTreeItem 
*litem);
-LayerTile *layers_tile_find_at_coordinate(const SpaceLayers *slayer, const 
ARegion *ar, const int co[2]);
+LayerTile *layers_tile_find_at_coordinate(
+        const struct SpaceLayers *slayer, const ARegion *ar, const int co[2],
+        int *r_tile_idx);
 
 /* layers_ops.c */
 void layers_operatortypes(void);
diff --git a/source/blender/editors/space_layers/layers_ops.c 
b/source/blender/editors/space_layers/layers_ops.c
index 01373d4..f28c00c 100644
--- a/source/blender/editors/space_layers/layers_ops.c
+++ b/source/blender/editors/space_layers/layers_ops.c
@@ -32,6 +32,9 @@
 #include "ED_object.h"
 #include "ED_screen.h"
 
+#include "RNA_access.h"
+#include "RNA_define.h"
+
 #include "WM_api.h"
 #include "WM_types.h"
 
@@ -76,7 +79,7 @@ static int layer_rename_invoke(bContext *C, wmOperator 
*UNUSED(op), const wmEven
 {
        SpaceLayers *slayer = CTX_wm_space_layers(C);
        ARegion *ar = CTX_wm_region(C);
-       LayerTile *tile = layers_tile_find_at_coordinate(slayer, ar, 
event->mval);
+       LayerTile *tile = layers_tile_find_at_coordinate(slayer, ar, 
event->mval, NULL);
        if (tile) {
                tile->flag |= LAYERTILE_RENAME;
 
@@ -101,21 +104,91 @@ static void LAYERS_OT_layer_rename(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-static void layers_deselect_all(const SpaceLayers *slayer)
+BLI_INLINE void layer_selection_set(SpaceLayers *slayer, LayerTile *tile, 
const int tile_idx, const bool enable)
 {
-       for (LayerTile *tile = slayer->layer_tiles.first; tile; tile = 
tile->next) {
+       if (enable) {
+               (tile->flag |= LAYERTILE_SELECTED);
+               slayer->last_selected = tile_idx;
+       }
+       else {
                tile->flag &= ~LAYERTILE_SELECTED;
        }
 }
 
-static int layer_select_invoke(bContext *C, wmOperator *UNUSED(op), const 
wmEvent *event)
+/**
+ * Change the selection state of all layer tiles.
+ * \param enable: If true, tiles are selected, else they are deselected.
+ */
+static void layers_selection_set_all(SpaceLayers *slayer, const bool enable)
+{
+       int i = 0;
+       for (LayerTile *tile = slayer->layer_tiles.first; tile; tile = 
tile->next, i++) {
+               layer_selection_set(slayer, tile, i, enable);
+       }
+}
+
+/**
+ * Select everything within the range of \a from to \a to.
+ * \return if anything got selected. Nothing is selected if from == to or one 
of them is < 0.
+ */
+static bool layers_select_fill(SpaceLayers *slayer, const int from, const int 
to)
+{
+       const int min = MIN2(from, to);
+       const int max = MAX2(from, to);
+
+       if (min < 0 || min == max)
+               return false;
+
+       int i = 0;
+       for (LayerTile *tile = slayer->layer_tiles.first; tile && i <= max; 
tile = tile->next, i++) {
+               if (i >= min) {
+                       layer_selection_set(slayer, tile, i, true);
+               }
+       }
+       return true;
+}
+
+static int layer_select_invoke(bContext *C, wmOperator *op, const wmEvent 
*event)
 {
        SpaceLayers *slayer = CTX_wm_space_layers(C);
        ARegion *ar = CTX_wm_region(C);
-       LayerTile *tile = layers_tile_find_at_coordinate(slayer, ar, 
event->mval);
+       const bool extend = RNA_boolean_get(op->ptr, "extend");
+       const bool deselect = RNA_boolean_get(op->ptr, "deselect");
+       const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+       const bool fill = RNA_boolean_get(op->ptr, "fill");
+
+       int tile_idx;
+       LayerTile *tile = layers_tile_find_at_coordinate(slayer, ar, 
event->mval, &tile_idx);
+
+       /* little helper for setting/unsetting selection flag */
+#define TILE_SET_SELECTION(enable) layer_selection_set(slayer, tile, tile_idx, 
enable);
+
        if (tile) {
-               layers_deselect_all(slayer);
-               tile->flag |= LAYERTILE_SELECTED;
+               /* deselect all, but only if extend, deselect and toggle are 
false */
+               if (((extend == deselect) == toggle) == false) {
+                       layers_selection_set_all(slayer, false);
+               }
+               if (extend) {
+                       if (fill && layers_select_fill(slayer, 
slayer->last_selected, tile_idx)) {
+                               /* skip */
+                       }
+                       else {
+                               TILE_SET_SELECTION(true);
+                       }
+               }
+               else if (deselect) {
+                       TILE_SET_SELECTION(false);
+               }
+               else {
+                       if (!tile->flag & LAYERTILE_SELECTED) {
+                               TILE_SET_SELECTION(true);
+                       }
+                       else if (toggle) {
+                               TILE_SET_SELECTION(false);
+                       }
+               }
+
+#undef TILE_SET_SELECTION
 
                ED_region_tag_redraw(ar);
                return OPERATOR_FINISHED;
@@ -123,16 +196,50 @@ static int layer_select_invoke(bContext *C, wmOperator 
*UNUSED(op), const wmEven
        return OPERATOR_CANCELLED;
 }
 
-static void LAYERS_OT_layer_select(wmOperatorType *ot)
+static void LAYERS_OT_select(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name = "Select Layer";
-       ot->idname = "LAYERS_OT_layer_select";
+       ot->idname = "LAYERS_OT_select";
        ot->description = "Select/activate the layer under the cursor";
 
        /* api callbacks */
        ot->invoke = layer_select_invoke;
        ot->poll = ED_operator_layers_active;
+
+       WM_operator_properties_mouse_select(ot);
+       PropertyRNA *prop = RNA_def_boolean(ot->srna, "fill", false, "Fill", 
"Select everything beginning "
+                                                                            
"with the last selection");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+static int layer_select_all_toggle_invoke(bContext *C, wmOperator *UNUSED(op), 
const wmEvent *UNUSED(event))
+{
+       SpaceLayers *slayer = CTX_wm_space_layers(C);
+       LayerTile *tile;
+
+       for (tile = slayer->layer_tiles.first; tile; tile = tile->next) {
+               if (tile->flag & LAYERTILE_SELECTED) {
+                       break;
+               }
+       }
+       /* if a tile was found we deselect all, else we select all */
+       layers_selection_set_all(slayer, tile == NULL);
+       ED_region_tag_redraw(CTX_wm_region(C));
+
+       return OPERATOR_FINISHED;
+}
+
+static void LAYERS_OT_select_all_toggle(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "(De)select All Layers";
+       ot->idname = "LAYERS_OT_select_all_toggle";
+       ot->description = "Select or deselect all layers";
+
+       /* api callbacks */
+       ot->invoke = layer_select_all_toggle_invoke;
+       ot->poll = ED_operator_layers_active;
 }
 
 
@@ -145,13 +252,23 @@ void layers_operatortypes(void)
        WM_operatortype_append(LAYERS_OT_layer_rename);
 
        /* states (activating selecting, highlighting) */
-       WM_operatortype_append(LAYERS_OT_layer_select);
+       WM_operatortype_append(LAYERS_OT_select);
+       WM_operatortype_append(LAYERS_OT_select_all_toggle);
 }
 
 void layers_keymap(wmKeyConfig *keyconf)
 {
        wmKeyMap *keymap = WM_keymap_find(keyconf, "Layer Manager", 
SPACE_LAYERS, 0);
-       WM_keymap_add_item(keymap, "LAYERS_OT_layer_select", LEFTMOUSE, 
KM_CLICK, 0, 0);
+       wmKeyMapItem *kmi;
+
+       /* selection */
+       WM_keymap_add_item(keymap, "LAYERS_OT_select", LEFTMOUSE, KM_CLICK, 0, 
0);
+       kmi = WM_keymap_add_item(keymap, "LAYERS_OT_select", LEFTMOUSE, 
KM_CLICK, KM_SHIFT, 0);
+       RNA_boolean_set(kmi->ptr, "toggle", true);
+       kmi = WM_keymap_add_item(keymap, "LAYERS_OT_select", LEFTMOUSE, 
KM_CLICK, KM_CTRL | KM_SHIFT, 0);
+       RNA_boolean_set(kmi->ptr, "extend", true);
+       RNA_boolean_set(kmi->ptr, "fill", true);
+       WM_keymap_add_item(keymap, "LAYERS_OT_select_all_toggle", AKEY, 
KM_PRESS, 0, 0);
 
        WM_keymap_add_item(keymap, "LAYERS_OT_layer_rename", LEFTMOUSE, 
KM_DBL_CLICK, 0, 0);
        WM_keymap_add_item(keymap, "LAYERS_OT_layer_rename", LEFTMOUSE, 
KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_layers/layers_util.c 
b/source/blender/editors/space_layers/layers_util.c
index dd32623..2a6fc23 100644
--- a/source/blender/editors/space_layers/layers_util.c
+++ b/source/blender/editors/space_layers/layers_util.c
@@ -51,16 +51,27 @@ LayerTile *layers_tile_add(SpaceLayers *slayer, 
LayerTreeItem *litem)
 
 /**
  * Find the tile at coordinate \a co (regionspace).
+ * \param r_tile_idx: Returns the index of the result, -1 if no tile was found.
  */
-LayerTile *layers_tile_find_at_coordinate(const SpaceLayers *slayer, const 
ARegion *ar, const int co[2])
+LayerTile *layers_tile_find_at_coordinate(
+        const SpaceLayers *slayer, const ARegion *ar, const int co[2],
+        int *r_tile_idx)
 {
+       LayerTile *tile;
        int ofsx = 0;
+       unsigned int idx = 0;
 
-       for (LayerTile *tile = slayer->layer_tiles.first; tile; tile = 
tile->next) {
+       for (tile = slayer->layer_tiles.first; tile; tile = tile->next, idx++) {
                ofsx += tile->litem->height;
                if (co[1] >= -ar->v2d.cur.ymin - ofsx) {
-                       return tile;
+                       /* found tile */
+                       break;
                }
        }
-       return NULL;
+
+       /* return values */
+       if (r_tile_idx) {
+               (*r_tile_idx) = (tile != NULL) ? idx : -1;
+       }
+       return tile;
 }
diff --git a/source/blender/editors/space_layers/space_layers.c 
b/source/blender/editors/space_layers/space_layers.c
index c54ec96..854d54c 100644
--- a/source/blender/editors/space_layers/space_layers.c
+++ b/source/blender/editors/space_layers/space_layers.c
@@ -55,6 +55,7 @@ static SpaceLink *layers_new(const bContext *UNUSED(C))
 
        slayer = MEM_callocN(sizeof(SpaceLayers), __func__);
        slayer->spacetype = SPACE_LAYERS;
+       slayer->last_selected = -1;
 
        /* header */
        ar = MEM_callocN(sizeof(ARegion), "header for layer manager");
diff --git a/source/blender/makesdna/DNA_space_types.h 
b/source/blender/makesdna/DNA_space_types.h
index 2c6d2f0..e8b6ade 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1338,8 +1338,9 @@ typedef struct SpaceLayers {
        SpaceLink *next, *prev;
        ListBase regionbase;        /* storage of regions for inactive spaces */
        int spacetype;
-       int pad;
 
+       /* index of last selected item, will likely become redundant when 
active layers are supported */
+       int last_selected;
        ListBase layer_tiles; /* LayerTile */
 } SpaceLayers;

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

Reply via email to