Added custom face data support in edit mode. The code used to do this is
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 11 Nov 2006 16:38:37 +0000 (16:38 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 11 Nov 2006 16:38:37 +0000 (16:38 +0000)
the CustomData module from the modifier stack rewrite, but with additions
to make it also usable in edit mode. Some of the datatypes from that
module were move to a DNA header file, they are not saved to file now, but
will be soon.

The only code that wasn't abstracted is the uv collapse / merging code. It
is rather complicated, will look into that in the future.

There should be no user level changes.

14 files changed:
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_customdata.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/BLI_editVert.h
source/blender/include/BIF_editmesh.h
source/blender/include/BIF_verse.h
source/blender/makesdna/DNA_customdata_types.h [new file with mode: 0644]
source/blender/src/editmesh.c
source/blender/src/editmesh_lib.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c

index d09cb458ba4ddca14da284b0bcfa4fea4a40b10e..4506f5740fb714ffe9a7accd22709aed3da5fe6f 100644 (file)
@@ -45,7 +45,7 @@
  *    conversion to DLM.
  */
 
-#include "BKE_customdata.h"
+#include "DNA_customdata_types.h"
 
 struct MVert;
 struct MEdge;
index 6f8d9911d89fa2530d77a299274f3fa0e99eeafc..9733c26ade2e4957d6bd82c9c64374fc34abae3e 100644 (file)
 * ***** END GPL LICENSE BLOCK *****
 */ 
 
-/* CustomData interface.
- * CustomData is a structure which stores custom element data associated
- * with mesh elements (vertices, edges or faces). The custom data is
- * organised into a series of layers, each with a data type (e.g. TFace,
- * MDeformVert, etc.).
- */
+/* CustomData interface, see also DNA_customdata_types.h. */
 
 #ifndef BKE_CUSTOMDATA_H
 #define BKE_CUSTOMDATA_H
 
-typedef struct CustomData {
-       struct LayerDesc *layers; /* data layer descriptors, ordered by type */
-       int numLayers;            /* current number of layers */
-       int maxLayers;            /* maximum number of layers */
-       int numElems;             /* current number of elements */
-       int maxElems;             /* maximum number of elements */
-       int subElems;             /* number of sub-elements layers can have */
-} CustomData;
-
-/* custom data types */
-enum {
-       LAYERTYPE_MVERT = 0,
-       LAYERTYPE_MSTICKY,
-       LAYERTYPE_MDEFORMVERT,
-       LAYERTYPE_MEDGE,
-       LAYERTYPE_MFACE,
-       LAYERTYPE_TFACE,
-       LAYERTYPE_MCOL,
-       LAYERTYPE_ORIGINDEX,
-       LAYERTYPE_NORMAL,
-       LAYERTYPE_FLAGS,
-       LAYERTYPE_NUMTYPES
-};
+struct CustomData;
 
 #define ORIGINDEX_NONE -1 /* indicates no original index for this element */
 
@@ -77,19 +50,19 @@ enum {
 /* initialises a CustomData object with space for the given number
  * of data layers and the given number of elements per layer
  */
-void CustomData_init(CustomData *data,
+void CustomData_init(struct CustomData *data,
                      int maxLayers, int maxElems, int subElems);
 
 /* initialises a CustomData object with the same layer setup as source
- * and memory space for maxElems elements
+ * and memory space for maxElems elements. flag is added to all layer flags
  */
-void CustomData_from_template(const CustomData *source, CustomData *dest,
-                              int maxElems);
+void CustomData_from_template(const struct CustomData *source,
+                              struct CustomData *dest, int flag, int maxElems);
 
 /* frees data associated with a CustomData object (doesn't free the object
  * itself, though)
  */
-void CustomData_free(CustomData *data);
+void CustomData_free(struct CustomData *data);
 
 /* adds a data layer of the given type to the CustomData object, optionally
  * backed by an external data array
@@ -100,25 +73,38 @@ void CustomData_free(CustomData *data);
  * grows the number of layers in data if data->maxLayers has been reached
  * returns 1 on success, 0 on failure
  */
-int CustomData_add_layer(CustomData *data, int type, int flag, void *layer);
+int CustomData_add_layer(struct CustomData *data, int type, int flag,
+                         void *layer);
+
+/* frees the first data layer with the give type.
+ * returns 1 on succes, 0 if no layer with the given type is found
+ */
+int CustomData_free_layer(struct CustomData *data, int type);
 
 /* returns 1 if the two objects are compatible (same layer types and
  * flags in the same order), 0 if not
  */
-int CustomData_compat(const CustomData *data1, const CustomData *data2);
+int CustomData_compat(const struct CustomData *data1,
+                      const struct CustomData *data2);
+
+/* returns 1 if a layer with the specified type exists */
+int CustomData_has_layer(const struct CustomData *data, int type);
 
 /* copies data from one CustomData object to another
  * objects need not be compatible, each source layer is copied to the
  * first dest layer of correct type (if there is none, the layer is skipped)
  * return 1 on success, 0 on failure
  */
-int CustomData_copy_data(const CustomData *source, CustomData *dest,
-                         int source_index, int dest_index, int count);
+int CustomData_copy_data(const struct CustomData *source,
+                         struct CustomData *dest, int source_index,
+                         int dest_index, int count);
+int CustomData_em_copy_data(struct CustomData *data, void *src_block,
+                            void **dest_block);
 
 /* frees data in a CustomData object
  * return 1 on success, 0 on failure
  */
-int CustomData_free_elem(CustomData *data, int index, int count);
+int CustomData_free_elem(struct CustomData *data, int index, int count);
 
 /* interpolates data from one CustomData object to another
  * objects need not be compatible, each source layer is interpolated to the
@@ -134,28 +120,47 @@ int CustomData_free_elem(CustomData *data, int index, int count);
  *
  * returns 1 on success, 0 on failure
  */
-int CustomData_interp(const CustomData *source, CustomData *dest,
+int CustomData_interp(const struct CustomData *source, struct CustomData *dest,
                       int *src_indices, float *weights, float *sub_weights,
                       int count, int dest_index);
+int CustomData_em_interp(struct CustomData *data,  void **src_blocks,
+                         float *weights, float *sub_weights, int count,
+                         void *dest_block);
 
 /* gets a pointer to the data element at index from the first layer of type
  * returns NULL if there is no layer of type
  */
-void *CustomData_get(const CustomData *data, int index, int type);
+void *CustomData_get(const struct CustomData *data, int index, int type);
+void *CustomData_em_get(const struct CustomData *data, void *block, int type);
 
 /* gets a pointer to the first layer of type
  * returns NULL if there is no layer of type
  */
-void *CustomData_get_layer(const CustomData *data, int type);
+void *CustomData_get_layer(const struct CustomData *data, int type);
 
 /* copies the data from source to the data element at index in the first
  * layer of type
  * no effect if there is no layer of type
  */
-void CustomData_set(const CustomData *data, int index, int type, void *source);
+void CustomData_set(const struct CustomData *data, int index, int type,
+                    void *source);
+void CustomData_em_set(struct CustomData *data, void *block, int type,
+                       void *source);
 
 /* sets the number of elements in a CustomData object
  * if the value given is more than the maximum, the maximum is used
  */
-void CustomData_set_num_elems(CustomData *data, int numElems);
+void CustomData_set_num_elems(struct CustomData *data, int numElems);
+
+/* alloc/free a block of custom data attached to one element in editmode */
+void CustomData_em_set_default(struct CustomData *data, void **block);
+void CustomData_em_free_block(struct CustomData *data, void **block);
+
+/* copy custom data to/from layers as in mesh/derivedmesh, to editmesh
+   blocks of data. the CustomData's must be compatible  */
+void CustomData_to_em_block(const struct CustomData *source,
+                            struct CustomData *dest, int index, void **block);
+void CustomData_from_em_block(const struct CustomData *source,
+                              struct CustomData *dest, void *block, int index);
+
 #endif
index 308a32439d488aa21f87283a1195dd8bbc415a14..04cb371226b50e5556f1e8bbda29496819e24d38 100644 (file)
@@ -59,6 +59,7 @@
 
 #include "BKE_utildefines.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_effect.h"
@@ -154,9 +155,9 @@ void DM_init(DerivedMesh *dm,
 void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
                       int numVerts, int numEdges, int numFaces)
 {
-       CustomData_from_template(&source->vertData, &dm->vertData, numVerts);
-       CustomData_from_template(&source->edgeData, &dm->edgeData, numEdges);
-       CustomData_from_template(&source->faceData, &dm->faceData, numFaces);
+       CustomData_from_template(&source->vertData, &dm->vertData, 0, numVerts);
+       CustomData_from_template(&source->edgeData, &dm->edgeData, 0, numEdges);
+       CustomData_from_template(&source->faceData, &dm->faceData, 0, numFaces);
 
        DM_init_funcs(dm);
 }
@@ -335,7 +336,7 @@ void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
                          int count, int dest_index)
 {
        CustomData_interp(&source->edgeData, &dest->edgeData, src_indices,
-                         weights, (float *)vert_weights, count, dest_index);
+                         weights, (float*)vert_weights, count, dest_index);
 }
 
 void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
@@ -344,7 +345,7 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
                          int count, int dest_index)
 {
        CustomData_interp(&source->faceData, &dest->faceData, src_indices,
-                         weights, (float *)vert_weights, count, dest_index);
+                         weights, (float*)vert_weights, count, dest_index);
 }
 
 typedef struct {
@@ -1087,24 +1088,27 @@ static void emDM_drawUVEdges(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditFace *efa;
+       TFace *tf;
 
        glBegin(GL_LINES);
        for(efa= emdm->em->faces.first; efa; efa= efa->next) {
-               if(!(efa->tf.flag&TF_HIDE)) {
-                       glVertex2fv(efa->tf.uv[0]);
-                       glVertex2fv(efa->tf.uv[1]);
+               tf = CustomData_em_get(&emdm->em->fdata, efa->data, LAYERTYPE_TFACE);
 
-                       glVertex2fv(efa->tf.uv[1]);
-                       glVertex2fv(efa->tf.uv[2]);
+               if(tf && !(tf->flag&TF_HIDE)) {
+                       glVertex2fv(tf->uv[0]);
+                       glVertex2fv(tf->uv[1]);
+
+                       glVertex2fv(tf->uv[1]);
+                       glVertex2fv(tf->uv[2]);
 
                        if (!efa->v4) {
-                               glVertex2fv(efa->tf.uv[2]);
-                               glVertex2fv(efa->tf.uv[0]);
+                               glVertex2fv(tf->uv[2]);
+                               glVertex2fv(tf->uv[0]);
                        } else {
-                               glVertex2fv(efa->tf.uv[2]);
-                               glVertex2fv(efa->tf.uv[3]);
-                               glVertex2fv(efa->tf.uv[3]);
-                               glVertex2fv(efa->tf.uv[0]);
+                               glVertex2fv(tf->uv[2]);
+                               glVertex2fv(tf->uv[3]);
+                               glVertex2fv(tf->uv[3]);
+                               glVertex2fv(tf->uv[0]);
                        }
                }
        }
index 1ec318ae455e991cd76d0c1d3d8e298008a4e6d8..21ad73aa24042c29a75df38c11352bbf36b0521b 100644 (file)
@@ -37,6 +37,7 @@
 #include "BIF_gl.h"
 
 #include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_mesh.h"
@@ -751,13 +752,11 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
        MEdge *medge = CDDM_get_edges(dm);
        MFace *mface = CDDM_get_faces(dm);
        int *index;
+       TFace *tf;
 
-       /* this maps from vert pointer to vert index */
-       GHash *vertHash = BLI_ghash_new(BLI_ghashutil_ptrhash,
-                                       BLI_ghashutil_ptrcmp);
-
+       /* set eve->hash to vert index */
        for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
-               BLI_ghash_insert(vertHash, eve, (void *)i);
+               eve->hash = i;
 
        if(me->msticky)
                CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
@@ -807,8 +806,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
            i++, eed = eed->next, index++) {
                MEdge *med = &medge[i];
 
-               med->v1 = (int) BLI_ghash_lookup(vertHash, eed->v1);
-               med->v2 = (int) BLI_ghash_lookup(vertHash, eed->v2);
+               med->v1 = eed->v1->hash;
+               med->v2 = eed->v2->hash;
                med->crease = (unsigned char) (eed->crease * 255.0f);
                med->flag = ME_EDGEDRAW|ME_EDGERENDER;
                
@@ -824,22 +823,21 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
            i++, efa = efa->next, index++) {
                MFace *mf = &mface[i];
 
-               mf->v1 = (int) BLI_ghash_lookup(vertHash, efa->v1);
-               mf->v2 = (int) BLI_ghash_lookup(vertHash, efa->v2);
-               mf->v3 = (int) BLI_ghash_lookup(vertHash, efa->v3);
-               mf->v4 = efa->v4 ? (int)BLI_ghash_lookup(vertHash, efa->v4) : 0;
+               mf->v1 = efa->v1->hash;
+               mf->v2 = efa->v2->hash;
+               mf->v3 = efa->v3->hash;
+               mf->v4 = efa->v4 ? efa->v4->hash : 0;
                mf->mat_nr = efa->mat_nr;
                mf->flag = efa->flag;
                test_index_face(mf, NULL, NULL, efa->v4?4:3);
 
                *index = i;
 
-               if(me->tface)
-                       DM_set_face_data(dm, i, LAYERTYPE_TFACE, &efa->tf);
+               tf = CustomData_em_get(&em->fdata, efa->data, LAYERTYPE_TFACE);
+               if(tf)
+                       DM_set_face_data(dm, i, LAYERTYPE_TFACE, tf);
        }
 
-       BLI_ghash_free(vertHash, NULL, NULL);
-
        return dm;
 }
 
@@ -976,7 +974,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
                }
        }
 
