svn merge ^/trunk/blender -r40432:40491
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Sep 2011 13:04:01 +0000 (13:04 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Sep 2011 13:04:01 +0000 (13:04 +0000)
26 files changed:
1  2 
release/scripts/startup/bl_ui/space_info.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/multires.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/operators/extrudeops.c
source/blender/editors/armature/editarmature.c
source/blender/editors/curve/editcurve.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/uvedit/uvedit_ops.c
source/blender/modifiers/intern/MOD_solidify.c
source/blender/modifiers/intern/MOD_warp.c
source/blender/modifiers/intern/MOD_weightvgedit.c
source/blender/modifiers/intern/MOD_weightvgmix.c
source/blender/modifiers/intern/MOD_weightvgproximity.c

index 31467c893eb1427c6655b206549ba66cd89c50a5,0000000000000000000000000000000000000000..805935a310007e42b4bd47b5c71020d2aa9e991c
mode 100644,000000..100644
--- /dev/null
@@@ -1,510 -1,0 +1,510 @@@
-               angle_poly_v3(angles, verts, f->len);
 +#include "MEM_guardedalloc.h"
 +
 +#include "BLI_utildefines.h"
 +
 +#include "BLI_ghash.h"
 +#include "BLI_memarena.h"
 +#include "BLI_blenlib.h"
 +#include "BLI_math.h"
 +#include "BLI_array.h"
 +
 +#include "bmesh.h"
 +#include "bmesh_private.h"
 +#include "bmesh_operators_private.h"
 +
 +#include <math.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#define EXT_INPUT 1
 +#define EXT_KEEP  2
 +#define EXT_DEL   4
 +
 +#define VERT_NONMAN 1
 +#define EDGE_NONMAN 1
 +#define FACE_MARK 1
 +
 +void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
 +{
 +      BMOIter siter;
 +      BMIter liter, liter2;
 +      BMFace *f, *f2, *f3;
 +      BMLoop *l, *l2, *l3, *l4;
 +      BMEdge **edges = NULL, *e, *laste;
 +      BMVert *v, *lastv, *firstv;
 +      BLI_array_declare(edges);
 +      int i;
 +
 +      BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
 +              BLI_array_empty(edges);
 +              i = 0;
 +              firstv = lastv = NULL;
 +              BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
 +                      BLI_array_growone(edges);
 +
 +                      v = BM_Make_Vert(bm, l->v->co, l->v);
 +
 +                      if (lastv) {
 +                              e = BM_Make_Edge(bm, lastv, v, l->e, 0);
 +                              edges[i++] = e;
 +                      }
 +
 +                      lastv = v;
 +                      laste = l->e;
 +                      if (!firstv) firstv = v;
 +              }
 +
 +              BLI_array_growone(edges);
 +              e = BM_Make_Edge(bm, v, firstv, laste, 0);
 +              edges[i++] = e;
 +
 +              BMO_SetFlag(bm, f, EXT_DEL);
 +
 +              f2 = BM_Make_Ngon(bm, firstv, BM_OtherEdgeVert(edges[0], firstv), edges, f->len, 0);
 +              if (!f2) {
 +                      BMO_RaiseError(bm, op, BMERR_MESH_ERROR, "Extrude failed; could not create face");
 +                      BLI_array_free(edges);
 +                      return;
 +              }
 +              
 +              BMO_SetFlag(bm, f2, EXT_KEEP);
 +              BM_Copy_Attributes(bm, bm, f, f2);
 +
 +              l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
 +              BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
 +                      BM_Copy_Attributes(bm, bm, l, l2);
 +
 +                      l3 = l->next;
 +                      l4 = l2->next;
 +
 +                      f3 = BM_Make_QuadTri(bm, l3->v, l4->v, l2->v, l->v, f, 0);
 +                      
 +                      BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3));
 +                      BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3)->next);
 +                      BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next);
 +                      BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next->next);
 +
 +                      l2 = BMIter_Step(&liter2);
 +              }
 +      }
 +
 +      BLI_array_free(edges);
 +
 +      BMO_CallOpf(bm, "del geom=%ff context=%d", EXT_DEL, DEL_ONLYFACES);
 +      BMO_Flag_To_Slot(bm, op, "faceout", EXT_KEEP, BM_FACE);
 +}
 +
 +void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op)
 +{
 +      BMOIter siter;
 +      BMOperator dupeop;
 +      BMVert *v1, *v2, *v3, *v4;
 +      BMEdge *e, *e2;
 +      BMFace *f;
 +      
 +      BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
 +              BMO_SetFlag(bm, e, EXT_INPUT);
 +              BMO_SetFlag(bm, e->v1, EXT_INPUT);
 +              BMO_SetFlag(bm, e->v2, EXT_INPUT);
 +      }
 +
 +      BMO_InitOpf(bm, &dupeop, "dupe geom=%fve", EXT_INPUT);
 +      BMO_Exec_Op(bm, &dupeop);
 +
 +      e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
 +      for (; e; e=BMO_IterStep(&siter)) {
 +              e2 = BMO_IterMapVal(&siter);
 +              e2 = *(BMEdge**)e2;
 +
 +              if (e->l && e->v1 != e->l->v) {
 +                      v1 = e->v1;
 +                      v2 = e->v2;
 +                      v3 = e2->v2;
 +                      v4 = e2->v1;
 +              } else {
 +                      v1 = e2->v1;
 +                      v2 = e2->v2;
 +                      v3 = e->v2;
 +                      v4 = e->v1;
 +              }
 +                      /*not sure what to do about example face, pass   NULL for now.*/
 +              f = BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);               
 +              
 +              if (BMO_TestFlag(bm, e, EXT_INPUT))
 +                      e = e2;
 +              
 +              BMO_SetFlag(bm, f, EXT_KEEP);
 +              BMO_SetFlag(bm, e, EXT_KEEP);
 +              BMO_SetFlag(bm, e->v1, EXT_KEEP);
 +              BMO_SetFlag(bm, e->v2, EXT_KEEP);
 +              
 +      }
 +
 +      BMO_Finish_Op(bm, &dupeop);
 +
 +      BMO_Flag_To_Slot(bm, op, "geomout", EXT_KEEP, BM_ALL);
 +}
 +
 +void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
 +{
 +      BMOIter siter;
 +      BMVert *v, *dupev;
 +      BMEdge *e;
 +
 +      v = BMO_IterNew(&siter, bm, op, "verts", BM_VERT);
 +      for (; v; v=BMO_IterStep(&siter)) {
 +              dupev = BM_Make_Vert(bm, v->co, v);
 +
 +              e = BM_Make_Edge(bm, v, dupev, NULL, 0);
 +
 +              BMO_SetFlag(bm, e, EXT_KEEP);
 +              BMO_SetFlag(bm, dupev, EXT_KEEP);
 +      }
 +
 +      BMO_Flag_To_Slot(bm, op, "vertout", EXT_KEEP, BM_VERT);
 +      BMO_Flag_To_Slot(bm, op, "edgeout", EXT_KEEP, BM_EDGE);
 +}
 +
 +void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
 +{
 +      BMOperator dupeop, delop;
 +      BMOIter siter;
 +      BMIter iter, fiter, viter;
 +      BMEdge *e, *newedge;
 +      BMLoop *l, *l2;
 +      BMVert *verts[4], *v, *v2;
 +      BMFace *f;
 +      int rlen, found, fwd, delorig=0;
 +
 +      /*initialize our sub-operators*/
 +      BMO_Init_Op(&dupeop, "dupe");
 +      
 +      BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
 +      
 +      /*if one flagged face is bordered by an unflagged face, then we delete
 +        original geometry unless caller explicitly asked to keep it. */
 +      if (!BMO_Get_Int(op, "alwayskeeporig")) {
 +              BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
 +                      if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
 +
 +                      found = 0;
 +                      f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
 +                      for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
 +                              if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
 +                                      found = 1;
 +                                      delorig = 1;
 +                                      break;
 +                              }
 +                      }
 +              
 +                      if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
 +              }
 +      }
 +
 +      /*calculate verts to delete*/
 +      BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +              found = 0;
 +
 +              BM_ITER(e, &viter, bm, BM_EDGES_OF_VERT, v) {
 +                      if (!BMO_TestFlag(bm, e, EXT_INPUT) || !BMO_TestFlag(bm, e, EXT_DEL)){
 +                              found = 1;
 +                              break;
 +                      }
 +              }
 +              
 +              BM_ITER(f, &viter, bm, BM_FACES_OF_VERT, v) {
 +                      if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
 +                              found = 1;
 +                              break;
 +                      }
 +              }
 +
 +              if (!found) {
 +                      BMO_SetFlag(bm, v, EXT_DEL);
 +              }
 +      }
 +      
 +      BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
 +              if (BMO_TestFlag(bm, f, EXT_INPUT))
 +                      BMO_SetFlag(bm, f, EXT_DEL);
 +      }
 +
 +      if (delorig) {
 +              BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d", 
 +                          EXT_DEL, DEL_ONLYTAGGED);
 +      }
 +
 +      BMO_CopySlot(op, &dupeop, "edgefacein", "geom");
 +      BMO_Exec_Op(bm, &dupeop);
 +
 +      if (bm->act_face && BMO_TestFlag(bm, bm->act_face, EXT_INPUT))
 +              bm->act_face = BMO_Get_MapPointer(bm, &dupeop, "facemap", bm->act_face);
 +
 +      if (delorig) BMO_Exec_Op(bm, &delop);
 +      
 +      /*if not delorig, reverse loops of original faces*/
 +      if (!delorig) {
 +              for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) {
 +                      if (BMO_TestFlag(bm, f, EXT_INPUT)) {
 +                              BM_flip_normal(bm, f);
 +                      }
 +              }
 +      }
 +      
 +      BMO_CopySlot(&dupeop, op, "newout", "geomout");
 +      e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
 +      for (; e; e=BMO_IterStep(&siter)) {
 +              if (BMO_InMap(bm, op, "exclude", e)) continue;
 +
 +              newedge = BMO_IterMapVal(&siter);
 +              newedge = *(BMEdge**)newedge;
 +              if (!newedge) continue;
 +
 +              /* orient loop to give same normal as a loop of newedge
 +              if it exists (will be an extruded face),
 +              else same normal as a loop of e, if it exists */
 +              if (!newedge->l)
 +                      fwd = !e->l || !(e->l->v == e->v1);
 +              else
 +                      fwd = (newedge->l->v == newedge->v1);
 +
 +              
 +              if (fwd) {
 +                      verts[0] = e->v1;
 +                      verts[1] = e->v2;
 +                      verts[2] = newedge->v2;
 +                      verts[3] = newedge->v1;
 +              } else {
 +                      verts[3] = e->v1;
 +                      verts[2] = e->v2;
 +                      verts[1] = newedge->v2;
 +                      verts[0] = newedge->v1;
 +              }
 +
 +              /*not sure what to do about example face, pass NULL for now.*/
 +              f = BM_Make_Quadtriangle(bm, verts, NULL, 4, NULL, 0);          
 +
 +              /*copy attributes*/
 +              l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
 +              for (; l; l=BMIter_Step(&iter)) {
 +                      if (l->e != e && l->e != newedge) continue;
 +                      l2 = l->radial_next;
 +                      
 +                      if (l2 == l) {
 +                              l2 = newedge->l;
 +                              BM_Copy_Attributes(bm, bm, l2->f, l->f);
 +
 +                              BM_Copy_Attributes(bm, bm, l2, l);
 +                              l2 = l2->next;
 +                              l = l->next;
 +                              BM_Copy_Attributes(bm, bm, l2, l);
 +                      } else {
 +                              BM_Copy_Attributes(bm, bm, l2->f, l->f);
 +
 +                              /*copy data*/
 +                              if (l2->v == l->v) {
 +                                      BM_Copy_Attributes(bm, bm, l2, l);
 +                                      l2 = l2->next;
 +                                      l = l->next;
 +                                      BM_Copy_Attributes(bm, bm, l2, l);
 +                              } else {
 +                                      l2 = l2->next;
 +                                      BM_Copy_Attributes(bm, bm, l2, l);
 +                                      l2 = l2->prev;
 +                                      l = l->next;
 +                                      BM_Copy_Attributes(bm, bm, l2, l);
 +                              }
 +                      }
 +              }
 +      }
 +
 +      /*link isolated verts*/
 +      v = BMO_IterNew(&siter, bm, &dupeop, "isovertmap", 0);
 +      for (; v; v=BMO_IterStep(&siter)) {
 +              v2 = *((void**)BMO_IterMapVal(&siter));
 +              BM_Make_Edge(bm, v, v2, v->e, 1);
 +      }
 +
 +      /*cleanup*/
 +      if (delorig) BMO_Finish_Op(bm, &delop);
 +      BMO_Finish_Op(bm, &dupeop);
 +}
 +
 +/*
 + *  Compute higher-quality vertex normals used by solidify.
 + *  Note that this will not work for non-manifold regions.
 + *
 + */
 +static void calc_solidify_normals(BMesh *bm)
 +{
 +      BMIter viter, eiter, fiter;
 +      BMVert *v;
 +      BMEdge *e;
 +      BMLoop *l;
 +      BMFace *f, *f1, *f2;
 +      float edge_normal[3];
 +
 +      BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, NULL) {
 +              /* Mark the non-manifold edges and the vertices they connect */
 +              if (BM_Nonmanifold_Edge(bm, e)) {
 +                      BMO_SetFlag(bm, e, EDGE_NONMAN);
 +                      BMO_SetFlag(bm, e->v1, VERT_NONMAN);
 +                      BMO_SetFlag(bm, e->v2, VERT_NONMAN);
 +              }
 +      }
 +
 +      BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
 +              BM_SetIndex(v, 0);
 +              zero_v3(v->no);
 +      }
 +
 +      BM_ITER(e, &eiter, bm, BM_EDGES_OF_MESH, NULL) {
 +              float angle;
 +
 +              if (BMO_TestFlag(bm, e, EDGE_NONMAN)) {
 +                      continue;
 +              }
 +
 +              l = e->l;
 +              f1 = l->f;
 +              f2 = bmesh_radial_nextloop(l)->f;
 +
 +              angle = angle_normalized_v3v3(f1->no, f2->no);
 +
 +              if (f1 != f2) {
 +                      if (angle > 0.0f) {
 +                              /* two faces using this edge, calculate the edges normal
 +                               * using the angle between the faces as a weighting */
 +                              add_v3_v3v3(edge_normal, f1->no, f2->no);
 +                              normalize_v3(edge_normal);
 +                              mul_v3_fl(edge_normal, angle);
 +                      }
 +                      else {
 +                              /* can't do anything useful here!
 +                                 Set the face index for a vert incase it gets a zero normal */
 +                              BM_SetIndex(e->v1, -1);
 +                              BM_SetIndex(e->v2, -1);
 +                              continue;
 +                      }
 +              }
 +              else {
 +                      /* only one face attached to that edge */
 +                      /* an edge without another attached- the weight on this is
 +                       * undefined, M_PI/2 is 90d in radians and that seems good enough */
 +                      copy_v3_v3(edge_normal, f1->no);
 +                      mul_v3_fl(edge_normal, M_PI/2);
 +              }
 +
 +              add_v3_v3(e->v1->no, edge_normal);
 +              add_v3_v3(e->v2->no, edge_normal);
 +      }
 +
 +      /* normalize accumulated vertex normals*/
 +      BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BMO_TestFlag(bm, v, VERT_NONMAN)) {
 +                      /* use standard normals for vertices connected to non-manifold
 +                         edges */
 +                      BM_Vert_UpdateNormal(bm, v);
 +              }
 +              else if (normalize_v3(v->no) == 0.0f && BM_GetIndex(v) < 0) {
 +                      /* exceptional case, totally flat. use the normal
 +                         of any face around the vertex */
 +                      f = BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
 +                      if (f) {
 +                              copy_v3_v3(v->no, f->no);
 +                      }
 +              }       
 +      }
 +}
 +
 +static void solidify_add_thickness(BMesh *bm, float dist)
 +{
 +      BMFace *f;
 +      BMVert *v;
 +      BMLoop *l;
 +      BMIter iter, loopIter;
 +      float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */
 +      float *vert_accum = vert_angles + bm->totvert;
 +      float angle;
 +      int i, index;
 +      float maxdist = dist * sqrtf(3.0f);
 +
 +      /* array for passing verts to angle_poly_v3 */
 +      float **verts = NULL;
 +      BLI_array_staticdeclare(verts, 16);
 +      /* array for receiving angles from angle_poly_v3 */
 +      float *angles = NULL;
 +      BLI_array_staticdeclare(angles, 16);
 +
 +      i = 0;
 +      BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +              BM_SetIndex(v, i++);
 +      }
 +
 +      BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
 +              if(!BMO_TestFlag(bm, f, FACE_MARK)) {
 +                      continue;
 +              }
 +
 +              BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
 +                      BLI_array_append(verts, l->v->co);
 +                      BLI_array_growone(angles);
 +              }
 +
