Curves: save active point to file
[blender.git] / source / blender / editors / curve / editcurve.c
index 6144c84f1ba5b895c9ed54d6bd92d24765ba98f1..f07d575ae5f6ec819bd2d155700ea5218ce3a160 100644 (file)
@@ -80,7 +80,7 @@
 /* Undo stuff */
 typedef struct {
        ListBase nubase;
-       void *lastsel;
+       int actvert;
        GHash *undoIndex;
        ListBase fcurves, drivers;
        int actnu;
@@ -123,27 +123,6 @@ ListBase *object_editcurve_get(Object *ob)
        return NULL;
 }
 
-/* this replaces the active flag used in uv/face mode */
-static void set_actNurb(Object *obedit, Nurb *nu)
-{
-       Curve *cu = obedit->data;
-       
-       if (nu == NULL)
-               cu->actnu = -1;
-       else {
-               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-               cu->actnu = BLI_findindex(nurbs, nu);
-       }
-}
-
-static Nurb *get_actNurb(Object *obedit)
-{
-       Curve *cu = obedit->data;
-       ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
-       return BLI_findlink(nurbs, cu->actnu);
-}
-
 /* ******************* SELECTION FUNCTIONS ********************* */
 
 
@@ -1217,11 +1196,9 @@ void make_editNurb(Object *obedit)
 {
        Curve *cu = (Curve *)obedit->data;
        EditNurb *editnurb = cu->editnurb;
-       Nurb *nu, *newnu, *nu_act = NULL;
+       Nurb *nu, *newnu;
        KeyBlock *actkey;
 
-       set_actNurb(obedit, NULL);
-
        if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                actkey = BKE_keyblock_from_object(obedit);
 
@@ -1242,18 +1219,10 @@ void make_editNurb(Object *obedit)
                }
 
                nu = cu->nurb.first;
-               cu->lastsel = NULL;   /* for select row */
-
                while (nu) {
                        newnu = BKE_nurb_duplicate(nu);
                        BKE_nurb_test2D(newnu); // after join, or any other creation of curve
                        BLI_addtail(&editnurb->nurbs, newnu);
-
-                       if (nu_act == NULL && isNurbsel(nu)) {
-                               nu_act = newnu;
-                               set_actNurb(obedit, newnu);
-                       }
-
                        nu = nu->next;
                }
 
@@ -1273,98 +1242,82 @@ void free_editNurb(Object *obedit)
        BKE_curve_editNurb_free(cu);
 }
 
-void CU_deselect_all(Object *obedit)
+void ED_curve_deselect_all(EditNurb *editnurb)
 {
-       ListBase *editnurb = object_editcurve_get(obedit);
-
-       if (editnurb) {
-               Nurb *nu;
-               int a;
-               ((Curve *)obedit->data)->lastsel = NULL;
+       Nurb *nu;
+       int a;
 
-               for (nu = editnurb->first; nu; nu = nu->next) {
-                       if (nu->bezt) {
-                               BezTriple *bezt;
-                               for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
-                                       bezt->f1 &= ~SELECT;
-                                       bezt->f2 &= ~SELECT;
-                                       bezt->f3 &= ~SELECT;
-                               }
+       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++) {
+                               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++) {
-                                       bp->f1 &= ~SELECT;
-                               }
+               }
+               else if (nu->bp) {
+                       BPoint *bp;
+                       for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+                               bp->f1 &= ~SELECT;
                        }
                }
        }
 }
 
-void CU_select_all(Object *obedit)
+void ED_curve_select_all(EditNurb *editnurb)
 {
-       ListBase *editnurb = object_editcurve_get(obedit);
-
-       if (editnurb) {
-               Nurb *nu;
-               int a;
-               for (nu = editnurb->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;
-                                       }
+       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;
-                               }
+               }
+               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 CU_select_swap(Object *obedit)
+void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
 {
-       ListBase *editnurb = object_editcurve_get(obedit);
-
-       if (editnurb) {
-               Curve *cu = obedit->data;
-               Nurb *nu;
-               BPoint *bp;
-               BezTriple *bezt;
-               int a;
-
-               cu->lastsel = NULL;
+       Nurb *nu;
+       BPoint *bp;
+       BezTriple *bezt;
+       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 == 0) {
-                                               bezt->f2 ^= SELECT; /* always do the center point */
-                                               if ((cu->drawflag & CU_HIDE_HANDLES) == 0) {
-                                                       bezt->f1 ^= SELECT;
-                                                       bezt->f3 ^= SELECT;
-                                               }
+       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++;
                                }
+                               bezt++;
                        }
