Merged changes in the trunk up to revision 51853.
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Sun, 4 Nov 2012 02:22:56 +0000 (02:22 +0000)
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Sun, 4 Nov 2012 02:22:56 +0000 (02:22 +0000)
Conflicts resolved:
source/blender/blenloader/intern/readfile.c
source/blender/bmesh/operators/bmo_utils.c

This commit also includes a fix of a bug identified during the merge and committed in revision 51853.
Thanks Thomas (dingto) for the timely fix!

32 files changed:
1  2 
doc/python_api/sphinx_doc_gen.py
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_operators.h
source/blender/bmesh/operators/bmo_similar.c
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/mesh/editmesh_select.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/space_file/filelist.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/transform/transform.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_action.c
source/blender/makesrna/intern/rna_color.c
source/blender/makesrna/intern/rna_main.c
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/render/intern/source/convertblender.c
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_files.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt

Simple merge
@@@ -2430,8 -2429,18 +2430,18 @@@ static void direct_link_nodetree(FileDa
                
                if (node->storage) {
                        /* could be handlerized at some point */
-                       if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
+                       if (ntree->type==NTREE_SHADER) {
+                               if (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB) {
 -                                      direct_link_curvemapping(fd, node->storage);
 +                              direct_link_curvemapping(fd, node->storage);
+                               }
+                               else if (node->type==SH_NODE_SCRIPT) {
+                                       NodeShaderScript *nss = (NodeShaderScript *) node->storage;
+                                       nss->bytecode = newdataadr(fd, nss->bytecode);
+                                       nss->prop = newdataadr(fd, nss->prop);
+                                       if (nss->prop)
+                                               IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+                               }
+                       }
                        else if (ntree->type==NTREE_COMPOSIT) {
                                if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
                                        direct_link_curvemapping(fd, node->storage);
@@@ -7326,7 -7147,30 +7336,30 @@@ static void do_version_node_fix_interna
                }
        }
  }
 -      
 +
+ static void do_version_logic_264(ListBase *regionbase)
+ {
+       ARegion *ar;
+       
+       /* view settings for logic changed */
+       for (ar = regionbase->first; ar; ar = ar->next) {
+               if (ar->regiontype == RGN_TYPE_WINDOW) {
+                       if (ar->v2d.keeptot == 0) {
+                               ar->v2d.maxzoom = 1.5f;
+                               
+                               ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT;
+                               ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
+                               ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X;
+                               ar->v2d.keepofs = V2D_KEEPOFS_Y;
+                       }
+               }
+       }
+       
+ }
+       
  static void do_versions(FileData *fd, Library *lib, Main *main)
  {
        /* WATCH IT!!!: pointers from libdata have not been converted */
                        do_version_node_fix_internal_links_264(NULL, NULL, ntree);
                
        }
 -      
 +
+       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
+               bScreen *sc;
+               
+               for (sc = main->screen.first; sc; sc = sc->id.next) {
+                       ScrArea *sa;
+                       for (sa = sc->areabase.first; sa; sa = sa->next) {
+                               SpaceLink *sl;
+                               if ( sa->spacetype == SPACE_LOGIC)
+                                       do_version_logic_264(&sa->regionbase);
+                               
+                               for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                       if (sl->spacetype == SPACE_LOGIC)
+                                               do_version_logic_264(&sl->regionbase);
+                               }
+                       }
+               }
+       }
+       
+       {
+               Object *ob;
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       if (ob->col_group == 0) {
+                               ob->col_group = 0x01;
+                               ob->col_mask = 0xff;
+                       }
+               }
+       }
 +      /* default values in Freestyle settings */
 +      {
 +              Scene *sce;
 +              SceneRenderLayer *srl;
 +              FreestyleLineStyle *linestyle;
 +
 +              for(sce = main->scene.first; sce; sce = sce->id.next) {
 +                      if (sce->r.line_thickness_mode == 0) {
 +                              sce->r.line_thickness_mode= R_LINE_THICKNESS_ABSOLUTE;
 +                              sce->r.unit_line_thickness= 1.f;
 +                      }
 +                      for(srl= sce->r.layers.first; srl; srl= srl->next) {
 +                              if (srl->freestyleConfig.mode == 0)
 +                                      srl->freestyleConfig.mode= FREESTYLE_CONTROL_EDITOR_MODE;
 +                              if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
 +                                      srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL) {
 +                                      srl->freestyleConfig.raycasting_algorithm= 0; /* deprecated */
 +                                      srl->freestyleConfig.flags |= FREESTYLE_CULLING;
 +                              }
 +                      }
 +              }
 +              for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
 +                      if (linestyle->thickness_position == 0) {
 +                              linestyle->thickness_position= LS_THICKNESS_CENTER;
 +                              linestyle->thickness_ratio= 0.5f;
 +                      }
 +                      if (linestyle->chaining == 0)
 +                              linestyle->chaining= LS_CHAINING_PLAIN;
 +                      if (linestyle->rounds == 0)
 +                              linestyle->rounds= 3;
 +              }
 +      }
 +
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
  