++              angle_poly_v3(angles, (const float **)verts, f->len);
 +
 +              i = 0;
 +              BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
 +                      v = l->v;
 +                      index = BM_GetIndex(v);
 +                      angle = angles[i];
 +                      vert_accum[index] += angle;
 +                      vert_angles[index] += shell_angle_to_dist(angle_normalized_v3v3(v->no, f->no)) * angle;
 +                      i++;
 +              }
 +
 +              BLI_array_empty(verts);
 +              BLI_array_empty(angles);
 +      }
 +
 +      BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +              index = BM_GetIndex(v);
 +              if(vert_accum[index]) { /* zero if unselected */
 +                      float vdist = MIN2(maxdist, dist * vert_angles[index] / vert_accum[index]);
 +                      madd_v3_v3fl(v->co, v->no, vdist);
 +              }
 +      }
 +
 +      MEM_freeN(vert_angles);
 +}
 +
 +void bmesh_solidify_face_region_exec(BMesh *bm, BMOperator *op)
 +{
 +      BMOperator extrudeop;
 +      BMOperator reverseop;
 +      float thickness;
 +  
 +      thickness = BMO_Get_Float(op, "thickness");
 +
 +      /* Flip original faces (so the shell is extruded inward) */
 +      BMO_Init_Op(&reverseop, "reversefaces");
 +      BMO_CopySlot(op, &reverseop, "geom", "faces");
 +      BMO_Exec_Op(bm, &reverseop);
 +      BMO_Finish_Op(bm, &reverseop);
 +
 +      calc_solidify_normals(bm);
 +
 +      /* Extrude the region */
 +      BMO_InitOpf(bm, &extrudeop, "extrudefaceregion alwayskeeporig=%i", 1);
 +      BMO_CopySlot(op, &extrudeop, "geom", "edgefacein");
 +      BMO_Exec_Op(bm, &extrudeop);
 +
 +      /* Push the verts of the extruded faces inward to create thickness */
 +      BMO_Flag_Buffer(bm, &extrudeop, "geomout", FACE_MARK, BM_FACE);
 +      solidify_add_thickness(bm, thickness);
 +
 +      BMO_CopySlot(&extrudeop, op, "geomout", "geomout");
 +
 +      BMO_Finish_Op(bm, &extrudeop);
 +}