-       CustomData_from_template(&dm->edgeData, &edgeData, BLI_edgehash_size(eh));
+       CustomData_from_template(&dm->edgeData, &edgeData, 0, BLI_edgehash_size(eh));
 
        if(!CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE))
                CustomData_add_layer(&edgeData, LAYERTYPE_MEDGE,
index d774324f1c120ee5942da20f9721d4e3a0fceb2d..b7b034be216698219b2ad9d3b53751d4fd01ace7 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "BLI_linklist.h"
 
+#include "DNA_customdata_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 
 /* number of layers to add when growing a CustomData object */
 #define CUSTOMDATA_GROW 5
 
-/* descriptor and storage for a custom data layer */
-typedef struct LayerDesc {
-       int type;   /* type of data in layer */
-       int flag;   /* general purpose flag */
-       void *data; /* layer data */
-} LayerDesc;
-
 /********************* Layer type information **********************/
 typedef struct LayerTypeInfo {
        int size; /* the memory size of one element of this layer's data */
@@ -83,44 +77,11 @@ typedef struct LayerTypeInfo {
         */
        void (*interp)(void **sources, float *weights, float *sub_weights,
                       int count, void *dest);
-} LayerTypeInfo;
-
-static void layerCopy_mdeformvert(const void *source, void *dest,
-                                  int count, int size);
-
-static void layerFree_mdeformvert(void *data, int count, int size);
-
-static void layerInterp_mdeformvert(void **sources, float *weights,
-                                    float *sub_weights, int count, void *dest);
 
-static void layerInterp_tface(void **sources, float *weights,
-                              float *sub_weights, int count, void *dest);
-
-static void layerInterp_mcol(void **sources, float *weights,
-                             float *sub_weights, int count, void *dest);
-
-const LayerTypeInfo LAYERTYPEINFO[LAYERTYPE_NUMTYPES] = {
-       {sizeof(MVert), NULL, NULL, NULL},
-       {sizeof(MSticky), NULL, NULL, NULL},
-       {sizeof(MDeformVert),
-        layerCopy_mdeformvert, layerFree_mdeformvert, layerInterp_mdeformvert},
-       {sizeof(MEdge), NULL, NULL, NULL},
-       {sizeof(MFace), NULL, NULL, NULL},
-       {sizeof(TFace), NULL, NULL, layerInterp_tface},
-       /* 4 MCol structs per face */
-       {sizeof(MCol) * 4, NULL, NULL, layerInterp_mcol},
-       {sizeof(int), NULL, NULL, NULL},
-       /* 3 floats per normal vector */
-       {sizeof(float) * 3, NULL, NULL, NULL},
-       {sizeof(int), NULL, NULL, NULL},
-};
-
-const LayerTypeInfo *layerType_getInfo(int type)
-{
-       if(type < 0 || type >= LAYERTYPE_NUMTYPES) return NULL;
-
-       return &LAYERTYPEINFO[type];
-}
+    /* a function to set a layer's data to default values. if NULL, the
+          default is assumed to be all zeros */
+       void (*set_default)(void *data);
+} LayerTypeInfo;
 
 static void layerCopy_mdeformvert(const void *source, void *dest,
                                   int count, int size)
@@ -210,6 +171,18 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
        BLI_linklist_free(dest_dw, linklist_free_simple);
 }
 