@@@ -51,10 -57,10 +57,11 @@@ enum 
        SIMFACE_MATERIAL = 201,
        SIMFACE_IMAGE,
        SIMFACE_AREA,
+       SIMFACE_SIDES,
        SIMFACE_PERIMETER,
        SIMFACE_NORMAL,
 -      SIMFACE_COPLANAR
 +      SIMFACE_COPLANAR,
 +      SIMFACE_FREESTYLE
  };
  
  /* similar edge selection slot values */
index 0000000,df03e50..b4566f6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,614 +1,620 @@@
+ /*
+  * ***** BEGIN GPL 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.
+  *
+  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+  *
+  * Contributor(s): Joseph Eagar, Campbell Barton
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ /** \file blender/bmesh/operators/bmo_similar.c
+  *  \ingroup bmesh
+  *
+  * bmesh operators to select based on
+  * comparisons with the existing selection.
+  */
+ #include "MEM_guardedalloc.h"
+ #include "DNA_object_types.h"
+ #include "DNA_meshdata_types.h"
+ #include "BLI_math.h"
+ #include "BKE_customdata.h"
+ #include "BKE_deform.h"
+ #include "bmesh.h"
+ #include "intern/bmesh_operators_private.h"  /* own include */
+ /* in fact these could all be the same */
+ /*
+  * extra face data (computed data)
+  */
+ typedef struct SimSel_FaceExt {
+       BMFace  *f;             /* the face */
+       float    c[3];          /* center */
+       union {
+               float   area;       /* area */
+               float   perim;      /* perimeter */
+               float   d;          /* 4th component of plane (the first three being the normal) */
+               struct Image *t;    /* image pointer */
+       };
+ } SimSel_FaceExt;
+ static int bm_sel_similar_cmp_fl(const float delta, const float thresh, const int compare)
+ {
+       switch (compare) {
+               case SIM_CMP_EQ:
+                       return (fabsf(delta) <= thresh);
+               case SIM_CMP_GT:
+                       return ((delta + thresh) >= 0.0f);
+               case SIM_CMP_LT:
+                       return ((delta - thresh) <= 0.0f);
+               default:
+                       BLI_assert(0);
+                       return 0;
+       }
+ }
+ static int bm_sel_similar_cmp_i(const int delta, const int compare)
+ {
+       switch (compare) {
+               case SIM_CMP_EQ:
+                       return (delta == 0);
+               case SIM_CMP_GT:
+                       return (delta > 0);
+               case SIM_CMP_LT:
+                       return (delta < 0);
+               default:
+                       BLI_assert(0);
+                       return 0;
+       }
+ }
+ /*
+  * Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+  * We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces
+  */
+ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
+ {
+ #define FACE_MARK     1
+       BMIter fm_iter;
+       BMFace *fs, *fm;
+       BMOIter fs_iter;
+       int num_sels = 0, num_total = 0, i = 0, idx = 0;
+       float angle = 0.0f;
+       SimSel_FaceExt *f_ext = NULL;
+       int *indices = NULL;
+       float t_no[3];  /* temporary normal */
+       const int type = BMO_slot_int_get(op, "type");
+       const float thresh = BMO_slot_float_get(op, "thresh");
+       const float thresh_radians = thresh * (float)M_PI;
+       const int compare = BMO_slot_int_get(op, "compare");
+       /* initial_elem - other_elem */
+       float delta_fl;
+       int   delta_i;
+       num_total = BM_mesh_elem_count(bm, BM_FACE);
+       /*
+        * The first thing to do is to iterate through all the the selected items and mark them since
+        * they will be in the selection anyway.
+        * This will increase performance, (especially when the number of originally selected faces is high)
+        * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces,
+        * and n is the total number of faces
+        */
+       BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) {
+               if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) {   /* is this really needed ? */
+                       BMO_elem_flag_enable(bm, fs, FACE_MARK);
+                       num_sels++;
+               }
+       }
+       /* allocate memory for the selected faces indices and for all temporary faces */
+       indices = (int *)MEM_callocN(sizeof(int) * num_sels, "face indices util.c");
+       f_ext = (SimSel_FaceExt *)MEM_callocN(sizeof(SimSel_FaceExt) * num_total, "f_ext util.c");
+       /* loop through all the faces and fill the faces/indices structure */
+       BM_ITER_MESH (fm, &fm_iter, bm, BM_FACES_OF_MESH) {
+               f_ext[i].f = fm;
+               if (BMO_elem_flag_test(bm, fm, FACE_MARK)) {
+                       indices[idx] = i;
+                       idx++;
+               }
+               i++;
+       }
+       /*
+        * Save us some computation burden: In case of perimeter/area/coplanar selection we compute
+        * only once.
+        */
+       if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) {
+               for (i = 0; i < num_total; i++) {
+                       switch (type) {
+                               case SIMFACE_PERIMETER:
+                                       /* set the perimeter */
+                                       f_ext[i].perim = BM_face_calc_perimeter(f_ext[i].f);
+                                       break;
+                               case SIMFACE_COPLANAR:
+                                       /* compute the center of the polygon */
+                                       BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c);
+                                       /* normalize the polygon normal */
+                                       copy_v3_v3(t_no, f_ext[i].f->no);
+                                       normalize_v3(t_no);
+                                       /* compute the plane distance */
+                                       f_ext[i].d = dot_v3v3(t_no, f_ext[i].c);
+                                       break;
+                               case SIMFACE_AREA:
+                                       f_ext[i].area = BM_face_calc_area(f_ext[i].f);
+                                       break;
+                               case SIMFACE_IMAGE:
+                                       f_ext[i].t = NULL;
+                                       if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) {
+                                               MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY);
+                                               f_ext[i].t = mtpoly->tpage;
+                                       }
+                                       break;
+                       }
+               }
+       }
+       /* now select the rest (if any) */
+       for (i = 0; i < num_total; i++) {
+               fm = f_ext[i].f;
+               if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) {
+                       int cont = TRUE;
+                       for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+                               fs = f_ext[indices[idx]].f;
+                               switch (type) {
+                                       case SIMFACE_MATERIAL:
+                                               if (fm->mat_nr == fs->mat_nr) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMFACE_IMAGE:
+                                               if (f_ext[i].t == f_ext[indices[idx]].t) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMFACE_NORMAL:
+                                               angle = angle_normalized_v3v3(fs->no, fm->no);  /* if the angle between the normals -> 0 */
+                                               if (angle <= thresh_radians) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMFACE_COPLANAR:
+                                               angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */
+                                               if (angle <= thresh_radians) { /* and dot product difference -> 0 */
+                                                       delta_fl = f_ext[i].d - f_ext[indices[idx]].d;
+                                                       if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                               BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                               cont = FALSE;
+                                                       }
+                                               }
+                                               break;
+                                       case SIMFACE_AREA:
+                                               delta_fl = f_ext[i].area - f_ext[indices[idx]].area;
+                                               if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMFACE_SIDES:
+                                               delta_i = fm->len - fs->len;
+                                               if (bm_sel_similar_cmp_i(delta_i, compare)) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMFACE_PERIMETER:
+                                               delta_fl = f_ext[i].perim - f_ext[indices[idx]].perim;
+                                               if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                       BMO_elem_flag_enable(bm, fm, FACE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       default:
+                                               BLI_assert(0);
+                               }
+                       }
+               }
+       }
+       MEM_freeN(f_ext);
+       MEM_freeN(indices);
+       /* transfer all marked faces to the output slot */
+       BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK);
+ #undef FACE_MARK
+ }
+ /**************************************************************************** *
+  * Similar Edges
+  **************************************************************************** */
+ /*
+  * extra edge information
+  */
+ typedef struct SimSel_EdgeExt {
+       BMEdge *e;
+       union {
+               float dir[3];
+               float angle;            /* angle between the face */
+       };
+       union {
+               float length;           /* edge length */
+               int   faces;            /* faces count */
+       };
+ } SimSel_EdgeExt;
+ /*
+  * select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+  * choices are length, direction, face, ...
+  */
+ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
+ {
+ #define EDGE_MARK     1
+       BMOIter es_iter;        /* selected edges iterator */
+       BMIter e_iter;          /* mesh edges iterator */
+       BMEdge *es;             /* selected edge */
+       BMEdge *e;              /* mesh edge */
+       int idx = 0, i = 0 /* , f = 0 */;
+       int *indices = NULL;
+       SimSel_EdgeExt *e_ext = NULL;
+       // float *angles = NULL;
+       float angle;
+       int num_sels = 0, num_total = 0;
+       const int type = BMO_slot_int_get(op, "type");
+       const float thresh = BMO_slot_float_get(op, "thresh");
+       const int compare = BMO_slot_int_get(op, "compare");
+       /* initial_elem - other_elem */
+       float delta_fl;
+       int   delta_i;
+       /* sanity checks that the data we need is available */
+       switch (type) {
+               case SIMEDGE_CREASE:
+                       if (!CustomData_has_layer(&bm->edata, CD_CREASE)) {
+                               return;
+                       }
+                       break;
+               case SIMEDGE_BEVEL:
+                       if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+                               return;
+                       }
+                       break;
+       }
+       num_total = BM_mesh_elem_count(bm, BM_EDGE);
+       /* iterate through all selected edges and mark them */
+       BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) {
+               BMO_elem_flag_enable(bm, es, EDGE_MARK);
+               num_sels++;
+       }
+       /* allocate memory for the selected edges indices and for all temporary edges */
+       indices = (int *)MEM_callocN(sizeof(int) * num_sels, __func__);
+       e_ext = (SimSel_EdgeExt *)MEM_callocN(sizeof(SimSel_EdgeExt) * num_total, __func__);
+       /* loop through all the edges and fill the edges/indices structure */
+       BM_ITER_MESH (e, &e_iter, bm, BM_EDGES_OF_MESH) {
+               e_ext[i].e = e;
+               if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+                       indices[idx] = i;
+                       idx++;
+               }
+               i++;
+       }
+       /* save us some computation time by doing heavy computation once */
+       if (type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR || type == SIMEDGE_FACE_ANGLE) {
+               for (i = 0; i < num_total; i++) {
+                       switch (type) {
+                               case SIMEDGE_LENGTH:    /* compute the length of the edge */
+                                       e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+                                       break;
+                               case SIMEDGE_DIR:               /* compute the direction */
+                                       sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+                                       normalize_v3(e_ext[i].dir);
+                                       break;
+                               case SIMEDGE_FACE:              /* count the faces around the edge */
+                                       e_ext[i].faces = BM_edge_face_count(e_ext[i].e);
+                                       break;
+                               case SIMEDGE_FACE_ANGLE:
+                                       e_ext[i].faces = BM_edge_face_count(e_ext[i].e);
+                                       if (e_ext[i].faces == 2)
+                                               e_ext[i].angle = BM_edge_calc_face_angle(e_ext[i].e);
+                                       break;
+                       }
+               }
+       }
+       /* select the edges if any */
+       for (i = 0; i < num_total; i++) {
+               e = e_ext[i].e;
+               if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+                       int cont = TRUE;
+                       for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+                               es = e_ext[indices[idx]].e;
+                               switch (type) {
+                                       case SIMEDGE_LENGTH:
+                                               delta_fl = e_ext[i].length - e_ext[indices[idx]].length;
+                                               if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMEDGE_DIR:
+                                               /* compute the angle between the two edges */
+                                               angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir);
+                                               if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */
+                                                       angle = fabsf(angle - (float)M_PI);
+                                               if (angle / (float)(M_PI / 2.0) <= thresh) {
+                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMEDGE_FACE:
+                                               delta_i = e_ext[i].faces - e_ext[indices[idx]].faces;
+                                               if (bm_sel_similar_cmp_i(delta_i, compare)) {
+                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMEDGE_FACE_ANGLE:
+                                               if (e_ext[i].faces == 2) {
+                                                       if (e_ext[indices[idx]].faces == 2) {
+                                                               if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) {
+                                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                                       cont = FALSE;
+                                                               }
+                                                       }
+                                               }
+                                               else {
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMEDGE_CREASE:
+                                               {
+                                                       float *c1, *c2;
+                                                       c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE);
+                                                       c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE);
+                                                       delta_fl = *c1 - *c2;
+                                                       if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                               BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                               cont = FALSE;
+                                                       }
+                                               }
+                                               break;
+                                       case SIMEDGE_BEVEL:
+                                               {
+                                                       float *c1, *c2;
+                                                       c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT);
+                                                       c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_BWEIGHT);
+                                                       delta_fl = *c1 - *c2;
+                                                       if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
+                                                               BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                               cont = FALSE;
+                                                       }
+                                               }
+                                               break;
+                                       case SIMEDGE_SEAM:
+                                               if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) {
+                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMEDGE_SHARP:
+                                               if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) {
+                                                       BMO_elem_flag_enable(bm, e, EDGE_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
++                                      case SIMEDGE_FREESTYLE:
++                                              if (BM_elem_flag_test(e, BM_ELEM_FREESTYLE) == BM_elem_flag_test(es, BM_ELEM_FREESTYLE)) {
++                                                      BMO_elem_flag_enable(bm, e, EDGE_MARK);
++                                                      cont = 0;
++                                              }
++                                              break;
+                                       default:
+                                               BLI_assert(0);
+                               }
+                       }
+               }
+       }
+       MEM_freeN(e_ext);
+       MEM_freeN(indices);
+       /* transfer all marked edges to the output slot */
+       BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK);
+ #undef EDGE_MARK
+ }
+ /**************************************************************************** *
+  * Similar Vertices
+  **************************************************************************** */
+ typedef struct SimSel_VertExt {
+       BMVert *v;
+       union {
+               int num_faces; /* adjacent faces */
+               int num_edges; /* adjacent edges */
+               MDeformVert *dvert; /* deform vertex */
+       };
+ } SimSel_VertExt;
+ /*
+  * select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+  * choices are normal, face, vertex group...
+  */
+ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op)
+ {
+ #define VERT_MARK     1
+       BMOIter vs_iter;        /* selected verts iterator */
+       BMIter v_iter;          /* mesh verts iterator */
+       BMVert *vs;             /* selected vertex */
+       BMVert *v;                      /* mesh vertex */
+       SimSel_VertExt *v_ext = NULL;
+       int *indices = NULL;
+       int num_total = 0, num_sels = 0, i = 0, idx = 0;
+       const int type = BMO_slot_int_get(op, "type");
+       const float thresh = BMO_slot_float_get(op, "thresh");
+       const float thresh_radians = thresh * (float)M_PI;
+       const int compare = BMO_slot_int_get(op, "compare");
+       /* initial_elem - other_elem */
+ //    float delta_fl;
+       int   delta_i;
+       num_total = BM_mesh_elem_count(bm, BM_VERT);
+       /* iterate through all selected edges and mark them */
+       BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) {
+               BMO_elem_flag_enable(bm, vs, VERT_MARK);
+               num_sels++;
+       }
+       /* allocate memory for the selected vertices indices and for all temporary vertices */
+       indices = (int *)MEM_mallocN(sizeof(int) * num_sels, "vertex indices");
+       v_ext = (SimSel_VertExt *)MEM_mallocN(sizeof(SimSel_VertExt) * num_total, "vertex extra");
+       /* loop through all the vertices and fill the vertices/indices structure */
+       BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) {
+               v_ext[i].v = v;
+               if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
+                       indices[idx] = i;
+                       idx++;
+               }
+               switch (type) {
+                       case SIMVERT_FACE:
+                               /* calling BM_vert_face_count every time is time consumming, so call it only once per vertex */
+                               v_ext[i].num_faces = BM_vert_face_count(v);
+                               break;
+                       case SIMVERT_VGROUP:
+                               if (CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT)) {
+                                       v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT);
+                               }
+                               else {
+                                       v_ext[i].dvert = NULL;
+                               }
+                               break;
+                       case SIMVERT_EDGE:
+                               v_ext[i].num_edges = BM_vert_edge_count(v);
+                               break;
+               }
+               i++;
+       }
+       /* select the vertices if any */
+       for (i = 0; i < num_total; i++) {
+               v = v_ext[i].v;
+               if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+                       int cont = TRUE;
+                       for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+                               vs = v_ext[indices[idx]].v;
+                               switch (type) {
+                                       case SIMVERT_NORMAL:
+                                               /* compare the angle between the normals */
+                                               if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) {
+                                                       BMO_elem_flag_enable(bm, v, VERT_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMVERT_FACE:
+                                               /* number of adjacent faces */
+                                               delta_i = v_ext[i].num_faces - v_ext[indices[idx]].num_faces;
+                                               if (bm_sel_similar_cmp_i(delta_i, compare)) {
+                                                       BMO_elem_flag_enable(bm, v, VERT_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       case SIMVERT_VGROUP:
+                                               if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) {
+                                                       if (defvert_find_shared(v_ext[i].dvert, v_ext[indices[idx]].dvert) != -1) {
+                                                               BMO_elem_flag_enable(bm, v, VERT_MARK);
+                                                               cont = FALSE;
+                                                       }
+                                               }
+                                               break;
+                                       case SIMVERT_EDGE:
+                                               /* number of adjacent edges */
+                                               delta_i = v_ext[i].num_edges - v_ext[indices[idx]].num_edges;
+                                               if (bm_sel_similar_cmp_i(delta_i, compare)) {
+                                                       BMO_elem_flag_enable(bm, v, VERT_MARK);
+                                                       cont = FALSE;
+                                               }
+                                               break;
+                                       default:
+                                               BLI_assert(0);
+                               }
+                       }
+               }
+       }
+       MEM_freeN(indices);
+       MEM_freeN(v_ext);
+       BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK);
+ #undef VERT_MARK
+ }
@@@ -2355,10 -2342,14 +2357,15 @@@ static void draw_dm_faces_sel(BMEditMes
        data.cols[0] = baseCol;
        data.em = em;
        data.cols[1] = selCol;
 -      data.cols[2] = actCol;
 +      data.cols[2] = markCol;
 +      data.cols[3] = actCol;
        data.efa_act = efa_act;
-       data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
+       /* double lookup */
+       data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
+       data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
+       if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) {
+               data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
+       }
  
        dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
  }
