svn merge -r38971:38972 https://svn.blender.org/svnroot/bf-blender/trunk/blender...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 5 Aug 2011 08:16:09 +0000 (08:16 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 5 Aug 2011 08:16:09 +0000 (08:16 +0000)
1  2 
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_generics.c

index a6cde37913aa62e5f011f3083ce8291fd1c0a5d8,39e26bc6436dfcce9fe6d3e877a1c9353ad15c34..6e9b78011a6dea6507024150f75c21786b3dd620
@@@ -4361,318 -4320,406 +4361,324 @@@ static int createSlideVerts(TransInfo *
                }
        }
  
 -      // Get # of selected verts
 -      for(ev=em->verts.first;ev;ev=ev->next) {
 -              if(ev->f & SELECT) vertsel++;
 +      j = 0;
 +      BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BM_TestHFlag(v, BM_SELECT)) {
 +                      BM_SetIndex(v, 1);
 +                      BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_POINTER(j));
 +                      j += 1;
 +              } else BM_SetIndex(v, 0);
        }
  
 -      // Test for multiple segments
 -      if(vertsel > numsel+1) {
 -              //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
 -              MEM_freeN(sld);
 +      if (!j)
                return 0;
 -      }
  
 -      // Get the edgeloop in order - mark f1 with SELECT once added
 -      for(eed=em->edges.first;eed;eed=eed->next) {
 -              if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
 -                      // If this is the first edge added, just put it in
 -                      if(!edgelist) {
 -                              BLI_linklist_prepend(&edgelist,eed);
 -                              numadded++;
 -                              first = eed;
 -                              last  = eed;
 -                              eed->f1 = SELECT;
 -                      } else {
 -                              if(editedge_getSharedVert(eed, last)) {
 -                                      BLI_linklist_append(&edgelist,eed);
 -                                      eed->f1 = SELECT;
 -                                      numadded++;
 -                                      last = eed;
 -                              }  else if(editedge_getSharedVert(eed, first)) {
 -                                      BLI_linklist_prepend(&edgelist,eed);
 -                                      eed->f1 = SELECT;
 -                                      numadded++;
 -                                      first = eed;
 -                              }
 -                      }
 -              }
 -              if(eed->next == NULL && numadded != numsel) {
 -                      eed=em->edges.first;
 -                      timesthrough++;
 -              }
 +      tempsv = MEM_callocN(sizeof(TransDataSlideVert)*j, "tempsv");
 +
 +      j = 0;
 +      while (1) {
 +              v = NULL;
 +              BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                      if (BM_GetIndex(v))
 +                              break;
  
 -              // It looks like there was an unexpected case - Hopefully should not happen
 -              if(timesthrough >= numsel*2) {
 -                      BLI_linklist_free(edgelist,NULL);
 -                      //BKE_report(op->reports, RPT_ERROR, "Could not order loop");
 -                      MEM_freeN(sld);
 -                      return 0;
                }
 -      }
  
 -      // Put the verts in order in a linklist
 -      look = edgelist;
 -      while(look) {
 -              eed = look->link;
 -              if(!vertlist) {
 -                      if(look->next) {
 -                              temp = look->next->link;
 +              if (!v)
 +                      break;
  
 -                              //This is the first entry takes care of extra vert
 -                              if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
 -                                      BLI_linklist_append(&vertlist,eed->v1);
 -                                      eed->v1->f1 = 1;
 -                              } else {
 -                                      BLI_linklist_append(&vertlist,eed->v2);
 -                                      eed->v2->f1 = 1;
 -                              }
 -                      } else {
 -                              //This is the case that we only have 1 edge
 -                              BLI_linklist_append(&vertlist,eed->v1);
 -                              eed->v1->f1 = 1;
 -                      }
 -              }
 -              // for all the entries
 -              if(eed->v1->f1 != 1) {
 -                      BLI_linklist_append(&vertlist,eed->v1);
 -                      eed->v1->f1 = 1;
 -              } else  if(eed->v2->f1 != 1) {
 -                      BLI_linklist_append(&vertlist,eed->v2);
 -                      eed->v2->f1 = 1;
 -              }
 -              look = look->next;
 -      }
 -
 -      // populate the SlideVerts
 -
 -      vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts gh");
 -      look = vertlist;
 -      while(look) {
 -              i=0;
 -              j=0;
 -              ev = look->link;
 -              tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert");
 -              tempsv->up = NULL;
 -              tempsv->down = NULL;
 -              tempsv->origvert.co[0] = ev->co[0];
 -              tempsv->origvert.co[1] = ev->co[1];
 -              tempsv->origvert.co[2] = ev->co[2];
 -              tempsv->origvert.no[0] = ev->no[0];
 -              tempsv->origvert.no[1] = ev->no[1];
 -              tempsv->origvert.no[2] = ev->no[2];
 -              // i is total edges that vert is on
 -              // j is total selected edges that vert is on
 -
 -              for(eed=em->edges.first;eed;eed=eed->next) {
 -                      if(eed->v1 == ev || eed->v2 == ev) {
 -                              i++;
 -                              if(eed->f & SELECT) {
 -                                       j++;
 -                              }
 -                      }
 -              }
 -              // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
 -              if(i == 4 && j == 2) {
 -                      for(eed=em->edges.first;eed;eed=eed->next) {
 -                              if(editedge_containsVert(eed, ev)) {
 -                                      if(!(eed->f & SELECT)) {
 -                                              if(!tempsv->up) {
 -                                                      tempsv->up = eed;
 -                                              } else if (!(tempsv->down)) {
 -                                                      tempsv->down = eed;
 -                                              }
 -                                      }
 -                              }
 -                      }
 -              }
 -              // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
 -              if(i >= 3 && j == 1) {
 -                      for(eed=em->edges.first;eed;eed=eed->next) {
 -                              if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
 -                                      for(efa = em->faces.first;efa;efa=efa->next) {
 -                                              if(editface_containsEdge(efa, eed)) {
 -                                                      if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e1;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e1;
 -                                                              }
 -                                                      }
 -                                                      if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e2;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e2;
 -                                                              }
 -                                                      }
 -                                                      if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e3;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e3;
 -                                                              }
 -                                                      }
 -                                                      if(efa->e4) {
 -                                                              if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
 -                                                                      if(!tempsv->up) {
 -                                                                              tempsv->up = efa->e4;
 -                                                                      } else if (!(tempsv->down)) {
 -                                                                              tempsv->down = efa->e4;
 -                                                                      }
 -                                                              }
 -                                                      }
 +              if (!v->e)
 +                      continue;
 +              
 +              first = v;
  
 -                                              }
 -                                      }
 -                              }
 +              /*walk along the edge loop*/
 +              e = v->e;
 +
 +              /*first, rewind*/
 +              numsel = 0;
 +              do {
 +                      e = get_other_edge(bm, v, e);
 +                      if (!e) {
 +                              e = v->e;
 +                              break;
                        }
 -              }
 -              if(i > 4 && j == 2) {
 -                      BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
 -                      BLI_linklist_free(vertlist,NULL);
 -                      BLI_linklist_free(edgelist,NULL);
 -                      return 0;
 -              }
 -              BLI_ghash_insert(vertgh,ev,tempsv);
  
 -              look = look->next;
 -      }
 +                      numsel += 1;
  
 -      // make sure the UPs and DOWNs are 'faceloops'
 -      // Also find the nearest slidevert to the cursor
 +                      if (!BM_GetIndex(BM_OtherEdgeVert(e, v)))
 +                              break;
  
 -      look = vertlist;
 -      nearest = NULL;
 -      vertdist = -1;
 -      while(look) {
 -              tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
 +                      v = BM_OtherEdgeVert(e, v);
 +              } while (e != first->e);
  
 -              if(!tempsv->up || !tempsv->down) {
 -                      //BKE_report(op->reports, RPT_ERROR, "Missing rails");
 -                      BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
 -                      BLI_linklist_free(vertlist,NULL);
 -                      BLI_linklist_free(edgelist,NULL);
 -                      return 0;
 -              }
 +              BM_SetIndex(v, 0);
  
 -              if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
 -                      if(!(tempsv->up->f & SELECT)) {
 -                              tempsv->up->f |= SELECT;
 -                              tempsv->up->f2 |= 16;
 -                      } else {
 -                              tempsv->up->f2 |= ~16;
 -                      }
 -                      if(!(tempsv->down->f & SELECT)) {
 -                              tempsv->down->f |= SELECT;
 -                              tempsv->down->f2 |= 16;
 -                      } else {
 -                              tempsv->down->f2 |= ~16;
 -                      }
 -              }
 +              l1 = l2 = l = NULL;
 +              l1 = e->l;
 +              l2 = e->l->radial_next;
  
 -              if(look->next != NULL) {
 -                      TransDataSlideVert *sv;
 -                      
 -                      ev = (EditVert*)look->next->link;
 -                      sv = BLI_ghash_lookup(vertgh, ev);
 +              l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +              sub_v3_v3v3(vec, BM_OtherEdgeVert(l->e, v)->co, v->co);
  
 -                      if(sv) {
 -                              float co[3], co2[3], tvec[3];
 +              if (l2 != l1) {
 +                      l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                      sub_v3_v3v3(vec2, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +              } else {
 +                      l2 = NULL;
 +              }
  
 -                              ev = (EditVert*)look->link;
 +              /*iterate over the loop*/
 +              first = v;
 +              j = 0;
 +              do {
 +                      TransDataSlideVert *sv = tempsv + j;
  
 -                              if(!sharesFace(em, tempsv->up,sv->up)) {
 -                                      EditEdge *swap;
 -                                      swap = sv->up;
 -                                      sv->up = sv->down;
 -                                      sv->down = swap;
 -                              }
 -                              
 -                              if (v3d) {
 -                                      ED_view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat);
 -                                      ED_view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat);
 -                              }
 +                      sv->v = v;
 +                      sv->origvert = *v;
 +                      VECCOPY(sv->upvec, vec);
 +                      if (l2)
 +                              VECCOPY(sv->downvec, vec2);
  
 -                              if (ev == tempsv->up->v1) {
 -                                      sub_v3_v3v3(tvec, co, co2);
 -                              } else {
 -                                      sub_v3_v3v3(tvec, co2, co);
 -                              }
 +                      l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +                      sv->up = BM_OtherEdgeVert(l->e, v);
  
 -                              add_v3_v3(start, tvec);
 +                      if (l2) {
 +                              l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                              sv->down = BM_OtherEdgeVert(l->e, v);
 +                      }
  
 -                              if (v3d) {
 -                                      ED_view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat);
 -                                      ED_view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat);
 -                              }
 +                      v2=v, v = BM_OtherEdgeVert(e, v);
  
 -                              if (ev == tempsv->down->v1) {
 -                                      sub_v3_v3v3(tvec, co2, co);
 -                              } else {
 -                                      sub_v3_v3v3(tvec, co, co2);
 -                              }
 +                      e1 = e;
 +                      e = get_other_edge(bm, v, e);
 +                      if (!e) {
 +                              //v2=v, v = BM_OtherEdgeVert(l1->e, v);
  
 -                              add_v3_v3(end, tvec);
 +                              sv = tempsv + j + 1;
 +                              sv->v = v;
 +                              sv->origvert = *v;
 +                              
 +                              l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +                              sv->up = BM_OtherEdgeVert(l->e, v);
 +                              sub_v3_v3v3(sv->upvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +
 +                              if (l2) {
 +                                      l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                                      sv->down = BM_OtherEdgeVert(l->e, v);
 +                                      sub_v3_v3v3(sv->downvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +                              }
  
 -                              totvec += 1.0f;
 -                              nearest = (EditVert*)look->link;
 +                              BM_SetIndex(v, 0);
 +                              BM_SetIndex(v2, 0);
 +                              
 +                              j += 2;
 +                              break;
                        }
 -              }
  
 +                      l1 = get_next_loop(bm, v, l1, e1, e, vec);
 +                      l2 = l2 ? get_next_loop(bm, v, l2, e1, e, vec2) : NULL;
  
 +                      j += 1;
  
 -              look = look->next;
 +                      BM_SetIndex(v, 0);
 +                      BM_SetIndex(v2, 0);
 +              } while (e != first->e && l1);
        }
  
 -      add_v3_v3(start, end);
 -      mul_v3_fl(start, 0.5f*(1.0f/totvec));
 -      VECCOPY(vec, start);
 -      start[0] = t->mval[0];
 -      start[1] = t->mval[1];
 -      add_v3_v3v3(end, start, vec);
 +      //EDBM_clear_flag_all(em, BM_SELECT);
  
 +      sld->sv = tempsv;
 +      sld->totsv = j;
 +      
 +      /*find mouse vector*/
 +      dis = z = -1.0f;
 +      size = 50.0;
 +      zero_v3(lastvec); zero_v3(dir);
 +      ee = le = NULL;
 +      BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
 +              if (BM_TestHFlag(e, BM_SELECT)) {
 +                      BMIter iter2;
 +                      BMEdge *e2;
 +                      float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d;
 +                                              
 +                      /*search cross edges for visible edge to the mouse cursor,
 +              then use the shared vertex to calculate screen vector*/
 +                      dis2 = -1.0f;
 +                      for (i=0; i<2; i++) {
 +                              v = i?e->v1:e->v2;
 +                              BM_ITER(e2, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
 +                                      if (BM_TestHFlag(e2, BM_SELECT))
 +                                              continue;
 +                                      
 +                                      if (!BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit))
 +                                              continue;
 +                                      
 +                                      j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
 +
 +                                      if (tempsv[j].down) {
 +                                              ED_view3d_project_float_v3(ar, tempsv[j].down->co, vec1, projectMat);
 +                                      } else {
 +                                              add_v3_v3v3(vec1, v->co, tempsv[j].downvec);
 +                                              ED_view3d_project_float_v3(ar, vec1, vec1, projectMat);
 +                                      }
 +                                      
 +                                      if (tempsv[j].up) {
 +                                              ED_view3d_project_float_v3(ar, tempsv[j].up->co, vec2, projectMat);
 +                                      } else {
 +                                              add_v3_v3v3(vec1, v->co, tempsv[j].upvec);
 +                                              ED_view3d_project_float_v3(ar, vec2, vec2, projectMat);
 +                                      }
  
 -      /* Ensure minimum screen distance, when looking top down on edge loops */
 -#define EDGE_SLIDE_MIN 30
 -      if (len_squared_v2v2(start, end) < (EDGE_SLIDE_MIN * EDGE_SLIDE_MIN)) {
 -              if(ABS(start[0]-end[0]) + ABS(start[1]-end[1]) < 4.0f) {
 -                      /* even more exceptional case, points are ontop of each other */
 -                      end[0]= start[0];
 -                      end[1]= start[1] + EDGE_SLIDE_MIN;
 -              }
 -              else {
 -                      sub_v2_v2(end, start);
 -                      normalize_v2(end);
 -                      mul_v2_fl(end, EDGE_SLIDE_MIN);
 -                      add_v2_v2(end, start);
 +                                      d = dist_to_line_segment_v2(mval, vec1, vec2);
 +                                      if (dis2 == -1.0f || d < dis2) {
 +                                              dis2 = d;
 +                                              ee = e2;
 +                                              size = len_v3v3(vec1, vec2);
 +                                              sub_v3_v3v3(dir, vec1, vec2);
 +                                      }
 +                              }
 +                      }
                }
        }
 -#undef EDGE_SLIDE_MIN
 +      
 +      em->bm->ob = t->obedit;
 +      bmesh_begin_edit(em->bm, BMOP_UNTAN_MULTIRES);
  
 +      /*create copies of faces for customdata projection*/
 +      tempsv = sld->sv;
 +      for (i=0; i<sld->totsv; i++, tempsv++) {
 +              BMIter fiter, liter;
 +              BMFace *f;
 +              BMLoop *l;
 +              
 +              BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
 +                      
 +                      if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)) {
 +                              BMFace *copyf = BM_Copy_Face(em->bm, f, 1, 1);
 +                              
 +                              BM_Select(em->bm, copyf, 0);
 +                              BM_SetHFlag(copyf, BM_HIDDEN);
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, copyf) {
 +                                      BM_Select(em->bm, l->v, 0);
 +                                      BM_SetHFlag(l->v, BM_HIDDEN);
 +                                      BM_Select(em->bm, l->e, 0);
 +                                      BM_SetHFlag(l->e, BM_HIDDEN);
 +                              }
  
 -      sld->start[0] = (int) start[0];
 -      sld->start[1] = (int) start[1];
 -      sld->end[0] = (int) end[0];
 -      sld->end[1] = (int) end[1];
 +                              BLI_smallhash_insert(&sld->origfaces, (uintptr_t)f, copyf);
 +                      }
 +              }
 +
 +              BLI_smallhash_insert(&sld->vhash, (uintptr_t)tempsv->v, tempsv);
 +      }
 +      
 +      sld->em = em;
 +      
 +      /*zero out start*/
 +      zero_v3(start);
        
 -      if (uvlay_tot) {
 -              int maxnum = 0;
 +      /*dir holds a vector along edge loop*/
 +      copy_v3_v3(end, dir);
 +      mul_v3_fl(end, 0.5);
 +      
 +      sld->start[0] = t->mval[0] + start[0];
 +      sld->start[1] = t->mval[1] + start[1];
  
 -              uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
 -              sld->totuv = uvlay_tot;
 -              suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */
 -              suv = NULL;
 +      sld->end[0] = t->mval[0] + end[0];
 +      sld->end[1] = t->mval[1] + end[1];
 +      
 +      sld->perc = 0.0f;
 +      
 +      t->customData = sld;
 +      
 +      BLI_smallhash_release(&table);
 +      BMBVH_FreeBVH(btree);
 +      
 +      return 1;
 +}
  
 -              for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
 +void projectSVData(TransInfo *t, int final)
 +{
 +      SlideData *sld = t->customData;
 +      TransDataSlideVert *tempsv;
 +      BMEditMesh *em = sld->em;
 +      SmallHash visit;
 +      int i;
 +      
 +      if (!em)
 +              return;
 +      
++      /* BMESH_TODO, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)
++       * currently all vertex data is interpolated which is nice mostly
++       * except for shape keys where you dont want to modify UVs for eg.
++       * current BMesh code doesnt make it easy to pick which data we interpolate
++       * - campbell */
 -                      uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts2 gh");
 +      BLI_smallhash_init(&visit);
 +      
 +              for (i=0, tempsv=sld->sv; i<sld->totsv; i++, tempsv++) {
 +              BMIter fiter;
 +              BMFace *f;
 +              
 +              BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
 +                      BMIter liter2;
 +                      BMFace *copyf, *copyf2;
 +                      BMLoop *l2;
 +                      int sel, do_vdata;
 +                      
 +                      if (BLI_smallhash_haskey(&visit, (uintptr_t)f))
 +                              continue;
 +                      
 +                      BLI_smallhash_insert(&visit, (uintptr_t)f, NULL);
 +                      
 +                      /*the face attributes of the copied face will get
 +                        copied over, so its necessary to save the selection state*/
 +                      sel = BM_TestHFlag(f, BM_SELECT);
 +                      
 +                      copyf2 = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)f);
 +                      
 +                      /*project onto copied projection face*/
 +                      BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_FACE, f) {
 +                              copyf = copyf2;
 +                              do_vdata = l2->v==tempsv->v;
 +                              
 +                              if (BM_TestHFlag(l2->e, BM_SELECT) || BM_TestHFlag(l2->prev->e, BM_SELECT)) {
 +                                      BMLoop *l3 = l2;
 +                                      
 +                                      do_vdata = 1;
 +                                      
 +                                      if (!BM_TestHFlag(l2->e, BM_SELECT))
 +                                              l3 = l3->prev;
 +                                      
 +                                      if (sld->perc < 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->down)) {
 +                                              copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
 +                                      } else if (sld->perc > 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->up)) {
 +                                              copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
 +                                      }
 +                              }
 +                              
 +                              BM_loop_interp_from_face(em->bm, l2, copyf, do_vdata, 0);
  
 -                      for(ev=em->verts.first;ev;ev=ev->next) {
 -                              ev->tmp.l = 0;
 -                      }
 -                      look = vertlist;
 -                      while(look) {
 -                              float *uv_new;
 -                              tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
 -
 -                              ev = look->link;
 -                              suv = NULL;
 -                              for(efa = em->faces.first;efa;efa=efa->next) {
 -                                      if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
 -                                              int k=-1; /* face corner */
 -
 -                                              /* Is this vert in the faces corner? */
 -                                              if              (efa->v1==ev)                           k=0;
 -                                              else if (efa->v2==ev)                           k=1;
 -                                              else if (efa->v3==ev)                           k=2;
 -                                              else if (efa->v4 && efa->v4==ev)        k=3;
 -
 -                                              if (k != -1) {
 -                                                      MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
 -                                                      EditVert *ev_up, *ev_down;
 -
 -                                                      uv_new = tf->uv[k];
 -
 -                                                      if (ev->tmp.l) {
 -                                                              if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001f || fabs(suv->origuv[1]-uv_new[1]) > 0.0001f) {
 -                                                                      ev->tmp.l = -1; /* Tag as invalid */
 -                                                                      BLI_linklist_free(suv->fuv_list,NULL);
 -                                                                      suv->fuv_list = NULL;
 -                                                                      BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
 -                                                                      suv = NULL;
 -                                                                      break;
 -                                                              }
 -                                                      } else {
 -                                                              ev->tmp.l = 1;
 -                                                              suv = suv_last;
 -
 -                                                              suv->fuv_list = NULL;
 -                                                              suv->uv_up = suv->uv_down = NULL;
 -                                                              suv->origuv[0] = uv_new[0];
 -                                                              suv->origuv[1] = uv_new[1];
 -
 -                                                              BLI_linklist_prepend(&suv->fuv_list, uv_new);
 -                                                              BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
 -
 -                                                              suv_last++; /* advance to next slide UV */
 -                                                              maxnum++;
 -                                                      }
 -
 -                                                      /* Now get the uvs along the up or down edge if we can */
 -                                                      if (suv) {
 -                                                              if (!suv->uv_up) {
 -                                                                      ev_up = editedge_getOtherVert(tempsv->up,ev);
 -                                                                      if              (efa->v1==ev_up)                                suv->uv_up = tf->uv[0];
 -                                                                      else if (efa->v2==ev_up)                                suv->uv_up = tf->uv[1];
 -                                                                      else if (efa->v3==ev_up)                                suv->uv_up = tf->uv[2];
 -                                                                      else if (efa->v4 && efa->v4==ev_up)             suv->uv_up = tf->uv[3];
 -                                                              }
 -                                                              if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
 -                                                                      ev_down = editedge_getOtherVert(tempsv->down,ev);
 -                                                                      if              (efa->v1==ev_down)                              suv->uv_down = tf->uv[0];
 -                                                                      else if (efa->v2==ev_down)                              suv->uv_down = tf->uv[1];
 -                                                                      else if (efa->v3==ev_down)                              suv->uv_down = tf->uv[2];
 -                                                                      else if (efa->v4 && efa->v4==ev_down)   suv->uv_down = tf->uv[3];
 -                                                              }
 -
 -                                                              /* Copy the pointers to the face UV's */
 -                                                              BLI_linklist_prepend(&suv->fuv_list, uv_new);
 -                                                      }
 -                                              }
 +                              if (final) {
 +                                      BM_loop_interp_multires(em->bm, l2, copyf);     
 +                                      if (copyf2 != copyf) {
 +                                              BM_loop_interp_multires(em->bm, l2, copyf2);
                                        }
                                }
 -                              look = look->next;
                        }
 -              } /* end uv layer loop */
 -      } /* end uvlay_tot */
 -
 -      sld->uvhash = uvarray;
 -      sld->slideuv = slideuvs;
 -      sld->vhash = vertgh;
 -      sld->nearest = nearest;
 -      sld->vertlist = vertlist;
 -      sld->edgelist = edgelist;
 -      sld->suv_last = suv_last;
 -      sld->uvlay_tot = uvlay_tot;
 -
 -      // we should have enough info now to slide
 -
 -      t->customData = sld;
 -
 -      return 1;
 +                      
 +                      /*make sure face-attributes are correct (e.g. MTexPoly)*/
 +                      BM_Copy_Attributes(em->bm, em->bm, copyf2, f);
 +                      
 +                      /*restore selection, and undo hidden flag*/
 +                      BM_ClearHFlag(f, BM_HIDDEN);
 +                      if (sel)
 +                              BM_Select(em->bm, f, sel);
 +              }
 +      }
 +      
 +      BLI_smallhash_release(&visit);
  }
  
  void freeSlideVerts(TransInfo *t)