+static void layerCopy_tface(const void *source, void *dest, int count, int size)
+{
+       const TFace *source_tf = (const TFace*)source;
+       TFace *dest_tf = (TFace*)dest;
+       int i;
+
+       for(i = 0; i < count; ++i) {
+               dest_tf[i] = source_tf[i];
+               dest_tf[i].flag &= ~TF_ACTIVE;
+       }
+}
+
 static void layerInterp_tface(void **sources, float *weights,
                               float *sub_weights, int count, void *dest)
 {
@@ -217,30 +190,32 @@ static void layerInterp_tface(void **sources, float *weights,
        int i, j, k;
        float uv[4][2];
        float col[4][4];
+       float *sub_weight;
 
        if(count <= 0) return;
 
        memset(uv, 0, sizeof(uv));
        memset(col, 0, sizeof(col));
 
+       sub_weight = sub_weights;
        for(i = 0; i < count; ++i) {
                float weight = weights ? weights[i] : 1;
                TFace *src = sources[i];
 
                for(j = 0; j < 4; ++j) {
                        if(sub_weights) {
-                               for(k = 0; k < 4; ++k) {
-                                       float sub_weight = sub_weights[j * 4 + k];
+                               for(k = 0; k < 4; ++k, ++sub_weight) {
+                                       float w = (*sub_weight) * weight;
                                        char *tmp_col = (char *)&src->col[k];
                                        float *tmp_uv = src->uv[k];
 
-                                       uv[j][0] += tmp_uv[0] * sub_weight * weight;
-                                       uv[j][1] += tmp_uv[1] * sub_weight * weight;
+                                       uv[j][0] += tmp_uv[0] * w;
+                                       uv[j][1] += tmp_uv[1] * w;
 
-                                       col[j][0] += tmp_col[0] * sub_weight * weight;
-                                       col[j][1] += tmp_col[1] * sub_weight * weight;
-                                       col[j][2] += tmp_col[2] * sub_weight * weight;
-                                       col[j][3] += tmp_col[3] * sub_weight * weight;
+                                       col[j][0] += tmp_col[0] * w;
+                                       col[j][1] += tmp_col[1] * w;
+                                       col[j][2] += tmp_col[2] * w;
+                                       col[j][3] += tmp_col[3] * w;
                                }
                        } else {
                                char *tmp_col = (char *)&src->col[j];
@@ -269,6 +244,14 @@ static void layerInterp_tface(void **sources, float *weights,
        }
 }
 
+static void layerDefault_tface(void *data)
+{
+       static TFace default_tf = {NULL, {{0, 1}, {0, 0}, {1, 0}, {1, 1}},
+                                  {~0, ~0, ~0, ~0}, TF_SELECT, 0, TF_DYNAMIC, 0, 0};
+
+       *((TFace*)data) = default_tf;
+}
+
 static void layerInterp_mcol(void **sources, float *weights,
                              float *sub_weights, int count, void *dest)
 {
@@ -280,14 +263,15 @@ static void layerInterp_mcol(void **sources, float *weights,
                float g;
                float b;
        } col[4];
+       float *sub_weight;
 
        if(count <= 0) return;
 
        memset(col, 0, sizeof(col));
-
+       
+       sub_weight = sub_weights;
        for(i = 0; i < count; ++i) {
                float weight = weights ? weights[i] : 1;
-               float *sub_weight = sub_weights;
 
                for(j = 0; j < 4; ++j) {
                        if(sub_weights) {
@@ -316,6 +300,41 @@ static void layerInterp_mcol(void **sources, float *weights,
        }
 }
 
+static void layerDefault_mcol(void *data)
+{
+       static MCol default_mcol = {255, 255, 255, 255};
+       MCol *mcol = (MCol*)data;
+
+       mcol[0]= default_mcol;
+       mcol[1]= default_mcol;
+       mcol[2]= default_mcol;
+       mcol[3]= default_mcol;
+}
+
+const LayerTypeInfo LAYERTYPEINFO[LAYERTYPE_NUMTYPES] = {
+       {sizeof(MVert), NULL, NULL, NULL, NULL},
+       {sizeof(MSticky), NULL, NULL, NULL, NULL},
+       {sizeof(MDeformVert), layerCopy_mdeformvert,
+        layerFree_mdeformvert, layerInterp_mdeformvert, NULL},
+       {sizeof(MEdge), NULL, NULL, NULL, NULL},
+       {sizeof(MFace), NULL, NULL, NULL, NULL},
+       {sizeof(TFace), layerCopy_tface, NULL, layerInterp_tface,
+        layerDefault_tface},
+       /* 4 MCol structs per face */
+       {sizeof(MCol) * 4, NULL, NULL, layerInterp_mcol, layerDefault_mcol},
+       {sizeof(int), NULL, NULL, NULL, NULL},
+       /* 3 floats per normal vector */
+       {sizeof(float) * 3, NULL, NULL, NULL, NULL},
+       {sizeof(int), NULL, NULL, NULL, NULL},
+};
+
+static const LayerTypeInfo *layerType_getInfo(int type)
+{
+       if(type < 0 || type >= LAYERTYPE_NUMTYPES) return NULL;
+
+       return &LAYERTYPEINFO[type];
+}
+
 /********************* CustomData functions *********************/
 void CustomData_init(CustomData *data,
                      int maxLayers, int maxElems, int subElems)
@@ -329,19 +348,36 @@ void CustomData_init(CustomData *data,
        data->subElems = subElems;
 }
 
+static void CustomData_update_offsets(CustomData *data)
+{
+       const LayerTypeInfo *typeInfo;
+       int i, offset = 0;
+
+       for(i = 0; i < data->numLayers; ++i) {
+               typeInfo = layerType_getInfo(data->layers[i].type);
+
+               data->layers[i].offset = offset;
+               offset += typeInfo->size;
+       }
+
+       data->totSize = offset;
+}
+
 void CustomData_from_template(const CustomData *source, CustomData *dest,
-                              int maxElems)
+                              int flag, int maxElems)
 {
-       int i;
+       int i, layerflag;
 
        CustomData_init(dest, source->maxLayers, maxElems, source->subElems);
 
        for(i = 0; i < source->numLayers; ++i) {
                if(source->layers[i].flag & LAYERFLAG_NOCOPY) continue;
 
-               CustomData_add_layer(dest, source->layers[i].type,
-                                    source->layers[i].flag & ~LAYERFLAG_NOFREE, NULL);
+               layerflag = (source->layers[i].flag & ~LAYERFLAG_NOFREE) | flag;
+               CustomData_add_layer(dest, source->layers[i].type, layerflag, NULL);
        }
+
+       CustomData_update_offsets(dest);
 }
 
 void CustomData_free(CustomData *data)
@@ -356,7 +392,8 @@ void CustomData_free(CustomData *data)
                                typeInfo->free(data->layers[i].data, data->numElems,
                                               typeInfo->size);
 
-                       MEM_freeN(data->layers[i].data);
+                       if(data->layers[i].data)
+                               MEM_freeN(data->layers[i].data);
                }
        }
 
@@ -368,10 +405,27 @@ void CustomData_free(CustomData *data)
        }
 }
 
-static int customData_grow(CustomData *data, int amount)
+/* gets index of first layer matching type after start_index
+ * if start_index < 0, starts searching at 0
+ * returns -1 if there is no layer of type
+ */
+static int CustomData_find_next(const CustomData *data, int type,
+                                int start_index)
+{
+       int i = start_index + 1;
+
+       if(i < 0) i = 0;
+
+       for(; i < data->numLayers; ++i)
+               if(data->layers[i].type == type) return i;
+
+       return -1;
+}
+
+static int customData_resize(CustomData *data, int amount)
 {
-       LayerDesc *tmp = MEM_callocN(sizeof(*tmp) * (data->maxLayers + amount),
-                                 "CustomData->layers");
+       CustomDataLayer *tmp = MEM_callocN(sizeof(*tmp)*(data->maxLayers + amount),
+                                       "CustomData->layers");
        if(!tmp) return 0;
 
        data->maxLayers += amount;
@@ -389,8 +443,8 @@ static int customData_add_layer__internal(CustomData *data, int type,
        int index = data->numLayers;
 
        if(index >= data->maxLayers)
-               if(!customData_grow(data, CUSTOMDATA_GROW)) return 0;
-
+               if(!customData_resize(data, CUSTOMDATA_GROW)) return 0;
+       
        /* keep layers ordered by type */
        for( ; index > 0 && data->layers[index - 1].type > type; --index)
                data->layers[index] = data->layers[index - 1];
@@ -401,6 +455,8 @@ static int customData_add_layer__internal(CustomData *data, int type,
 
        data->numLayers++;
 
+       CustomData_update_offsets(data);
+
        return 1;
 }
 
@@ -409,7 +465,7 @@ int CustomData_add_layer(CustomData *data, int type, int flag, void *layer)
        int size = layerType_getInfo(type)->size * data->numElems;
        void *tmp_layer = layer;
 
-       if(!layer) tmp_layer = MEM_callocN(size, "LayerDesc.data");
+       if(!layer) tmp_layer = MEM_callocN(size, "CustomDataLayer.data");
 
        if(!tmp_layer) return 0;
 
@@ -421,6 +477,30 @@ int CustomData_add_layer(CustomData *data, int type, int flag, void *layer)
        }
 }
 
+int CustomData_free_layer(CustomData *data, int type)
+{
+       int index = CustomData_find_next(data, type, -1);
+
+       if (index < 0) return 0;
+
+       for(++index; index < data->numLayers; ++index)
+               data->layers[index - 1] = data->layers[index];
+
+       data->numLayers--;
+
+       if(data->numLayers <= data->maxLayers-CUSTOMDATA_GROW)
+               customData_resize(data, -CUSTOMDATA_GROW);
+
+       CustomData_update_offsets(data);
+
+       return 1;
+}
+
+int CustomData_has_layer(const struct CustomData *data, int type)
+{
+       return (CustomData_find_next(data, type, -1) != -1);
+}
+
 int CustomData_compat(const CustomData *data1, const CustomData *data2)
 {
        int i;
@@ -435,23 +515,6 @@ int CustomData_compat(const CustomData *data1, const CustomData *data2)
        return 1;
 }
 
-/* gets index of first layer matching type after start_index
- * if start_index < 0, starts searching at 0
- * returns -1 if there is no layer of type
- */
-static int CustomData_find_next(const CustomData *data, int type,
-                                int start_index)
-{
-       int i = start_index + 1;
-
-       if(i < 0) i = 0;
-
-       for(; i < data->numLayers; ++i)
-               if(data->layers[i].type == type) return i;
-
-       return -1;
-}
-
 int CustomData_copy_data(const CustomData *source, CustomData *dest,
                          int source_index, int dest_index, int count)
 {
@@ -558,7 +621,7 @@ int CustomData_interp(const CustomData *source, CustomData *dest,
 
        /* interpolates a layer at a time */
        for(src_i = 0; src_i < source->numLayers; ++src_i) {
-               LayerDesc *source_layer = &source->layers[src_i];
+               CustomDataLayer *source_layer = &source->layers[src_i];
                const LayerTypeInfo *type_info =
                                        layerType_getInfo(source_layer->type);
 
@@ -628,3 +691,177 @@ void CustomData_set_num_elems(CustomData *data, int numElems)
        if(numElems < data->maxElems) data->numElems = numElems;
        else data->numElems = data->maxElems;
 }
+
+/* EditMesh functions */
+
+static void CustomData_em_alloc_block(CustomData *data, void **block)
+{
+       /* TODO: optimize free/alloc */
+
+       if (*block)
+               MEM_freeN(*block);
+
+       if (data->totSize > 0)
+               *block = MEM_callocN(data->totSize, "CustomData EM block");
+       else
+               *block = NULL;
+}
+
+void CustomData_em_free_block(CustomData *data, void **block)
+{
+       if (*block) {
+               MEM_freeN(*block);
+               *block = NULL;
+       }
+}
+
+int CustomData_em_copy_data(CustomData *data, void *src_block, void **dest_block)
+{
+       const LayerTypeInfo *type_info;
+       int i;
+
+       if (!*dest_block)
+               CustomData_em_alloc_block(data, dest_block);
+       
+       /* copies a layer at a time */
+       for(i = 0; i < data->numLayers; ++i) {
+               int offset = data->layers[i].offset;
+               char *src_data = (char*)src_block + offset;
+               char *dest_data = (char*)*dest_block + offset;
+
+               type_info = layerType_getInfo(data->layers[i].type);
+
+               if(type_info->copy)
+                       type_info->copy(src_data, dest_data, 1, type_info->size);
+               else
+                       memcpy(dest_data, src_data, type_info->size);
+       }
+
+       return 1;
+}
+
+void *CustomData_em_get(const CustomData *data, void *block, int type)
+{
+       int layer_index;
+       
+       /* get the layer index of the first layer of type */
+       layer_index = CustomData_find_next(data, type, -1);
+       if(layer_index < 0) return NULL;
+
+       return (char *)block + data->layers[layer_index].offset;
+}
+
+void CustomData_em_set(CustomData *data, void *block, int type, void *source)
+{
+       void *dest = CustomData_em_get(data, index, type);
+       const LayerTypeInfo *type_info = layerType_getInfo(type);
+
+       if(!dest) return;
+
+       if(type_info->copy)
+               type_info->copy(source, dest, 1, type_info->size);
+       else
+               memcpy(dest, source, type_info->size);
+}
+
+int CustomData_em_interp(CustomData *data, void **src_blocks, float *weights,
+                         float *sub_weights, int count, void *dest_block)
+{
+       int i, j;
+       void *source_buf[SOURCE_BUF_SIZE];
+       void **sources = source_buf;
+
+       if(count <= 0) return 0;
+
+       /* slow fallback in case we're interpolating a ridiculous number of
+        * elements
+        */
+       if(count > SOURCE_BUF_SIZE)
+               sources = MEM_callocN(sizeof(*sources) * count,
+                                     "CustomData_interp sources");
+
+       /* interpolates a layer at a time */
+       for(i = 0; i < data->numLayers; ++i) {
+               CustomDataLayer *layer = &data->layers[i];
+               const LayerTypeInfo *type_info = layerType_getInfo(layer->type);
+
+               if(type_info->interp) {
+                       for(j = 0; j < count; ++j)
+                               sources[j] = (char *)src_blocks[j] + layer->offset;
+
+                       type_info->interp(sources, weights, sub_weights, count,
+                                         (char *)dest_block + layer->offset);
+               }
+       }
+
+       if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
+       return 1;
+}
+
+void CustomData_em_set_default(CustomData *data, void **block)
+{
+       const LayerTypeInfo *type_info;
+       int i;
+
+       if (!*block)
+               CustomData_em_alloc_block(data, block);
+
+       for(i = 0; i < data->numLayers; ++i) {
+               int offset = data->layers[i].offset;
+
+               type_info = layerType_getInfo(data->layers[i].type);
+
+               if(type_info->set_default)
+                       type_info->set_default((char*)*block + offset);
+       }
+}
+
+void CustomData_to_em_block(const CustomData *source, CustomData *dest,
+                            int src_index, void **dest_block)
+{
+       const LayerTypeInfo *type_info;
+       int i, src_offset;
+
+       if (!*dest_block)
+               CustomData_em_alloc_block(dest, dest_block);
+       
+       /* copies a layer at a time */
+       for(i = 0; i < dest->numLayers; ++i) {
+               int offset = dest->layers[i].offset;
+               char *src_data = source->layers[i].data;
+               char *dest_data = (char*)*dest_block + offset;
+
+               type_info = layerType_getInfo(dest->layers[i].type);
+               src_offset = src_index * type_info->size;
+
+               if(type_info->copy)
+                       type_info->copy(src_data + src_offset, dest_data, 1,
+                                       type_info->size);
+               else
+                       memcpy(dest_data, src_data + src_offset, type_info->size);
+       }
+}
+
+void CustomData_from_em_block(const CustomData *source, CustomData *dest,
+                              void *src_block, int dest_index)
+{
+       const LayerTypeInfo *type_info;
+       int i, dest_offset;
+
+       /* copies a layer at a time */
+       for(i = 0; i < dest->numLayers; ++i) {
+               int offset = source->layers[i].offset;
+               char *src_data = (char*)src_block + offset;
+               char *dest_data = dest->layers[i].data;
+
+               type_info = layerType_getInfo(dest->layers[i].type);
+               dest_offset = dest_index * type_info->size;
+
+               if(type_info->copy)
+                       type_info->copy(src_data, dest_data + dest_offset, 1,
+                                       type_info->size);
+               else
+                       memcpy(dest_data + dest_offset, src_data, type_info->size);
+       }
+}
+
index f8798de2650ae2419082515fc9b38e3062888cdf..3b6a7dba40b6d664613218b07fbbc65a16d807ee 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "BKE_bad_level_calls.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
 #include "BKE_utildefines.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
index 0592f04f05d2afb70197818757b82680fb62bdd8..25559043bc8ce58cb2a432c54eef02562b1a2fd4 100644 (file)
@@ -38,6 +38,7 @@
 #ifndef BLI_EDITVERT_H
 #define BLI_EDITVERT_H
 
+#include "DNA_customdata_types.h"
 #include "DNA_mesh_types.h"
 
 struct DerivedMesh;
@@ -125,7 +126,6 @@ typedef struct EditFace
                float                   fp;
        } tmp;
        float n[3], cent[3];
-       struct TFace tf;        /* a copy of original tface. */
        unsigned char mat_nr, flag;
        unsigned char f, f1, h;
        unsigned char fast;                     /* only 0 or 1, for editmesh_fastmalloc */
@@ -133,6 +133,7 @@ typedef struct EditFace
 /*#ifdef WITH_VERSE*/
        void *vface;
 /*#endif*/
+       void *data;             /* custom face data */
 } EditFace;
 
 
@@ -167,6 +168,8 @@ typedef struct EditMesh
        char retopo_mode; /* 0=OFF, 1=ON, 2=PAINT */
        struct RetopoPaintData *retopo_paint_data;
 
+       CustomData fdata;
+
 #ifdef WITH_VERSE
        void *vnode;
 #endif
index 0df24d17917f8d00b3be395ed6304f08fa1879f8..ef568b9d84fc81d2b608eebe9809e397fbce9fb1 100644 (file)
@@ -104,6 +104,11 @@ extern int faceselectedAND(struct EditFace *efa, int flag);
 extern void recalc_editnormals(void);
 extern void flip_editnormals(void);
 
+extern struct EditFace *EM_face_from_faces(struct EditFace *efa1,
+       struct EditFace *efa2, int i1, int i2, int i3, int i4);
+extern void EM_interp_from_faces(struct EditFace *efa1, struct EditFace *efa2,
+       struct EditFace *efan, int i1, int i2, int i3, int i4);
+
 /* ******************* editmesh_mods.c */
 
 extern void EM_init_index_arrays(int forVert, int forEdge, int forFace);
index 01b6123c9665be1785041e359204fca7f11678bf..2145b8209d0b85a3fc6355cb05380e512e4449bb 100644 (file)
@@ -83,7 +83,7 @@ struct VNode *create_geom_vnode_data_from_mesh(struct VerseSession *session, str
 void destroy_unused_geometry(struct VNode *vnode);
 void destroy_binding_between_versemesh_and_editmesh(struct VNode *vnode);
 
-void destroy_verse_mesh(struct VNode *vnode);
+void destroy_versemesh(struct VNode *vnode);
 
 void unsubscribe_from_geom_node(struct VNode *vnode);
 
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
new file mode 100644 (file)
index 0000000..2886f01
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef DNA_CUSTOMDATA_TYPES_H
+#define DNA_CUSTOMDATA_TYPES_H
+
+/* descriptor and storage for a custom data layer */
+typedef struct CustomDataLayer {
+       int type;       /* type of data in layer */
+       int offset;     /* in editmode, offset of layer in block */
+       int flag, pad;  /* general purpose flag */
+       void *data;     /* layer data */
+} CustomDataLayer;
+
+/* structure which stores custom element data associated with mesh elements
+ * (vertices, edges or faces). The custom data is organised into a series of
+ * layers, each with a data type (e.g. TFace, MDeformVert, etc.). */
+typedef struct CustomData {
+       CustomDataLayer *layers;  /* data layer descriptors, ordered by type */
+       int numLayers;            /* current number of layers */
+       int maxLayers;            /* maximum number of layers */
+       int numElems;             /* current number of elements */
+       int maxElems;             /* maximum number of elements */
+       int subElems;             /* number of sub-elements layers can have */
+       int totSize;              /* in editmode, total size of all data layers */
+} CustomData;
+
+/* custom data types */
+#define LAYERTYPE_MVERT                        0
+#define LAYERTYPE_MSTICKY              1
+#define LAYERTYPE_MDEFORMVERT  2
+#define LAYERTYPE_MEDGE                        3
+#define LAYERTYPE_MFACE                        4
+#define LAYERTYPE_TFACE                        5
+#define LAYERTYPE_MCOL                 6
+#define LAYERTYPE_ORIGINDEX            7
+#define LAYERTYPE_NORMAL               8
+#define LAYERTYPE_FLAGS                        9
+#define LAYERTYPE_NUMTYPES             10
+
+#endif
index e138631e5482120b6c0e6d388b6259f17e062ea8..a891fe1adab3c343e09acf37ef9701f29987cab0 100644 (file)
@@ -43,6 +43,7 @@
 
 #include "PIL_time.h"
 
+#include "DNA_customdata_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
@@ -64,6 +65,7 @@
 
 #include "BKE_DerivedMesh.h"
 #include "BKE_depsgraph.h"
+#include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_library.h"
@@ -150,7 +152,6 @@ EditVert *addvertlist(float *vec)
         * have a pre-editmode vertex order
         */
        eve->keyindex = -1;
-
 #ifdef WITH_VERSE
        createVerseVert(eve);
 #endif
@@ -325,9 +326,9 @@ void free_editface(EditFace *efa)
        }
 #endif
        EM_remove_selection(efa, EDITFACE);
-       if(efa->fast==0){ 
+       CustomData_em_free_block(&G.editMesh->fdata, &efa->data);
+       if(efa->fast==0)
                free(efa);
-       }
 }
 
 void free_vertlist(ListBase *edve) 
@@ -409,17 +410,14 @@ EditFace *addfacelist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
 
        if(example) {
                efa->mat_nr= example->mat_nr;
-               efa->tf= example->tf;
-               efa->tf.flag &= ~TF_ACTIVE;
                efa->flag= example->flag;
+               CustomData_em_copy_data(&em->fdata, example->data, &efa->data);
        }
        else {
                if (G.obedit && G.obedit->actcol)
                        efa->mat_nr= G.obedit->actcol-1;
-               default_uv(efa->tf.uv, 1.0);
 
-               /* Initialize colors */
-               efa->tf.col[0]= efa->tf.col[1]= efa->tf.col[2]= efa->tf.col[3]= vpaint_get_current_col();
+               CustomData_em_set_default(&em->fdata, &efa->data);
        }
 
        BLI_addtail(&em->faces, efa);
@@ -511,7 +509,6 @@ static void *calloc_fastface(size_t size, size_t nr)
 */
 static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
 {
-       
        if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
        else em->allverts= NULL;
        em->curvert= em->allverts;
@@ -556,6 +553,9 @@ void free_editMesh(EditMesh *em)
        if(em->edges.first) free_edgelist(&em->edges);
        if(em->faces.first) free_facelist(&em->faces);
        if(em->selected.first) BLI_freelistN(&(em->selected));
+
+       CustomData_free(&em->fdata);
+
        if(em->derivedFinal) {
                if (em->derivedFinal!=em->derivedCage) {
                        em->derivedFinal->release(em->derivedFinal);
@@ -774,6 +774,7 @@ static void edge_drawflags(void)
 void make_editMesh()
 {
        Mesh *me= G.obedit->data;
+       EditMesh *em= G.editMesh;
        MFace *mface;
        TFace *tface;
        MVert *mvert;
@@ -783,6 +784,7 @@ void make_editMesh()
        EditFace *efa;
        EditEdge *eed;
        EditSelection *ese;
+       CustomData mfdata;
        int tot, a, eekadoodle= 0;
 
 #ifdef WITH_VERSE
@@ -793,7 +795,7 @@ void make_editMesh()
 #endif
 
        /* because of reload */
-       free_editMesh(G.editMesh);
+       free_editMesh(em);
        
        G.totvert= tot= me->totvert;
        G.totedge= me->totedge;
@@ -804,9 +806,8 @@ void make_editMesh()
                return;
        }
        
-
        /* initialize fastmalloc for editmesh */
-       init_editmesh_fastmalloc(G.editMesh, me->totvert, me->totedge, me->totface);
+       init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
 
        actkey = ob_get_keyblock(G.obedit);
        if(actkey) {
@@ -847,10 +848,9 @@ void make_editMesh()
                }
 
        }
-       
+
        if(actkey && actkey->totelem!=me->totvert);
        else {
-               unsigned int *mcol;
                MEdge *medge= me->medge;
                
                /* make edges */
@@ -870,11 +870,19 @@ void make_editMesh()
                        }
                }
                
+               /* fill a CustomData, this is only temporary until Mesh get its own */
+               CustomData_init(&mfdata, 0, me->totface, SUB_ELEMS_FACE);
+               if(me->mcol)
+                       CustomData_add_layer(&mfdata, LAYERTYPE_MCOL, LAYERFLAG_NOFREE, me->mcol);
+               if(me->tface)
+                       CustomData_add_layer(&mfdata, LAYERTYPE_TFACE, LAYERFLAG_NOFREE, me->tface);
+
+               CustomData_from_template(&mfdata, &em->fdata, 0, 0);
+               
                /* make faces */
                mface= me->mface;
                tface= me->tface;
-               mcol= (unsigned int *)me->mcol;
-               
+
                for(a=0; a<me->totface; a++, mface++) {
                        eve1= evlist[mface->v1];
                        eve2= evlist[mface->v2];
@@ -885,13 +893,8 @@ void make_editMesh()
                        efa= addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
 
                        if(efa) {
-                       
-                               if(mcol) memcpy(efa->tf.col, mcol, 4*sizeof(int));
+                               CustomData_to_em_block(&mfdata, &em->fdata, a, &efa->data);
 
-                               if(me->tface) {
-                                       efa->tf= *tface;
-                               }
-                       
                                efa->mat_nr= mface->mat_nr;
                                efa->flag= mface->flag & ~ME_HIDE;
                                
@@ -902,18 +905,18 @@ void make_editMesh()
                                        }
                                        if(mface->flag & ME_HIDE) efa->h= 1;
                                }
-                               else if (tface) {
-                                       if( tface->flag & TF_HIDE) 
+                               else if((tface = CustomData_get(&mfdata, a, LAYERTYPE_TFACE))) {
+                                       if(tface->flag & TF_HIDE) 
                                                efa->h= 1;
-                                       else if( tface->flag & TF_SELECT) {
+                                       else if(tface->flag & TF_SELECT)
                                                EM_select_face(efa, 1);
-                                       }
                                }
                        }
 
                        if(me->tface) tface++;
-                       if(mcol) mcol+=4;
                }
+
+               CustomData_free(&mfdata);
        }
        
        if(eekadoodle)
@@ -936,7 +939,7 @@ void make_editMesh()
                                if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
                                if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
                                if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
-                               BLI_addtail(&(G.editMesh->selected),ese);
+                               BLI_addtail(&(em->selected),ese);
                        }
                }
                EM_free_index_arrays();