-                       else {
-                               bp = nu->bp;
-                               a = nu->pntsu * nu->pntsv;
-                               while (a--) {
-                                       swap_selection_bpoint(bp);
-                                       bp++;
-                               }
+               }
+               else {
+                       bp = nu->bp;
+                       a = nu->pntsu * nu->pntsv;
+                       while (a--) {
+                               swap_selection_bpoint(bp);
+                               bp++;
                        }
                }
        }
@@ -1699,7 +1652,7 @@ static void weightflagNurb(ListBase *editnurb, short flag, float w)
        }
 }
 
-static int deleteflagNurb(Object *obedit, short flag)
+static void ed_surf_delete_selected(Object *obedit)
 {
        Curve *cu = obedit->data;
        ListBase *editnurb = object_editcurve_get(obedit);
@@ -1707,11 +1660,7 @@ static int deleteflagNurb(Object *obedit, short flag)
        BPoint *bp, *bpn, *newbp;
        int a, b, newu, newv;
 
-       if (obedit->type != OB_SURF) {
-               return OPERATOR_CANCELLED;
-       }
-
-       cu->lastsel = NULL;
+       BLI_assert(obedit->type != OB_SURF);
 
        nu = editnurb->first;
        while (nu) {
@@ -1722,7 +1671,7 @@ static int deleteflagNurb(Object *obedit, short flag)
                a = nu->pntsu * nu->pntsv;
                while (a) {
                        a--;
-                       if (bp->f1 & flag) {
+                       if (bp->f1 & SELECT) {
                                /* pass */
                        }
                        else {
@@ -1736,7 +1685,7 @@ static int deleteflagNurb(Object *obedit, short flag)
                        BKE_nurb_free(nu); nu = NULL;
                }
                else {
-                       if (isNurbselU(nu, &newv, flag)) {
+                       if (isNurbselU(nu, &newv, SELECT)) {
                                /* U direction selected */
                                newv = nu->pntsv - newv;
                                if (newv != nu->pntsv) {
@@ -1744,7 +1693,7 @@ static int deleteflagNurb(Object *obedit, short flag)
                                        bp = nu->bp;
                                        bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
                                        for (b = 0; b < nu->pntsv; b++) {
-                                               if ((bp->f1 & flag) == 0) {
+                                               if ((bp->f1 & SELECT) == 0) {
                                                        memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
                                                        keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
                                                        bpn += nu->pntsu;
@@ -1762,7 +1711,7 @@ static int deleteflagNurb(Object *obedit, short flag)
                                        BKE_nurb_knot_calc_v(nu);
                                }
                        }
-                       else if (isNurbselV(nu, &newu, flag)) {
+                       else if (isNurbselV(nu, &newu, SELECT)) {
                                /* V direction selected */
                                newu = nu->pntsu - newu;
                                if (newu != nu->pntsu) {
@@ -1771,7 +1720,7 @@ static int deleteflagNurb(Object *obedit, short flag)
                                        bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
                                        for (b = 0; b < nu->pntsv; b++) {
                                                for (a = 0; a < nu->pntsu; a++, bp++) {
-                                                       if ((bp->f1 & flag) == 0) {
+                                                       if ((bp->f1 & SELECT) == 0) {
                                                                *bpn = *bp;
                                                                keyIndex_updateBP(cu->editnurb, bp, bpn, 1);
                                                                bpn++;
@@ -1801,8 +1750,150 @@ static int deleteflagNurb(Object *obedit, short flag)
                }
                nu = next;
        }
+}
 
-       return OPERATOR_FINISHED;
+static void ed_curve_delete_selected(Object *obedit)
+{
+       Curve *cu = obedit->data;
+       EditNurb *editnurb = cu->editnurb;
+       ListBase *nubase = &editnurb->nurbs;
+       Nurb *nu, *next;
+       BezTriple *bezt, *bezt1;
+       BPoint *bp, *bp1;
+       int a, type, nuindex = 0;
+
+       /* first loop, can we remove entire pieces? */
+       nu = nubase->first;
+       while (nu) {
+               next = nu->next;
+               if (nu->type == CU_BEZIER) {
+                       bezt = nu->bezt;
+                       a = nu->pntsu;
+                       if (a) {
+                               while (a) {
+                                       if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+                                               /* pass */
+                                       }
+                                       else {
+                                               break;
+                                       }
+                                       a--;
+                                       bezt++;
+                               }
+                               if (a == 0) {
+                                       if (cu->actnu == nuindex)
+                                               cu->actnu = -1;
+
+                                       BLI_remlink(nubase, nu);
+                                       keyIndex_delNurb(editnurb, nu);
+                                       BKE_nurb_free(nu); nu = NULL;
+                               }
+                       }
+               }
+               else {
+                       bp = nu->bp;
+                       a = nu->pntsu * nu->pntsv;
+                       if (a) {
+                               while (a) {
+                                       if (bp->f1 & SELECT) {
+                                               /* pass */
+                                       }
+                                       else {
+                                               break;
+                                       }
+                                       a--;
+                                       bp++;
+                               }
+                               if (a == 0) {
+                                       if (cu->actnu == nuindex)
+                                               cu->actnu = -1;
+
+                                       BLI_remlink(nubase, nu);
+                                       keyIndex_delNurb(editnurb, nu);
+                                       BKE_nurb_free(nu); nu = NULL;
+                               }
+                       }
+               }
+
+               /* Never allow the order to exceed the number of points
+                * - note, this is ok but changes unselected nurbs, disable for now */
+#if 0
+               if ((nu != NULL) && (nu->type == CU_NURBS)) {
+                       clamp_nurb_order_u(nu);
+               }
+#endif
+               nu = next;
+               nuindex++;
+       }
+       /* 2nd loop, delete small pieces: just for curves */
+       nu = nubase->first;
+       while (nu) {
+               next = nu->next;
+               type = 0;
+               if (nu->type == CU_BEZIER) {
+                       int delta = 0;
+                       bezt = nu->bezt;
+                       for (a = 0; a < nu->pntsu; a++) {
+                               if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+                                       memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
+                                       keyIndex_delBezt(editnurb, bezt + delta);
+                                       keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
+                                       nu->pntsu--;
+                                       a--;
+                                       type = 1;
+                                       delta++;
+                               }
+                               else {
+                                       bezt++;
+                               }
+                       }
+                       if (type) {
+                               bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
+                               memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
+                               keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
+                               MEM_freeN(nu->bezt);
+                               nu->bezt = bezt1;
+                               BKE_nurb_handles_calc(nu);
+                       }
+               }
+               else if (nu->pntsv == 1) {
+                       int delta = 0;
+                       bp = nu->bp;
+
+                       for (a = 0; a < nu->pntsu; a++) {
+                               if (bp->f1 & SELECT) {
+                                       memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
+                                       keyIndex_delBP(editnurb, bp + delta);
+                                       keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
+                                       nu->pntsu--;
+                                       a--;
+                                       type = 1;
+                                       delta++;
+                               }
+                               else {
+                                       bp++;
+                               }
+                       }
+                       if (type) {
+                               bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
+                               memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
+                               keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
+                               MEM_freeN(nu->bp);
+                               nu->bp = bp1;
+
+                               /* Never allow the order to exceed the number of points
+                                * - note, this is ok but changes unselected nurbs, disable for now */
+#if 0
+                               if (nu->type == CU_NURBS) {
+                                       clamp_nurb_order_u(nu);
+                               }
+#endif
+                       }
+                       BKE_nurb_order_clamp_u(nu);
+                       BKE_nurb_knot_calc_u(nu);
+               }
+               nu = next;
+       }
 }
 
 /* only for OB_SURF */
@@ -2155,8 +2246,7 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
        }
 
        if (newnurb->first != NULL) {
-               cu->lastsel = NULL;
-               cu->actnu = -1;
+               cu->actnu = cu->actvert = CU_ACT_NONE;
 
                for (nu = newnurb->first; nu; nu = nu->next) {
                        if (nu->type == CU_BEZIER) {
@@ -2734,7 +2824,7 @@ void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool
        if (obedit == NULL) return;
 
        cu = (Curve *)obedit->data;
-       cu->lastsel = NULL;
+       cu->actvert = CU_ACT_NONE;
 
        for (nu = editnurb->first; nu; nu = nu->next) {
                if (nu->type == CU_BEZIER) {
@@ -2786,6 +2876,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
 
        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;
 }
@@ -2811,6 +2902,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
 
        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;
 }
@@ -2871,6 +2963,7 @@ static short nurb_has_selected_cps(ListBase *editnurb)
 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");
 
@@ -2882,17 +2975,18 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
 
        switch (action) {
                case SEL_SELECT:
-                       CU_select_all(obedit);
+                       ED_curve_select_all(cu->editnurb);
                        break;
                case SEL_DESELECT:
-                       CU_deselect_all(obedit);
+                       ED_curve_deselect_all(cu->editnurb);
                        break;
                case SEL_INVERT:
-                       CU_select_swap(obedit);
+                       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;
 }
@@ -2968,6 +3062,7 @@ static int hide_exec(bContext *C, wmOperator *op)
 
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+       BKE_curve_nurb_vert_active_validate(obedit->data);
 
        return OPERATOR_FINISHED;
 }
@@ -4098,7 +4193,7 @@ static int merge_nurb(bContext *C, wmOperator *op)
        
        BLI_freelistN(&nsortbase);
        
-       set_actNurb(obedit, NULL);
+       BKE_curve_nurb_active_set(obedit->data, NULL);
 
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
        DAG_id_tag_update(obedit->data, 0);
@@ -4266,7 +4361,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
                                BKE_nurb_free(nu2); nu2 = NULL;
                        }
 
-                       set_actNurb(obedit, nu1);   /* for selected */
+                       BKE_curve_nurb_active_set(cu, nu1);   /* for selected */
                        ok = 1;
                }
        }
@@ -4327,6 +4422,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
        Nurb *nu;
        BezTriple *bezt = NULL;
        BPoint *bp = NULL;
+       const void *vert = BKE_curve_vert_active_get(cu);
        int location[2];
        short hand;
        
@@ -4342,17 +4438,17 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
                        if (bezt) {
                                if (hand == 1) {
                                        select_beztriple(bezt, SELECT, SELECT, HIDDEN);
-                                       cu->lastsel = bezt;
+                                       BKE_curve_nurb_vert_active_set(cu, nu, bezt);
                                }
                                else {
                                        if (hand == 0) bezt->f1 |= SELECT;
                                        else bezt->f3 |= SELECT;
 
-                                       cu->lastsel = NULL;
+                                       cu->actvert = CU_ACT_NONE;
                                }
                        }
                        else {
-                               cu->lastsel = bp;
+                               BKE_curve_nurb_vert_active_set(cu, nu, bp);
                                select_bpoint(bp, SELECT, SELECT, HIDDEN);
                        }
                }
@@ -4360,7 +4456,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
                        if (bezt) {
                                if (hand == 1) {
                                        select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
-                                       if (bezt == cu->lastsel) cu->lastsel = NULL;
+                                       if (bezt == vert) cu->actvert = CU_ACT_NONE;
                                }
                                else if (hand == 0) {
                                        bezt->f1 &= ~SELECT;
@@ -4371,7 +4467,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
                        }
                        else {
                                select_bpoint(bp, DESELECT, SELECT, HIDDEN);
-                               if (cu->lastsel == bp) cu->lastsel = NULL;
+                               if (bp == vert) cu->actvert = CU_ACT_NONE;
                        }
                }
                else if (toggle) {
@@ -4379,11 +4475,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
                                if (hand == 1) {
                                        if (bezt->f2 & SELECT) {
                                                select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
-                                               if (bezt == cu->lastsel) cu->lastsel = NULL;
+                                               if (bezt == vert) cu->actvert = CU_ACT_NONE;
                                        }
                                        else {
                                                select_beztriple(bezt, SELECT, SELECT, HIDDEN);
-                                               cu->lastsel = bezt;
+                                               BKE_curve_nurb_vert_active_set(cu, nu, bezt);
                                        }
                                }
                                else if (hand == 0) {
@@ -4396,11 +4492,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
                        else {
                                if (bp->f1 & SELECT) {
                                        select_bpoint(bp, DESELECT, SELECT, HIDDEN);
-                                       if (cu->lastsel == bp) cu->lastsel = NULL;
+                                       if (bp == vert) cu->actvert = CU_ACT_NONE;
                                }
                                else {
                                        select_bpoint(bp, SELECT, SELECT, HIDDEN);
-                                       cu->lastsel = bp;
+                                       BKE_curve_nurb_vert_active_set(cu, nu, bp);
                                }
                        }
                }
@@ -4411,23 +4507,25 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
 
                                if (hand == 1) {
                                        select_beztriple(bezt, SELECT, SELECT, HIDDEN);
-                                       cu->lastsel = bezt;
+                                       BKE_curve_nurb_vert_active_set(cu, nu, bezt);
                                }
                                else {
                                        if (hand == 0) bezt->f1 |= SELECT;
                                        else bezt->f3 |= SELECT;
 
-                                       cu->lastsel = NULL;
+                                       cu->actvert = CU_ACT_NONE;
                                }
                        }
                        else {
-                               cu->lastsel = bp;
+                               BKE_curve_nurb_vert_active_set(cu, nu, bp);
                                select_bpoint(bp, SELECT, SELECT, HIDDEN);
                        }
                }
 
-               if (nu != get_actNurb(obedit))
-                       set_actNurb(obedit, nu);
+               if (nu != BKE_curve_nurb_active_get(cu)) {
+                       cu->actvert = CU_ACT_NONE;
+                       BKE_curve_nurb_active_set(cu, nu);
+               }
 
                WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
 
@@ -4626,7 +4724,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                                }
 
                                BLI_addtail(&editnurb->nurbs, newnu);
-                               set_actNurb(obedit, newnu);
                                newnu->bezt = newbezt;
                                newnu->pntsu = 1;
 
@@ -4650,12 +4747,10 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                                newbp->radius = 1;
                                newbp->alfa = 0;
                                newbp->f1 |= SELECT;
-                               cu->lastsel = newbp;
 
                                newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
                                memcpy(newnu, nu, sizeof(Nurb));
                                BLI_addtail(&editnurb->nurbs, newnu);
-                               set_actNurb(obedit, newnu);
                                newnu->bp = newbp;
                                newnu->orderu = 2;
                                newnu->pntsu = 1;
@@ -4688,7 +4783,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        nu->bezt = newbezt;
                        newbezt += nu->pntsu;
                        BEZ_SEL(newbezt);
-                       cu->lastsel = newbezt;
                        newbezt->h1 = newbezt->h2;
                        bezt = &nu->bezt[nu->pntsu - 1];
                        ok = 1;
@@ -4704,7 +4798,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        ED_curve_beztcpy(editnurb, newbezt + 1, bezt, nu->pntsu);
                        *newbezt = *bezt;
                        BEZ_SEL(newbezt);
-                       cu->lastsel = newbezt;
                        newbezt->h2 = newbezt->h1;
                        copy_v3_v3(temp, bezt->vec[1]);
                        MEM_freeN(nu->bezt);
@@ -4728,12 +4821,10 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
                        memcpy(newnu, nu, sizeof(Nurb));
                        BLI_addtail(&editnurb->nurbs, newnu);
-                       set_actNurb(obedit, newnu);
                        newnu->bezt = newbezt;
                        newnu->pntsu = 1;
 
-                       cu->lastsel = newbezt;
-
+                       nu = newnu;
                        bezt = newbezt;
                        ok = 1;
                }
@@ -4782,7 +4873,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        nu->bp = newbp;
                        newbp += nu->pntsu;
                        newbp->f1 |= SELECT;
-                       cu->lastsel = newbp;
                        bp = newbp - 1;
                        ok = 1;
                }
@@ -4792,7 +4882,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        ED_curve_bpcpy(editnurb, newbp + 1, bp, nu->pntsu);
                        *newbp = *bp;
                        newbp->f1 |= SELECT;
-                       cu->lastsel = newbp;
                        MEM_freeN(nu->bp);
                        nu->bp = newbp;
                        bp = newbp + 1;
@@ -4803,17 +4892,16 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
                        newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
                        *newbp = *bp;
                        newbp->f1 |= SELECT;
-                       cu->lastsel = newbp;
 
                        newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
                        memcpy(newnu, nu, sizeof(Nurb));
                        BLI_addtail(&editnurb->nurbs, newnu);
-                       set_actNurb(obedit, newnu);
                        newnu->bp = newbp;
                        newnu->orderu = 2;
                        newnu->pntsu = 1;
                        newnu->knotsu = newnu->knotsv = NULL;
 
+                       nu = newnu;
                        bp = newbp;
                        ok = 1;
                }
@@ -4844,6 +4932,13 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
        }
 
        if (ok) {
+               if (nu->bezt) {
+                       BKE_curve_nurb_vert_active_set(cu, nu, newbezt);
+               }
+               else {
+                       BKE_curve_nurb_vert_active_set(cu, nu, newbp);
+               }
+
                BKE_nurb_test2D(nu);
 
                if (ED_curve_updateAnimPaths(obedit->data))
@@ -5194,9 +5289,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
        Nurb *nu;
        BezTriple *bezt;
        BPoint *bp;
-       int a, deselect;
-
-       deselect = RNA_boolean_get(op->ptr, "deselect");
+       int a;
+       const bool select = !RNA_boolean_get(op->ptr, "deselect");
 
        view3d_operator_needs_opengl(C);
        view3d_set_viewcontext(C, &vc);
@@ -5207,8 +5301,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
                a = nu->pntsu;
                bezt = nu->bezt;
                while (a--) {
-                       if (deselect) select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
-                       else select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+                       select_beztriple(bezt, select, SELECT, VISIBLE);
                        bezt++;
                }
        }
@@ -5216,13 +5309,15 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
                a = nu->pntsu * nu->pntsv;
                bp = nu->bp;
                while (a--) {
-                       if (deselect) select_bpoint(bp, DESELECT, SELECT, VISIBLE);
-                       else select_bpoint(bp, SELECT, SELECT, VISIBLE);
+                       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;
 }
@@ -5254,50 +5349,30 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
        ListBase *editnurb = object_editcurve_get(obedit);
        static BPoint *last = NULL;
        static int direction = 0;
-       Nurb *nu;
-       BPoint *bp;
-       int u = 0, v = 0, a, b, ok = 0;
+       Nurb *nu = NULL;
+       BPoint *bp = NULL;
+       int u = 0, v = 0, a, b;
 
-       if (editnurb->first == NULL)
-               return OPERATOR_CANCELLED;
-       if (cu->lastsel == NULL)
+       if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
                return OPERATOR_CANCELLED;
 
-       /* find the correct nurb and toggle with u of v */
-       for (nu = editnurb->first; nu; nu = nu->next) {
-               bp = nu->bp;
-               for (v = 0; v < nu->pntsv; v++) {
-                       for (u = 0; u < nu->pntsu; u++, bp++) {
-                               if (bp == cu->lastsel) {
-                                       if (bp->f1 & SELECT) {
-                                               ok = 1;
-                                               break;
-                                       }
-                               }
-                       }
-                       if (ok) break;
-               }
+       if (last == bp) {
+               direction = 1 - direction;
+               BKE_nurbList_flag_set(editnurb, 0);
+       }
+       last = bp;
 
-               if (ok) {
-                       if (last == cu->lastsel) {
-                               direction = 1 - direction;
-                               BKE_nurbList_flag_set(editnurb, 0);
+       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);
                        }
-                       last = cu->lastsel;
-
-                       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);
-                                       }
-                               }
+                       else {
+                               if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
                        }
