Index: source/blender/editors/curve/curve_ops.c =================================================================== --- source/blender/editors/curve/curve_ops.c (revision 58780) +++ source/blender/editors/curve/curve_ops.c (working copy) @@ -87,6 +87,7 @@ WM_operatortype_append(CURVE_OT_reveal); WM_operatortype_append(CURVE_OT_separate); + WM_operatortype_append(CURVE_OT_split); WM_operatortype_append(CURVE_OT_duplicate); WM_operatortype_append(CURVE_OT_delete); @@ -244,6 +245,7 @@ RNA_boolean_set(kmi->ptr, "deselect", TRUE); WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "CURVE_OT_split", YKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CURVE_OT_extrude_move", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CURVE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0); Index: source/blender/editors/curve/curve_intern.h =================================================================== --- source/blender/editors/curve/curve_intern.h (revision 58780) +++ source/blender/editors/curve/curve_intern.h (working copy) @@ -76,6 +76,7 @@ void CURVE_OT_reveal(struct wmOperatorType *ot); void CURVE_OT_separate(struct wmOperatorType *ot); +void CURVE_OT_split(struct wmOperatorType *ot); void CURVE_OT_duplicate(struct wmOperatorType *ot); void CURVE_OT_delete(struct wmOperatorType *ot); Index: source/blender/editors/curve/editcurve.c =================================================================== --- source/blender/editors/curve/editcurve.c (revision 58780) +++ source/blender/editors/curve/editcurve.c (working copy) @@ -108,6 +108,8 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus); static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus); +static void adduplicateflagNurb(ListBase *newnurb, Object *obedit, short flag, short split); +static int delete_selected(bContext *C, int type); /* still need to eradicate a few :( */ #define CALLOC_STRUCT_N(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name) @@ -1463,6 +1465,42 @@ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/******************** split operator ***********************/ + +static int split_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + ListBase newnurb = {0}; + + adduplicateflagNurb(&newnurb, obedit, 1, 1); + + if (newnurb.first != NULL) { + delete_selected(C, 0); + BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + } + else { + BKE_report(op->reports, RPT_ERROR, "Cannot split current selection"); + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +void CURVE_OT_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Split"; + ot->idname = "CURVE_OT_split"; + ot->description = "Split off selected points from connected unselected points"; + + /* api callbacks */ + ot->exec = split_exec; + ot->poll = ED_operator_editsurfcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ******************* FLAGS ********************* */ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag) @@ -1614,7 +1652,7 @@ } } -static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) +static int deleteflagNurb(bContext *C, int flag) { Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; @@ -1869,14 +1907,14 @@ return ok; } -static void adduplicateflagNurb(Object *obedit, short flag) +static void adduplicateflagNurb(ListBase *newnurb, Object *obedit, short flag, short split) { ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu, *newnu; BezTriple *bezt, *bezt1; BPoint *bp, *bp1; Curve *cu = (Curve *)obedit->data; - int a, b, starta, enda, newu, newv; + int a, b, starta, enda, diffa, newu, newv; char *usel; cu->lastsel = NULL; @@ -1889,27 +1927,42 @@ enda = -1; starta = a; while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { - select_beztriple(bezt, DESELECT, flag, HIDDEN); + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; enda = a; if (a >= nu->pntsu - 1) break; a++; bezt++; } if (enda >= starta) { + diffa = enda - starta; + newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN"); memcpy(newnu, nu, sizeof(Nurb)); - BLI_addtail(editnurb, newnu); + BLI_addtail(newnurb, newnu); set_actNurb(obedit, newnu); - newnu->pntsu = enda - starta + 1; - newnu->bezt = (BezTriple *)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN"); + newnu->pntsu = diffa + 1; + newnu->bezt = (BezTriple *)MEM_mallocN((diffa + 1) * sizeof(BezTriple), "adduplicateN"); memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple)); - b = newnu->pntsu; - bezt1 = newnu->bezt; - while (b--) { - select_beztriple(bezt1, SELECT, flag, HIDDEN); - bezt1++; + if (!split || nu->pntsu == diffa + 1) { + /* if not split then deselect all, otherwise select all for deletion */ + for (b = 0, bezt1 = nu->bezt; b <= enda; b++, bezt1++) { + select_beztriple(bezt1, split, flag, HIDDEN); + } } + else if (starta == 0) { + /* start of curve, deselect last selected */ + select_beztriple(bezt - 1, DESELECT, flag, HIDDEN); + } + else if (enda >= nu->pntsu - 1) { + /* end of curve, deselect first selected */ + select_beztriple(bezt - diffa, DESELECT, flag, HIDDEN); + } + else if (enda != nu->pntsu - 1 && starta != 0) { + /* deselect both beginning and end of selection */ + select_beztriple(bezt - 1, DESELECT, flag, HIDDEN); + select_beztriple(bezt - diffa - 1, DESELECT, flag, HIDDEN); + } if (nu->flagu & CU_NURB_CYCLIC) { if (starta != 0 || enda != nu->pntsu - 1) { @@ -1926,27 +1979,41 @@ enda = -1; starta = a; while (bp->f1 & flag) { - select_bpoint(bp, DESELECT, flag, HIDDEN); enda = a; if (a >= nu->pntsu - 1) break; a++; bp++; } if (enda >= starta) { + diffa = enda - starta; + newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN3"); memcpy(newnu, nu, sizeof(Nurb)); set_actNurb(obedit, newnu); - BLI_addtail(editnurb, newnu); - newnu->pntsu = enda - starta + 1; - newnu->bp = (BPoint *)MEM_mallocN((enda - starta + 1) * sizeof(BPoint), "adduplicateN4"); + BLI_addtail(newnurb, newnu); + newnu->pntsu = diffa + 1; + newnu->bp = (BPoint *)MEM_mallocN((diffa + 1) * sizeof(BPoint), "adduplicateN4"); memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint)); - b = newnu->pntsu; - bp1 = newnu->bp; - while (b--) { - select_bpoint(bp1, SELECT, flag, HIDDEN); - bp1++; + if (split == 0 || nu->pntsu == diffa + 1) { + /* if not split then deselect all, otherwise select all for deletion */ + for (b = 0, bp1 = nu->bp; b <= enda; b++, bp1++) { + select_bpoint(bp1, split, flag, HIDDEN); + } } + else if (starta == 0) { + /* start of curve, deselect last selected */ + select_bpoint(bp - 1, DESELECT, flag, HIDDEN); + } + else if (enda >= nu->pntsu - 1) { + /* end of curve, deselect first selected */ + select_bpoint(bp - diffa, DESELECT, flag, HIDDEN); + } + else if (enda != nu->pntsu - 1 && starta != 0) { + /* deselect both beginning and end of selection */ + select_bpoint(bp - 1, DESELECT, flag, HIDDEN); + select_bpoint(bp - diffa - 1, DESELECT, flag, HIDDEN); + } if (nu->flagu & CU_NURB_CYCLIC) { if (starta != 0 || enda != nu->pntsu - 1) { @@ -1990,12 +2057,16 @@ printf("Can't duplicate Nurb\n"); } else { + int startu = -1, startv = -1; + /* selection of points too small, set split to 0 to deselect all */ + if (newu != nu->pntsu && newv != nu->pntsv) split = 0; + if (newu == 1) SWAP(int, newu, newv); newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN5"); memcpy(newnu, nu, sizeof(Nurb)); - BLI_addtail(editnurb, newnu); + BLI_addtail(newnurb, newnu); set_actNurb(obedit, newnu); newnu->pntsu = newu; newnu->pntsv = newv; @@ -2011,10 +2082,50 @@ for (b = 0; b < nu->pntsu; b++, bp1++) { if (bp1->f1 & flag) { memcpy(bp, bp1, sizeof(BPoint)); - select_bpoint(bp1, DESELECT, flag, HIDDEN); bp++; + + if (split) { + BPoint *bpv = bp1, *bpu = bp1; + + /* get 'next' v and u points and set start points */ + if (a != nu->pntsv - 1) bpv = bp1 + nu->pntsu; + if (b != nu->pntsu - 1) bpu = bp1 + 1; + if (startv == -1) startv = a; + if (startu == -1) startu = b; + + if (bpv->f1 & flag) { + if (a != 0 && startv == a) { + /* deselect start of mid point selection or single end point */ + select_bpoint(bp1, DESELECT, flag, HIDDEN); + continue; + } + } + else { + /* deselect single start or mid point */ + select_bpoint(bp1, DESELECT, flag, HIDDEN); + continue; + } + + if (bpu->f1 & flag) { + if (b != 0 && startu == b) { + select_bpoint(bp1, DESELECT, flag, HIDDEN); + } + } + else { + select_bpoint(bp1, DESELECT, flag, HIDDEN); + } + } + else { + /* deselect all for duplicate */ + select_bpoint(bp1, DESELECT, flag, HIDDEN); + } } } + if (startu == -1) { + /* if no points from u selected, reset startv */ + startv = -1; + } + startu = -1; } if (BKE_nurb_check_valid_u(newnu)) { if (nu->pntsu == newnu->pntsu && nu->knotsu) { @@ -5672,10 +5783,15 @@ static int duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); + ListBase newnurb = {0}; - adduplicateflagNurb(obedit, 1); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + adduplicateflagNurb(&newnurb, obedit, 1, 0); + if (newnurb.first != NULL) { + BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + return OPERATOR_FINISHED; } @@ -5696,7 +5812,7 @@ /********************** delete operator *********************/ -static int delete_exec(bContext *C, wmOperator *op) +static int delete_selected(bContext *C, int type) { Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; @@ -5705,12 +5821,12 @@ Nurb *nu, *nu1; BezTriple *bezt, *bezt1, *bezt2; BPoint *bp, *bp1, *bp2; - int a, cut = 0, type = RNA_enum_get(op->ptr, "type"); + int a, cut = 0; int nuindex = 0; if (obedit->type == OB_SURF) { if (type == 0) { - deleteflagNurb(C, op, 1); + deleteflagNurb(C, 1); } else { keyIndex_delNurbList(editnurb, nubase); @@ -6028,6 +6144,11 @@ return OPERATOR_FINISHED; } +static int delete_exec(bContext *C, wmOperator *op) +{ + return delete_selected(C, RNA_enum_get(op->ptr, "type")); +} + static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *obedit = CTX_data_edit_object(C); Index: release/scripts/startup/bl_ui/space_view3d.py =================================================================== --- release/scripts/startup/bl_ui/space_view3d.py (revision 58780) +++ release/scripts/startup/bl_ui/space_view3d.py (working copy) @@ -2141,6 +2141,7 @@ layout.operator("curve.extrude_move") layout.operator("curve.duplicate_move") + layout.operator("curve.split") layout.operator("curve.separate") layout.operator("curve.make_segment") layout.operator("curve.cyclic_toggle")