@@ -962,6 +965,7 @@ void load_editMesh(void)
        MFace *mface;
        MSticky *ms;
        MSelect *mselect;
+       TFace *tf;
        EditVert *eve;
        EditFace *efa;
        EditEdge *eed;
@@ -969,7 +973,7 @@ void load_editMesh(void)
        float *fp, *newkey, *oldkey, nor[3];
        int i, a, ototvert, totedge=0;
        MDeformVert *dvert;
-
+       CustomData mfdata;
 
 #ifdef WITH_VERSE
        if(em->vnode) {
@@ -1005,7 +1009,7 @@ void load_editMesh(void)
        /* new Face block */
        if(G.totface==0) mface= NULL;
        else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh face");
-       
+
        /* are we adding dverts? */
        if (G.totvert==0) dvert= NULL;
        else if(G.obedit->defbase.first==NULL) dvert= NULL;
@@ -1028,9 +1032,21 @@ void load_editMesh(void)
        me->totedge= totedge;
        
        if(me->mface) MEM_freeN(me->mface);
+
        me->mface= mface;
        me->totface= G.totface;
-               
+
+       /* face data */
+       if(me->tface) {
+               MEM_freeN(me->tface);
+               me->tface = NULL;
+       }
+       if(me->mcol) {
+               MEM_freeN(me->mcol);
+               me->mcol = NULL;
+       }
+       CustomData_from_template(&em->fdata, &mfdata, LAYERFLAG_NOFREE, me->totface);
+
        /* the vertices, use ->tmp.l as counter */
        eve= em->verts.first;
        a= 0;
@@ -1145,9 +1161,11 @@ void load_editMesh(void)
                        efa->e4->f2= 2;
                }
 
+               CustomData_from_em_block(&em->fdata, &mfdata, efa->data, i);
 
                /* no index '0' at location 3 or 4 */
-               test_index_face(mface, NULL, &efa->tf, efa->v4?4:3);
+               test_index_face(mface, CustomData_get(&mfdata, i, LAYERTYPE_MCOL),
+                               CustomData_get(&mfdata, i, LAYERTYPE_TFACE), efa->v4?4:3);
 
 #ifdef WITH_VERSE
                if(efa->vface) {
@@ -1159,55 +1177,27 @@ void load_editMesh(void)
                i++;
                efa= efa->next;
        }
-       
-       /* tface block */
-       if( me->tface && me->totface ) {
-               TFace *tfn, *tf;
-                       
-               tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
-               efa= em->faces.first;
-               while(efa) {
-                               
-                       *tf= efa->tf;
-                               
-                       if(G.f & G_FACESELECT) {
-                               if( efa->h) tf->flag |= TF_HIDE;
+
+       /* sync hide and select flags with faceselect mode */
+       if(G.f & G_FACESELECT) {
+               if(me->tface && (me->totface > 0)) {
+                       efa= em->faces.first;
+                       for(a=0, efa=em->faces.first; efa; a++, efa++) {
+                               tf = CustomData_get(&mfdata, a, LAYERTYPE_TFACE);
+
+                               if(efa->h) tf->flag |= TF_HIDE;
                                else tf->flag &= ~TF_HIDE;
-                               if( efa->f & SELECT)  tf->flag |= TF_SELECT;
+                               if(efa->f & SELECT)  tf->flag |= TF_SELECT;
                                else tf->flag &= ~TF_SELECT;
                        }
-                               
-                       tf++;
-                       efa= efa->next;
                }
-
-               if(me->tface) MEM_freeN(me->tface);
-               me->tface= tfn;
-       }
-       else if(me->tface) {
-               MEM_freeN(me->tface);
-               me->tface= NULL;
        }
-               
-       /* mcol: same as tface... */
-       if(me->mcol && me->totface) {
-               unsigned int *mcn, *mc;
 
-               mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
-               efa= em->faces.first;
-               while(efa) {
-                       memcpy(mc, efa->tf.col, 4*sizeof(int));
-                               
-                       mc+=4;
-                       efa= efa->next;
-               }
-               if(me->mcol) MEM_freeN(me->mcol);
-                       me->mcol= (MCol *)mcn;
-       }
-       else if(me->mcol) {
-               MEM_freeN(me->mcol);
-               me->mcol= 0;
-       }
+       /* from CustomData to tface and mcol in Mesh */
+       me->tface = CustomData_get(&mfdata, 0, LAYERTYPE_TFACE);
+       me->mcol = CustomData_get(&mfdata, 0, LAYERTYPE_MCOL);
+
+       CustomData_free(&mfdata);
 
        /* patch hook indices */
        {
@@ -1576,6 +1566,7 @@ void separate_mesh(void)
        emcopy.alledges= NULL;
        emcopy.allfaces= NULL;
        emcopy.derivedFinal= emcopy.derivedCage= NULL;
+       memset(&emcopy.fdata, 0, sizeof(emcopy.fdata));
        free_editMesh(&emcopy);
        
        em->verts= edve;
@@ -1769,6 +1760,7 @@ void separate_mesh_loose(void)
                        emcopy.alledges= NULL;
                        emcopy.allfaces= NULL;
                        emcopy.derivedFinal= emcopy.derivedCage= NULL;
+                       memset(&emcopy.fdata, 0, sizeof(emcopy.fdata));
                        free_editMesh(&emcopy);
                        
                        em->verts= edve;
@@ -1839,14 +1831,13 @@ typedef struct UndoMesh {
        EditEdgeC *edges;
        EditFaceC *faces;
        EditSelectionC *selected;
-       TFace *tfaces;
-       int totvert, totedge, totface,totsel;
+       int totvert, totedge, totface, totsel;
        short selectmode;
        RetopoPaintData *retopo_paint_data;
        char retopo_mode;
+       CustomData fdata;
 } UndoMesh;
 
-
 /* for callbacks */
 
 static void free_undoMesh(void *umv)
@@ -1862,9 +1853,9 @@ static void free_undoMesh(void *umv)
        if(um->verts) MEM_freeN(um->verts);
        if(um->edges) MEM_freeN(um->edges);
        if(um->faces) MEM_freeN(um->faces);
-       if(um->tfaces) MEM_freeN(um->tfaces);
        if(um->selected) MEM_freeN(um->selected);
        if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
+       CustomData_free(&um->fdata);
        MEM_freeN(um);
 }
 
@@ -1872,7 +1863,6 @@ static void *editMesh_to_undoMesh(void)
 {
        EditMesh *em= G.editMesh;
        UndoMesh *um;
-       Mesh *me= G.obedit->data;
        EditVert *eve;
        EditEdge *eed;
        EditFace *efa;
@@ -1881,7 +1871,6 @@ static void *editMesh_to_undoMesh(void)
        EditEdgeC *eedc=NULL;
        EditFaceC *efac=NULL;
        EditSelectionC *esec=NULL;
-       TFace *tface= NULL;
        int a;
        
        um= MEM_callocN(sizeof(UndoMesh), "undomesh");
@@ -1898,11 +1887,8 @@ static void *editMesh_to_undoMesh(void)
        if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
        if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
        if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
-       
-       if(me->tface || me->mcol) tface= um->tfaces= MEM_mallocN(um->totface*sizeof(TFace), "all tfacesC");
 
-               //printf("copy editmesh %d\n", um->totvert*sizeof(EditVert) + um->totedge*sizeof(EditEdge) + um->totface*sizeof(EditFace));
-               //printf("copy undomesh %d\n", um->totvert*sizeof(EditVertC) + um->totedge*sizeof(EditEdgeC) + um->totface*sizeof(EditFaceC));
+       if(um->totface) CustomData_from_template(&em->fdata, &um->fdata, 0, um->totface);
        
        /* now copy vertices */
        a = 0;
@@ -1946,12 +1932,10 @@ static void *editMesh_to_undoMesh(void)
                efac->f= efa->f;
                efac->h= efa->h;
                efac->fgonf= efa->fgonf;
-               
-               if(tface) {
-                       *tface= efa->tf;
-                       tface++;
-               }
+
                efa->tmp.l = a; /*store index*/
+
+               CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
        }
        
        a = 0;
@@ -1980,7 +1964,6 @@ static void undoMesh_to_editMesh(void *umv)
        EditEdgeC *eedc;
        EditFaceC *efac;
        EditSelectionC *esec;
-       TFace *tface;
        int a=0;
 
 #ifdef WITH_VERSE
@@ -2031,7 +2014,9 @@ static void undoMesh_to_editMesh(void *umv)
        }
        
        /* copy faces */
-       tface= um->tfaces;
+       CustomData_free(&em->fdata);
+       CustomData_from_template(&um->fdata, &em->fdata, 0, 0);
+
        for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
                if(efac->v4 != -1)
                        efa= addfacelist(evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
@@ -2044,10 +2029,7 @@ static void undoMesh_to_editMesh(void *umv)
                efa->h= efac->h;
                efa->fgonf= efac->fgonf;
                
-               if(tface) {
-                       efa->tf= *tface;
-                       tface++;
-               }
+               CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
        }
        
        end_editmesh_fastmalloc();
index 2f742d8e985820394023ff560a0db183e0b238cb..ca03dcef5550e6a74e1554ad2b141a3d86c97a35 100644 (file)
@@ -57,6 +57,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
 #include "BLI_arithb.h"
 #include "BLI_editVert.h"
 
+#include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
 #include "BKE_utildefines.h"
@@ -708,6 +709,44 @@ void EM_hide_reset(void)
                
 }
 
+void EM_interp_from_faces(EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4)
+{
+       EditMesh *em= G.editMesh;
+       float w[2][4][4];
+       void *src[2];
+       int count = (efa2)? 2: 1;
+
+       /* set weights for copying from corners directly to other corners */
+       memset(w, 0, sizeof(w));
+
+       w[i1/4][0][i1%4]= 1.0f;
+       w[i2/4][1][i2%4]= 1.0f;
+       w[i3/4][2][i3%4]= 1.0f;
+       if (i4 != -1)
+               w[i4/4][3][i4%4]= 1.0f;
+
+       src[0]= efa1->data;
+       src[1]= (efa2)? efa2->data: NULL;
+
+       CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data);
+}
+
+EditFace *EM_face_from_faces(EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4)
+{
+       EditFace *efan;
+       EditVert **v[2];
+       
+       v[0]= &efa1->v1;
+       v[1]= (efa2)? &efa2->v1: NULL;
+
+       efan= addfacelist(v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4],
+               (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL);
+
+       if (efa1->data)
+               EM_interp_from_faces(efa1, efa2, efan, i1, i2, i3, i4);
+       
+       return efan;
+}
 
 /* ********  EXTRUDE ********* */
 
