Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 18 Dec 2018 19:33:04 +0000 (20:33 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 18 Dec 2018 19:33:04 +0000 (20:33 +0100)
Conflicts:
source/blender/editors/transform/transform_conversions.c

1  2 
source/blender/editors/transform/transform_conversions.c

@@@ -2635,254 -2477,251 +2640,261 @@@ static void VertsToTransData(TransInfo 
  
  static void createTransEditVerts(TransInfo *t)
  {
 -      TransData *tob = NULL;
 -      TransDataExtension *tx = NULL;
 -      BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
 -      Mesh *me = t->obedit->data;
 -      BMesh *bm = em->bm;
 -      BMVert *eve;
 -      BMIter iter;
 -      float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
 -      float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
 -      float *dists = NULL;
 -      int a;
 -      const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
 -      int mirror = 0;
 -      int cd_vert_bweight_offset = -1;
 -      bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
 -
 -      struct TransIslandData *island_info = NULL;
 -      int island_info_tot;
 -      int *island_vert_map = NULL;
 -
 -      /* Snap rotation along normal needs a common axis for whole islands, otherwise one get random crazy results,
 -       * see T59104. However, we do not want to use the island center for the pivot/translation reference... */
 -      const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
 -                                   /* There is not guarantee that snapping is initialized yet at this point... */
 -                                   (usingSnappingNormal(t) || (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
 -                                   (t->around != V3D_AROUND_LOCAL_ORIGINS));
 -      /* Even for translation this is needed because of island-orientation, see: T51651. */
 -      const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
 -      /* Original index of our connected vertex when connected distances are calculated.
 -       * Optional, allocate if needed. */
 -      int *dists_index = NULL;
 -
 -      if (t->flag & T_MIRROR) {
 -              EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
 -              mirror = 1;
 -      }
 -
 -      /**
 -       * Quick check if we can transform.
 -       *
 -       * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
 -       * \note in prop mode we need at least 1 selected.
 -       */
 -      if (bm->totvertsel == 0) {
 -              goto cleanup;
 -      }
 -
 -      if (t->mode == TFM_BWEIGHT) {
 -              BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_VERT_BWEIGHT);
 -              cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
 -      }
 +      FOREACH_TRANS_DATA_CONTAINER (t, tc) {
 +              TransData *tob = NULL;
 +              TransDataExtension *tx = NULL;
 +              BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
 +              Mesh *me = tc->obedit->data;
 +              BMesh *bm = em->bm;
 +              BMVert *eve;
 +              BMIter iter;
 +              float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
 +              float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
 +              float *dists = NULL;
 +              int a;
 +              const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
 +              int mirror = 0;
 +              int cd_vert_bweight_offset = -1;
 +              bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
 +
 +              struct TransIslandData *island_info = NULL;
 +              int island_info_tot;
 +              int *island_vert_map = NULL;
 +
++              /* Snap rotation along normal needs a common axis for whole islands, otherwise one get random crazy results,
++               * see T59104. However, we do not want to use the island center for the pivot/translation reference... */
++              const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
++                                           /* There is not guarantee that snapping is initialized yet at this point... */
++                                           (usingSnappingNormal(t) || (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
++                                           (t->around != V3D_AROUND_LOCAL_ORIGINS));
 +              /* Even for translation this is needed because of island-orientation, see: T51651. */
-               const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
++              const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
 +              /* Original index of our connected vertex when connected distances are calculated.
 +               * Optional, allocate if needed. */
 +              int *dists_index = NULL;
  
 -      if (prop_mode) {
 -              unsigned int count = 0;
 -              BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
 -                      if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
 -                              count++;
 +              if (t->flag & T_MIRROR) {
 +                      /* TODO(campbell): xform: We need support for many mirror objects at once! */
 +                      if (tc->is_active) {
 +                              EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
 +                              mirror = 1;
                        }
                }
  
 -              t->total = count;
 +              /**
 +               * Quick check if we can transform.
 +               *
 +               * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
 +               * \note in prop mode we need at least 1 selected.
 +               */
 +              if (bm->totvertsel == 0) {
 +                      goto cleanup;
 +              }
  
 -              /* allocating scratch arrays */
 -              if (prop_mode & T_PROP_CONNECTED) {
 -                      dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
 -                      if (is_island_center) {
 -                              dists_index =  MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
 -                      }
 +              if (t->mode == TFM_BWEIGHT) {
 +                      BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
 +                      cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
                }
 -      }
 -      else {
 -              t->total = bm->totvertsel;
 -      }
  
 -      tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)");
 -      if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
 -              /* warning, this is overkill, we only need 2 extra floats,
 -               * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
 -               * since we may not use the 'alt' transform mode to maintain shell thickness,
 -               * but with generic transform code its hard to lazy init vars */
 -              tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension),
 -                                        "TransObData ext");
 -      }
 +              if (prop_mode) {
 +                      unsigned int count = 0;
 +                      BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
 +                              if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
 +                                      count++;
 +                              }
 +                      }
  
 -      copy_m3_m4(mtx, t->obedit->obmat);
 -      /* we use a pseudoinverse so that when one of the axes is scaled to 0,
 -       * matrix inversion still works and we can still moving along the other */
 -      pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
 +                      tc->data_len = count;
  
 -      if (prop_mode & T_PROP_CONNECTED) {
 -              editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
 -      }
 +                      /* allocating scratch arrays */
 +                      if (prop_mode & T_PROP_CONNECTED) {
 +                              dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
 +                              if (is_island_center) {
 +                                      dists_index =  MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
 +                              }
 +                      }
 +              }
 +              else {
 +                      tc->data_len = bm->totvertsel;
 +              }
  
 -      if (is_island_center) {
 -              /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
 -              const bool calc_single_islands = (
 -                      (prop_mode & T_PROP_CONNECTED) &&
 -                      (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
 -                      (em->selectmode & SCE_SELECT_VERTEX));
 +              tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
 +              if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
 +                      /* warning, this is overkill, we only need 2 extra floats,
 +                       * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
 +                       * since we may not use the 'alt' transform mode to maintain shell thickness,
 +                       * but with generic transform code its hard to lazy init vars */
 +                      tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObData ext");
 +              }
  
 -              island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
 -      }
 +              copy_m3_m4(mtx, tc->obedit->obmat);
 +              /* we use a pseudoinverse so that when one of the axes is scaled to 0,
 +               * matrix inversion still works and we can still moving along the other */
 +              pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
  
 -      /* detect CrazySpace [tm] */
 -      if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) != -1) {
 -              int totleft = -1;
 -              if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
 -                      /* check if we can use deform matrices for modifier from the
 -                       * start up to stack, they are more accurate than quats */
 -                      totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(t->scene, t->obedit, em, &defmats, &defcos);
 +              if (prop_mode & T_PROP_CONNECTED) {
 +                      editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
                }
  
 -              /* if we still have more modifiers, also do crazyspace
 -               * correction with quats, relative to the coordinates after
 -               * the modifiers that support deform matrices (defcos) */
 +              if (is_island_center) {
 +                      /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
 +                      const bool calc_single_islands = (
 +                              (prop_mode & T_PROP_CONNECTED) &&
 +                              (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
 +                              (em->selectmode & SCE_SELECT_VERTEX));
 +
 +                      island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
 +              }
 +
 +              /* detect CrazySpace [tm] */
 +              if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
 +                      int totleft = -1;
 +                      if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
 +                              /* Use evaluated state because we need b-bone cache. */
 +                              Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
 +                              Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
 +                              BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
 +                              /* check if we can use deform matrices for modifier from the
 +                               * start up to stack, they are more accurate than quats */
 +                              totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
 +                                      t->depsgraph, scene_eval, obedit_eval, em_eval,
 +                                      &defmats, &defcos);
 +                      }
 +
 +                      /* if we still have more modifiers, also do crazyspace
 +                       * correction with quats, relative to the coordinates after
 +                       * the modifiers that support deform matrices (defcos) */
  
  #if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
 -              if ((totleft > 0) || (totleft == -1))
 +                      if ((totleft > 0) || (totleft == -1))
  #else
 -              if (totleft > 0)
 +                      if (totleft > 0)
  #endif
 -              {
 -                      mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
 -                      quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
 -                      BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
 -                      if (mappedcos)
 -                              MEM_freeN(mappedcos);
 -              }
 +                      {
 +                              mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, t->scene, tc->obedit);
 +                              quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
 +                              BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
 +                              if (mappedcos)
 +                                      MEM_freeN(mappedcos);
 +                      }
  
 -              if (defcos) {
 -                      MEM_freeN(defcos);
 +                      if (defcos) {
 +                              MEM_freeN(defcos);
 +                      }
                }
 -      }
  
 -      /* find out which half we do */
 -      if (mirror) {
 -              BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
 -                      if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
 -                              if (eve->co[0] < 0.0f) {
 -                                      t->mirror = -1;
 -                                      mirror = -1;
 +              /* find out which half we do */
 +              if (mirror) {
 +                      BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
 +                              if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
 +                                      if (eve->co[0] < 0.0f) {
 +                                              t->mirror = -1;
 +                                              mirror = -1;
 +                                      }
 +                                      break;
                                }
 -                              break;
                        }
                }
 -      }
  
 -      BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
 -              if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
 -                      if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
 -                              struct TransIslandData *v_island = NULL;
 -                              float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
 -
 -                              if (island_info) {
 -                                      const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
 -                                      v_island = (island_vert_map[connected_index] != -1) ?
 -                                                 &island_info[island_vert_map[connected_index]] : NULL;
 -                              }
 +              BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
 +                      if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
 +                              if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
 +                                      struct TransIslandData *v_island = NULL;
 +                                      float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
 +
 +                                      if (island_info) {
 +                                              const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
 +                                              v_island = (island_vert_map[connected_index] != -1) ?
 +                                                         &island_info[island_vert_map[connected_index]] : NULL;
 +                                      }
  
  