Simple merge
@@@ -575,27 -631,8 +632,25 @@@ static void rna_Main_grease_pencil_remo
        else
                BKE_reportf(reports, RPT_ERROR, "Grease pencil '%s' must have zero users to be removed, found %d",
                            gpd->id.name + 2, ID_REAL_USERS(gpd));
-       /* XXX python now has invalid pointer? */
  }
  
 +FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char* name)
 +{
 +      FreestyleLineStyle *linestyle = FRS_new_linestyle(name, bmain);
 +      id_us_min(&linestyle->id);
 +      return linestyle;
 +}
 +
 +void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
 +{
 +      if(ID_REAL_USERS(linestyle) <= 0)
 +              BKE_libblock_free(&bmain->linestyle, linestyle);
 +      else
 +              BKE_reportf(reports, RPT_ERROR, "Line style \"%s\" must have zero users to be removed, found %d.", linestyle->id.name+2, ID_REAL_USERS(linestyle));
 +
 +      /* XXX python now has invalid pointer? */
 +}
 +
  /* tag functions, all the same */
  static void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); }
  static void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); }
@@@ -1622,33 -1681,8 +1700,34 @@@ void RNA_def_main_masks(BlenderRNA *brn
        func = RNA_def_function(srna, "remove", "rna_Main_masks_remove");
        RNA_def_function_ui_description(func, "Remove a masks from the current blendfile.");
        parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to remove");
-       RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+       RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+       RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
  }
  
 +void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
 +{
 +      StructRNA *srna;
 +      FunctionRNA *func;
 +      PropertyRNA *parm;
 +
 +      RNA_def_property_srna(cprop, "BlendDataLineStyles");
 +      srna= RNA_def_struct(brna, "BlendDataLineStyles", NULL);
 +      RNA_def_struct_sdna(srna, "Main");
 +      RNA_def_struct_ui_text(srna, "Main Line Styles", "Collection of line styles");
 +
 +      func= RNA_def_function(srna, "new", "rna_Main_linestyles_new");
 +      RNA_def_function_ui_description(func, "Add a new line style instance to the main database");
 +      parm= RNA_def_string(func, "name", "FreestyleLineStyle", 0, "", "New name for the datablock");
 +      RNA_def_property_flag(parm, PROP_REQUIRED);
 +      /* return type */
 +      parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "New line style datablock");
 +      RNA_def_function_return(func, parm);
 +
 +      func= RNA_def_function(srna, "remove", "rna_Main_linestyles_remove");
 +      RNA_def_function_flag(func, FUNC_USE_REPORTS);
 +      RNA_def_function_ui_description(func, "Remove a line style instance from the current blendfile");
 +      parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "Line style to remove");
 +      RNA_def_property_flag(parm, PROP_REQUIRED);
 +}
 +
  #endif
Simple merge