|
|
|
@@ -26,7 +26,6 @@
|
|
|
|
|
|
|
|
|
|
#define _USE_MATH_DEFINES
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
@@ -44,7 +43,6 @@
|
|
|
|
|
#include "BIF_gl.h"
|
|
|
|
|
#include "BIF_glutil.h" /* for paint cursor */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "ED_screen.h"
|
|
|
|
|
#include "ED_space_api.h"
|
|
|
|
|
#include "ED_view3d.h"
|
|
|
|
@@ -110,7 +108,7 @@ typedef struct KnifePosData {
|
|
|
|
|
BMFace *bmface;
|
|
|
|
|
int is_space;
|
|
|
|
|
|
|
|
|
|
int mval[2]; /* mouse screen position */
|
|
|
|
|
int mval[2]; /* mouse screen position */
|
|
|
|
|
} KnifePosData;
|
|
|
|
|
|
|
|
|
|
/* struct for properties used while drawing */
|
|
|
|
@@ -185,7 +183,8 @@ static void knife_project_v3(knifetool_opdata *kcd, const float co[3], float sco
|
|
|
|
|
ED_view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void knife_pos_data_clear(KnifePosData *kpd) {
|
|
|
|
|
static void knife_pos_data_clear(KnifePosData *kpd)
|
|
|
|
|
{
|
|
|
|
|
zero_v3(kpd->co);
|
|
|
|
|
zero_v3(kpd->cage);
|
|
|
|
|
kpd->vert = NULL;
|
|
|
|
@@ -490,13 +489,12 @@ static int verge_linehit(const void *vlh1, const void *vlh2)
|
|
|
|
|
{
|
|
|
|
|
const BMEdgeHit *lh1 = vlh1, *lh2 = vlh2;
|
|
|
|
|
|
|
|
|
|
if (lh1->l < lh2->l) return -1;
|
|
|
|
|
else if (lh1->l > lh2->l) return 1;
|
|
|
|
|
if (lh1->l < lh2->l) return -1;
|
|
|
|
|
else if (lh1->l > lh2->l) return 1;
|
|
|
|
|
else return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void knife_add_single_cut_through(knifetool_opdata *kcd,
|
|
|
|
|
KnifeVert *v1, KnifeVert *v2, BMFace *f)
|
|
|
|
|
static void knife_add_single_cut_through(knifetool_opdata *kcd, KnifeVert *v1, KnifeVert *v2, BMFace *f)
|
|
|
|
|
{
|
|
|
|
|
KnifeEdge *kfenew;
|
|
|
|
|
|
|
|
|
@@ -551,7 +549,7 @@ static void knife_cut_through(knifetool_opdata *kcd)
|
|
|
|
|
BMFace *f;
|
|
|
|
|
KnifeEdge *kfe, *kfe2, *kfe3;
|
|
|
|
|
KnifeVert *v1, *v2, *firstv = NULL, *lastv = NULL;
|
|
|
|
|
ListBase firstfaces = {NULL, NULL}, lastfaces = { NULL, NULL};
|
|
|
|
|
ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL};
|
|
|
|
|
Ref *r, *r2;
|
|
|
|
|
KnifeEdge **splitkfe;
|
|
|
|
|
int i, j, found;
|
|
|
|
@@ -590,7 +588,7 @@ static void knife_cut_through(knifetool_opdata *kcd)
|
|
|
|
|
if (firstv) {
|
|
|
|
|
/* For each face incident to firstv,
|
|
|
|
|
* find the first following linehit (if any) sharing that face and connect */
|
|
|
|
|
for (r = firstfaces.first; r; r = r->next ) {
|
|
|
|
|
for (r = firstfaces.first; r; r = r->next) {
|
|
|
|
|
f = r->ref;
|
|
|
|
|
found = 0;
|
|
|
|
|
for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit; j++, lh2++) {
|
|
|
|
@@ -627,8 +625,8 @@ static void knife_cut_through(knifetool_opdata *kcd)
|
|
|
|
|
kfe2 = lh2->kfe;
|
|
|
|
|
for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
|
|
|
|
|
if (r2->ref == f) {
|
|
|
|
|
v1 = splitkfe[i]? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
|
|
|
|
|
v2 = splitkfe[j]? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
|
|
|
|
|
v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
|
|
|
|
|
v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
|
|
|
|
|
knife_add_single_cut_through(kcd, v1, v2, f);
|
|
|
|
|
found = 1;
|
|
|
|
|
break;
|
|
|
|
@@ -638,7 +636,7 @@ static void knife_cut_through(knifetool_opdata *kcd)
|
|
|
|
|
if (!found && lastv) {
|
|
|
|
|
for (r2 = lastfaces.first; r2; r2 = r2->next) {
|
|
|
|
|
if (r2->ref == f) {
|
|
|
|
|
v1 = splitkfe[i]? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
|
|
|
|
|
v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
|
|
|
|
|
knife_add_single_cut_through(kcd, v1, lastv, f);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -1080,8 +1078,8 @@ static BMEdgeHit *knife_edge_tri_isect(knifetool_opdata *kcd, BMBVHTree *bmtree,
|
|
|
|
|
if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
|
|
|
|
|
BMEdgeHit hit;
|
|
|
|
|
|
|
|
|
|
if ( len_squared_v3v3(p, kcd->cur.co) < depsilon_squared ||
|
|
|
|
|
len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
|
|
|
|
|
if (len_squared_v3v3(p, kcd->cur.co) < depsilon_squared ||
|
|
|
|
|
len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
@@ -1238,7 +1236,6 @@ static void knife_input_ray_cast(knifetool_opdata *kcd, const int mval_i[2],
|
|
|
|
|
mul_m3_v3(imat, r_ray);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static BMFace *knife_find_closest_face(knifetool_opdata *kcd, float co[3], float cageco[3], int *is_space)
|
|
|
|
|
{
|
|
|
|
|
BMFace *f;
|
|
|
|
@@ -1422,7 +1419,8 @@ static KnifeEdge *knife_find_closest_edge(knifetool_opdata *kcd, float p[3], flo
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* find a vertex near the mouse cursor, if it exists */
|
|
|
|
|
static KnifeVert *knife_find_closest_vert(knifetool_opdata *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space)
|
|
|
|
|
static KnifeVert *knife_find_closest_vert(knifetool_opdata *kcd, float p[3], float cagep[3], BMFace **fptr,
|
|
|
|
|
int *is_space)
|
|
|
|
|
{
|
|
|
|
|
BMFace *f;
|
|
|
|
|
float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh);
|
|
|
|
@@ -1553,12 +1551,12 @@ static int knife_update_active(knifetool_opdata *kcd)
|
|
|
|
|
* Note that drawing lines in `free-space` isn't properly supported
|
|
|
|
|
* but theres no guarantee (0,0,0) has any geometry either - campbell */
|
|
|
|
|
if (kcd->cur.vert == NULL && kcd->cur.edge == NULL) {
|
|
|
|
|
float origin[3], ray[3], co[3];
|
|
|
|
|
float origin[3], ray[3], co[3];
|
|
|
|
|
|
|
|
|
|
knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray);
|
|
|
|
|
add_v3_v3v3(co, origin, ray);
|
|
|
|
|
knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray);
|
|
|
|
|
add_v3_v3v3(co, origin, ray);
|
|
|
|
|
|
|
|
|
|
closest_to_line_v3(kcd->cur.cage, kcd->prev.cage, co, origin);
|
|
|
|
|
closest_to_line_v3(kcd->cur.cage, kcd->prev.cage, co, origin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (kcd->mode == MODE_DRAGGING) {
|
|
|
|
@@ -1659,7 +1657,7 @@ static void remerge_faces(knifetool_opdata *kcd)
|
|
|
|
|
f2 = BM_faces_join(bm, faces, BLI_array_count(faces));
|
|
|
|
|
if (f2) {
|
|
|
|
|
BMO_elem_flag_enable(bm, f2, FACE_NEW);
|
|
|
|
|
BM_elem_index_set(f2, idx); /* set_dirty! */ /* BMESH_TODO, check if this is valid or not */
|
|
|
|
|
BM_elem_index_set(f2, idx); /* set_dirty! *//* BMESH_TODO, check if this is valid or not */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -1724,7 +1722,7 @@ static void knifenet_fill_faces(knifetool_opdata *kcd)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we want to only do changed faces. first, go over new edges and add to
|
|
|
|
|
* face net lists.*/
|
|
|
|
|
* face net lists.*/
|
|
|
|
|
i = j = k = 0;
|
|
|
|
|
BLI_mempool_iternew(kcd->kedges, &iter);
|
|
|
|
|
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
|
|
|
|
@@ -1836,7 +1834,7 @@ static void knifenet_fill_faces(knifetool_opdata *kcd)
|
|
|
|
|
ScanFillEdge *eed;
|
|
|
|
|
eed = BLI_addfilledge(lasteve, eve);
|
|
|
|
|
if (entry->kfe->oe)
|
|
|
|
|
eed->f = FILLBOUNDARY; /* mark as original boundary edge */
|
|
|
|
|
eed->f = FILLBOUNDARY; /* mark as original boundary edge */
|
|
|
|
|
|
|
|
|
|
BMO_elem_flag_disable(bm, entry->kfe->e->v1, DEL);
|
|
|
|
|
BMO_elem_flag_disable(bm, entry->kfe->e->v2, DEL);
|
|
|
|
@@ -1863,8 +1861,8 @@ static void knifenet_fill_faces(knifetool_opdata *kcd)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
f2 = BM_face_create_quad_tri(bm,
|
|
|
|
|
v1, v2, v3, NULL,
|
|
|
|
|
NULL, FALSE);
|
|
|
|
|
v1, v2, v3, NULL,
|
|
|
|
|
NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
BMO_elem_flag_enable(bm, f2, FACE_NEW);
|
|
|
|
|
|
|
|
|
@@ -1874,7 +1872,7 @@ static void knifenet_fill_faces(knifetool_opdata *kcd)
|
|
|
|
|
} while ((l_iter = l_iter->next) != BM_FACE_FIRST_LOOP(f2));
|
|
|
|
|
|
|
|
|
|
BMO_elem_flag_disable(bm, f2, DEL);
|
|
|
|
|
BM_elem_index_set(f2, i); /* set_dirty! */ /* note, not 100% sure this is dirty? need to check */
|
|
|
|
|
BM_elem_index_set(f2, i); /* set_dirty! *//* note, not 100% sure this is dirty? need to check */
|
|
|
|
|
|
|
|
|
|
BM_face_normal_update(bm, f2);
|
|
|
|
|
if (dot_v3v3(f->no, f2->no) < 0.0f) {
|
|
|
|
@@ -1931,7 +1929,8 @@ static void knifenet_fill_faces(knifetool_opdata *kcd)
|
|
|
|
|
#else /* use direct (non-scanfill) method for cuts */
|
|
|
|
|
|
|
|
|
|
/* assuming v is on line ab, what fraction of the way is v from a to b? */
|
|
|
|
|
static float frac_along(const float a[3], const float b[3], const float v[3]) {
|
|
|
|
|
static float frac_along(const float a[3], const float b[3], const float v[3])
|
|
|
|
|
{
|
|
|
|
|
float lab;
|
|
|
|
|
|
|
|
|
|
lab = len_v3v3(a, b);
|
|
|
|
@@ -1944,7 +1943,8 @@ static float frac_along(const float a[3], const float b[3], const float v[3]) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* sort list of kverts by fraction along edge e */
|
|
|
|
|
static void sort_by_frac_along(ListBase *lst, BMEdge *e) {
|
|
|
|
|
static void sort_by_frac_along(ListBase *lst, BMEdge *e)
|
|
|
|
|
{
|
|
|
|
|
KnifeVert *vcur, *vprev;
|
|
|
|
|
float *v1co, *v2co;
|
|
|
|
|
Ref *cur = NULL, *prev = NULL, *next = NULL;
|
|
|
|
@@ -1976,8 +1976,9 @@ static void sort_by_frac_along(ListBase *lst, BMEdge *e) {
|
|
|
|
|
/* 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 int find_chain_search(knifetool_opdata *kcd, KnifeVert *kfv,
|
|
|
|
|
ListBase *fedges, SmallHash *visited, ListBase *chain) {
|
|
|
|
|
static int find_chain_search(knifetool_opdata *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
|
|
|
|
|
ListBase *chain)
|
|
|
|
|
{
|
|
|
|
|
Ref *r;
|
|
|
|
|
KnifeEdge *kfe;
|
|
|
|
|
KnifeVert *kfv_other;
|
|
|
|
@@ -2007,8 +2008,8 @@ static int find_chain_search(knifetool_opdata *kcd, KnifeVert *kfv,
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ListBase * find_chain_from_vertex(knifetool_opdata *kcd, KnifeEdge *kfe,
|
|
|
|
|
BMVert *v, ListBase *fedges) {
|
|
|
|
|
static ListBase * find_chain_from_vertex(knifetool_opdata *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges)
|
|
|
|
|
{
|
|
|
|
|
SmallHash visited_, *visited = &visited_;
|
|
|
|
|
ListBase *ans;
|
|
|
|
|
int found;
|
|
|
|
@@ -2037,7 +2038,8 @@ static ListBase * find_chain_from_vertex(knifetool_opdata *kcd, KnifeEdge *kfe,
|
|
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
|
static ListBase * find_chain(knifetool_opdata *kcd, ListBase *fedges)
|
|
|
|
|
{
|
|
|
|
|
Ref *r, *ref;
|
|
|
|
|
KnifeEdge *kfe;
|
|
|
|
|
BMVert *v1, *v2;
|
|
|
|
@@ -2075,8 +2077,9 @@ static ListBase * find_chain(knifetool_opdata *kcd, ListBase *fedges) {
|
|
|
|
|
/* 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 int find_hole_search(knifetool_opdata *kcd, KnifeVert *kfvfirst, KnifeVert *kfv,
|
|
|
|
|
ListBase *fedges, SmallHash *visited, ListBase *hole) {
|
|
|
|
|
static int find_hole_search(knifetool_opdata *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
|
|
|
|
|
SmallHash *visited, ListBase *hole)
|
|
|
|
|
{
|
|
|
|
|
Ref *r;
|
|
|
|
|
KnifeEdge *kfe, *kfelast;
|
|
|
|
|
KnifeVert *kfv_other;
|
|
|
|
@@ -2109,7 +2112,8 @@ static int find_hole_search(knifetool_opdata *kcd, KnifeVert *kfvfirst, KnifeVer
|
|
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
|
static ListBase *find_hole(knifetool_opdata *kcd, ListBase *fedges)
|
|
|
|
|
{
|
|
|
|
|
ListBase *ans;
|
|
|
|
|
Ref *r, *ref;
|
|
|
|
|
KnifeEdge *kfe;
|
|
|
|
@@ -2151,8 +2155,9 @@ static ListBase *find_hole(knifetool_opdata *kcd, ListBase *fedges) {
|
|
|
|
|
* 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 int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
ListBase **mainchain, ListBase **sidechain) {
|
|
|
|
|
static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
|
|
|
|
|
ListBase **sidechain)
|
|
|
|
|
{
|
|
|
|
|
float **fco, **hco;
|
|
|
|
|
BMVert **fv;
|
|
|
|
|
KnifeVert **hv;
|
|
|
|
@@ -2189,11 +2194,12 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
he[i] = kfe;
|
|
|
|
|
if (kfvother == NULL) {
|
|
|
|
|
kfv = kfe->v1;
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
kfv = kfvother;
|
|
|
|
|
BLI_assert(kfv == kfe->v1 || kfv == kfe->v2);
|
|
|
|
|
}
|
|
|
|
|
hco[i] = BLI_memarena_alloc(kcd->arena, 2*sizeof(float));
|
|
|
|
|
hco[i] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float));
|
|
|
|
|
hco[i][0] = kfv->co[ax];
|
|
|
|
|
hco[i][1] = kfv->co[ay];
|
|
|
|
|
hv[i] = kfv;
|
|
|
|
@@ -2203,7 +2209,7 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
|
BM_ITER(v, &iter, kcd->em->bm, BM_VERTS_OF_FACE, f) {
|
|
|
|
|
fco[j] = BLI_memarena_alloc(kcd->arena, 2*sizeof(float));
|
|
|
|
|
fco[j] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float));
|
|
|
|
|
fco[j][0] = v->co[ax];
|
|
|
|
|
fco[j][1] = v->co[ay];
|
|
|
|
|
fv[j] = v;
|
|
|
|
@@ -2238,17 +2244,17 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
|
|
|
|
|
ok = TRUE;
|
|
|
|
|
for (k = 0; k < nh && ok; k++) {
|
|
|
|
|
if (k == i || (k+1) % nh == i)
|
|
|
|
|
if (k == i || (k + 1) % nh == i)
|
|
|
|
|
continue;
|
|
|
|
|
if (isect_line_line_v2(hco[i], fco[j], hco[k], hco[(k+1) % nh]))
|
|
|
|
|
if (isect_line_line_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)
|
|
|
|
|
if (k == j || (k + 1) % nf == j)
|
|
|
|
|
continue;
|
|
|
|
|
if (isect_line_line_v2(hco[i], fco[j], fco[k], fco[(k+1) % nf]))
|
|
|
|
|
if (isect_line_line_v2(hco[i], fco[j], fco[k], fco[(k + 1) % nf]))
|
|
|
|
|
ok = FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (ok) {
|
|
|
|
@@ -2269,7 +2275,7 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
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) {
|
|
|
|
|
for (i = besti[0]; i != besti[1]; i = (i + 1) % nh) {
|
|
|
|
|
knife_append_list(kcd, chain, he[i]);
|
|
|
|
|
}
|
|
|
|
|
kfe = new_knife_edge(kcd);
|
|
|
|
@@ -2279,7 +2285,7 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
*mainchain = chain;
|
|
|
|
|
|
|
|
|
|
chain = knife_empty_list(kcd);
|
|
|
|
|
for (i = besti[1]; i != besti[0]; i = (i+1) % nh) {
|
|
|
|
|
for (i = besti[1]; i != besti[0]; i = (i + 1) % nh) {
|
|
|
|
|
knife_append_list(kcd, chain, he[i]);
|
|
|
|
|
}
|
|
|
|
|
*sidechain = chain;
|
|
|
|
@@ -2291,7 +2297,8 @@ static int find_hole_chains(knifetool_opdata *kcd, ListBase *hole, BMFace *f,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int knife_edge_in_face(knifetool_opdata *kcd, KnifeEdge *kfe, BMFace *f) {
|
|
|
|
|
static int knife_edge_in_face(knifetool_opdata *kcd, KnifeEdge *kfe, BMFace *f)
|
|
|
|
|
{
|
|
|
|
|
BMesh *bm = kcd->em->bm;
|
|
|
|
|
BMVert *v1, *v2;
|
|
|
|
|
BMLoop *l1, *l2, *l;
|
|
|
|
@@ -2333,13 +2340,14 @@ static int knife_edge_in_face(knifetool_opdata *kcd, KnifeEdge *kfe, BMFace *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 **newface) {
|
|
|
|
|
static void knife_make_chain_cut(knifetool_opdata *kcd, BMFace *f, ListBase *chain, BMFace **newface)
|
|
|
|
|
{
|
|
|
|
|
BMesh *bm = kcd->em->bm;
|
|
|
|
|
KnifeEdge *kfe, *kfelast;
|
|
|
|
|
BMVert *v1, *v2;
|
|
|
|
|
BMFace *fnew;
|
|
|
|
|
Ref *ref;
|
|
|
|
|
KnifeVert *kfv, *kfvprev;
|
|
|
|
|
KnifeVert *kfv, *kfvprev;
|
|
|
|
|
BMLoop *lnew, *l_iter;
|
|
|
|
|
int i;
|
|
|
|
|
int nco = BLI_countlist(chain) - 1;
|
|
|
|
@@ -2354,10 +2362,10 @@ static void knife_make_chain_cut(knifetool_opdata *kcd, BMFace *f, ListBase *cha
|
|
|
|
|
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++) {
|
|
|
|
|
for (ref = chain->first, i = 0; i < nco && ref != chain->last; ref = ref->next, i++) {
|
|
|
|
|
kfe = ref->ref;
|
|
|
|
|
BLI_assert(kfvprev == kfe->v1 || kfvprev == kfe->v2);
|
|
|
|
|
kfv = kfe->v1 == kfvprev? kfe->v2 : kfe->v1;
|
|
|
|
|
kfv = kfe->v1 == kfvprev ? kfe->v2 : kfe->v1;
|
|
|
|
|
copy_v3_v3(cos[i], kfv->co);
|
|
|
|
|
kverts[i] = kfv;
|
|
|
|
|
kfvprev = kfv;
|
|
|
|
@@ -2366,7 +2374,8 @@ static void knife_make_chain_cut(knifetool_opdata *kcd, BMFace *f, ListBase *cha
|
|
|
|
|
lnew = NULL;
|
|
|
|
|
if (nco == 0) {
|
|
|
|
|
*newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, TRUE);
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fnew = BM_face_split_n(bm, f, v1, v2, cos, nco, &lnew, NULL);
|
|
|
|
|
*newface = fnew;
|
|
|
|
|
|
|
|
|
@@ -2383,7 +2392,8 @@ static void knife_make_chain_cut(knifetool_opdata *kcd, BMFace *f, ListBase *cha
|
|
|
|
|
BLI_array_fixedstack_free(kverts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void knife_make_face_cuts(knifetool_opdata *kcd, BMFace *f, ListBase *kfedges) {
|
|
|
|
|
static void knife_make_face_cuts(knifetool_opdata *kcd, BMFace *f, ListBase *kfedges)
|
|
|
|
|
{
|
|
|
|
|
BMesh *bm = kcd->em->bm;
|
|
|
|
|
KnifeEdge *kfe;
|
|
|
|
|
BMFace *fnew, *fnew2, *fhole;
|
|
|
|
@@ -2524,7 +2534,7 @@ static void knife_make_cuts(knifetool_opdata *kcd)
|
|
|
|
|
BLI_mempool_iternew(kcd->kverts, &iter);
|
|
|
|
|
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
|
|
|
|
|
if (kfv->v)
|
|
|
|
|
continue; /* already have a BMVert */
|
|
|
|
|
continue; /* already have a BMVert */
|
|
|
|
|
for (ref = kfv->edges.first; ref; ref = ref->next) {
|
|
|
|
|
kfe = ref->ref;
|
|
|
|
|
e = kfe->e;
|
|
|
|
@@ -2575,7 +2585,7 @@ static void knifetool_finish(bContext *C, wmOperator *op)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
DAG_id_tag_update(kcd->ob->data, OB_RECALC_DATA);
|
|
|
|
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, kcd->ob->data);
|
|
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, kcd->ob->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copied from paint_image.c */
|
|
|
|
@@ -2608,7 +2618,7 @@ static void knife_recalc_projmat(knifetool_opdata *kcd)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* called when modal loop selection is done... */
|
|
|
|
|
static void knifetool_exit (bContext *UNUSED(C), wmOperator *op)
|
|
|
|
|
static void knifetool_exit(bContext *UNUSED(C), wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
knifetool_opdata *kcd = op->customdata;
|
|
|
|
|
|
|
|
|
@@ -2641,8 +2651,7 @@ static void knifetool_exit (bContext *UNUSED(C), wmOperator *op)
|
|
|
|
|
op->customdata = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cage_mapped_verts_callback(void *userData, int index, float *co,
|
|
|
|
|
float *UNUSED(no_f), short *UNUSED(no_s))
|
|
|
|
|
static void cage_mapped_verts_callback(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
|
|
|
|
|
{
|
|
|
|
|
void **data = userData;
|
|
|
|
|
BMEditMesh *em = data[0];
|
|
|
|
@@ -2689,7 +2698,7 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
|
|
|
|
|
cage->foreachMappedVert(cage, cage_mapped_verts_callback, data);
|
|
|
|
|
BLI_smallhash_release(&shash);
|
|
|
|
|
|
|
|
|
|
kcd->bmbvh = BMBVH_NewBVH(kcd->em, BMBVH_USE_CAGE|BMBVH_RETURN_ORIG, scene, obedit);
|
|
|
|
|
kcd->bmbvh = BMBVH_NewBVH(kcd->em, BMBVH_USE_CAGE | BMBVH_RETURN_ORIG, scene, obedit);
|
|
|
|
|
kcd->arena = BLI_memarena_new(1 << 15, "knife");
|
|
|
|
|
kcd->vthresh = KMAXDIST - 1;
|
|
|
|
|
kcd->ethresh = KMAXDIST;
|
|
|
|
@@ -2717,14 +2726,14 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int knifetool_cancel (bContext *C, wmOperator *op)
|
|
|
|
|
static int knifetool_cancel(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
/* this is just a wrapper around exit() */
|
|
|
|
|
knifetool_exit(C, op);
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int knifetool_invoke (bContext *C, wmOperator *op, wmEvent *evt)
|
|
|
|
|
static int knifetool_invoke(bContext *C, wmOperator *op, wmEvent *evt)
|
|
|
|
|
{
|
|
|
|
|
knifetool_opdata *kcd;
|
|
|
|
|
|
|
|
|
@@ -2758,27 +2767,28 @@ enum {
|
|
|
|
|
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
|
|
|
|
|
{
|
|
|
|
|
static EnumPropertyItem modal_items[] = {
|
|
|
|
|
{KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
|
|
|
|
|
{KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
|
|
|
|
|
{KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""},
|
|
|
|
|
{KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""},
|
|
|
|
|
{KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
|
|
|
|
|
{KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
|
|
|
|
|
{KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""},
|
|
|
|
|
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
|
|
|
|
|
{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
|
|
|
|
|
{KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
|
|
|
|
|
{KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
|
|
|
|
|
{KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""},
|
|
|
|
|
{KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""},
|
|
|
|
|
{KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
|
|
|
|
|
{KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
|
|
|
|
|
{KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""},
|
|
|
|
|
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
|
|
|
|
|
{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
|
|
|
|
|
|
|
|
|
|
{0, NULL, 0, NULL, NULL}};
|
|
|
|
|
|
|
|
|
|
wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Knife Tool Modal Map");
|
|
|
|
|
|
|
|
|
|
/* this function is called for each spacetype, only needs to add map once */
|
|
|
|
|
if (keymap) return NULL;
|
|
|
|
|
if (keymap)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
keymap = WM_modalkeymap_add(keyconf, "Knife Tool Modal Map", modal_items);
|
|
|
|
|
|
|
|
|
|
/* items for modal map */
|
|
|
|
|
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
|
|
|
|
|
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
|
|
|
|
|
WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_ADD_CUT);
|
|
|
|
|
WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
|
|
|
|
|
WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
|
|
|
|
@@ -2802,7 +2812,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
|
|
|
|
|
return keymap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
|
static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
Object *obedit;
|
|
|
|
|
knifetool_opdata *kcd = op->customdata;
|
|
|
|
@@ -2887,7 +2897,7 @@ static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
|
|
|
|
|
|
ED_region_tag_redraw(kcd->ar);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { /* non-modal-mapped events */
|
|
|
|
|
switch (event->type) {
|
|
|
|
@@ -2907,7 +2917,7 @@ static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
|
ED_region_tag_redraw(kcd->ar);
|
|
|
|
|
return OPERATOR_PASS_THROUGH;
|
|
|
|
|
|
|
|
|
|
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
|
|
|
|
|
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
|
|
|
|
|
if (kcd->mode != MODE_PANNING) {
|
|
|
|
|
knife_recalc_projmat(kcd);
|
|
|
|
|
kcd->vc.mval[0] = event->mval[0];
|
|
|
|
@@ -2925,7 +2935,7 @@ static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MESH_OT_knifetool (wmOperatorType *ot)
|
|
|
|
|
void MESH_OT_knifetool(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* description */
|
|
|
|
|
ot->name = "Knife Topology Tool";
|
|
|
|
@@ -2939,5 +2949,5 @@ void MESH_OT_knifetool (wmOperatorType *ot)
|
|
|
|
|
ot->poll = ED_operator_editmesh_view3d;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
|
|
|
|
|
}
|
|
|
|
|