static bool swap_selection_bpoint(BPoint *bp) { if (bp->f1 & SELECT) return select_bpoint(bp, DESELECT, SELECT, VISIBLE); else return select_bpoint(bp, SELECT, SELECT, VISIBLE); }
static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_dst) { const int u = nu->pntsu; int i; if (vert_src > vert_dst) { SWAP(int, vert_src, vert_dst); } if (nu->flagu & CU_NURB_CYCLIC) { if (curve_calc_dist_span(nu, vert_src, vert_dst) > curve_calc_dist_span(nu, vert_dst, vert_src)) { SWAP(int, vert_src, vert_dst); } } i = vert_src; while (true) { if (nu->type & CU_BEZIER) { select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN); } else { select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN); } if (i == vert_dst) { break; } i = (i + 1) % u; } }
static void select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset) { int a, startrow, startpnt; int row, pnt; startrow = (bp - nu->bp) / nu->pntsu; startpnt = (bp - nu->bp) % nu->pntsu; a = nu->pntsu * nu->pntsv; bp = &nu->bp[a - 1]; row = nu->pntsv - 1; pnt = nu->pntsu - 1; while (a--) { const int depth = abs(pnt - startpnt) + abs(row - startrow); if ((offset + depth) % (skip + nth) >= skip) { select_bpoint(bp, DESELECT, SELECT, HIDDEN); } pnt--; if (pnt < 0) { pnt = nu->pntsu - 1; row--; } bp--; } }
static void curve_select_random(ListBase *editnurb, float randfac, bool select) { Nurb *nu; BezTriple *bezt; BPoint *bp; int a; for (nu = editnurb->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; while (a--) { if (!bezt->hide) { if (BLI_frand() < randfac) { select_beztriple(bezt, select, SELECT, VISIBLE); } } bezt++; } } else { bp = nu->bp; a = nu->pntsu * nu->pntsv; while (a--) { if (!bp->hide) { if (BLI_frand() < randfac) { select_bpoint(bp, select, SELECT, VISIBLE); } } bp++; } } } }
static void select_nth_bp(Nurb *nu, BPoint *bp, const struct CheckerIntervalParams *params) { int a, startrow, startpnt; int row, pnt; startrow = (bp - nu->bp) / nu->pntsu; startpnt = (bp - nu->bp) % nu->pntsu; a = nu->pntsu * nu->pntsv; bp = &nu->bp[a - 1]; row = nu->pntsv - 1; pnt = nu->pntsu - 1; while (a--) { const int depth = abs(pnt - startpnt) + abs(row - startrow); if (WM_operator_properties_checker_interval_test(params, depth)) { select_bpoint(bp, DESELECT, SELECT, HIDDEN); } pnt--; if (pnt < 0) { pnt = nu->pntsu - 1; row--; } bp--; } }
/** * \param next: -1/1 for prev/next * \param cont: when true select continuously * \param selstatus: inverts behavior */ static void select_adjacent_cp( ListBase *editnurb, short next, const bool cont, const bool selstatus) { Nurb *nu; BezTriple *bezt; BPoint *bp; int a; bool lastsel = false; if (next == 0) return; for (nu = editnurb->first; nu; nu = nu->next) { lastsel = false; if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; if (next < 0) bezt = &nu->bezt[a - 1]; while (a--) { if (a - abs(next) < 0) break; if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { bezt += next; if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); if ((sel == 1) && (cont == 0)) lastsel = true; } } else { bezt += next; lastsel = false; } /* move around in zigzag way so that we go through each */ bezt -= (next - next / abs(next)); } } else { a = nu->pntsu * nu->pntsv; bp = nu->bp; if (next < 0) bp = &nu->bp[a - 1]; while (a--) { if (a - abs(next) < 0) break; if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) { bp += next; if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); if ((sel == 1) && (cont == 0)) lastsel = true; } } else { bp += next; lastsel = false; } /* move around in zigzag way so that we go through each */ bp -= (next - next / abs(next)); } } } }
/* (de)selects first or last of visible part of each Nurb depending on selFirst * selFirst: defines the end of which to select * doswap: defines if selection state of each first/last control point is swapped * selstatus: selection status in case doswap is false */ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu; BPoint *bp; BezTriple *bezt; Curve *cu; int a; if (obedit == NULL) return; cu = (Curve *)obedit->data; cu->actvert = CU_ACT_NONE; for (nu = editnurb->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { a = nu->pntsu; /* which point? */ if (selfirst == LAST) { /* select last */ bezt = &nu->bezt[a - 1]; } else { /* select first */ bezt = nu->bezt; } while (a--) { bool sel; if (doswap) sel = swap_selection_beztriple(bezt); else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); if (sel == true) break; } } else { a = nu->pntsu * nu->pntsv; /* which point? */ if (selfirst == LAST) { /* select last */ bp = &nu->bp[a - 1]; } else { /* select first */ bp = nu->bp; } while (a--) { if (bp->hide == 0) { bool sel; if (doswap) sel = swap_selection_bpoint(bp); else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); if (sel == true) break; } } } } }
static void curve_select_similar_weight__bp(Nurb *nu, float weight_ref, int compare, float thresh) { BPoint *bp; int i; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { if (!bp->hide) { if (curve_select_similar_cmp_fl(bp->weight - weight_ref, thresh, compare)) { select_bpoint(bp, SELECT, SELECT, VISIBLE); } } } }
static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; ListBase *editnurb = object_editcurve_get(obedit); static BPoint *last = NULL; static int direction = 0; Nurb *nu = NULL; BPoint *bp = NULL; int u = 0, v = 0, a, b; if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp)) return OPERATOR_CANCELLED; if (last == bp) { direction = 1 - direction; BKE_nurbList_flag_set(editnurb, 0); } last = bp; u = cu->actvert % nu->pntsu; v = cu->actvert / nu->pntsu; bp = nu->bp; for (a = 0; a < nu->pntsv; a++) { for (b = 0; b < nu->pntsu; b++, bp++) { if (direction) { if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE); } else { if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE); } } } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; }
static void curve_select_similar_direction__bp(Nurb *nu, const float dir_ref[3], float angle_cos) { BPoint *bp; int i; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { if (!bp->hide) { float dir[3]; BKE_nurb_bpoint_calc_normal(nu, bp, dir); if (fabsf(dot_v3v3(dir_ref, dir)) >= angle_cos) { select_bpoint(bp, SELECT, SELECT, VISIBLE); } } } }
static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); ViewContext vc; Nurb *nu; BezTriple *bezt; BPoint *bp; int a; const bool select = !RNA_boolean_get(op->ptr, "deselect"); view3d_operator_needs_opengl(C); view3d_set_viewcontext(C, &vc); if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu, &bezt, &bp, NULL)) { return OPERATOR_CANCELLED; } if (bezt) { a = nu->pntsu; bezt = nu->bezt; while (a--) { select_beztriple(bezt, select, SELECT, VISIBLE); bezt++; } } else if (bp) { a = nu->pntsu * nu->pntsv; bp = nu->bp; while (a--) { select_bpoint(bp, select, SELECT, VISIBLE); bp++; } } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); if (!select) { BKE_curve_nurb_vert_active_validate(obedit->data); } return OPERATOR_FINISHED; }
/* basic method: deselect if control point doesn't have all neighbors selected */ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu; BPoint *bp; BezTriple *bezt; int a; int sel = 0; short lastsel = false; if (obedit->type == OB_SURF) { for (nu = editnurb->first; nu; nu = nu->next) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; selbpoints = BLI_BITMAP_NEW(a, "selectlist"); while (a--) { if ((bp->hide == 0) && (bp->f1 & SELECT)) { sel = 0; /* check if neighbors have been selected */ /* edges of surface are an exception */ if ((a + 1) % nu->pntsu == 0) { sel++; } else { bp--; if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++; bp++; } if ((a + 1) % nu->pntsu == 1) { sel++; } else { bp++; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp--; } if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) { sel++; } else { bp -= nu->pntsu; if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++; bp += nu->pntsu; } if (a < nu->pntsu) { sel++; } else { bp += nu->pntsu; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp -= nu->pntsu; } if (sel != 4) { select_bpoint(bp, DESELECT, SELECT, VISIBLE); BLI_BITMAP_ENABLE(selbpoints, a); } } else { lastsel = false; } bp++; } MEM_freeN(selbpoints); } } else { for (nu = editnurb->first; nu; nu = nu->next) { lastsel = false; /* check what type of curve/nurb it is */ if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; while (a--) { if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { sel = (lastsel == 1); /* check if neighbors have been selected */ /* first and last are exceptions */ if (a == nu->pntsu - 1) { sel++; } else { bezt--; if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++; bezt++; } if (a == 0) { sel++; } else { bezt++; if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++; bezt--; } if (sel != 2) { select_beztriple(bezt, DESELECT, SELECT, VISIBLE); lastsel = true; } else { lastsel = false; } } else { lastsel = false; } bezt++; } } else { a = nu->pntsu * nu->pntsv; bp = nu->bp; while (a--) { if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) { if (lastsel != 0) sel = 1; else sel = 0; /* first and last are exceptions */ if (a == nu->pntsu * nu->pntsv - 1) { sel++; } else { bp--; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp++; } if (a == 0) { sel++; } else { bp++; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp--; } if (sel != 2) { select_bpoint(bp, DESELECT, SELECT, VISIBLE); lastsel = true; } else { lastsel = false; } } else { lastsel = false; } bp++; } } } } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); return OPERATOR_FINISHED; }
static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu; BPoint *bp, *tempbp; int a; short sel = 0; /* note that NURBS surface is a special case because we mimic */ /* the behavior of "select more" of mesh tools. */ /* The algorithm is designed to work in planar cases so it */ /* may not be optimal always (example: end of NURBS sphere) */ if (obedit->type == OB_SURF) { for (nu = editnurb->first; nu; nu = nu->next) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; selbpoints = BLI_BITMAP_NEW(a, "selectlist"); while (a > 0) { if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) { /* upper control point */ if (a % nu->pntsu != 0) { tempbp = bp - 1; if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE); } /* left control point. select only if it is not selected already */ if (a - nu->pntsu > 0) { sel = 0; tempbp = bp + nu->pntsu; if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); /* make sure selected bpoint is discarded */ if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu); } /* right control point */ if (a + nu->pntsu < nu->pntsu * nu->pntsv) { tempbp = bp - nu->pntsu; if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE); } /* lower control point. skip next bp in case selection was made */ if (a % nu->pntsu != 1) { sel = 0; tempbp = bp + 1; if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); if (sel) { bp++; a--; } } } bp++; a--; } MEM_freeN(selbpoints); } } else { select_adjacent_cp(editnurb, 1, 0, SELECT); select_adjacent_cp(editnurb, -1, 0, SELECT); } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; }
static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst) { Heap *heap; int i, vert_curr; int totu = nu->pntsu; int totv = nu->pntsv; int vert_num = totu * totv; /* custom data */ struct PointAdj { int vert, vert_prev; float cost; } *data; /* init connectivity data */ data = MEM_mallocN(sizeof(*data) * vert_num, __func__); for (i = 0; i < vert_num; i++) { data[i].vert = i; data[i].vert_prev = -1; data[i].cost = FLT_MAX; } /* init heap */ heap = BLI_heap_new(); BLI_heap_insert(heap, 0.0f, &data[vert_src].vert); data[vert_src].cost = 0.0f; data[vert_src].vert_prev = vert_src; /* nop */ while (!BLI_heap_is_empty(heap)) { int axis, sign; int u, v; vert_curr = *((int *)BLI_heap_popmin(heap)); if (vert_curr == vert_dst) { break; } BKE_nurb_index_to_uv(nu, vert_curr, &u, &v); /* loop over 4 adjacent verts */ for (sign = -1; sign != 3; sign += 2) { for (axis = 0; axis != 2; axis += 1) { int uv_other[2] = {u, v}; int vert_other; uv_other[axis] += sign; vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]); if (vert_other != -1) { const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other); if (data[vert_other].cost > dist) { data[vert_other].cost = dist; if (data[vert_other].vert_prev == -1) { BLI_heap_insert(heap, data[vert_other].cost, &data[vert_other].vert); } data[vert_other].vert_prev = vert_curr; } } } } } BLI_heap_free(heap, NULL); if (vert_curr == vert_dst) { i = 0; while (vert_curr != vert_src && i++ < vert_num) { if (nu->type == CU_BEZIER) { select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN); } else { select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN); } vert_curr = data[vert_curr].vert_prev; } } MEM_freeN(data); }