Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Wed, 2 May 2018 12:37:32 +0000 (14:37 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 2 May 2018 12:37:32 +0000 (14:37 +0200)
1  2 
source/blender/editors/uvedit/uvedit_ops.c

index 6fa75b0a2b3db97fd6f343a9074b80a4c15c69d8,9c6f468532f1032e476b30bb29af1e9e41b09600..97075eba61e08cd8fb3190f42de4ce5a65d82c84
@@@ -1111,52 -1211,57 +1111,52 @@@ static int uv_select_edgeloop
  /** \name Select Linked
   * \{ */
  
 -static void uv_select_linked(
 -        Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], UvNearestHit *hit_final,
 -        bool extend, bool deselect, bool toggle, bool select_faces)
 +static void uv_select_linked_multi(
 +        Scene *scene, Image *ima, Object **objects, const uint objects_len, const float limit[2],
-         UvNearestHit *hit_final, bool extend, bool select_faces)
++        UvNearestHit *hit_final, bool extend, bool deselect, bool toggle, bool select_faces)
  {
 -      BMFace *efa;
 -      BMLoop *l;
 -      BMIter iter, liter;
 -      MLoopUV *luv;
 -      UvVertMap *vmap;
 -      UvMapVert *vlist, *iterv, *startv;
 -      int i, stacksize = 0, *stack;
 -      unsigned int a;
 -      char *flag;
 -
 -      const int cd_loop_uv_offset  = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 -      const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
 +      /* loop over objects, or just use hit_final->ob */
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              if (hit_final && ob_index != 0) {
 +                      break;
 +              }
 +              Object *obedit = hit_final ? hit_final->ob : objects[ob_index];
  
 -      BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
 +              BMFace *efa;
 +              BMLoop *l;
 +              BMIter iter, liter;
 +              MLoopUV *luv;
 +              UvVertMap *vmap;
 +              UvMapVert *vlist, *iterv, *startv;
 +              int i, stacksize = 0, *stack;
 +              unsigned int a;
 +              char *flag;
  
 -      /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
 -       * this made *every* projection split the island into front/back islands.
 -       * Keep 'use_winding' to false, see: T50970.
 -       *
 -       * Better solve this by having a delimit option for select-linked operator,
 -       * keeping island-select working as is. */
 -      vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
 +              BMEditMesh *em = BKE_editmesh_from_object(obedit);
 +              const int cd_loop_uv_offset  = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
  
 -      if (vmap == NULL)
 -              return;
 +              BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
  
 -      stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
 -      flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
 +              /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320
 +               * this made *every* projection split the island into front/back islands.
 +               * Keep 'use_winding' to false, see: T50970.
 +               *
 +               * Better solve this by having a delimit option for select-linked operator,
 +               * keeping island-select working as is. */
 +              vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false);
  
 -      if (hit_final == NULL) {
 -              /* Use existing selection */
 -              BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 -                      MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
 +              if (vmap == NULL)
 +                      return;
  
 -                      if (uvedit_face_visible_test(scene, ima, efa, tf)) {
 -                              if (select_faces) {
 -                                      if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
 -                                              stack[stacksize] = a;
 -                                              stacksize++;
 -                                              flag[a] = 1;
 -                                      }
 -                              }
 -                              else {
 -                                      BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
 -                                              luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 +              stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack");
 +              flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag");
  
 -                                              if (luv->flag & MLOOPUV_VERTSEL) {
 +              if (hit_final == NULL) {
 +                      /* Use existing selection */
 +                      BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 +                              if (uvedit_face_visible_test(scene, obedit, ima, efa)) {
 +                                      if (select_faces) {
 +                                              if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
                                                        stack[stacksize] = a;
                                                        stacksize++;
                                                        flag[a] = 1;
                                }
                        }
                }
 -      }
 -      else {
 -              BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 -                      if (efa == hit_final->efa) {
 -                              stack[stacksize] = a;
 -                              stacksize++;
 -                              flag[a] = 1;
 -                              break;
 +              else {
 +                      BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 +                              if (efa == hit_final->efa) {
 +                                      stack[stacksize] = a;
 +                                      stacksize++;
 +                                      flag[a] = 1;
 +                                      break;
 +                              }
                        }
                }
 -      }
  
 -      while (stacksize > 0) {
 +              while (stacksize > 0) {
  
 -              stacksize--;
 -              a = stack[stacksize];
 +                      stacksize--;
 +                      a = stack[stacksize];
  
 -              efa = BM_face_at_index(em->bm, a);
 +                      efa = BM_face_at_index(em->bm, a);
  
 -              BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
 +                      BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
  
 -                      /* make_uv_vert_map_EM sets verts tmp.l to the indices */
 -                      vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
 -                      
 -                      startv = vlist;
 +                              /* make_uv_vert_map_EM sets verts tmp.l to the indices */
 +                              vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
  
 -                      for (iterv = vlist; iterv; iterv = iterv->next) {
 -                              if (iterv->separate)
 -                                      startv = iterv;
 -                              if (iterv->f == a)
 -                                      break;
 -                      }
 +                              startv = vlist;
  
 -                      for (iterv = startv; iterv; iterv = iterv->next) {
 -                              if ((startv != iterv) && (iterv->separate))
 -                                      break;
 -                              else if (!flag[iterv->f]) {
 -                                      flag[iterv->f] = 1;
 -                                      stack[stacksize] = iterv->f;
 -                                      stacksize++;
 +                              for (iterv = vlist; iterv; iterv = iterv->next) {
 +                                      if (iterv->separate)
 +                                              startv = iterv;
 +                                      if (iterv->f == a)
 +                                              break;
                                }
 -                      }
 -              }
 -      }
  
 -      /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */
 -      if ((toggle == true) && (extend == false) && (deselect == false)) {
 -              BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 -                      bool found_selected = false;
 -                      if (!flag[a]) {
 -                              continue;
 +                              for (iterv = startv; iterv; iterv = iterv->next) {
 +                                      if ((startv != iterv) && (iterv->separate))
 +                                              break;
 +                                      else if (!flag[iterv->f]) {
 +                                              flag[iterv->f] = 1;
 +                                              stack[stacksize] = iterv->f;
 +                                              stacksize++;
 +                                      }
 +                              }
                        }
 +              }
  
-               if (!extend) {
-                       BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
-                               if (select_faces) {
-                                       if (flag[a])
-                                               BM_face_select_set(em->bm, efa, true);
-                                       else
-                                               BM_face_select_set(em->bm, efa, false);
-                               }
-                               else {
-                                       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-                                               luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                               if (flag[a])
-                                                       luv->flag |= MLOOPUV_VERTSEL;
-                                               else
-                                                       luv->flag &= ~MLOOPUV_VERTSEL;
-                                       }
-                               }
-                       }
-               }
-               else {
 -                      if (select_faces) {
 -                              if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
 -                                      found_selected = true;
++              /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */
++              if ((toggle == true) && (extend == false) && (deselect == false)) {
 +                      BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
++                              bool found_selected = false;
 +                              if (!flag[a]) {
 +                                      continue;
                                }
 -                      }
 -                      else {
 -                              BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
 -                                      luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
  
 -                                      if (luv->flag & MLOOPUV_VERTSEL) {
 +                              if (select_faces) {
-                                       if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
-                                               break;
++                                      if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+                                               found_selected = true;
+                                       }
                                }
 +                              else {
 +                                      BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
 +                                              luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
  
 -                              if (found_selected) {
 -                                      deselect = true;
 -                                      break;
 +                                              if (luv->flag & MLOOPUV_VERTSEL) {
-                                                       break;
++                                                      found_selected = true;
 +                                              }
 +                                      }
 +
-                                       if (l) {
++                                      if (found_selected) {
++                                              deselect = true;
 +                                              break;
 +                                      }
                                }
                        }
 -      }
+               }
  
-                       if (efa) {
-                               BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
-                                       if (!flag[a]) {
-                                               continue;
-                                       }
-                                       if (select_faces) {
-                                               BM_face_select_set(em->bm, efa, false);
-                                       }
-                                       else {
-                                               BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-                                                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                                                       luv->flag &= ~MLOOPUV_VERTSEL;
-                                               }
-                                       }
+ #define SET_SELECTION(value) \
 -      if (select_faces) { \
 -              BM_face_select_set(em->bm, efa, value); \
 -      } \
 -      else { \
 -              BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \
 -                      luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \
 -                      luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \
++              if (select_faces) { \
++                      BM_face_select_set(em->bm, efa, value); \
+               } \
 -      } (void)0
++              else { \
++                      BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \
++                              luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \
++                              luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \
++                      } \
++              } (void)0
 -      BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
 -              if (!flag[a]) {
 -                      if (!extend && !deselect && !toggle) {
 -                              SET_SELECTION(false);
++              BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
++                      if (!flag[a]) {
++                              if (!extend && !deselect && !toggle) {
++                                      SET_SELECTION(false);
 +                              }
++                              continue;
                        }
-                       else {
-                               BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
-                                       if (!flag[a]) {
-                                               continue;
-                                       }
-                                       if (select_faces) {
-                                               BM_face_select_set(em->bm, efa, true);
-                                       }
-                                       else {
-                                               BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-                                                       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
 -                      continue;
 -              }
  
-                                                       luv->flag |= MLOOPUV_VERTSEL;
-                                               }
-                                       }
-                               }
 -              if (!deselect) {
 -                      SET_SELECTION(true);
 -              }
 -              else {
 -                      SET_SELECTION(false);
++                      if (!deselect) {
++                              SET_SELECTION(true);
++                      }
++                      else {
++                              SET_SELECTION(false);
 +                      }
                }
 -      }
  
 -      MEM_freeN(stack);
 -      MEM_freeN(flag);
 -      BM_uv_vert_map_free(vmap);