index eccaecaad2a3677c88aaa8aea5388d086b673fb9,44d85af858c2b40f40e477a025c304c37a112dda..b0a778434214a2a61ef2d66e23941ecdd960723b
@@@ -292,13 -291,13 +292,13 @@@ static char *view3d_modeselect_pup(Scen
        if(U.transopts&USER_TR_IFACE)
                title= BLF_gettext(title);
  
-       sprintf(str, title);
+       BLI_strncpy(str, title, sizeof(string));
  
        str += modeselect_addmode(str, N_("Object Mode"), OB_MODE_OBJECT, ICON_OBJECT_DATA);
 -      
 +
        if(ob==NULL || ob->data==NULL) return string;
        if(ob->id.lib) return string;
 -      
 +
        if(!((ID *)ob->data)->lib) {
                /* if active object is editable */
                if ( ((ob->type == OB_MESH)
index ed98a179d05dc4e35eff7eac4c46e3afbb481252,83f79eae4f2581bc0b1210d7ee9fe5854bb9ff52..105026093583955be7db1ce887cf74f7afe4d006
@@@ -1816,95 -1807,96 +1816,95 @@@ void flushTransParticles(TransInfo *t
  /* ********************* mesh ****************** */
  
  /* proportional distance based on connectivity  */
- #define THRESHOLD     0.0001f
+ #define THRESHOLDFACTOR (1.0f-0.0001f)
  
 -static int connectivity_edge(float mtx[][3], EditVert *v1, EditVert *v2)
 +/*I did this wrong, it should be a breadth-first search
 +  but instead it's a depth-first search, fudged
 +  to report shortest distances.  I have no idea how fast
 +  or slow this is.*/
 +static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[][3], float *dists)
  {
 -      float edge_vec[3];
 -      float edge_len;
 -      int done = 0;
 -
 -      /* note: hidden verts are not being checked for, this assumes
 -       * flushing of hidden faces & edges is working right */
 -      
 -      if (v1->f2 + v2->f2 == 4)
 -              return 0;
 +      BMVert **queue = NULL;
 +      float *dqueue = NULL;
 +      int *tots = MEM_callocN(sizeof(int)*em->bm->totvert, "tots editmesh_set_connectivity_distance");
 +      BLI_array_declare(queue);
 +      BLI_array_declare(dqueue);
 +      SmallHash svisit, *visit=&svisit;
 +      BMVert *v;
 +      BMIter viter;
 +      int i, start;
        
 -      sub_v3_v3v3(edge_vec, v1->co, v2->co);
 -      mul_m3_v3(mtx, edge_vec);
 -
 -      edge_len = len_v3(edge_vec);
 -
 -      if (v1->f2) {
 -              if (v2->f2) {
 -                      if (v2->tmp.fp + edge_len < THRESHOLDFACTOR * v1->tmp.fp) {
 -                              v1->tmp.fp = v2->tmp.fp + edge_len;
 -                              done = 1;
 -                      } else if (v1->tmp.fp + edge_len < THRESHOLDFACTOR * v2->tmp.fp) {
 -                              v2->tmp.fp = v1->tmp.fp + edge_len;
 -                              done = 1;
 -                      }
 -              }
 -              else {
 -                      v2->f2 = 1;
 -                      v2->tmp.fp = v1->tmp.fp + edge_len;
 -                      done = 1;
 -              }
 -      }
 -      else if (v2->f2) {
 -              v1->f2 = 1;
 -              v1->tmp.fp = v2->tmp.fp + edge_len;
 -              done = 1;
 +      i = 0;
 +      BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              BM_SetIndex(v, i);
 +              dists[i] = FLT_MAX;
 +              i++;
        }
 +      
 +      BLI_smallhash_init(visit);
  
 -      return done;
 -}
 -
 -static void editmesh_set_connectivity_distance(EditMesh *em, float mtx[][3])
 -{
 -      EditVert *eve;
 -      EditEdge *eed;
 -      EditFace *efa;
 -      int done= 1;
 -
 -      /* f2 flag is used for 'selection' */
 -      /* tmp.l is offset on scratch array   */
 -      for(eve= em->verts.first; eve; eve= eve->next) {
 -              if(eve->h==0) {
 -                      eve->tmp.fp = 0;
 -
 -                      if(eve->f & SELECT) {
 -                              eve->f2= 2;
 -                      }
 -                      else {
 -                              eve->f2 = 0;
 -                      }
 -              }
 +      BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BM_TestHFlag(v, BM_SELECT)==0 || BM_TestHFlag(v, BM_HIDDEN))
 +                      continue;
 +                      
 +              
 +              BLI_smallhash_insert(visit, (uintptr_t)v, NULL);
 +              BLI_array_append(queue, v);
 +              BLI_array_append(dqueue, 0.0f);
 +              dists[BM_GetIndex(v)] = 0.0f;
        }
 +      
 +      start = 0;
 +      while (start < BLI_array_count(queue)) {
 +              BMIter eiter;
 +              BMEdge *e;
 +              BMVert *v3, *v2;
 +              float d, vec[3];
 +              
 +              v2 = queue[start];
 +              d = dqueue[start];
 +              
 +              BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v2) {
 +                      float d2;
 +                      v3 = BM_OtherEdgeVert(e, v2);
 +                      
 +                      if (BM_TestHFlag(v3, BM_SELECT) || BM_TestHFlag(v3, BM_HIDDEN))
 +                              continue;
 +                      
 +                      sub_v3_v3v3(vec, v2->co, v3->co);
 +                      mul_m3_v3(mtx, vec);
 +                      
 +                      d2 = d + len_v3(vec);
 +                      
 +                      if (dists[BM_GetIndex(v3)] != FLT_MAX)
 +                              dists[BM_GetIndex(v3)] = MIN2(d2, dists[BM_GetIndex(v3)]);
 +                      else
 +                              dists[BM_GetIndex(v3)] = d2;
 +                      
 +                      tots[BM_GetIndex(v3)] = 1;
  
 -
 -      /* Floodfill routine */
 -      /*
 -      At worst this is n*n of complexity where n is number of edges
 -      Best case would be n if the list is ordered perfectly.
 -      Estimate is n log n in average (so not too bad)
 -      */
 -      while(done) {
 -              done= 0;
 -
 -              for(eed= em->edges.first; eed; eed= eed->next) {
 -                      if(eed->h==0) {
 -                              done |= connectivity_edge(mtx, eed->v1, eed->v2);
 -                      }
 +                      if (BLI_smallhash_haskey(visit, (uintptr_t)v3))
 +                              continue;
 +                      
 +                      BLI_smallhash_insert(visit, (uintptr_t)v3, NULL);
 +                      
 +                      BLI_array_append(queue, v3);
 +                      BLI_array_append(dqueue, d2);
                }
 +              
 +              start++;
 +      }
  
 -              /* do internal edges for quads */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if (efa->v4 && efa->h==0) {
 -                              done |= connectivity_edge(mtx, efa->v1, efa->v3);
 -                              done |= connectivity_edge(mtx, efa->v2, efa->v4);
 -                      }
 -              }
 +      BLI_smallhash_release(visit);
 +      
 +      for (i=0; i<em->bm->totvert; i++) {
 +              if (tots[i])
 +                      dists[i] /= (float)tots[i];
        }
 +      
 +      BLI_array_free(queue);
 +      BLI_array_free(dqueue);
 +      MEM_freeN(tots);
  }
  
  /* loop-in-a-loop I know, but we need it! (ton) */
index a56fe7aa96078026671d388c023f1a8d876d9c6c,757da28e4b598c894626345c7d26da09b17f800a..07394298666670d26d55e5fa8cb00688ef349d64
@@@ -549,7 -544,14 +552,8 @@@ static DerivedMesh *applyModifier(Modif
                const unsigned char crease_outer= smd->crease_outer * 255.0f;
                const unsigned char crease_inner= smd->crease_inner * 255.0f;
  
 -              const int edge_indices[4][4] = {
 -                              {1, 0, 0, 1},
 -                              {2, 1, 1, 2},
 -                              {3, 2, 2, 3},
 -                              {0, 3, 3, 0}};
 -
                /* add faces & edges */
+               origindex= result->getEdgeDataArray(result, CD_ORIGINDEX);
                ed= medge + (numEdges * 2);
                for(i=0; i<newEdges; i++, ed++) {
                        ed->v1= new_vert_arr[i];
                }
  
                /* faces */
 -              mf= mface + (numFaces * 2);
 -              origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
 -              for(i=0; i<newFaces; i++, mf++) {
 +              edge_origIndex = CustomData_get_layer(&result->edgeData, CD_ORIGINDEX);
 +              
 +              mp= mpoly + (numFaces * 2);
++              origindex= result->getTessFaceDataArray(result, CD_ORIGINDEX);
 +              ml = mloop + (numLoops * 2);
 +              j = 0;
 +              for(i=0; i<newFaces; i++, mp++) {
                        int eidx= new_edge_arr[i];
                        int fidx= edge_users[eidx];
 -                      int flip;
 +                      int flip, k1, k2;
 +                      MLoop *ml2;
  
                        if(fidx >= numFaces) {
                                fidx -= numFaces;
  
                        /* copy most of the face settings */
                        DM_copy_face_data(dm, result, fidx, (numFaces * 2) + i, 1);
 -
 +                      mp->loopstart = j+numLoops*2;
 +                      mp->flag = mpoly[fidx].flag;
 +                      mp->totloop = 4;
 +                      
 +                      ml2 = mloop + mpoly[fidx].loopstart;
 +                      for (k1=0; k1<mpoly[fidx].totloop; k1++, ml2++) {
 +                              if (ml2->e == eidx)
 +                                      break;
 +                      }
 +                      
 +                      if (k1 == mpoly[fidx].totloop) {
 +                              printf("eek in solidify!!!!\n");
 +                      }
 +                      
 +                      if (ed->v2 == mloop[mpoly[fidx].loopstart+k1].v) {
 +                              k2 = (k1 + mp->totloop - 1)%mp->totloop;
 +                              SWAP(int, k1, k2);
 +                      } else if (ed->v1 == mloop[mpoly[fidx].loopstart+k1].v) {
 +                              k2 = (k1+1)%mp->totloop;
 +                      } else {
 +                              printf("eek in solidify!!!\n");
 +                              k2 = k1;
 +                      }
 +                      
 +                      k1 += mpoly[fidx].loopstart;
 +                      k2 += mpoly[fidx].loopstart;
 +                      
                        if(flip) {
 -                              DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
 -
 -                              mf->v1= ed->v1;
 -                              mf->v2= ed->v2;
 -                              mf->v3= ed->v2 + numVerts;
 -                              mf->v4= ed->v1 + numVerts;
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+1, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+2, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+3, 1);
 +                              
 +                              ml[j].v = ed->v1;
 +                              ml[j++].e = eidx;
 +                              
 +                              ml[j].v = ed->v2;
 +                              ml[j++].e = numEdges*2 + old_vert_arr[ed->v2];
 +                              
 +                              ml[j].v = ed->v2+numVerts;
 +                              ml[j++].e = eidx+numEdges;
 +                              
 +                              ml[j].v = ed->v1+numVerts;
 +                              ml[j++].e = numEdges*2 + old_vert_arr[ed->v1];
                        }
                        else {
 -                              DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
 -
 -                              mf->v1= ed->v2;
 -                              mf->v2= ed->v1;
 -                              mf->v3= ed->v1 + numVerts;
 -                              mf->v4= ed->v2 + numVerts;
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+1, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+2, 1);
 +                              CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+3, 1);
 +
 +                              ml[j].v = ed->v1+numVerts;
 +                              ml[j++].e = eidx+numEdges;
 +
 +                              ml[j].v = ed->v2+numVerts;
 +                              ml[j++].e = numEdges*2 + old_vert_arr[ed->v2];
 +                              
 +                              ml[j].v = ed->v2;
 +                              ml[j++].e = eidx;
 +                              
 +                              ml[j].v = ed->v1;
 +                              ml[j++].e = numEdges*2 + old_vert_arr[ed->v1];
                        }
                        
 -                      /* use the next material index if option enabled */
 -                      if(mat_ofs_rim) {
 -                              mf->mat_nr += mat_ofs_rim;
 -                              CLAMP(mf->mat_nr, 0, mat_nr_max);
 +                      if (edge_origIndex) {
 +                              edge_origIndex[ml[j-3].e] = ORIGINDEX_NONE;
 +                              edge_origIndex[ml[j-1].e] = ORIGINDEX_NONE;
                        }
-                       
                        if(crease_outer) {
                                /* crease += crease_outer; without wrapping */
 -                              unsigned char *cr= (unsigned char *)&(ed->crease);
 +                              unsigned char *cr= (unsigned char *)&(medge[eidx].crease);
                                int tcr= *cr + crease_outer;
                                *cr= tcr > 255 ? 255 : tcr;
                        }