@@ -1442,8 +1481,8 @@ short extrudeflag_vert(short flag, float *nor)
                        if(eed->tmp.f) {
                                efa = eed->tmp.f;
                                efa2->mat_nr= efa->mat_nr;
-                               efa2->tf= efa->tf;
                                efa2->flag= efa->flag;
+                               CustomData_em_copy_data(&em->fdata, &efa->data, &efa2->data);
                        }
                        
                        /* Needs smarter adaption of existing creases.
@@ -1761,18 +1800,15 @@ void flipface(EditFace *efa)
                SWAP(EditVert *, efa->v2, efa->v4);
                SWAP(EditEdge *, efa->e1, efa->e4);
                SWAP(EditEdge *, efa->e2, efa->e3);
-               SWAP(unsigned int, efa->tf.col[1], efa->tf.col[3]);
-               SWAP(float, efa->tf.uv[1][0], efa->tf.uv[3][0]);
-               SWAP(float, efa->tf.uv[1][1], efa->tf.uv[3][1]);
+               EM_interp_from_faces(efa, NULL, efa, 0, 3, 2, 1);
        }
        else {
                SWAP(EditVert *, efa->v2, efa->v3);
                SWAP(EditEdge *, efa->e1, efa->e3);
-               SWAP(unsigned int, efa->tf.col[1], efa->tf.col[2]);
                efa->e2->dir= 1-efa->e2->dir;
-               SWAP(float, efa->tf.uv[1][0], efa->tf.uv[2][0]);
-               SWAP(float, efa->tf.uv[1][1], efa->tf.uv[2][1]);
+               EM_interp_from_faces(efa, NULL, efa, 0, 2, 1, 3);
        }
+
        if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
        else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
 }
index d0e9302f82b7eca7a1ed9568f9bd786e22b7e88d..c5958be912b61ae4e34dd339302cce02142a199a 100644 (file)
@@ -62,6 +62,7 @@ editmesh_mods.c, UI level access, no geometry changes
 #include "BKE_displist.h"
 #include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
 #include "BKE_material.h"
@@ -824,13 +825,26 @@ int facegroup_select(short mode)
                                        }
                                }
                        } else if (mode==2) { /* same image */
+                               TFace *tf, *base_tf;
+
+                               base_tf = (TFace*)CustomData_em_get(&em->fdata, base_efa->data,
+                                                                   LAYERTYPE_TFACE);
+
+                               if(!base_tf)
+                                       return selcount;
+
                                for(efa= em->faces.first; efa; efa= efa->next) {
-                                       if (!(efa->f & SELECT) && !efa->h && base_efa->tf.tpage == efa->tf.tpage) {
-                                               EM_select_face(efa, 1);
-                                               selcount++;
-                                               deselcount--;
-                                               if (!deselcount) /*have we selected all posible faces?, if so return*/
-                                                       return selcount;
+                                       if (!(efa->f & SELECT) && !efa->h) {
+                                               tf = (TFace*)CustomData_em_get(&em->fdata, efa->data,
+                                                                              LAYERTYPE_TFACE);
+
+                                               if(base_tf->tpage == tf->tpage) {
+                                                       EM_select_face(efa, 1);
+                                                       selcount++;
+                                                       deselcount--;
+                                                       if (!deselcount) /*have we selected all posible faces?, if so return*/
+                                                               return selcount;
+                                               }
                                        }
                                }
                        } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
@@ -2888,17 +2902,6 @@ static int tface_is_selected(TFace *tf)
        return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
 }
 
-static int faceselect_nfaces_selected(Mesh *me)
-{
-       int i, count= 0;
-
-       for (i=0; i<me->totface; i++)
-               if (tface_is_selected(&me->tface[i]))
-                       count++;
-
-       return count;
-}
-
        /* XXX, code for both these functions should be abstract,
         * then unified, then written for other things (like objects,
         * which would use same as vertices method), then added
@@ -2906,38 +2909,39 @@ static int faceselect_nfaces_selected(Mesh *me)
         */
 void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
 {
-       if (!faceselect_nfaces_selected(me)) {
-               error("No faces selected.");
-       } else {
-               float norm[3];
-               int i;
-
-               norm[0]= norm[1]= norm[2]= 0.0;
-               for (i=0; i<me->totface; i++) {
-                       MFace *mf= ((MFace*) me->mface) + i;
-                       TFace *tf= ((TFace*) me->tface) + i;
-       
-                       if (tface_is_selected(tf)) {
-                               float *v1, *v2, *v3, fno[3];
-
-                               v1= me->mvert[mf->v1].co;
-                               v2= me->mvert[mf->v2].co;
-                               v3= me->mvert[mf->v3].co;
-                               if (mf->v4) {
-                                       float *v4= me->mvert[mf->v4].co;
-                                       CalcNormFloat4(v1, v2, v3, v4, fno);
-                               } else {
-                                       CalcNormFloat(v1, v2, v3, fno);
-                               }
-
-                               norm[0]+= fno[0];
-                               norm[1]+= fno[1];
-                               norm[2]+= fno[2];
+       float norm[3];
+       int i, totselected = 0;
+
+       norm[0]= norm[1]= norm[2]= 0.0;
+       for (i=0; i<me->totface; i++) {
+               MFace *mf= ((MFace*) me->mface) + i;
+               TFace *tf= ((TFace*) me->tface) + i;
+
+               if (tface_is_selected(tf)) {
+                       float *v1, *v2, *v3, fno[3];
+
+                       v1= me->mvert[mf->v1].co;
+                       v2= me->mvert[mf->v2].co;
+                       v3= me->mvert[mf->v3].co;
+                       if (mf->v4) {
+                               float *v4= me->mvert[mf->v4].co;
+                               CalcNormFloat4(v1, v2, v3, v4, fno);
+                       } else {
+                               CalcNormFloat(v1, v2, v3, fno);
                        }
+
+                       norm[0]+= fno[0];
+                       norm[1]+= fno[1];
+                       norm[2]+= fno[2];
+
+                       totselected++;
                }
+       }
 
+       if (totselected == 0)
+               error("No faces selected.");
+       else
                view3d_align_axis_to_vector(v3d, axis, norm);
-       }
 }
 
 void editmesh_align_view_to_selected(View3D *v3d, int axis)
index 33f47fe76dda00f9e0306d5db4a4826c33a3343d..2d10f93ef1c38b854ca82f359ba2bec734ad3c61 100644 (file)
@@ -66,6 +66,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 #include "BLI_heap.h"
 
 #include "BKE_depsgraph.h"
+#include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_mesh.h"
@@ -163,41 +164,16 @@ void convert_to_triface(int direction)
                                fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
                                /* this makes sure exact squares get split different in both cases */
                                if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
-                                       
-                                       efan= addfacelist(efa->v1, efa->v2, efa->v3, 0, efa, NULL);
+                                       efan= EM_face_from_faces(efa, NULL, 0, 1, 2, -1);
                                        if(efa->f & SELECT) EM_select_face(efan, 1);
-                                       efan= addfacelist(efa->v1, efa->v3, efa->v4, 0, efa, NULL);
+                                       efan= EM_face_from_faces(efa, NULL, 0, 2, 3, -1);
                                        if(efa->f & SELECT) EM_select_face(efan, 1);
-
-                                       efan->tf.uv[1][0]= efan->tf.uv[2][0];
-                                       efan->tf.uv[1][1]= efan->tf.uv[2][1];
-                                       efan->tf.uv[2][0]= efan->tf.uv[3][0];
-                                       efan->tf.uv[2][1]= efan->tf.uv[3][1];
-                                       
-                                       efan->tf.col[1]= efan->tf.col[2];
-                                       efan->tf.col[2]= efan->tf.col[3];
                                }
                                else {
-                                       efan= addfacelist(efa->v1, efa->v2, efa->v4, 0, efa, NULL);
+                                       efan= EM_face_from_faces(efa, NULL, 0, 1, 3, -1);
                                        if(efa->f & SELECT) EM_select_face(efan, 1);
-                                       
-                                       efan->tf.uv[2][0]= efan->tf.uv[3][0];
-                                       efan->tf.uv[2][1]= efan->tf.uv[3][1];
-                                       efan->tf.col[2]= efan->tf.col[3];
-                                       
-                                       efan= addfacelist(efa->v2, efa->v3, efa->v4, 0, efa, NULL);
+                                       efan= EM_face_from_faces(efa, NULL, 1, 2, 3, -1);
                                        if(efa->f & SELECT) EM_select_face(efan, 1);
-                                       
-                                       efan->tf.uv[0][0]= efan->tf.uv[1][0];
-                                       efan->tf.uv[0][1]= efan->tf.uv[1][1];
-                                       efan->tf.uv[1][0]= efan->tf.uv[2][0];
-                                       efan->tf.uv[1][1]= efan->tf.uv[2][1];
-                                       efan->tf.uv[2][0]= efan->tf.uv[3][0];
-                                       efan->tf.uv[2][1]= efan->tf.uv[3][1];
-                                       
-                                       efan->tf.col[0]= efan->tf.col[1];
-                                       efan->tf.col[1]= efan->tf.col[2];
-                                       efan->tf.col[2]= efan->tf.col[3];
                                }
                                
                                BLI_remlink(&em->faces, efa);
@@ -217,7 +193,6 @@ void convert_to_triface(int direction)
        
 }
 