-                                       VertsToTransData(t, tob, tx, em, eve, bweight, v_island);
 -                              /* Do not use the island center in case we are using islands
 -                               * only to get axis for snap/rotate to normal... */
 -                              VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
 -                              if (tx)
 -                                      tx++;
++                                      /* Do not use the island center in case we are using islands
++                                       * only to get axis for snap/rotate to normal... */
++                                      VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
 +                                      if (tx)
 +                                              tx++;
  
 -                              /* selected */
 -                              if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
 -                                      tob->flag |= TD_SELECTED;
 +                                      /* selected */
 +                                      if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
 +                                              tob->flag |= TD_SELECTED;
  
 -                              if (prop_mode) {
 -                                      if (prop_mode & T_PROP_CONNECTED) {
 -                                              tob->dist = dists[a];
 -                                      }
 -                                      else {
 -                                              tob->flag |= TD_NOTCONNECTED;
 -                                              tob->dist = FLT_MAX;
 +                                      if (prop_mode) {
 +                                              if (prop_mode & T_PROP_CONNECTED) {
 +                                                      tob->dist = dists[a];
 +                                              }
 +                                              else {
 +                                                      tob->flag |= TD_NOTCONNECTED;
 +                                                      tob->dist = FLT_MAX;
 +                                              }
                                        }
 -                              }
  
 -                              /* CrazySpace */
 -                              if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
 -                                      float mat[3][3], qmat[3][3], imat[3][3];
 +                                      /* CrazySpace */
 +                                      if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
 +                                              float mat[3][3], qmat[3][3], imat[3][3];
  
 -                                      /* use both or either quat and defmat correction */
 -                                      if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
 -                                              quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
 +                                              /* use both or either quat and defmat correction */
 +                                              if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
 +                                                      quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
  
 -                                              if (defmats)
 -                                                      mul_m3_series(mat, defmats[a], qmat, mtx);
 +                                                      if (defmats)
 +                                                              mul_m3_series(mat, defmats[a], qmat, mtx);
 +                                                      else
 +                                                              mul_m3_m3m3(mat, mtx, qmat);
 +                                              }
                                                else
 -                                                      mul_m3_m3m3(mat, mtx, qmat);
 -                                      }
 -                                      else
 -                                              mul_m3_m3m3(mat, mtx, defmats[a]);
 +                                                      mul_m3_m3m3(mat, mtx, defmats[a]);
  
 -                                      invert_m3_m3(imat, mat);
 +                                              invert_m3_m3(imat, mat);
  
 -                                      copy_m3_m3(tob->smtx, imat);
 -                                      copy_m3_m3(tob->mtx, mat);
 -                              }
 -                              else {
 -                                      copy_m3_m3(tob->smtx, smtx);
 -                                      copy_m3_m3(tob->mtx, mtx);
 -                              }
 +                                              copy_m3_m3(tob->smtx, imat);
 +                                              copy_m3_m3(tob->mtx, mat);
 +                                      }
 +                                      else {
 +                                              copy_m3_m3(tob->smtx, smtx);
 +                                              copy_m3_m3(tob->mtx, mtx);
 +                                      }
  
 -                              /* Mirror? */
 -                              if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
 -                                      BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
 -                                      if (vmir && vmir != eve) {
 -                                              tob->extra = vmir;
 +                                      /* Mirror? */
 +                                      if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
 +                                              BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
 +                                              if (vmir && vmir != eve) {
 +                                                      tob->extra = vmir;
 +                                              }
                                        }
 +                                      tob++;
                                }
 -                              tob++;
                        }
                }
 -      }
  
 -      if (island_info) {
 -              MEM_freeN(island_info);
 -              MEM_freeN(island_vert_map);
 -      }
 +              if (island_info) {
 +                      MEM_freeN(island_info);
 +                      MEM_freeN(island_vert_map);
 +              }
  
 -      if (mirror != 0) {
 -              tob = t->data;
 -              for (a = 0; a < t->total; a++, tob++) {
 -                      if (ABS(tob->loc[0]) <= 0.00001f) {
 -                              tob->flag |= TD_MIRROR_EDGE;
 +              if (mirror != 0) {
 +                      tob = tc->data;
 +                      for (a = 0; a < tc->data_len; a++, tob++) {
 +                              if (ABS(tob->loc[0]) <= 0.00001f) {
 +                                      tob->flag |= TD_MIRROR_EDGE;
 +                              }
                        }
                }
 -      }
  
  cleanup:
 -      /* crazy space free */
 -      if (quats)
 -              MEM_freeN(quats);
 -      if (defmats)
 -              MEM_freeN(defmats);
 -      if (dists)
 -              MEM_freeN(dists);
 -      if (dists_index)
 -              MEM_freeN(dists_index);
 -
 -      if (t->flag & T_MIRROR) {
 -              EDBM_verts_mirror_cache_end(em);
 +              /* crazy space free */
 +              if (quats)
 +                      MEM_freeN(quats);
 +              if (defmats)
 +                      MEM_freeN(defmats);
 +              if (dists)
 +                      MEM_freeN(dists);
 +              if (dists_index)
 +                      MEM_freeN(dists_index);
 +
 +              if (t->flag & T_MIRROR) {
 +                      EDBM_verts_mirror_cache_end(em);
 +              }
        }
  }