Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_material.h1
-rw-r--r--source/blender/blenkernel/intern/material.c56
-rw-r--r--source/blender/blenlib/intern/edgehash.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c587
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c2
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c37
6 files changed, 178 insertions, 507 deletions
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index d32d679e7ed..87e59885415 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -51,6 +51,7 @@ void test_object_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
+void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);
struct Material *localize_material(struct Material *ma);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 8614deddc3e..b913e6de433 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -969,6 +969,62 @@ void BKE_material_remap_object(Object *ob, const unsigned int *remap)
}
}
+/**
+ * Calculate a material remapping from \a ob_src to \a ob_dst.
+ *
+ * \param remap_src_to_dst: An array the size of `ob_src->totcol`
+ * where index values are filled in which map to \a ob_dst materials.
+ */
+void BKE_material_remap_object_calc(
+ Object *ob_dst, Object *ob_src,
+ short *remap_src_to_dst)
+{
+ if (ob_src->totcol == 0) {
+ return;
+ }
+
+ GHash *gh_mat_map = BLI_ghash_ptr_new_ex(__func__, ob_src->totcol);
+
+ for (int i = 0; i < ob_dst->totcol; i++) {
+ Material *ma_src = give_current_material(ob_dst, i + 1);
+ BLI_ghash_reinsert(gh_mat_map, ma_src, SET_INT_IN_POINTER(i), NULL, NULL);
+ }
+
+ /* setup default mapping (when materials don't match) */
+ {
+ int i = 0;
+ if (ob_dst->totcol >= ob_src->totcol) {
+ for (; i < ob_src->totcol; i++) {
+ remap_src_to_dst[i] = i;
+ }
+ }
+ else {
+ for (; i < ob_dst->totcol; i++) {
+ remap_src_to_dst[i] = i;
+ }
+ for (; i < ob_src->totcol; i++) {
+ remap_src_to_dst[i] = 0;
+ }
+ }
+ }
+
+ for (int i = 0; i < ob_src->totcol; i++) {
+ Material *ma_src = give_current_material(ob_src, i + 1);
+
+ if ((i < ob_dst->totcol) && (ma_src == give_current_material(ob_dst, i + 1))) {
+ /* when objects have exact matching materials - keep existing index */
+ }
+ else {
+ void **index_src_p = BLI_ghash_lookup_p(gh_mat_map, ma_src);
+ if (index_src_p) {
+ remap_src_to_dst[i] = GET_INT_FROM_POINTER(*index_src_p);
+ }
+ }
+ }
+
+ BLI_ghash_free(gh_mat_map, NULL, NULL);
+}
+
/* XXX - this calls many more update calls per object then are needed, could be optimized */
void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index d6eae348d52..358b5b5696f 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -171,7 +171,7 @@ BLI_INLINE EdgeEntry *edgehash_lookup_entry_prev_ex(
EdgeEntry **r_e_prev, const unsigned int bucket_index)
{
BLI_assert(v0 < v1);
- for (EdgeEntry *e_prev = NULL, *e = eh->buckets[bucket_index]; e; e = e->next) {
+ for (EdgeEntry *e_prev = NULL, *e = eh->buckets[bucket_index]; e; e_prev = e, e = e->next) {
if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
*r_e_prev = e_prev;
return e;
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 818526ab772..5b9af2fa75c 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -75,6 +75,9 @@
#include "mesh_intern.h" /* own include */
+/* detect isolated holes and fill them */
+#define USE_NET_ISLAND_CONNECT
+
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
/* WARNING: knife float precision is fragile:
@@ -166,6 +169,11 @@ typedef struct KnifeTool_OpData {
MemArena *arena;
+#ifdef USE_NET_ISLAND_CONNECT
+ /* cleared each use */
+ MemArena *arena_edgenet;
+#endif
+
GHash *origvertmap;
GHash *origedgemap;
GHash *kedgefacemap;
@@ -2205,330 +2213,6 @@ static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cu
else return 0;
}
-/* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
- * If possible, complete the chain to another instantiated vertex and return 1, else return 0.
- * The visited hash says which KnifeVert's have already been tried, not including kfv. */
-static bool find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
- ListBase *chain)
-{
- Ref *r;
- KnifeEdge *kfe;
- KnifeVert *kfv_other;
-
- if (kfv->v)
- return true;
-
- BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
- /* Try all possible next edges. Could either go through fedges
- * (all the KnifeEdges for the face being cut) or could go through
- * kve->edges and restrict to cutting face and uninstantiated edges.
- * Not clear which is better. Let's do the first. */
- for (r = fedges->first; r; r = r->next) {
- kfe = r->ref;
- kfv_other = NULL;
- if (kfe->v1 == kfv)
- kfv_other = kfe->v2;
- else if (kfe->v2 == kfv)
- kfv_other = kfe->v1;
- if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
- knife_append_list(kcd, chain, kfe);
- if (find_chain_search(kcd, kfv_other, fedges, visited, chain))
- return true;
- BLI_remlink(chain, chain->last);
- }
- }
- return false;
-}
-
-static ListBase *find_chain_from_vertex(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges)
-{
- SmallHash visited_, *visited = &visited_;
- ListBase *ans;
- bool found;
-
- ans = knife_empty_list(kcd);
- knife_append_list(kcd, ans, kfe);
- found = false;
- BLI_smallhash_init(visited);
- if (kfe->v1->v == v) {
- BLI_smallhash_insert(visited, (uintptr_t)(kfe->v1), NULL);
- found = find_chain_search(kcd, kfe->v2, fedges, visited, ans);
- }
- else {
- BLI_assert(kfe->v2->v == v);
- BLI_smallhash_insert(visited, (uintptr_t)(kfe->v2), NULL);
- found = find_chain_search(kcd, kfe->v1, fedges, visited, ans);
- }
-
- BLI_smallhash_release(visited);
-
- if (found)
- return ans;
- else
- return NULL;
-}
-
-/* Find a chain in fedges from one instantiated vertex to another.
- * Remove the edges in the chain from fedges and return a separate list of the chain. */
-static ListBase *find_chain(KnifeTool_OpData *kcd, ListBase *fedges)
-{
- Ref *r, *ref;
- KnifeEdge *kfe;
- BMVert *v1, *v2;
- ListBase *ans;
-
- ans = NULL;
-
- for (r = fedges->first; r; r = r->next) {
- kfe = r->ref;
- v1 = kfe->v1->v;
- v2 = kfe->v2->v;
- if (v1 && v2) {
- ans = knife_empty_list(kcd);
- knife_append_list(kcd, ans, kfe);
- break;
- }
- if (v1)
- ans = find_chain_from_vertex(kcd, kfe, v1, fedges);
- else if (v2)
- ans = find_chain_from_vertex(kcd, kfe, v2, fedges);
- if (ans)
- break;
- }
- if (ans) {
- BLI_assert(!BLI_listbase_is_empty(ans));
- for (r = ans->first; r; r = r->next) {
- ref = find_ref(fedges, r->ref);
- BLI_assert(ref != NULL);
- BLI_remlink(fedges, ref);
- }
- }
- return ans;
-}
-
-/* The hole so far goes from kfvfirst to kfv (some may be reversed).
- * If possible, complete the hole back to kfvfirst and return 1, else return 0.
- * The visited hash says which KnifeVert's have already been tried, not including kfv or kfvfirst. */
-static bool find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
- SmallHash *visited, ListBase *hole)
-{
- Ref *r;
- KnifeEdge *kfe, *kfelast;
- KnifeVert *kfv_other;
-
- if (kfv == kfvfirst)
- return true;
-
- BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
- kfelast = ((Ref *)hole->last)->ref;
- for (r = fedges->first; r; r = r->next) {
- kfe = r->ref;
- if (kfe == kfelast)
- continue;
- if (kfe->v1->v || kfe->v2->v)
- continue;
- kfv_other = NULL;
- if (kfe->v1 == kfv)
- kfv_other = kfe->v2;
- else if (kfe->v2 == kfv)
- kfv_other = kfe->v1;
- if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
- knife_append_list(kcd, hole, kfe);
- if (find_hole_search(kcd, kfvfirst, kfv_other, fedges, visited, hole))
- return true;
- BLI_remlink(hole, hole->last);
- }
- }
- return false;
-}
-
-/* Find a hole (simple cycle with no instantiated vertices).
- * Remove the edges in the cycle from fedges and return a separate list of the cycle */
-static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges)
-{
- ListBase *ans;
- Ref *r, *ref;
- KnifeEdge *kfe;
- SmallHash visited_, *visited = &visited_;
- bool found;
-
- ans = NULL;
- found = false;
-
- for (r = fedges->first; r && !found; r = r->next) {
- kfe = r->ref;
- if (kfe->v1->v || kfe->v2->v || kfe->v1 == kfe->v2)
- continue;
-
- BLI_smallhash_init(visited);
- ans = knife_empty_list(kcd);
- knife_append_list(kcd, ans, kfe);
-
- found = find_hole_search(kcd, kfe->v1, kfe->v2, fedges, visited, ans);
-
- BLI_smallhash_release(visited);
- }
-
- if (found) {
- for (r = ans->first; r; r = r->next) {
- kfe = r->ref;
- ref = find_ref(fedges, r->ref);
- if (ref)
- BLI_remlink(fedges, ref);
- }
- return ans;
- }
- else {
- return NULL;
- }
-}
-
-/* Try to find "nice" diagonals - short, and far apart from each other.
- * If found, return true and make a 'main chain' going across f which uses
- * the two diagonals and one part of the hole, and a 'side chain' that
- * completes the hole. */
-static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
- ListBase **sidechain)
-{
- float (*fco)[2], (*hco)[2];
- BMVert **fv;
- KnifeVert **hv;
- KnifeEdge **he;
- Ref *r;
- KnifeVert *kfv, *kfvother;
- KnifeEdge *kfe;
- ListBase *chain;
- BMVert *v;
- BMIter iter;
- int nh, nf, i, j, k, m, ax, ay, sep = 0 /* Quite warnings */, bestsep;
- int besti[2], bestj[2];
- float dist_sq, dist_best_sq;
-
- nh = BLI_listbase_count(hole);
- nf = f->len;
- if (nh < 2 || nf < 3)
- return false;
-
- /* Gather 2d projections of hole and face vertex coordinates.
- * Use best-axis projection - not completely accurate, maybe revisit */
- axis_dominant_v3(&ax, &ay, f->no);
- hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float[2]));
- fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float[2]));
- hv = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeVert *));
- fv = BLI_memarena_alloc(kcd->arena, nf * sizeof(BMVert *));
- he = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeEdge *));
-
- i = 0;
- kfv = NULL;
- kfvother = NULL;
- for (r = hole->first; r; r = r->next) {
- kfe = r->ref;
- he[i] = kfe;
- if (kfvother == NULL) {
- kfv = kfe->v1;
- }
- else {
- kfv = kfvother;
- BLI_assert(kfv == kfe->v1 || kfv == kfe->v2);
- }
- hco[i][0] = kfv->co[ax];
- hco[i][1] = kfv->co[ay];
- hv[i] = kfv;
- kfvother = (kfe->v1 == kfv) ? kfe->v2 : kfe->v1;
- i++;
- }
-
- j = 0;
- BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
- fco[j][0] = v->co[ax];
- fco[j][1] = v->co[ay];
- fv[j] = v;
- j++;
- }
-
- /* For first diagonal (m == 0), want shortest length.
- * For second diagonal (m == 1), want max separation of index of hole
- * vertex from the hole vertex used in the first diagonal, and from there
- * want the one with shortest length not to the same vertex as the first diagonal. */
- for (m = 0; m < 2; m++) {
- besti[m] = -1;
- bestj[m] = -1;
- dist_best_sq = FLT_MAX;
- bestsep = 0;
- for (i = 0; i < nh; i++) {
- if (m == 1) {
- if (i == besti[0])
- continue;
- sep = (i + nh - besti[0]) % nh;
- sep = MIN2(sep, nh - sep);
- if (sep < bestsep)
- continue;
- dist_best_sq = FLT_MAX;
- }
- for (j = 0; j < nf; j++) {
- bool ok;
-
- if (m == 1 && j == bestj[0])
- continue;
- dist_sq = len_squared_v2v2(hco[i], fco[j]);
- if (dist_sq > dist_best_sq)
- continue;
-
- ok = true;
- for (k = 0; k < nh && ok; k++) {
- if (k == i || (k + 1) % nh == i)
- continue;
- if (isect_seg_seg_v2(hco[i], fco[j], hco[k], hco[(k + 1) % nh]))
- ok = false;
- }
- if (!ok)
- continue;
- for (k = 0; k < nf && ok; k++) {
- if (k == j || (k + 1) % nf == j)
- continue;
- if (isect_seg_seg_v2(hco[i], fco[j], fco[k], fco[(k + 1) % nf]))
- ok = false;
- }
- if (ok) {
- besti[m] = i;
- bestj[m] = j;
- if (m == 1)
- bestsep = sep;
- dist_best_sq = dist_sq;
- }
- }
- }
- }
-
- if (besti[0] != -1 && besti[1] != -1) {
- BLI_assert(besti[0] != besti[1] && bestj[0] != bestj[1]);
- kfe = new_knife_edge(kcd);
- kfe->v1 = get_bm_knife_vert(kcd, fv[bestj[0]]);
- kfe->v2 = hv[besti[0]];
- chain = knife_empty_list(kcd);
- knife_append_list(kcd, chain, kfe);
- for (i = besti[0]; i != besti[1]; i = (i + 1) % nh) {
- knife_append_list(kcd, chain, he[i]);
- }
- kfe = new_knife_edge(kcd);
- kfe->v1 = hv[besti[1]];
- kfe->v2 = get_bm_knife_vert(kcd, fv[bestj[1]]);
- knife_append_list(kcd, chain, kfe);
- *mainchain = chain;
-
- chain = knife_empty_list(kcd);
- for (i = besti[1]; i != besti[0]; i = (i + 1) % nh) {
- knife_append_list(kcd, chain, he[i]);
- }
- *sidechain = chain;
-
- return true;
- }
- else {
- return false;
- }
-}
-
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
{
bool v1_inside, v2_inside;
@@ -2572,201 +2256,110 @@ static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
return false;
}
-static bool knife_edge_in_face(KnifeEdge *kfe, BMFace *f)
-{
- return knife_verts_edge_in_face(kfe->v1, kfe->v2, f);
-}
-
-/* Split face f with KnifeEdges on chain. f remains as one side, the face formed is put in *newface.
- * The new face will be on the left side of the chain as viewed from the normal-out side of f. */
-static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *chain, BMFace **r_f_new)
+static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges)
{
BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe, *kfelast;
- BMVert *v1, *v2;
- BMLoop *l_v1, *l_v2;
- BMFace *f_new;
+ KnifeEdge *kfe;
Ref *ref;
- KnifeVert *kfv, *kfvprev;
- BMLoop *l_new, *l_iter;
+ int edge_array_len = BLI_listbase_count(kfedges);
+ bool ok;
int i;
- int nco = BLI_listbase_count(chain) - 1;
- float (*cos)[3] = BLI_array_alloca(cos, nco);
- KnifeVert **kverts = BLI_array_alloca(kverts, nco);
-
- kfe = ((Ref *)chain->first)->ref;
- v1 = kfe->v1->v ? kfe->v1->v : kfe->v2->v;
- kfelast = ((Ref *)chain->last)->ref;
- v2 = kfelast->v2->v ? kfelast->v2->v : kfelast->v1->v;
- BLI_assert(v1 != NULL && v2 != NULL);
- kfvprev = kfe->v1->v == v1 ? kfe->v1 : kfe->v2;
- for (ref = chain->first, i = 0; i < nco && ref != chain->last; ref = ref->next, i++) {
+
+ BMFace **face_arr;
+ int face_arr_len;
+
+ BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len);
+
+ /* point to knife edges we've created edges in, edge_array aligned */
+ KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
+
+ i = 0;
+ for (ref = kfedges->first; ref; ref = ref->next) {
+ bool is_new_edge = false;
kfe = ref->ref;
- BLI_assert(kfvprev == kfe->v1 || kfvprev == kfe->v2);
- kfv = kfe->v1 == kfvprev ? kfe->v2 : kfe->v1;
- copy_v3_v3(cos[i], kfv->co);
- kverts[i] = kfv;
- kfvprev = kfv;
- }
- BLI_assert(i == nco);
- l_new = NULL;
- if ((l_v1 = BM_face_vert_share_loop(f, v1)) &&
- (l_v2 = BM_face_vert_share_loop(f, v2)))
- {
- if (nco == 0) {
- /* Want to prevent creating two-sided polygons */
- if (v1 == v2 || BM_edge_exists(v1, v2)) {
- f_new = NULL;
+ if (kfe->e == NULL) {
+ if (kfe->v1->v && kfe->v2->v) {
+ kfe->e = BM_edge_exists(kfe->v1->v, kfe->v2->v);
}
- else {
- f_new = BM_face_split(bm, f, l_v1, l_v2, &l_new, NULL, true);
+ }
+
+ if (kfe->e) {
+ if (BM_edge_in_face(kfe->e, f)) {
+ /* shouldn't happen, but in this case - just ignore */
+ continue;
}
}
else {
- f_new = BM_face_split_n(bm, f, l_v1, l_v2, cos, nco, &l_new, NULL);
- if (f_new) {
- /* Now go through lnew chain matching up chain kv's and assign real v's to them */
- for (l_iter = l_new->next, i = 0; i < nco; l_iter = l_iter->next, i++) {
- BLI_assert(equals_v3v3(cos[i], l_iter->v->co));
- if (kcd->select_result) {
- BM_edge_select_set(bm, l_iter->e, true);
- }
- kverts[i]->v = l_iter->v;
+ if (kfe->v1->v == NULL) {
+ kfe->v1->v = BM_vert_create(bm, kfe->v1->co, NULL, 0);
+ }
+ if (kfe->v2->v == NULL) {
+ kfe->v2->v = BM_vert_create(bm, kfe->v2->co, NULL, 0);
+ }
+ BLI_assert(kfe->e == NULL);
+ kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
+ if (kfe->e) {
+ if (kcd->select_result || BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_edge_select_set(bm, kfe->e, true);
}
+ is_new_edge = true;
}
}
- }
- else {
- f_new = NULL;
- }
- /* the select chain above doesnt account for the first loop */
- if (kcd->select_result) {
- if (l_new) {
- BM_edge_select_set(bm, l_new->e, true);
- }
- }
- else if (f_new) {
- BM_elem_select_copy(bm, bm, f_new, f);
+ BLI_assert(kfe->e);
+
+ kfe_array[i] = is_new_edge ? kfe : 0;
+ edge_array[i] = kfe->e;
+ i += 1;
}
- *r_f_new = f_new;
-}
+ if (i) {
+ const int edge_array_len_orig = i;
+ edge_array_len = i;
-static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges)
-{
- BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe;
- BMFace *fnew, *fnew2, *fhole;
- ListBase *chain, *hole, *sidechain;
- Ref *ref, *refnext;
- int count, oldcount;
-
- oldcount = BLI_listbase_count(kfedges);
- while ((chain = find_chain(kcd, kfedges)) != NULL) {
- ListBase fnew_kfedges;
- knife_make_chain_cut(kcd, f, chain, &fnew);
- if (!fnew) {
- return;
- }
-
- /* Move kfedges to fnew_kfedges if they are now in fnew.
- * The chain edges were removed already */
- BLI_listbase_clear(&fnew_kfedges);
- for (ref = kfedges->first; ref; ref = refnext) {
- kfe = ref->ref;
- refnext = ref->next;
- if (knife_edge_in_face(kfe, fnew)) {
- BLI_remlink(kfedges, ref);
- kfe->basef = fnew;
- BLI_addtail(&fnew_kfedges, ref);
- }
- else if (!knife_edge_in_face(kfe, f)) {
- /* Concave ngon's - this edge might not be in either faces, T41730 */
- BLI_remlink(kfedges, ref);
+#ifdef USE_NET_ISLAND_CONNECT
+ unsigned int edge_array_holes_len;
+ BMEdge **edge_array_holes;
+ if (BM_face_split_edgenet_connect_islands(
+ bm, f,
+ edge_array, edge_array_len,
+ kcd->arena_edgenet,
+ &edge_array_holes, &edge_array_holes_len))
+ {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ for (i = edge_array_len; i < edge_array_holes_len; i++) {
+ BM_edge_select_set(bm, edge_array_holes[i], true);
+ }
}
- }
- if (fnew_kfedges.first)
- knife_make_face_cuts(kcd, fnew, &fnew_kfedges);
- /* find_chain should always remove edges if it returns true,
- * but guard against infinite loop anyway */
- count = BLI_listbase_count(kfedges);
- if (count >= oldcount) {
- BLI_assert(!"knife find_chain infinite loop");
- return;
+ edge_array_len = edge_array_holes_len;
+ edge_array = edge_array_holes; /* owned by the arena */
}
- oldcount = count;
- }
+#endif
- while ((hole = find_hole(kcd, kfedges)) != NULL) {
- if (find_hole_chains(kcd, hole, f, &chain, &sidechain)) {
- ListBase fnew_kfedges, fnew2_kfedges;
+ ok = BM_face_split_edgenet(
+ bm, f, edge_array, edge_array_len,
+ &face_arr, &face_arr_len);
- /* chain goes across f and sidechain comes back
- * from the second last vertex to the second vertex.
- */
- knife_make_chain_cut(kcd, f, chain, &fnew);
- if (!fnew) {
- BLI_assert(!"knife failed hole cut");
- return;
- }
- kfe = ((Ref *)sidechain->first)->ref;
- if (knife_edge_in_face(kfe, f)) {
- knife_make_chain_cut(kcd, f, sidechain, &fnew2);
- if (fnew2 == NULL) {
- return;
- }
- fhole = f;
- }
- else if (knife_edge_in_face(kfe, fnew)) {
- knife_make_chain_cut(kcd, fnew, sidechain, &fnew2);
- if (fnew2 == NULL) {
- return;
- }
- fhole = fnew2;
- }
- else {
- /* shouldn't happen except in funny edge cases */
- return;
- }
- BM_face_kill(bm, fhole);
- /* Move kfedges to either fnew or fnew2 if appropriate.
- * The hole edges were removed already */
- BLI_listbase_clear(&fnew_kfedges);
- BLI_listbase_clear(&fnew2_kfedges);
- for (ref = kfedges->first; ref; ref = refnext) {
- kfe = ref->ref;
- refnext = ref->next;
- if (knife_edge_in_face(kfe, fnew)) {
- BLI_remlink(kfedges, ref);
- kfe->basef = fnew;
- BLI_addtail(&fnew_kfedges, ref);
- }
- else if (knife_edge_in_face(kfe, fnew2)) {
- BLI_remlink(kfedges, ref);
- kfe->basef = fnew2;
- BLI_addtail(&fnew2_kfedges, ref);
+ if (ok) {
+ MEM_freeN(face_arr);
+ }
+
+ /* remove dangling edges, not essential - but nice for users */
+ for (i = 0; i < edge_array_len_orig; i++) {
+ if (kfe_array[i]) {
+ if (BM_edge_is_wire(kfe_array[i]->e)) {
+ BM_edge_kill(bm, kfe_array[i]->e);
+ kfe_array[i]->e = NULL;
}
}
- /* We'll skip knife edges that are in the newly formed hole.
- * (Maybe we shouldn't have made a hole in the first place?) */
- if (fnew != fhole && fnew_kfedges.first)
- knife_make_face_cuts(kcd, fnew, &fnew_kfedges);
- if (fnew2 != fhole && fnew2_kfedges.first)
- knife_make_face_cuts(kcd, fnew2, &fnew2_kfedges);
- if (f == fhole)
- break;
- /* find_hole should always remove edges if it returns true,
- * but guard against infinite loop anyway */
- count = BLI_listbase_count(kfedges);
- if (count >= oldcount) {
- BLI_assert(!"knife find_hole infinite loop");
- return;
- }
- oldcount = count;
}
+
+
+#ifdef USE_NET_ISLAND_CONNECT
+ BLI_memarena_clear(kcd->arena_edgenet);
+#endif
}
}
@@ -2915,6 +2508,9 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
BLI_ghash_free(kcd->facetrimap, NULL, NULL);
BLI_memarena_free(kcd->arena);
+#ifdef USE_NET_ISLAND_CONNECT
+ BLI_memarena_free(kcd->arena_edgenet);
+#endif
/* tag for redraw */
ED_region_tag_redraw(kcd->ar);
@@ -3000,6 +2596,9 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
knifetool_init_bmbvh(kcd);
kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
+#ifdef USE_NET_ISLAND_CONNECT
+ kcd->arena_edgenet = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), __func__);
+#endif
kcd->vthresh = KMAXDIST - 1;
kcd->ethresh = KMAXDIST;
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 8eead9b8e44..5f046e3b6c6 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -480,7 +480,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
// FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
- uiDefButO(block, UI_BTYPE_BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, 150, 20,
+ uiDefButO(block, UI_BTYPE_BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, UI_UNIT_X * 7.0f, UI_UNIT_Y,
TIP_("Adds a new F-Modifier for the active NLA Strip"));
/* copy/paste (as sub-row)*/
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 57318e44eec..92570263856 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -54,7 +54,9 @@
#include "MOD_util.h"
#ifdef USE_BMESH
+#include "BLI_alloca.h"
#include "BLI_math_geom.h"
+#include "BKE_material.h"
#include "MEM_guardedalloc.h"
#include "bmesh.h"
@@ -238,17 +240,30 @@ static DerivedMesh *applyModifier_bmesh(
/* we need face normals because of 'BM_face_split_edgenet'
* we could calculate on the fly too (before calling split). */
- float nmat[4][4];
- invert_m4_m4(nmat, omat);
-
- BMFace *efa;
- i = 0;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- mul_transposed_mat3_m4_v3(nmat, efa->no);
- normalize_v3(efa->no);
- BM_elem_flag_enable(efa, BM_FACE_TAG); /* temp tag to test which side split faces are from */
- if (++i == i_faces_end) {
- break;
+ {
+ float nmat[4][4];
+ invert_m4_m4(nmat, omat);
+
+ const short ob_src_totcol = bmd->object->totcol;
+ short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1);
+
+ BKE_material_remap_object_calc(ob, bmd->object, material_remap);
+
+ BMFace *efa;
+ i = 0;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ mul_transposed_mat3_m4_v3(nmat, efa->no);
+ normalize_v3(efa->no);
+ BM_elem_flag_enable(efa, BM_FACE_TAG); /* temp tag to test which side split faces are from */
+
+ /* remap material */
+ if (LIKELY(efa->mat_nr < ob_src_totcol)) {
+ efa->mat_nr = material_remap[efa->mat_nr];
+ }
+
+ if (++i == i_faces_end) {
+ break;
+ }
}
}
}