-
-                       break;
                }
        }
        
@@ -5634,6 +5709,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
        }
        
        WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+       BKE_curve_nurb_vert_active_validate(obedit->data);
 
        return OPERATOR_FINISHED;
 }
@@ -5699,6 +5775,7 @@ static int curve_select_random_exec(bContext *C, wmOperator *op)
        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);
        
@@ -5726,34 +5803,6 @@ void CURVE_OT_select_random(wmOperatorType *ot)
 
 /********************* every nth number of point *******************/
 
-static bool point_in_nurb(Nurb *nu, void *point)
-{
-       if (nu->bezt) {
-               return ARRAY_HAS_ITEM((BezTriple *)point, nu->bezt, nu->pntsu);
-       }
-       else {
-               return ARRAY_HAS_ITEM((BPoint *)point, nu->bp, nu->pntsu);
-       }
-}
-
-static Nurb *get_lastsel_nurb(Curve *cu)
-{
-       ListBase *nubase = BKE_curve_editNurbs_get(cu);
-       Nurb *nu = nubase->first;
-
-       if (!cu->lastsel)
-               return NULL;
-
-       while (nu) {
-               if (point_in_nurb(nu, cu->lastsel))
-                       return nu;
-
-               nu = nu->next;
-       }
-
-       return NULL;
-}
-
 static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth)
 {
        int a, start;
@@ -5800,23 +5849,22 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth)
        }
 }
 
