diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-07-08 16:24:16 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-07-08 17:09:26 +0300 |
commit | 4a328a76895c4f03b528b3c7e251475e76c68351 (patch) | |
tree | 6a876d72be674294f63d3619b4464c4e8c262b0b /source/blender/editors/curve/editcurve.c | |
parent | de6b4dc7f7f5e78ebfefdfe804218a69631d778e (diff) |
EditCurve: move selection into own file
Diffstat (limited to 'source/blender/editors/curve/editcurve.c')
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 1133 |
1 files changed, 14 insertions, 1119 deletions
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 1a10814bbf1..d17c05a4491 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -37,9 +37,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BLI_bitmap.h" #include "BLI_math.h" -#include "BLI_rand.h" #include "BLI_ghash.h" #include "BLF_translation.h" @@ -96,23 +94,7 @@ typedef struct { Nurb *orig_nu; } CVKeyIndex; -typedef enum eVisible_Types { - HIDDEN = true, - VISIBLE = false, -} eVisible_Types; - -typedef enum eEndPoint_Types { - FIRST = true, - LAST = false, -} eEndPoint_Types; - -typedef enum eCurveElem_Types { - CURVE_VERTEX = 0, - CURVE_SEGMENT, -} eCurveElem_Types; - void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus); -static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus); static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split); static int curve_delete_segments(Object *obedit, const bool split); @@ -127,61 +109,6 @@ ListBase *object_editcurve_get(Object *ob) /* ******************* SELECTION FUNCTIONS ********************* */ - -/* returns 1 in case (de)selection was successful */ -static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden) -{ - if ((bezt->hide == 0) || (hidden == HIDDEN)) { - if (selstatus == SELECT) { /* selects */ - bezt->f1 |= flag; - bezt->f2 |= flag; - bezt->f3 |= flag; - return true; - } - else { /* deselects */ - bezt->f1 &= ~flag; - bezt->f2 &= ~flag; - bezt->f3 &= ~flag; - return true; - } - } - - return false; -} - -/* returns 1 in case (de)selection was successful */ -static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden) -{ - if ((bp->hide == 0) || (hidden == 1)) { - if (selstatus == SELECT) { - bp->f1 |= flag; - return true; - } - else { - bp->f1 &= ~flag; - return true; - } - } - - return false; -} - -static bool swap_selection_beztriple(BezTriple *bezt) -{ - if (bezt->f2 & SELECT) - return select_beztriple(bezt, DESELECT, SELECT, VISIBLE); - else - return select_beztriple(bezt, SELECT, SELECT, VISIBLE); -} - -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); -} - int isNurbsel(Nurb *nu) { BezTriple *bezt; @@ -1407,64 +1334,6 @@ void ED_curve_deselect_all(EditNurb *editnurb) } } -void ED_curve_select_all(EditNurb *editnurb) -{ - Nurb *nu; - int a; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (nu->bezt) { - BezTriple *bezt; - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->hide == 0) { - bezt->f1 |= SELECT; - bezt->f2 |= SELECT; - bezt->f3 |= SELECT; - } - } - } - else if (nu->bp) { - BPoint *bp; - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->hide == 0) - bp->f1 |= SELECT; - } - } - } -} - -void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) -{ - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (bezt->hide == 0) { - bezt->f2 ^= SELECT; /* always do the center point */ - if (!hide_handles) { - bezt->f1 ^= SELECT; - bezt->f3 ^= SELECT; - } - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - swap_selection_bpoint(bp); - bp++; - } - } - } -} - /******************** separate operator ***********************/ static int separate_exec(bContext *C, wmOperator *op) @@ -2925,274 +2794,6 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** selection utility *************************/ - -/* next == 1 -> select next */ -/* next == -1 -> select previous */ -/* cont == 1 -> select continuously */ -/* 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)); - } - } - } -} - -/**************** select start/end operators **************/ - -/* (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 - */ -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 int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - - selectend_nurb(obedit, FIRST, true, DESELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_de_select_first(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "(De)select First"; - ot->idname = "CURVE_OT_de_select_first"; - ot->description = "(De)select first of visible part of each NURBS"; - - /* api cfirstbacks */ - ot->exec = de_select_first_exec; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - - selectend_nurb(obedit, LAST, true, DESELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_de_select_last(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "(De)select Last"; - ot->idname = "CURVE_OT_de_select_last"; - ot->description = "(De)select last of visible part of each NURBS"; - - /* api clastbacks */ - ot->exec = de_select_last_exec; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/******************* de select all operator ***************/ - -static bool nurb_has_selected_cps(ListBase *editnurb) -{ - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - if (bezt->hide == 0) { - if ((bezt->f1 & SELECT) || - (bezt->f2 & SELECT) || - (bezt->f3 & SELECT)) - { - return 1; - } - } - bezt++; - } - } - else { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - if ((bp->hide == 0) && (bp->f1 & SELECT)) return 1; - bp++; - } - } - } - - return 0; -} - -static int de_select_all_exec(bContext *C, wmOperator *op) -{ - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - int action = RNA_enum_get(op->ptr, "action"); - - if (action == SEL_TOGGLE) { - action = SEL_SELECT; - if (nurb_has_selected_cps(editnurb)) - action = SEL_DESELECT; - } - - switch (action) { - case SEL_SELECT: - ED_curve_select_all(cu->editnurb); - break; - case SEL_DESELECT: - ED_curve_deselect_all(cu->editnurb); - break; - case SEL_INVERT: - ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0); - break; - } - - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(cu); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_select_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "(De)select All"; - ot->idname = "CURVE_OT_select_all"; - ot->description = "(De)select all control points"; - - /* api callbacks */ - ot->exec = de_select_all_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_select_all(ot); -} - /********************** hide operator *********************/ static int hide_exec(bContext *C, wmOperator *op) @@ -3754,7 +3355,7 @@ void CURVE_OT_subdivide(wmOperatorType *ot) /******************** find nearest ************************/ -static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +static void ED_curve_pick_vert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; } *data = userData; @@ -3790,7 +3391,9 @@ static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, } } -static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], Nurb **nurb, BezTriple **bezt, BPoint **bp) +bool ED_curve_pick_vert( + ViewContext *vc, short sel, const int mval[2], + Nurb **r_nurb, BezTriple **r_bezt, BPoint **r_bp, short *r_handle) { /* (sel == 1): selected gets a disadvantage */ /* in nurb and bezt or bp the nearest is written */ @@ -3804,13 +3407,17 @@ static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], data.mval_fl[1] = mval[1]; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + *r_nurb = data.nurb; + *r_bezt = data.bezt; + *r_bp = data.bp; - *nurb = data.nurb; - *bezt = data.bezt; - *bp = data.bp; + if (r_handle) { + *r_handle = data.hpoint; + } - return data.hpoint; + return (data.bezt || data.bp); } static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt, BPoint **bp) @@ -4637,9 +4244,8 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool location[0] = mval[0]; location[1] = mval[1]; - hand = findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp); - if (bezt || bp) { + if (ED_curve_pick_vert(&vc, 1, location, &nu, &bezt, &bp, &hand)) { if (extend) { if (bezt) { if (hand == 1) { @@ -5545,717 +5151,6 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in"); } -/***************** select linked operator ******************/ - -static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - Curve *cu = (Curve *)obedit->data; - EditNurb *editnurb = cu->editnurb; - ListBase *nurbs = &editnurb->nurbs; - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - for (nu = nurbs->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - select_beztriple(bezt, SELECT, SELECT, VISIBLE); - bezt++; - } - break; - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->f1 & SELECT) { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); - bp++; - } - break; - } - bp++; - } - } - } - - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - return select_linked_exec(C, op); -} - -void CURVE_OT_select_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked All"; - ot->idname = "CURVE_OT_select_linked"; - ot->description = "Select all control points linked to active one"; - - /* api callbacks */ - ot->exec = select_linked_exec; - ot->invoke = select_linked_invoke; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ -} - - -/***************** select linked pick operator ******************/ - -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); - - findnearestNurbvert(&vc, 1, event->mval, &nu, &bezt, &bp); - - 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; -} - -void CURVE_OT_select_linked_pick(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked"; - ot->idname = "CURVE_OT_select_linked_pick"; - ot->description = "Select all control points linked to already selected ones"; - - /* api callbacks */ - ot->invoke = select_linked_pick_invoke; - ot->poll = ED_operator_editsurfcurve_region_view3d; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them"); -} - -/***************** select row operator **********************/ - -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; -} - -void CURVE_OT_select_row(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Control Point Row"; - ot->idname = "CURVE_OT_select_row"; - ot->description = "Select a row of control points including active one"; - - /* api callbacks */ - ot->exec = select_row_exec; - ot->poll = ED_operator_editsurf; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/***************** select next operator **********************/ - -static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - - select_adjacent_cp(editnurb, 1, 0, SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_select_next(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Next"; - ot->idname = "CURVE_OT_select_next"; - ot->description = "Select control points following already selected ones along the curves"; - - /* api callbacks */ - ot->exec = select_next_exec; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/***************** select previous operator **********************/ - -static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - - select_adjacent_cp(editnurb, -1, 0, SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_select_previous(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Previous"; - ot->idname = "CURVE_OT_select_previous"; - ot->description = "Select control points preceding already selected ones along the curves"; - - /* api callbacks */ - ot->exec = select_previous_exec; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/***************** select more operator **********************/ - -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; -} - -void CURVE_OT_select_more(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select More"; - ot->idname = "CURVE_OT_select_more"; - ot->description = "Select control points directly linked to already selected ones"; - - /* api callbacks */ - ot->exec = select_more_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/******************** select less operator *****************/ - -/* 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; -} - -void CURVE_OT_select_less(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Less"; - ot->idname = "CURVE_OT_select_less"; - ot->description = "Reduce current selection by deselecting boundary elements"; - - /* api callbacks */ - ot->exec = select_less_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/********************** select random *********************/ - -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 int curve_select_random_exec(bContext *C, wmOperator *op) -{ - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; - - curve_select_random(editnurb, randfac, select); - BKE_curve_nurb_vert_active_validate(obedit->data); - - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_select_random(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Random"; - ot->idname = "CURVE_OT_select_random"; - ot->description = "Randomly select some control points"; - - /* api callbacks */ - ot->exec = curve_select_random_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, - "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f); - WM_operator_properties_select_action_simple(ot, SEL_SELECT); -} - -/********************* every nth number of point *******************/ - -static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset) -{ - int a, start; - - start = bezt - nu->bezt; - a = nu->pntsu; - bezt = &nu->bezt[a - 1]; - - while (a--) { - const int depth = abs(start - a); - if ((offset + depth) % (skip + nth) >= skip) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - } - - bezt--; - } -} - -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--; - } -} - -bool ED_curve_select_nth(Curve *cu, int nth, int skip, int offset) -{ - Nurb *nu = NULL; - void *vert = NULL; - - if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) - return false; - - if (nu->bezt) { - select_nth_bezt(nu, vert, nth, skip, offset); - } - else { - select_nth_bp(nu, vert, nth, skip, offset); - } - - return true; -} - -static int select_nth_exec(bContext *C, wmOperator *op) -{ - Object *obedit = CTX_data_edit_object(C); - const int nth = RNA_int_get(op->ptr, "nth") - 1; - const int skip = RNA_int_get(op->ptr, "skip"); - int offset = RNA_int_get(op->ptr, "offset"); - - /* so input of offset zero ends up being (nth - 1) */ - offset = mod_i(offset, nth + skip); - - if (!ED_curve_select_nth(obedit->data, nth, skip, offset)) { - if (obedit->type == OB_SURF) { - BKE_report(op->reports, RPT_ERROR, "Surface has not got active point"); - } - else { - BKE_report(op->reports, RPT_ERROR, "Curve has not got active point"); - } - - return OPERATOR_CANCELLED; - } - - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void CURVE_OT_select_nth(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Checker Deselect"; - ot->description = "Deselect every other vertex"; - ot->idname = "CURVE_OT_select_nth"; - - /* api callbacks */ - ot->exec = select_nth_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); - RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100); - RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100); -} - /********************** add duplicate operator *********************/ static int duplicate_exec(bContext *C, wmOperator *op) |