-
 int removedoublesflag(short flag, float limit)         /* return amount */
 {
        EditMesh *em = G.editMesh;
@@ -395,15 +370,11 @@ int removedoublesflag(short flag, float limit)            /* return amount */
                                if(efa->v4) {
                                        if(test==1 || test==2) {
                                                efa->v2= efa->v3;
-                                               efa->tf.uv[1][0] = efa->tf.uv[2][0];
-                                               efa->tf.uv[1][1] = efa->tf.uv[2][1];
-                                               efa->tf.col[1] = efa->tf.col[2];
-                                               
                                                efa->v3= efa->v4;
-                                               efa->tf.uv[2][0] = efa->tf.uv[3][0];
-                                               efa->tf.uv[2][1] = efa->tf.uv[3][1];
-                                               efa->tf.col[2] = efa->tf.col[3];
                                                efa->v4= 0;
+
+                                               EM_interp_from_faces(efa, NULL, efa, 0, 2, 3, 3);
+
                                                test= 0;
                                        }
                                        else if(test==8 || test==16) {
@@ -1424,21 +1395,21 @@ static void facecopy(EditFace *source, EditFace *target)
 {
        float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
        float *v4 = source->v4? source->v4->co: NULL;
+       float w[4][4];
+
+       CustomData_em_copy_data(&G.editMesh->fdata, source->data, &target->data);
+
+       target->mat_nr = source->mat_nr;
+       target->flag   = source->flag;  
 
-       interp_uv_vcol(v1, v2, v3, v4, target->v1->co, &source->tf, &target->tf, 0);
-       interp_uv_vcol(v1, v2, v3, v4, target->v2->co, &source->tf, &target->tf, 1);
-       interp_uv_vcol(v1, v2, v3, v4, target->v3->co, &source->tf, &target->tf, 2);
+       InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
+       InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
+       InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
        if (target->v4)
-               interp_uv_vcol(v1, v2, v3, v4, target->v4->co, &source->tf, &target->tf, 3);
-
-       target->mat_nr   = source->mat_nr;
-       target->tf.flag = source->tf.flag&~TF_ACTIVE;
-       target->tf.transp  = source->tf.transp;
-       target->tf.mode = source->tf.mode;
-       target->tf.tile = source->tf.tile;
-       target->tf.unwrap  = source->tf.unwrap;
-       target->tf.tpage   = source->tf.tpage;
-       target->flag       = source->flag;      
+               InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
+       
+       CustomData_em_interp(&G.editMesh->fdata, &source->data, NULL,
+                            (float*)w, 1, target->data);
 }
 
 static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
@@ -1972,7 +1943,7 @@ static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts)
 
 static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts)
 {
-       EditEdge *cedge[3];
+       EditEdge *cedge[3]={0};
        EditVert *v[4], **verts[3];
        EditFace *hold;
        short start=0, start2=0, start3=0, vertsize, i, repeats;
@@ -2924,99 +2895,47 @@ static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
 #define VTEST(face, num, other) \
        (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3) 
 
-static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, float **uv, unsigned int *col)
+static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex)
 {
        if VTEST(efa, 1, efa1) {
-       //if(efa->v1!=efa1->v1 && efa->v1!=efa1->v2 && efa->v1!=efa1->v3) {
                *v1= efa->v1;
                *v2= efa->v2;
-               uv[0] = efa->tf.uv[0];
-               uv[1] = efa->tf.uv[1];
-               col[0] = efa->tf.col[0];
-               col[1] = efa->tf.col[1];
+               vindex[0]= 0;
+               vindex[1]= 1;
        }
        else if VTEST(efa, 2, efa1) {
-       //else if(efa->v2!=efa1->v1 && efa->v2!=efa1->v2 && efa->v2!=efa1->v3) {
                *v1= efa->v2;
                *v2= efa->v3;
-               uv[0] = efa->tf.uv[1];
-               uv[1] = efa->tf.uv[2];
-               col[0] = efa->tf.col[1];
-               col[1] = efa->tf.col[2];
+               vindex[0]= 1;
+               vindex[1]= 2;
        }
        else if VTEST(efa, 3, efa1) {
-       // else if(efa->v3!=efa1->v1 && efa->v3!=efa1->v2 && efa->v3!=efa1->v3) {
                *v1= efa->v3;
                *v2= efa->v1;
-               uv[0] = efa->tf.uv[2];
-               uv[1] = efa->tf.uv[0];
-               col[0] = efa->tf.col[2];
-               col[1] = efa->tf.col[0];
+               vindex[0]= 2;
+               vindex[1]= 0;
        }
        
        if VTEST(efa1, 1, efa) {
-       // if(efa1->v1!=efa->v1 && efa1->v1!=efa->v2 && efa1->v1!=efa->v3) {
                *v3= efa1->v1;
-               uv[2] = efa1->tf.uv[0];
-               col[2] = efa1->tf.col[0];
-
                *v4= efa1->v2;
-               uv[3] = efa1->tf.uv[1];
-               col[3] = efa1->tf.col[1];
-/*
-if(efa1->v2== *v2) {
-                       *v4= efa1->v3;
-                       uv[3] = efa1->tf.uv[2];
-               } else {
-                       *v4= efa1->v2;
-                       uv[3] = efa1->tf.uv[1];
-               }       
-               */
+               vindex[2]= 0;
+               vindex[3]= 1;
        }
        else if VTEST(efa1, 2, efa) {
-       // else if(efa1->v2!=efa->v1 && efa1->v2!=efa->v2 && efa1->v2!=efa->v3) {
                *v3= efa1->v2;
-               uv[2] = efa1->tf.uv[1];
-               col[2] = efa1->tf.col[1];
-
                *v4= efa1->v3;
-               uv[3] = efa1->tf.uv[2];
-               col[3] = efa1->tf.col[2];
-/*
-if(efa1->v3== *v2) {
-                       *v4= efa1->v1;
-                       uv[3] = efa1->tf.uv[0];
-               } else {        
-                       *v4= efa1->v3;
-                       uv[3] = efa1->tf.uv[2];
-               }       
-               */
+               vindex[2]= 1;
+               vindex[3]= 2;
        }
        else if VTEST(efa1, 3, efa) {
-       // else if(efa1->v3!=efa->v1 && efa1->v3!=efa->v2 && efa1->v3!=efa->v3) {
                *v3= efa1->v3;
-               uv[2] = efa1->tf.uv[2];
-               col[2] = efa1->tf.col[2];
-
                *v4= efa1->v1;
-               uv[3] = efa1->tf.uv[0];
-               col[3] = efa1->tf.col[0];
-/*
-if(efa1->v1== *v2) {
-                       *v4= efa1->v2;
-                       uv[3] = efa1->tf.uv[3];
-               } else {        
-                       *v4= efa1->v1;
-                       uv[3] = efa1->tf.uv[0];
-               }       
-               */
+               vindex[2]= 2;
+               vindex[3]= 0;
        }
-       else {
+       else
                *v3= *v4= NULL;
-               
-               return;
-       }
-       
 }
 
 /* Helper functions for edge/quad edit features*/
@@ -3071,10 +2990,8 @@ void beauty_fill(void)
        // void **efaar, **efaa;
        EVPTuple *efaar;
        EVPtr *efaa;
-       float *uv[4];
-       unsigned int col[4];
        float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
-       int totedge, ok, notbeauty=8, onedone;
+       int totedge, ok, notbeauty=8, onedone, vindex[4];
 
        /* - all selected edges with two faces
                * - find the faces: store them in edges (using datablock)
@@ -3121,7 +3038,7 @@ void beauty_fill(void)
                                
                                if(ok) {
                                        /* test convex */
-                                       givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col);
+                                       givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
                                        if(v1 && v2 && v3 && v4) {
                                                if( convex(v1->co, v2->co, v3->co, v4->co) ) {
 
@@ -3174,22 +3091,14 @@ void beauty_fill(void)
                                                                        efa= efaa[1];
                                                                        efa->f1= 1;
 
-                                                                       w= addfacelist(v1, v2, v3, 0, efa, NULL);
+                                                                       w= EM_face_from_faces(efaa[0], efaa[1],
+                                                                               vindex[0], vindex[1], 4+vindex[2], -1);
                                                                        w->f |= SELECT;
-                                                                       
-                                                                       UVCOPY(w->tf.uv[0], uv[0]);
-                                                                       UVCOPY(w->tf.uv[1], uv[1]);
-                                                                       UVCOPY(w->tf.uv[2], uv[2]);
 
-                                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2];
-                                                                       w= addfacelist(v1, v3, v4, 0, efa, NULL);
-                                                                       w->f |= SELECT;
-
-                                                                       UVCOPY(w->tf.uv[0], uv[0]);
-                                                                       UVCOPY(w->tf.uv[1], uv[2]);
-                                                                       UVCOPY(w->tf.uv[2], uv[3]);
 
-                                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3];
+                                                                       w= EM_face_from_faces(efaa[0], efaa[1],
+                                                                               vindex[0], 4+vindex[2], 4+vindex[3], -1);
+                                                                       w->f |= SELECT;
 
                                                                        onedone= 1;
                                                                }
@@ -3202,20 +3111,16 @@ void beauty_fill(void)
                                                                        efa= efaa[1];
                                                                        efa->f1= 1;
 
-                                                                       w= addfacelist(v2, v3, v4, 0, efa, NULL);
+
+                                                                       w= EM_face_from_faces(efaa[0], efaa[1],
+                                                                               vindex[1], 4+vindex[2], 4+vindex[3], -1);
                                                                        w->f |= SELECT;
 
-                                                                       UVCOPY(w->tf.uv[0], uv[1]);
-                                                                       UVCOPY(w->tf.uv[1], uv[3]);
-                                                                       UVCOPY(w->tf.uv[2], uv[4]);
 
-                                                                       w= addfacelist(v1, v2, v4, 0, efa, NULL);
+                                                                       w= EM_face_from_faces(efaa[0], efaa[1],
+                                                                               vindex[0], 4+vindex[1], 4+vindex[3], -1);
                                                                        w->f |= SELECT;
 
-                                                                       UVCOPY(w->tf.uv[0], uv[0]);
-                                                                       UVCOPY(w->tf.uv[1], uv[1]);
-                                                                       UVCOPY(w->tf.uv[2], uv[3]);
-
                                                                        onedone= 1;
                                                                }
                                                        }
@@ -3414,10 +3319,15 @@ static int compareFaceUV(EditFace *f1, EditFace *f2)
 {
        EditVert **faceVert1, **faceVert2, *faceVerts1[5], *faceVerts2[5];
        int i1, i2;
+       TFace *tf1, *tf2;
+
+       tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_TFACE);
+       tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_TFACE);
        
-       if(f1->tf.tpage == NULL && f2->tf.tpage == NULL)
+       if(tf1 == NULL || tf2 == NULL) return 1;
+       else if(tf1->tpage == NULL && tf2->tpage == NULL)
                return 1;
-       else if(f1->tf.tpage != f2->tf.tpage)
+       else if(tf1->tpage != tf2->tpage)
                return 0;
 
        FILL_FACEVERTS(f1, faceVerts1);
@@ -3430,7 +3340,7 @@ static int compareFaceUV(EditFace *f1, EditFace *f2)
                i2 = 0;
                while(*faceVert2){
                        if( *faceVert1 == *faceVert2){
-                               if(!compare2(f1->tf.uv[i1], f2->tf.uv[i2], UV_LIMIT))
+                               if(!compare2(tf1->uv[i1], tf2->uv[i2], UV_LIMIT))
                                        return 0;
                        }
                        i2++;
@@ -3447,6 +3357,18 @@ static int compareFaceCol(EditFace *f1, EditFace *f2)
 {
        EditVert **faceVert1, **faceVert2, *faceVerts1[5], *faceVerts2[5];
        int i1, i2;
+       TFace *tf1, *tf2;
+       unsigned int *col1, *col2;
+
+       tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_TFACE);
+       tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_TFACE);
+
+       if(tf1) col1 = tf1->col;
+       else col1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_MCOL);
+       if(tf2) col2 = tf2->col;
+       else col2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_MCOL);
+
+       if(!col1 || !col2) return 1;
        
        FILL_FACEVERTS(f1, faceVerts1);
        FILL_FACEVERTS(f2, faceVerts2);
@@ -3458,7 +3380,7 @@ static int compareFaceCol(EditFace *f1, EditFace *f2)
                i2 = 0;
                while(*faceVert2){
                        if( *faceVert1 == *faceVert2){
-                               if(!compare3(f1->tf.col[i1], f2->tf.col[i2], COL_LIMIT))
+                               if(!compare3(col1[i1], col2[i2], COL_LIMIT))
                                        return 0;
                        }
                        i2++;
@@ -3475,7 +3397,6 @@ static void meshJoinFaces(EditEdge *joined)
        FacePairL *fpl = joined->tmp.p;
        EditFace *face1, *face2, *efa;
        EditVert *v1free, *v2free;
-       int i;
        
        face1 = fpl->face1;
        face2 = fpl->face2;
@@ -3490,75 +3411,12 @@ static void meshJoinFaces(EditEdge *joined)
        face2->v2->f1 = 1;
        face2->v3->f1 = 2;
        
-switch(v1free->f1){
-               case 0:
-                       i = 2;
-                       break;
-               case 1:
-                       i = 3;
-                       break;
-               case 2:
-                       i = 1;
-                       break;
-       }
-
-       switch(i){
-               case 2:
-                       /*this is really lazy...*/
-                       efa = addfacelist(face1->v1, face1->v2, v2free, face1->v3, face1, NULL);
-                       efa->tf.uv[0][0] = face1->tf.uv[0][0];
-                       efa->tf.uv[0][1] = face1->tf.uv[0][1];
-                       efa->tf.col[0] = face1->tf.col[0];
-                       
-                       efa->tf.uv[1][0] = face1->tf.uv[1][0];
-                       efa->tf.uv[1][1] = face1->tf.uv[1][1];
-                       efa->tf.col[1] = face1->tf.col[1];
-                       
-                       efa->tf.uv[2][0] = face2->tf.uv[v2free->f1][0];
-                       efa->tf.uv[2][1] = face2->tf.uv[v2free->f1][1];
-                       efa->tf.col[2] = face2->tf.col[v2free->f1];
-                       
-                       efa->tf.uv[3][0] = face1->tf.uv[2][0];
-                       efa->tf.uv[3][1] = face1->tf.uv[2][1];
-                       efa->tf.col[3] = face1->tf.col[2];
-                       break;
-               case 3:
-                       efa = addfacelist(face1->v1, face1->v2, face1->v3, v2free, face1, NULL);
-                       efa->tf.uv[0][0] = face1->tf.uv[0][0];
-                       efa->tf.uv[0][1] = face1->tf.uv[0][1];
-                       efa->tf.col[0] = face1->tf.col[0];
-                       
-                       efa->tf.uv[1][0] = face1->tf.uv[1][0];
-                       efa->tf.uv[1][1] = face1->tf.uv[1][1];
-                       efa->tf.col[1] = face1->tf.col[1];
-                       
-                       efa->tf.uv[2][0] = face1->tf.uv[2][0];
-                       efa->tf.uv[2][1] = face1->tf.uv[2][1];
-                       efa->tf.col[2] = face1->tf.col[2];
-                       
-                       efa->tf.uv[3][0] = face2->tf.uv[v2free->f1][0];
-                       efa->tf.uv[3][1] = face2->tf.uv[v2free->f1][1];
-                       efa->tf.col[3] = face1->tf.col[v2free->f1];
-                       break;
-               case 1:
-                       efa = addfacelist(face1->v1, v2free, face1->v2, face1->v3, face1, NULL);
-                       efa->tf.uv[0][0] = face1->tf.uv[0][0];
-                       efa->tf.uv[0][1] = face1->tf.uv[0][1];
-                       efa->tf.col[0] = face1->tf.col[0];
-                       
-                       efa->tf.uv[1][0] = face2->tf.uv[v2free->f1][0];
-                       efa->tf.uv[1][1] = face2->tf.uv[v2free->f1][1];
-                       efa->tf.col[1] = face2->tf.col[v2free->f1];
-                       
-                       efa->tf.uv[2][0] = face1->tf.uv[1][0];
-                       efa->tf.uv[2][1] = face1->tf.uv[1][1];
-                       efa->tf.col[2] = face1->tf.col[1];
-                       
-                       efa->tf.uv[3][0] = face1->tf.uv[2][0];
-                       efa->tf.uv[3][1] = face1->tf.uv[2][1];
-                       efa->tf.col[3] = face1->tf.col[2];
-                       break;
-       }
+       if(v1free->f1 == 0)
+               efa= EM_face_from_faces(face1, face2, 0, 1, 4+v2free->f1, 2);
+       else if(v1free->f1 == 1)
+               efa= EM_face_from_faces(face1, face2, 0, 1, 2, 4+v2free->f1);
+       else /* if(v1free->f1 == 2) */
+               efa= EM_face_from_faces(face1, face2, 0, 4+v2free->f1, 1, 2);
        
        EM_select_face(efa,1);
        /*flag for removal*/
@@ -3771,11 +3629,7 @@ void edge_flip(void)
        //void **efaar, **efaa;
        EVPTuple *efaar;
        EVPtr *efaa;
-
-       float *uv[4];
-       unsigned int col[4];
-
-       int totedge, ok;
+       int totedge, ok, vindex[4];
        
        /* - all selected edges with two faces
         * - find the faces: store them in edges (using datablock)
@@ -3812,7 +3666,7 @@ void edge_flip(void)
                        
                        if(ok) {
                                /* test convex */
-                               givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col);
+                               givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
 
 /*
                4-----3         4-----3
@@ -3827,27 +3681,19 @@ void edge_flip(void)
                                if (v1 && v2 && v3) {
                                        if( convex(v1->co, v2->co, v3->co, v4->co) ) {
                                                if(exist_face(v1, v2, v3, v4)==0) {
-                                                       w = addfacelist(v1, v2, v3, 0, efaa[1], NULL); /* outch this may break seams */ 
+                                                       /* outch this may break seams */ 
+                                                       w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
+                                                               vindex[1], 4+vindex[2], -1);
+
                                                        EM_select_face(w, 1);
                                                        untag_edges(w);
 