-int CU_select_nth(Object *obedit, int nth)
+bool ED_curve_select_nth(Curve *cu, int nth)
 {
-       Curve *cu = (Curve *)obedit->data;
-       Nurb *nu;
+       Nurb *nu = NULL;
+       void *vert = NULL;
 
-       nu = get_lastsel_nurb(cu);
-       if (!nu)
-               return 0;
+       if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
+               return false;
 
        if (nu->bezt) {
-               select_nth_bezt(nu, cu->lastsel, nth);
+               select_nth_bezt(nu, vert, nth);
        }
        else {
-               select_nth_bp(nu, cu->lastsel, nth);
+               select_nth_bp(nu, vert, nth);
        }
 
-       return 1;
+       return true;
 }
 
 static int select_nth_exec(bContext *C, wmOperator *op)
@@ -5824,7 +5872,7 @@ static int select_nth_exec(bContext *C, wmOperator *op)
        Object *obedit = CTX_data_edit_object(C);
        int nth = RNA_int_get(op->ptr, "nth");
 
-       if (!CU_select_nth(obedit, nth)) {
+       if (!ED_curve_select_nth(obedit->data, nth)) {
                if (obedit->type == OB_SURF) {
                        BKE_report(op->reports, RPT_ERROR, "Surface has not got active point");
                }
@@ -5897,149 +5945,11 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
 
 static int curve_delete_vertices(Object *obedit)
 {
-       Curve *cu = obedit->data;
-       EditNurb *editnurb = cu->editnurb;
-       ListBase *nubase = &editnurb->nurbs;
-       Nurb *nu, *next;
-       BezTriple *bezt, *bezt1;
-       BPoint *bp, *bp1;
-       int a, type, nuindex = 0;
-
        if (obedit->type == OB_SURF) {
-               return deleteflagNurb(obedit, SELECT);
-       }
-
-       /* first loop, can we remove entire pieces? */
-       nu = nubase->first;
-       while (nu) {
-               next = nu->next;
-               if (nu->type == CU_BEZIER) {
-                       bezt = nu->bezt;
-                       a = nu->pntsu;
-                       if (a) {
-                               while (a) {
-                                       if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
-                                               /* pass */
-                                       }
-                                       else {
-                                               break;
-                                       }
-                                       a--;
-                                       bezt++;
-                               }
-                               if (a == 0) {
-                                       if (cu->actnu == nuindex)
-                                               cu->actnu = -1;
-
-                                       BLI_remlink(nubase, nu);
-                                       keyIndex_delNurb(editnurb, nu);
-                                       BKE_nurb_free(nu); nu = NULL;
-                               }
-                       }
-               }
-               else {
-                       bp = nu->bp;
-                       a = nu->pntsu * nu->pntsv;
-                       if (a) {
-                               while (a) {
-                                       if (bp->f1 & SELECT) {
-                                               /* pass */
-                                       }
-                                       else {
-                                               break;
-                                       }
-                                       a--;
-                                       bp++;
-                               }
-                               if (a == 0) {
-                                       if (cu->actnu == nuindex)
-                                               cu->actnu = -1;
-
-                                       BLI_remlink(nubase, nu);
-                                       keyIndex_delNurb(editnurb, nu);
-                                       BKE_nurb_free(nu); nu = NULL;
-                               }
-                       }
-               }
-
-               /* Never allow the order to exceed the number of points
-                * - note, this is ok but changes unselected nurbs, disable for now */
-#if 0
-               if ((nu != NULL) && (nu->type == CU_NURBS)) {
-                       clamp_nurb_order_u(nu);
-               }
-#endif
-               nu = next;
-               nuindex++;
+               ed_surf_delete_selected(obedit);
        }
-       /* 2nd loop, delete small pieces: just for curves */
-       nu = nubase->first;
-       while (nu) {
-               next = nu->next;
-               type = 0;
-               if (nu->type == CU_BEZIER) {
-                       int delta = 0;
-                       bezt = nu->bezt;
-                       for (a = 0; a < nu->pntsu; a++) {
-                               if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
-                                       memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
-                                       keyIndex_delBezt(editnurb, bezt + delta);
-                                       keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
-                                       nu->pntsu--;
-                                       a--;
-                                       type = 1;
-                                       delta++;
-                               }
-                               else {
-                                       bezt++;
-                               }
-                       }
-                       if (type) {
-                               bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
-                               memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
-                               keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
-                               MEM_freeN(nu->bezt);
-                               nu->bezt = bezt1;
-                               BKE_nurb_handles_calc(nu);
-                       }
-               }
-               else if (nu->pntsv == 1) {
-                       int delta = 0;
-                       bp = nu->bp;
-
-                       for (a = 0; a < nu->pntsu; a++) {
-                               if (bp->f1 & SELECT) {
-                                       memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
-                                       keyIndex_delBP(editnurb, bp + delta);
-                                       keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
-                                       nu->pntsu--;
-                                       a--;
-                                       type = 1;
-                                       delta++;
-                               }
-                               else {
-                                       bp++;
-                               }
-                       }
-                       if (type) {
-                               bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
-                               memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
-                               keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
-                               MEM_freeN(nu->bp);
-                               nu->bp = bp1;
-
-                               /* Never allow the order to exceed the number of points
-                                * - note, this is ok but changes unselected nurbs, disable for now */
-#if 0
-                               if (nu->type == CU_NURBS) {
-                                       clamp_nurb_order_u(nu);
-                               }
-#endif
-                       }
-                       BKE_nurb_order_clamp_u(nu);
-                       BKE_nurb_knot_calc_u(nu);
-               }
-               nu = next;
+       else {
+               ed_curve_delete_selected(obedit);
        }
 
        return OPERATOR_FINISHED;
@@ -6454,8 +6364,7 @@ static int curve_delete_exec(bContext *C, wmOperator *op)
        else BLI_assert(0);
 
        if (retval == OPERATOR_FINISHED) {
-               cu->lastsel = NULL;
-               cu->actnu = -1;
+               cu->actnu = cu->actvert = CU_ACT_NONE;
 
                if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
 
@@ -6723,24 +6632,6 @@ void CURVE_OT_tilt_clear(wmOperatorType *ot)
 
 /****************** undo for curves ****************/
 
-static void *undo_check_lastsel(void *lastsel, Nurb *nu, Nurb *newnu)
-{
-       if (nu->bezt) {
-               BezTriple *lastbezt = (BezTriple *)lastsel;
-               if (lastbezt >= nu->bezt && lastbezt < &nu->bezt[nu->pntsu]) {
-                       return &newnu->bezt[lastbezt - nu->bezt];
-               }
-       }
-       else {
-               BPoint *lastbp = (BPoint *)lastsel;
-               if (lastbp >= nu->bp && lastbp < &nu->bp[nu->pntsu * nu->pntsv]) {
-                       return &newnu->bp[lastbp - nu->bp];
-               }
-       }
-
-       return NULL;
-}
-
 static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
 {
        Curve *cu = cu_v;
@@ -6749,7 +6640,6 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
        ListBase *editbase = BKE_curve_editNurbs_get(cu);
        Nurb *nu, *newnu;
        EditNurb *editnurb = cu->editnurb;
-       void *lastsel = NULL;
        AnimData *ad = BKE_animdata_from_id(&cu->id);
 
        BKE_nurbList_free(editbase);
@@ -6773,10 +6663,6 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
        for (nu = undobase->first; nu; nu = nu->next) {
                newnu = BKE_nurb_duplicate(nu);
 
-               if (lastsel == NULL) {
-                       lastsel = undo_check_lastsel(undoCurve->lastsel, nu, newnu);
-               }
-
                if (editnurb->keyindex) {
                        keyIndex_updateNurb(editnurb, nu, newnu);
                }
@@ -6784,7 +6670,7 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
                BLI_addtail(editbase, newnu);
        }
 
-       cu->lastsel = lastsel;
+       cu->actvert = undoCurve->actvert;
        cu->actnu = undoCurve->actnu;
        ED_curve_updateAnimPaths(cu);
 }
@@ -6796,7 +6682,6 @@ static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
        UndoCurve *undoCurve;
        EditNurb *editnurb = cu->editnurb, tmpEditnurb;
        Nurb *nu, *newnu;
-       void *lastsel = NULL;
        AnimData *ad = BKE_animdata_from_id(&cu->id);
 
        undoCurve = MEM_callocN(sizeof(UndoCurve), "undoCurve");
@@ -6817,10 +6702,6 @@ static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
        for (nu = nubase->first; nu; nu = nu->next) {
                newnu = BKE_nurb_duplicate(nu);
 
-               if (lastsel == NULL) {
-                       lastsel = undo_check_lastsel(cu->lastsel, nu, newnu);
-               }
-
                if (undoCurve->undoIndex) {
                        keyIndex_updateNurb(&tmpEditnurb, nu, newnu);
                }
@@ -6828,7 +6709,7 @@ static void *editCurve_to_undoCurve(void *UNUSED(edata), void *cu_v)
                BLI_addtail(&undoCurve->nubase, newnu);
        }
 
-       undoCurve->lastsel = lastsel;
+       undoCurve->actvert = cu->actvert;
        undoCurve->actnu = cu->actnu;
 
        return undoCurve;
@@ -6873,25 +6754,24 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
        keyIndex_updateBP(editnurb, src, dst, count);
 }
 
-int ED_curve_actSelection(Curve *cu, float center[3])
+bool ED_curve_active_center(Curve *cu, float center[3])
 {
-       Nurb *nu = get_lastsel_nurb(cu);
-
-       if (!nu)
-               return 0;
+       Nurb *nu = NULL;
+       void *vert = NULL;
 
-       if (nu->bezt) {
-               BezTriple *bezt = cu->lastsel;
+       if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
+               return false;
 
+       if (nu->type == CU_BEZIER) {
+               BezTriple *bezt = (BezTriple *)vert;
                copy_v3_v3(center, bezt->vec[1]);
        }
        else {
-               BPoint *bp = cu->lastsel;
-
+               BPoint *bp = (BPoint *)vert;
                copy_v3_v3(center, bp->vec);
        }
 
-       return 1;
+       return true;
 }
 
 /******************** Match texture space operator ***********************/