Select: Add 'deselect on nothing' to UV editor.
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 30 Apr 2019 13:18:00 +0000 (15:18 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 30 Apr 2019 14:09:58 +0000 (16:09 +0200)
As with mask, when this is enabled there is now a maximum click distance
from an item to actually select it.

Part of T63995.

release/scripts/presets/keyconfig/keymap_data/blender_default.py
source/blender/editors/uvedit/uvedit_ops.c

index 7f7fa44..a773498 100644 (file)
@@ -783,7 +783,7 @@ def km_uv_editor(params):
         *_template_items_uv_select_mode(params),
         ("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
         ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value},
-         {"properties": [("extend", False)]}),
+         {"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
         ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True},
          {"properties": [("extend", True)]}),
         ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True},
index d2d8543..e699043 100644 (file)
@@ -2457,8 +2457,13 @@ static bool uv_sticky_select(
   return false;
 }
 
-static int uv_mouse_select_multi(
-    bContext *C, Object **objects, uint objects_len, const float co[2], bool extend, bool loop)
+static int uv_mouse_select_multi(bContext *C,
+                                 Object **objects,
+                                 uint objects_len,
+                                 const float co[2],
+                                 const bool extend,
+                                 const bool deselect_all,
+                                 const bool loop)
 {
   Depsgraph *depsgraph = CTX_data_depsgraph(C);
   SpaceImage *sima = CTX_wm_space_image(C);
@@ -2472,6 +2477,7 @@ static int uv_mouse_select_multi(
   UvNearestHit hit = UV_NEAREST_HIT_INIT;
   int i, selectmode, sticky, sync, *hitv = NULL;
   bool select = true;
+  bool found_item = false;
   /* 0 == don't flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
   int flush = 0;
   int hitlen = 0;
@@ -2516,79 +2522,86 @@ static int uv_mouse_select_multi(
   /* find nearest element */
   if (loop) {
     /* find edge */
-    if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
-
-    hitlen = 0;
+    found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
   }
   else if (selectmode == UV_SELECT_VERTEX) {
     /* find vertex */
-    if (!uv_find_nearest_vert_multi(scene, ima, objects, objects_len, co, penalty_dist, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
+    found_item = uv_find_nearest_vert_multi(
+        scene, ima, objects, objects_len, co, penalty_dist, &hit);
+    found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
 
-    /* mark 1 vertex as being hit */
-    hitv = BLI_array_alloca(hitv, hit.efa->len);
-    hituv = BLI_array_alloca(hituv, hit.efa->len);
-    copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+    if (found_item) {
+      /* mark 1 vertex as being hit */
+      hitv = BLI_array_alloca(hitv, hit.efa->len);
+      hituv = BLI_array_alloca(hituv, hit.efa->len);
+      copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
 
-    hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
-    hituv[hit.lindex] = hit.luv->uv;
+      hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
+      hituv[hit.lindex] = hit.luv->uv;
 
-    hitlen = hit.efa->len;
+      hitlen = hit.efa->len;
+    }
   }
   else if (selectmode == UV_SELECT_EDGE) {
     /* find edge */
-    if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
+    found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+    found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
 
-    /* mark 2 edge vertices as being hit */
-    hitv = BLI_array_alloca(hitv, hit.efa->len);
-    hituv = BLI_array_alloca(hituv, hit.efa->len);
-    copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
+    if (found_item) {
+      /* mark 2 edge vertices as being hit */
+      hitv = BLI_array_alloca(hitv, hit.efa->len);
+      hituv = BLI_array_alloca(hituv, hit.efa->len);
+      copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
 
-    hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
-    hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
-    hituv[hit.lindex] = hit.luv->uv;
-    hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
+      hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
+      hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
+      hituv[hit.lindex] = hit.luv->uv;
+      hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
 
-    hitlen = hit.efa->len;
+      hitlen = hit.efa->len;
+    }
   }
   else if (selectmode == UV_SELECT_FACE) {
     /* find face */
-    if (!uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
+    found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit);
+    found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
 
-    BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
-    const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+    if (found_item) {
+      BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
+      const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 
-    /* make active */
-    BM_mesh_active_face_set(em->bm, hit.efa);
+      /* make active */
+      BM_mesh_active_face_set(em->bm, hit.efa);
 
-    /* mark all face vertices as being hit */
+      /* mark all face vertices as being hit */
 
-    hitv = BLI_array_alloca(hitv, hit.efa->len);
-    hituv = BLI_array_alloca(hituv, hit.efa->len);
-    BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) {
-      luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-      hituv[i] = luv->uv;
-      hitv[i] = BM_elem_index_get(l->v);
-    }
+      hitv = BLI_array_alloca(hitv, hit.efa->len);
+      hituv = BLI_array_alloca(hituv, hit.efa->len);
+      BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) {
+        luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+        hituv[i] = luv->uv;
+        hitv[i] = BM_elem_index_get(l->v);
+      }
 
-    hitlen = hit.efa->len;
+      hitlen = hit.efa->len;
+    }
   }
   else if (selectmode == UV_SELECT_ISLAND) {
-    if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
-
-    hitlen = 0;
+    found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit);
+    found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
   }
-  else {
-    hitlen = 0;
+
+  if (!found_item) {
+    if (deselect_all) {
+      uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
+
+      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+        Object *obedit = objects[ob_index];
+        uv_select_tag_update_for_object(depsgraph, ts, obedit);
+      }
+
+      return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
+    }
     return OPERATOR_CANCELLED;
   }
 
@@ -2742,13 +2755,14 @@ static int uv_mouse_select_multi(
 
   return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
 }
-static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loop)
+static int uv_mouse_select(
+    bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop)
 {
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
       view_layer, ((View3D *)NULL), &objects_len);
-  int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, loop);
+  int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop);
   MEM_freeN(objects);
   return ret;
 }
@@ -2756,13 +2770,13 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
 static int uv_select_exec(bContext *C, wmOperator *op)
 {
   float co[2];
-  bool extend, loop;
 
   RNA_float_get_array(op->ptr, "location", co);
-  extend = RNA_boolean_get(op->ptr, "extend");
-  loop = false;
+  const bool extend = RNA_boolean_get(op->ptr, "extend");
+  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+  const bool loop = false;
 
-  return uv_mouse_select(C, co, extend, loop);
+  return uv_mouse_select(C, co, extend, deselect_all, loop);
 }
 
 static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2790,11 +2804,19 @@ static void UV_OT_select(wmOperatorType *ot)
   ot->poll = ED_operator_uvedit; /* requires space image */
 
   /* properties */
+  PropertyRNA *prop;
   RNA_def_boolean(ot->srna,
                   "extend",
                   0,
                   "Extend",
                   "Extend selection rather than clearing the existing selection");
+  prop = RNA_def_boolean(ot->srna,
+                         "deselect_all",
+                         false,
+                         "Deselect On Nothing",
+                         "Deselect all when nothing under the cursor");
+  RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
   RNA_def_float_vector(
       ot->srna,
       "location",
@@ -2817,13 +2839,13 @@ static void UV_OT_select(wmOperatorType *ot)
 static int uv_select_loop_exec(bContext *C, wmOperator *op)
 {
   float co[2];
-  bool extend, loop;
 
   RNA_float_get_array(op->ptr, "location", co);
-  extend = RNA_boolean_get(op->ptr, "extend");
-  loop = true;
+  const bool extend = RNA_boolean_get(op->ptr, "extend");
+  const bool deselect_all = false;
+  const bool loop = true;
 
-  return uv_mouse_select(C, co, extend, loop);
+  return uv_mouse_select(C, co, extend, deselect_all, loop);
 }
 
 static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)