+ #undef SET_SELECTION
 +              MEM_freeN(stack);
 +              MEM_freeN(flag);
 +              BM_uv_vert_map_free(vmap);
 +      }
  }
  
  /* WATCH IT: this returns first selected UV,
@@@ -2239,24 -2287,13 +2215,25 @@@ static int uv_mouse_select_multi
                return OPERATOR_CANCELLED;
        }
  
 +      Object *obedit = hit.ob;
 +      BMEditMesh *em = BKE_editmesh_from_object(obedit);
 +      const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
 +
        /* do selection */
        if (loop) {
 -              flush = uv_select_edgeloop(scene, ima, em, &hit, limit, extend);
 +              if (!extend) {
 +                      /* TODO(MULTI_EDIT): We only need to de-select non-active */
 +                      uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
 +              }
 +              flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend);
        }
        else if (selectmode == UV_SELECT_ISLAND) {
-               uv_select_linked_multi(scene, ima, objects, objects_len, limit, &hit, extend, false);
 +              if (!extend) {
 +                      /* TODO(MULTI_EDIT): We only need to de-select non-active */
 +                      uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
 +              }
 -              uv_select_linked(scene, ima, em, limit, &hit, false, false, extend, false);
+               /* Current behavior of 'extend' is actually toggling, so pass extend flag as 'toggle' here */
++              uv_select_linked_multi(scene, ima, objects, objects_len, limit, &hit, false, false, extend, false);
        }
        else if (extend) {
                if (selectmode == UV_SELECT_VERTEX) {
@@@ -2487,10 -2517,11 +2464,10 @@@ static int uv_select_linked_internal(bC
        SpaceImage *sima = CTX_wm_space_image(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *ts = scene->toolsettings;
 -      Object *obedit = CTX_data_edit_object(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        Image *ima = CTX_data_edit_image(C);
 -      BMEditMesh *em = BKE_editmesh_from_object(obedit);
        float limit[2];
-       int extend;
+       int extend, deselect;
        bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
  
        UvNearestHit hit = UV_NEAREST_HIT_INIT;
        }
  
        extend = RNA_boolean_get(op->ptr, "extend");
+       deselect = RNA_boolean_get(op->ptr, "deselect");
        uvedit_pixel_to_float(sima, limit, 0.05f);
  
 +      uint objects_len = 0;
 +      Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, &objects_len);
 +
        if (pick) {
                float co[2];
  
                }
        }
  
 -      uv_select_linked(scene, ima, em, limit, pick ? &hit : NULL, extend, deselect, false, select_faces);
 +      if (!extend) {
 +              uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
 +      }
  
-       uv_select_linked_multi(scene, ima, objects, objects_len, limit, pick ? &hit : NULL, extend, select_faces);
 -      DAG_id_tag_update(obedit->data, 0);
 -      WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
++      uv_select_linked_multi(
++              scene, ima, objects, objects_len, limit, pick ? &hit : NULL,
++              extend, deselect, false, select_faces);
 +
 +      /* weak!, but works */
 +      Object **objects_free = objects;
 +      if (pick) {
 +              objects = &hit.ob;
 +              objects_len = 1;
 +      }
 +
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              Object *obedit = objects[ob_index];
 +              DEG_id_tag_update(obedit->data, 0);
 +              WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
 +      }
 +
 +      MEM_SAFE_FREE(objects_free);
  
        return OPERATOR_FINISHED;
  }