-                                                       UVCOPY(w->tf.uv[0], uv[0]);
-                                                       UVCOPY(w->tf.uv[1], uv[1]);
-                                                       UVCOPY(w->tf.uv[2], uv[2]);
+                                                       /* outch this may break seams */
+                                                       w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
+                                                               4+vindex[2], 4+vindex[3], -1);
 
-                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2]; 
-                                                       
-                                                       w = addfacelist(v1, v3, v4, 0, efaa[1], NULL); /* outch this may break seams */
                                                        EM_select_face(w, 1);
                                                        untag_edges(w);
-
-                                                       UVCOPY(w->tf.uv[0], uv[0]);
-                                                       UVCOPY(w->tf.uv[1], uv[2]);
-                                                       UVCOPY(w->tf.uv[2], uv[3]);
-
-                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3]; 
-                                                       
-                                                       /* erase old faces and edge */
                                                }
                                                /* tag as to-be-removed */
                                                FACE_MARKCLEAR(efaa[1]);
@@ -3880,326 +3726,153 @@ void edge_flip(void)
 static void edge_rotate(EditEdge *eed,int dir)
 {
        EditMesh *em = G.editMesh;
+       EditVert **verts[2];
        EditFace *face[2], *efa, *newFace[2];
-       EditVert *faces[2][4],*v1,*v2,*v3,*v4,*vtemp;
-       EditEdge *srchedge = NULL;
-       short facecount=0, p1=0,p2=0,p3=0,p4=0,fac1=4,fac2=4,i,j,numhidden;
-       EditEdge **hiddenedges;
+       EditEdge **edges[2], **hiddenedges, *srchedge;
+       int facecount, p1, p2, p3, p4, fac1, fac2, i, j;
+       int numhidden, numshared, p[2][4];
        
        /* check to make sure that the edge is only part of 2 faces */
+       facecount = 0;
        for(efa = em->faces.first;efa;efa = efa->next) {
                if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) {
-                       if(facecount == 2) {
+                       if(facecount >= 2) {
+                               /* more than two faces with this edge */
                                return;
                        }
-                       if(facecount < 2)
+                       else {
                                face[facecount] = efa;
-                       facecount++;
+                               facecount++;
+                       }
                }
        }
  
-       if(facecount < 2) {
+       if(facecount < 2)
                return;
-       }
 
        /* how many edges does each face have */
-       if(face[0]->e4 == NULL)
-               fac1=3;
-       else
-               fac1=4;
-       if(face[1]->e4 == NULL)
-               fac2=3;
-       else
-               fac2=4;
-       
-       /*store the face info in a handy array */                       
-       faces[0][0] =  face[0]->v1;
-       faces[0][1] =  face[0]->v2;
-       faces[0][2] =  face[0]->v3;
-       if(face[0]->e4 != NULL)
-               faces[0][3] =  face[0]->v4;
-       else
-               faces[0][3] = NULL;
-                       
-       faces[1][0] =  face[1]->v1;
-       faces[1][1] =  face[1]->v2;
-       faces[1][2] =  face[1]->v3;
-       if(face[1]->e4 != NULL)
-               faces[1][3] =  face[1]->v4;
-       else
-               faces[1][3] = NULL;
+       if(face[0]->e4) fac1= 4;
+       else fac1= 3;
+
+       if(face[1]->e4) fac2= 4;
+       else fac2= 3;
        
+       /* make a handy array for verts and edges */
+       verts[0]= &face[0]->v1;
+       edges[0]= &face[0]->e1;
+       verts[1]= &face[1]->v1;
+       edges[1]= &face[1]->e1;
 
        /* we don't want to rotate edges between faces that share more than one edge */
-       
-       j=0;
-       if(face[0]->e1 == face[1]->e1 ||
-          face[0]->e1 == face[1]->e2 ||
-          face[0]->e1 == face[1]->e3 ||
-          ((face[1]->e4) && face[0]->e1 == face[1]->e4) )
-          j++;
-          
-       if(face[0]->e2 == face[1]->e1 ||
-          face[0]->e2 == face[1]->e2 ||
-          face[0]->e2 == face[1]->e3 ||
-          ((face[1]->e4) && face[0]->e2 == face[1]->e4) )
-          j++;
-          
-       if(face[0]->e3 == face[1]->e1 ||
-          face[0]->e3 == face[1]->e2 ||
-          face[0]->e3 == face[1]->e3 ||
-          ((face[1]->e4) && face[0]->e3 == face[1]->e4) )
-          j++;    
-
-       if(face[0]->e4) {
-               if(face[0]->e4 == face[1]->e1 ||
-                  face[0]->e4 == face[1]->e2 ||
-                  face[0]->e4 == face[1]->e3 ||
-                  ((face[1]->e4) && face[0]->e4 == face[1]->e4) )
-                          j++; 
-        }                 
-       if(j > 1) {
+       numshared= 0;
+       for(i=0; i<fac1; i++)
+               for(j=0; j<fac2; j++)
+                       if (edges[0][i] == edges[1][j])
+                               numshared++;
+
+       if(numshared > 1)
                return;
-       }
        
-       /* Coplaner Faces Only Please */
-       if(Inpf(face[0]->n,face[1]->n) <= 0.000001) {   
+       /* coplaner faces only please */
+       if(Inpf(face[0]->n,face[1]->n) <= 0.000001)
                return;
-       }
        
-       /*get the edges verts */
-       v1 = eed->v1;
-       v2 = eed->v2;
-       v3 = eed->v1;
-       v4 = eed->v2;
-
-       /*figure out where the edges verts lie one the 2 faces */
-       for(i=0;i<4;i++) {
-               if(v1 == faces[0][i])
-                       p1 = i;
-               if(v2 == faces[0][i])
-                       p2 = i;
-               if(v1 == faces[1][i])
-                       p3 = i;
-               if(v2 == faces[1][i])
-                       p4 = i;
-       }
-       
-       /*make sure the verts are in the correct order */
-       if((p1+1)%fac1 == p2) {
-               vtemp = v2;
-               v2 = v1;
-               v1 = vtemp;
-               
-               i = p1;
-               p1 = p2;
-               p2 = i;
-       }
-       if((p3+1)%fac2 == p4) {
-               vtemp = v4;
-               v4 = v3;
-               v3 = vtemp;
-               
-               i = p3;
-               p3 = p4;
-               p4 = i; 
-       }       
+       /* we want to construct an array of vertex indicis in both faces, starting at
+          the last vertex of the edge being rotated.
+          - first we find the two vertices that lie on the rotating edge
+          - then we make sure they are ordered according to the face vertex order
+          - and then we construct the array */
+       p1= p2= p3= p4= 0;
 
+       for(i=0; i<4; i++) {
+               if(eed->v1 == verts[0][i]) p1 = i;
+               if(eed->v2 == verts[0][i]) p2 = i;
+               if(eed->v1 == verts[1][i]) p3 = i;
+               if(eed->v2 == verts[1][i]) p4 = i;
+       }
+       
+       if((p1+1)%fac1 == p2)
+               SWAP(int, p1, p2);
+       if((p3+1)%fac2 == p4)
+               SWAP(int, p3, p4);
+       
+       for (i = 0; i < 4; i++) {
+               p[0][i]= (p1 + i)%fac1;
+               p[1][i]= (p3 + i)%fac2;
+       }
 
-       /* Create an Array of the Edges who have h set prior to rotate */
+       /* create an Array of the Edges who have h set prior to rotate */
        numhidden = 0;
-       for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) {
-               if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) {
+       for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next)
+               if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT)))
                        numhidden++;
-               }
-       }
-       hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1,"Hidden Vert Scratch Array for Rotate Edges");
+
+       hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts");
        if(!hiddenedges) {
         error("Malloc Was not happy!");
         return;   
     }
+
     numhidden = 0;
-       for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) {
-               if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) {
-                       hiddenedges[numhidden] = srchedge;
-                       numhidden++;
-               }
-       }       
-                                                       
-       /* create the 2 new faces */                                                            
+       for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+               if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT))
+                       hiddenedges[numhidden++] = srchedge;
+
+       /* create the 2 new faces */
        if(fac1 == 3 && fac2 == 3) {
-               /*No need of reverse setup*/
-               newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%3],NULL,NULL,NULL);
-               newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%3],NULL,NULL,NULL);
-       
-               newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3];
-               newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3];
-               newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%3];
-               newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3];
-               newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3];
-               newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3];
-       
-               UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]);
-               UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); 
-               UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%3]);
-               UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]);
-               UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]);
-               UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]);
+               /* no need of reverse setup */
+
+               newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+               newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
        }
        else if(fac1 == 4 && fac2 == 3) {
                if(dir == 1) {
-                       newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%3],NULL,NULL);
-                       newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%4],NULL,NULL,NULL);
-       
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4];
-                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4];
-                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4];
-                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%3];
-                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3];
-                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4];
-       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); 
-                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]);         
-                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%3]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]); 
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
                } else if (dir == 2) {
-                       newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3+1)%3],faces[0][(p1)%4],faces[0][(p1+1 )%4],NULL,NULL);
-                       newFace[1] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3)%3],faces[1][(p3+1 )%3],NULL,NULL,NULL);
-
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2)%4];
-                       newFace[0]->tf.col[1] = face[1]->tf.col[(p3+1)%3];
-                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1  )%4];
-                       newFace[0]->tf.col[3] = face[0]->tf.col[(p1+1)%4];
-                       newFace[1]->tf.col[0] = face[0]->tf.col[(p1+2)%4];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3  )%3];
-                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+1)%3];
-       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[1]->tf.uv[(p3+1)%3]);  
-                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1  )%4]);          
-                       UVCOPY(newFace[0]->tf.uv[3],face[0]->tf.uv[(p1+1)%4]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3  )%3]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+1)%3]);  
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
                        
-                       faces[0][(p1+2)%fac1]->f |= SELECT;
-                       faces[1][(p3+1)%fac2]->f |= SELECT;             
+                       verts[0][p[0][2]]->f |= SELECT;
+                       verts[1][p[1][1]]->f |= SELECT;         
                }
        }
-
        else if(fac1 == 3 && fac2 == 4) {
                if(dir == 1) {
-                       newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%4],NULL,NULL,NULL);
-                       newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%3],NULL,NULL);
-       
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3];
-                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3];
-                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4];             
-                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%3];
-       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); 
-                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%3]);
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
                } else if (dir == 2) {
-                       newFace[0] = addfacelist(faces[0][(p1)%3],faces[0][(p1+1 )%3],faces[1][(p3+2 )%4],NULL,NULL,NULL);
-                       newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],NULL,NULL);
-       
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1 )%3];
-                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+1 )%3];
-                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3];             
-                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%3];
-       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1 )%3]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+1 )%3]); 
-                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]);
-                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%3]); 
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
                        
-                       faces[0][(p1+1)%fac1]->f |= SELECT;
-                       faces[1][(p3+2)%fac2]->f |= SELECT;     
+                       verts[0][p[0][1]]->f |= SELECT;
+                       verts[1][p[1][2]]->f |= SELECT; 
                }
        
        }
