Merging r59182 through r59257 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / bmesh / operators / bmo_inset.c
index d58894d7a1cbbec519ee146120ec592becaf3d19..731b895a6b5221d69261854c6fb43cd15f2f462c 100644 (file)
@@ -76,6 +76,7 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
        const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
        const float depth = BMO_slot_float_get(op->slots_in, "depth");
        const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+       const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
        const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
 
        /* Only tag faces in slot */
@@ -83,7 +84,7 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
 
        BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
 
-       BMO_ITER(f, &oiter, op->slots_in, "faces", BM_FACE) {
+       BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
                BMFace *f_new_inner;
                BMLoop *l_iter, *l_first;
                BMLoop *l_iter_inner = NULL;
@@ -146,6 +147,10 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
                        }
 
                        /* Modify vertices and their normals */
+                       if (use_relative_offset) {
+                               mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
+                       }
+
                        madd_v3_v3fl(v_new_co, tvec, thickness);
 
                        /* Set normal, add depth and write new vertex position*/
@@ -169,7 +174,7 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
                /* Copy Face Data */
                /* interpolate loop data or just stretch */
                if (use_interpolate) {
-                       BM_face_interp_from_face(bm, f_new_inner, f);
+                       BM_face_interp_from_face(bm, f_new_inner, f, true);
                }
                else {
                        BM_elem_attrs_copy(bm, bm, f, f_new_inner);
@@ -256,7 +261,8 @@ typedef struct SplitEdgeInfo {
 /* just enough of a face to store interpolation data we can use once the inset is done */
 typedef struct InterpFace {
        BMFace *f;
-       void **blocks;
+       void **blocks_l;
+       void **blocks_v;
        float (*cos_2d)[2];
        float axis_mat[3][3];
 } InterpFace;
@@ -265,11 +271,14 @@ typedef struct InterpFace {
 static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
 {
        BMLoop *l_iter, *l_first;
-       void **blocks      = iface->blocks = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks) * f->len);
+       void **blocks_l    = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
+       void **blocks_v    = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
        float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
        void *axis_mat     = iface->axis_mat;
        int i;
 
+       BLI_assert(BM_face_is_normal_valid(f));
+
        axis_dominant_v3_to_m3(axis_mat, f->no);
 
        iface->f = f;
@@ -278,22 +287,27 @@ static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemAre
        l_iter = l_first = BM_FACE_FIRST_LOOP(f);
        do {
                mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
-               blocks[i] = NULL;
-               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks[i]);
+               blocks_l[i] = NULL;
+               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
                /* if we were not modifying the loops later we would do... */
                // blocks[i] = l_iter->head.data;
 
+               blocks_v[i] = NULL;
+               CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
+
                /* use later for index lookups */
                BM_elem_index_set(l_iter, i); /* set_ok */
        } while (i++, (l_iter = l_iter->next) != l_first);
 }
 static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
 {
-       void **blocks = iface->blocks;
+       void **blocks_l = iface->blocks_l;
+       void **blocks_v = iface->blocks_v;
        int i;
 
        for (i = 0; i < iface->f->len; i++) {
-               CustomData_bmesh_free_block(&bm->ldata, &blocks[i]);
+               CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
+               CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
        }
 }
 
@@ -316,7 +330,7 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l)
                l_iter = l;
                do {
                        if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
-                               /* more then one tagged face - bail out early! */
+                               /* more than one tagged face - bail out early! */
                                if (tot_tag == 1) {
                                        return NULL;
                                }
@@ -443,7 +457,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
 
 
                /* run the separate arg */
-               bmesh_edge_separate(bm, es->e_old, es->l);
+               bmesh_edge_separate(bm, es->e_old, es->l, false);
 
                /* calc edge-split info */
                es->e_new = es->l->e;
@@ -465,13 +479,22 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
 
                /* initialize interpolation vars */
                /* this could go in its own loop,
-                * only use the 'es->l->f' so we don't store loops for faces which have no mixed selection */
+                * only use the 'es->l->f' so we don't store loops for faces which have no mixed selection
+                *
+                * note: faces on the other side of the inset will be interpolated too since this is hard to
+                * detect, just allow it even though it will cause some redundant interpolation */
                if (use_interpolate) {
-                       const int j = BM_elem_index_get((f = es->l->f));
-                       if (iface_array[j] == NULL) {
-                               InterpFace *iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
-                               bm_interp_face_store(iface, bm, f, interp_arena);
-                               iface_array[j] = iface;
+                       BMIter viter;
+                       BM_ITER_ELEM (v, &viter, es->l->e, BM_VERTS_OF_EDGE) {
+                               BMIter fiter;
+                               BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+                                       const int j = BM_elem_index_get(f);
+                                       if (iface_array[j] == NULL) {
+                                               InterpFace *iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
+                                               bm_interp_face_store(iface, bm, f, interp_arena);
+                                               iface_array[j] = iface;
+                                       }
+                               }
                        }
                }
                /* done interpolation */
@@ -512,7 +535,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
                                /* disable touching twice, this _will_ happen if the flags not disabled */
                                BM_elem_flag_disable(v, BM_ELEM_TAG);
 
-                               bmesh_vert_separate(bm, v, &vout, &r_vout_len);
+                               bmesh_vert_separate(bm, v, &vout, &r_vout_len, false);
                                v = NULL; /* don't use again */
 
                                /* in some cases the edge doesn't split off */
@@ -724,8 +747,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
                for (i = 0; i < iface_array_len; i++) {
                        if (iface_array[i]) {
                                InterpFace *iface = iface_array[i];
-                               BM_face_interp_from_face_ex(bm, iface->f, iface->f,
-                                                           iface->blocks, iface->cos_2d, iface->axis_mat);
+                               BM_face_interp_from_face_ex(bm, iface->f, iface->f, true,
+                                                           iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat);
                        }
                }
        }
@@ -773,7 +796,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
 #if 0
                /* don't use this because face boundaries have no adjacent loops and won't be filled in.
                 * instead copy from the opposite side with the code below */
-               BM_face_copy_shared(bm, f);
+               BM_face_copy_shared(bm, f, NULL, NULL);
 #else
                {
                        /* 2 inner loops on the edge between the new face and the original */
@@ -800,8 +823,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
                                InterpFace *iface = iface_array[BM_elem_index_get(es->l->f)];
                                const int i_a = BM_elem_index_get(l_a_other);
                                const int i_b = BM_elem_index_get(l_b_other);
-                               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks[i_a], &l_b->head.data);
-                               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks[i_b], &l_a->head.data);
+                               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_a], &l_b->head.data);
+                               CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_b], &l_a->head.data);
                        }
                        else {
                                BM_elem_attrs_copy(bm, bm, l_a_other, l_b);