-       
        else if(fac1 == 4 && fac2 == 4) {
                if(dir == 1) {
-                       newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],NULL,NULL);
-                       newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],NULL,NULL);
-       
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4];
-                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4];
-                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4];
-                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4];             
-                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%4];
-                                                                       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); 
-                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]);         
-                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%4]);         
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
                } else if (dir == 2) {
-                       newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],NULL,NULL);
-                       newFace[1] = addfacelist(faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],NULL,NULL);
-       
-                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2 )%4];
-                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+3 )%4];
-                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4];
-                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+2 )%4];
-                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+3 )%4];
-                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4];             
-                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%4];
-                                                                       
-                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2 )%4]);
-                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+3 )%4]); 
-                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]);         
-                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+2 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+3 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]);
-                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%4]);         
+                       newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
+                       newFace[1]= EM_face_from_faces(face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
                        
-                       faces[0][(p1+2)%fac1]->f |= SELECT;
-                       faces[1][(p3+2)%fac2]->f |= SELECT;     
+                       verts[0][p[0][2]]->f |= SELECT;
+                       verts[1][p[1][2]]->f |= SELECT; 
                }
-               
-
        }               
-       else{
-               /*This should never happen*/
-               return;
-       }
+       else
+               return; /* This should never happen */
 
-       if(dir == 1) {
-               faces[0][(p1+1)%fac1]->f |= SELECT;
-               faces[1][(p3+1)%fac2]->f |= SELECT;
+       if(dir == 1 || (fac1 == 3 && fac2 == 3)) {
+               verts[0][p[0][1]]->f |= SELECT;
+               verts[1][p[1][1]]->f |= SELECT;
        }
        
-       /*Copy old edge's flags to new center edge*/
+       /* copy old edge's flags to new center edge*/
        for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) {
-               if(srchedge->v1->f & SELECT &&srchedge->v2->f & SELECT  ) {
+               if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) {
                        srchedge->f = eed->f;
                        srchedge->h = eed->h;
                        srchedge->dir = eed->dir;
@@ -4208,63 +3881,15 @@ static void edge_rotate(EditEdge *eed,int dir)
                }
        }
        
-       
-       /* copy flags and material */
-       
-       newFace[0]->mat_nr       = face[0]->mat_nr;
-       newFace[0]->tf.flag     = face[0]->tf.flag;
-       newFace[0]->tf.transp  = face[0]->tf.transp;
-       newFace[0]->tf.mode     = face[0]->tf.mode;
-       newFace[0]->tf.tile     = face[0]->tf.tile;
-       newFace[0]->tf.unwrap  = face[0]->tf.unwrap;
-       newFace[0]->tf.tpage   = face[0]->tf.tpage;
-       newFace[0]->flag           = face[0]->flag;
-
-       newFace[1]->mat_nr       = face[1]->mat_nr;
-       newFace[1]->tf.flag     = face[1]->tf.flag;
-       newFace[1]->tf.transp  = face[1]->tf.transp;
-       newFace[1]->tf.mode     = face[1]->tf.mode;
-       newFace[1]->tf.tile     = face[1]->tf.tile;
-       newFace[1]->tf.unwrap  = face[1]->tf.unwrap;
-       newFace[1]->tf.tpage   = face[1]->tf.tpage;
-       newFace[1]->flag           = face[1]->flag;
-       
-       /* Resetting Hidden Flag */
-       for(numhidden--;numhidden>=0;numhidden--) {
-               hiddenedges[numhidden]->h = 1;
-                  
-       }
+       /* resetting hidden flag */
+       for(numhidden--; numhidden>=0; numhidden--)
+               hiddenedges[numhidden]->h= 1;
        
        /* check for orhphan edges */
-       for(srchedge=em->edges.first;srchedge;srchedge = srchedge->next) {
-               srchedge->f1 = -1;   
-       }
+       for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+               srchedge->f1= -1;   
        
-       /*for(efa = em->faces.first;efa;efa = efa->next) {
-               if(efa->h == 0) {
-                       efa->e1->f1 = 1;   
-                       efa->e2->f1 = 1;   
-                       efa->e3->f1 = 1;   
-                       if(efa->e4) {
-                               efa->e4->f1 = 1;   
-                       }
-               }
-               if(efa->h == 1) {
-                       if(efa->e1->f1 == -1) {
-                               efa->e1->f1 = 0; 
-                       }  
-                       if(efa->e2->f1 == -1) {
-                               efa->e2->f1 = 0; 
-                       } 
-                                               if(efa->e1->f1 == -1) {
-                               efa->e1->f1 = 0; 
-                       }       
-                       if(efa->e4) {
-                               efa->e4->f1 = 1;   
-                       }
-               }               
-       }
-        A Little Cleanup */
+       /* cleanup */
        MEM_freeN(hiddenedges);
        
        /* get rid of the old edge and faces*/
@@ -4274,8 +3899,7 @@ static void edge_rotate(EditEdge *eed,int dir)
        free_editface(face[0]); 
        BLI_remlink(&em->faces, face[1]);
        free_editface(face[1]);         
-       return;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
-}                                              
+}
 
 /* only accepts 1 selected edge, or 2 selected faces */
 void edge_rotate_selected(int dir)
@@ -6355,14 +5979,15 @@ static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase
        wUV *curwvert, *newwvert;
        wUVNode *newnode;
        int found;
+       TFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE);
        
        found = 0;
        
        for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
-               if(curwvert->eve == eve && curwvert->u == efa->tf.uv[tfindex][0] && curwvert->v == efa->tf.uv[tfindex][1]){
+               if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){
                        newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
-                       newnode->u = &(efa->tf.uv[tfindex][0]);
-                       newnode->v = &(efa->tf.uv[tfindex][1]);
+                       newnode->u = &(tf->uv[tfindex][0]);
+                       newnode->v = &(tf->uv[tfindex][1]);
                        BLI_addtail(&(curwvert->nodes), newnode);
                        found = 1;
                        break;
@@ -6371,8 +5996,8 @@ static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase
        
        if(!found){
                newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
-               newnode->u = &(efa->tf.uv[tfindex][0]);
-               newnode->v = &(efa->tf.uv[tfindex][1]);
+               newnode->u = &(tf->uv[tfindex][0]);
+               newnode->v = &(tf->uv[tfindex][1]);
                
                newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert");
                newwvert->u = *(newnode->u);
@@ -6400,21 +6025,22 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
 {
        wUVEdge *curwedge, *newwedge;
        int v1tfindex, v2tfindex, found;
+       TFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE);
        
        found = 0;
        
        if(eed->v1 == efa->v1) v1tfindex = 0;
        else if(eed->v1 == efa->v2) v1tfindex = 1;
        else if(eed->v1 == efa->v3) v1tfindex = 2;
-       else if(eed->v1 == efa->v4) v1tfindex = 3;
+       else /* if(eed->v1 == efa->v4) */ v1tfindex = 3;
                        
        if(eed->v2 == efa->v1) v2tfindex = 0;
        else if(eed->v2 == efa->v2) v2tfindex = 1;
        else if(eed->v2 == efa->v3) v2tfindex = 2;
-       else if(eed->v2 == efa->v4) v2tfindex = 3;
+       else /* if(eed->v2 == efa->v4) */ v2tfindex = 3;
 
        for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
-                       if(curwedge->eed == eed && curwedge->v1uv[0] == efa->tf.uv[v1tfindex][0] && curwedge->v1uv[1] == efa->tf.uv[v1tfindex][1] && curwedge->v2uv[0] == efa->tf.uv[v2tfindex][0] && curwedge->v2uv[1] == efa->tf.uv[v2tfindex][1]){
+                       if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){
                                found = 1;
                                break; //do nothing, we don't need another welded uv edge
                        }
@@ -6422,10 +6048,10 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
        
        if(!found){
                newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge");
-               newwedge->v1uv[0] = efa->tf.uv[v1tfindex][0];
-               newwedge->v1uv[1] = efa->tf.uv[v1tfindex][1];
-               newwedge->v2uv[0] = efa->tf.uv[v2tfindex][0];
-               newwedge->v2uv[1] = efa->tf.uv[v2tfindex][1];
+               newwedge->v1uv[0] = tf->uv[v1tfindex][0];
+               newwedge->v1uv[1] = tf->uv[v1tfindex][1];
+               newwedge->v2uv[0] = tf->uv[v2tfindex][0];
+               newwedge->v2uv[1] = tf->uv[v2tfindex][1];
                newwedge->eed = eed;
                
                BLI_addtail(uvedges, newwedge);
@@ -6434,7 +6060,6 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
 
 static void build_weldedUVEdges(ListBase *uvedges, ListBase *uvverts)
 {
-       
        wUV *curwvert;
        wUVEdge *curwedge;
        EditFace *efa;
@@ -6480,6 +6105,9 @@ static void collapse_edgeuvs(void)
        Collection *wuvecollection, *newcollection;
        int curtag, balanced, collectionfound, vcount;
        float avg[2];
+
+       if (!CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE))
+               return;
        
        uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL;
        
@@ -6576,62 +6204,64 @@ static void collapse_edgeuvs(void)
 static void collapseuvs(void)
 {
        EditFace *efa;
+       TFace *tf;
        int uvcount;
        float uvav[2];
+
+       if (!CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE))
+               return;
        
        uvcount = 0;
        uvav[0] = 0;
        uvav[1] = 0;
        
        for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+               tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE);
+
                if(efa->v1->f1){
-                       uvav[0] += efa->tf.uv[0][0];
-                       uvav[1] += efa->tf.uv[0][1];
+                       uvav[0] += tf->uv[0][0];
+                       uvav[1] += tf->uv[0][1];
                        uvcount += 1;
                }
                if(efa->v2->f1){
-                       uvav[0] += efa->tf.uv[1][0];            
-                       uvav[1] += efa->tf.uv[1][1];
+                       uvav[0] += tf->uv[1][0];                
+                       uvav[1] += tf->uv[1][1];
                        uvcount += 1;
                }
                if(efa->v3->f1){
-                       uvav[0] += efa->tf.uv[2][0];
-                       uvav[1] += efa->tf.uv[2][1];
+                       uvav[0] += tf->uv[2][0];
+                       uvav[1] += tf->uv[2][1];
                        uvcount += 1;
                }
-               if(efa->v4){
-                       if(efa->v4->f1){
-                               uvav[0] += efa->tf.uv[3][0];
-                               uvav[1] += efa->tf.uv[3][1];
-                               uvcount += 1;
-                       }
+               if(efa->v4 && efa->v4->f1){
+                       uvav[0] += tf->uv[3][0];
+                       uvav[1] += tf->uv[3][1];
+                       uvcount += 1;
                }
        }
        
-       
-       
-       if(uvav[0] && uvav[1]){
+       if(uvcount > 0) {
                uvav[0] /= uvcount; 
                uvav[1] /= uvcount;
        
                for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+                       tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE);
+
                        if(efa->v1->f1){
-                               efa->tf.uv[0][0] = uvav[0];
-                               efa->tf.uv[0][1] = uvav[1];
+                               tf->uv[0][0] = uvav[0];
+                               tf->uv[0][1] = uvav[1];
                        }
                        if(efa->v2->f1){
-                               efa->tf.uv[1][0] = uvav[0];             
-                               efa->tf.uv[1][1] = uvav[1];
+                               tf->uv[1][0] = uvav[0];         
+                               tf->uv[1][1] = uvav[1];
                        }
                        if(efa->v3->f1){
-                               efa->tf.uv[2][0] = uvav[0];
-                               efa->tf.uv[2][1] = uvav[1];
+                               tf->uv[2][0] = uvav[0];
+                               tf->uv[2][1] = uvav[1];
                        }
-                       if(efa->v4){
-                               if(efa->v4->f1){
-                                       efa->tf.uv[3][0] = uvav[0];
-                                       efa->tf.uv[3][1] = uvav[1];
-                               }
+                       if(efa->v4 && efa->v4->f1){
+                               tf->uv[3][0] = uvav[0];
+                               tf->uv[3][1] = uvav[1];
                        }
                }
        }
@@ -6646,11 +6276,9 @@ int collapseEdges(void)
        CollectedEdge *curredge;
        Collection *edgecollection;
        
-       
        int totedges, groupcount, mergecount,vcount;
        float avgcount[3];
        
-       
        allcollections.first = 0;
        allcollections.last = 0;
        
@@ -6686,15 +6314,17 @@ int collapseEdges(void)
                        VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount);
                }
                
-               /*uv collapse*/
-               for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
-               for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
-               for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
-                       curredge->eed->v1->f1 = 1;
-                       curredge->eed->v2->f1 = 1;
-                       curredge->eed->f1 = 1;
+               if (CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)) {
+                       /*uv collapse*/
+                       for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+                       for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+                       for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+                               curredge->eed->v1->f1 = 1;
+                               curredge->eed->v2->f1 = 1;
+                               curredge->eed->f1 = 1;
+                       }
+                       collapse_edgeuvs();
                }
-               collapse_edgeuvs();
                
        }
        freecollections(&allcollections);
@@ -6727,7 +6357,7 @@ int merge_firstlast(int first, int uvmerge)
                }
        }
        
-       if(uvmerge){
+       if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)){
                
                for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
                for(eve=G.editMesh->verts.first; eve; eve=eve->next){
@@ -6748,7 +6378,7 @@ int merge_target(int target, int uvmerge)
        if(target) snap_sel_to_curs();
        else snap_to_center();
        
-       if(uvmerge){
+       if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)){
                for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
                for(eve=G.editMesh->verts.first; eve; eve=eve->next){
                                if(eve->f&SELECT) eve->f1 = 1;
@@ -7109,7 +6739,6 @@ void loop_to_region(void)
                                if(efa->f1 == testflag){
                                        if(efa->f&SELECT) EM_select_face(efa, 0);
                                        else EM_select_face(efa,1);
-                                       
                                }
                        }
                }