Curves: save active point to file
authorKevin Mackay <mackay.ka@gmail.com>
Mon, 27 Jan 2014 04:18:40 +0000 (15:18 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 27 Jan 2014 04:21:04 +0000 (15:21 +1100)
Changed curve active point from pointer to index. Allows curve active point to be saved to file and retained between modes for free. Also some small optimisations by removing pointer look up code.

- Made active point access functions into BKE API calls.
- Fixes operators where curve de-selection resulted in unsel-active point.
- Split curve delete into 2 functions

15 files changed:
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/intern/curve.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editcurve_add.c
source/blender/editors/include/ED_curve.h
source/blender/editors/include/UI_resources.h
source/blender/editors/interface/resources.c
source/blender/editors/object/object_add.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_orientations.c
source/blender/makesdna/DNA_curve_types.h

index 589ca68c798f4b572bdac199173ba575db311645..afa053012dab999cccd2b2d679745d3a48ec101d 100644 (file)
@@ -86,7 +86,14 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
 void BKE_curve_material_index_remove(struct Curve *cu, int index);
 void BKE_curve_material_index_clear(struct Curve *cu);
 
-ListBase *BKE_curve_nurbs_get(struct Curve *cu);
+ListBase    *BKE_curve_nurbs_get(struct Curve *cu);
+
+void         BKE_curve_nurb_active_set(struct Curve *cu, struct Nurb *nu);
+struct Nurb *BKE_curve_nurb_active_get(struct Curve *cu);
+void        *BKE_curve_vert_active_get(struct Curve *cu);
+void         BKE_curve_nurb_vert_active_set(struct Curve *cu, struct Nurb *nu,    void *vert);
+bool         BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
+void         BKE_curve_nurb_vert_active_validate(struct Curve *cu);
 
 float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3];
 void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
index dfcd8f6769852fdbd586100036621aae8a1bcb1f..cba4b7e1ea27d3604e422bb94014396d0d9ab19d 100644 (file)
@@ -224,7 +224,6 @@ Curve *BKE_curve_copy(Curve *cu)
 
        cun->editnurb = NULL;
        cun->editfont = NULL;
-       cun->lastsel = NULL;
 
 #if 0   // XXX old animation system
        /* single user ipo too */
@@ -3931,6 +3930,105 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
        return &cu->nurb;
 }
 
+void BKE_curve_nurb_active_set(Curve *cu, Nurb *nu)
+{
+       if (nu == NULL) {
+               cu->actnu = -1;
+       }
+       else {
+               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+               cu->actnu = BLI_findindex(nurbs, nu);
+       }
+}
+
+Nurb *BKE_curve_nurb_active_get(Curve *cu)
+{
+       ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+       return BLI_findlink(nurbs, cu->actnu);
+}
+
+/* Get active vert for curve */
+void *BKE_curve_vert_active_get(Curve *cu)
+{
+       Nurb *nu = NULL;
+       void *vert = NULL;
+
+       BKE_curve_nurb_vert_active_get(cu, &nu, &vert);
+       return vert;
+}
+
+/* Set active nurb and active vert for curve */
+void BKE_curve_nurb_vert_active_set(Curve *cu, Nurb *nu, void *vert)
+{
+       if (nu) {
+               BKE_curve_nurb_active_set(cu, nu);
+
+               if (nu->type == CU_BEZIER) {
+                       BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu));
+                       cu->actvert = (BezTriple *)vert - nu->bezt;
+               }
+               else {
+                       BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv));
+                       cu->actvert = (BPoint *)vert - nu->bp;
+               }
+       }
+       else {
+               cu->actnu = cu->actvert = CU_ACT_NONE;
+       }
+}
+
+/* Get points to active active nurb and active vert for curve */
+bool BKE_curve_nurb_vert_active_get(Curve *cu, Nurb **r_nu, void **r_vert)
+{
+       Nurb *nu = NULL;
+       void *vert = NULL;
+
+       if (cu->actvert != CU_ACT_NONE) {
+               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+               nu = BLI_findlink(nurbs, cu->actnu);
+
+               if (nu) {
+                       if (nu->type == CU_BEZIER) {
+                               BLI_assert(nu->pntsu > cu->actvert);
+                               vert = &nu->bezt[cu->actvert];
+                       }
+                       else {
+                               BLI_assert((nu->pntsu * nu->pntsv) > cu->actvert);
+                               vert = &nu->bp[cu->actvert];
+                       }
+               }
+               /* get functions should never set! */
+#if 0
+               else {
+                       cu->actnu = cu->actvert = CU_ACT_NONE;
+               }
+#endif
+       }
+
+       *r_nu = nu;
+       *r_vert = vert;
+
+       return (*r_vert != NULL);
+}
+
+void BKE_curve_nurb_vert_active_validate(Curve *cu)
+{
+       Nurb *nu;
+       void *vert;
+
+       if (BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
+               if (nu->type == CU_BEZIER) {
+                       if ((((BezTriple *)vert)->f1 & SELECT) == 0) {
+                               cu->actvert = CU_ACT_NONE;
+                       }
+               }
+               else {
+                       if ((((BPoint *)vert)->f1 & SELECT) == 0) {
+                               cu->actvert = CU_ACT_NONE;
+                       }
+               }
+       }
+}
 
 /* basic vertex data functions */
 bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
index 88e7f85a03d3e4ef0c6afb9ba40966f9e90e1a62..913bdfd1521bcee927af34b61d09a5b4241262c9 100644 (file)
@@ -3388,7 +3388,6 @@ static void direct_link_curve(FileData *fd, Curve *cu)
        }
 
        cu->editnurb = NULL;
-       cu->lastsel = NULL;
        cu->editfont = NULL;
        
        for (nu = cu->nurb.first; nu; nu = nu->next) {
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 ***********************/
index a1d144a92e9638042b0860e71a497f5a297f1bc4..c2a7a509fb3ab1d04c54a64fc44e3b840d5f4c52 100644 (file)
@@ -459,7 +459,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
        if (nu) { /* should always be set */
                nu->flag |= CU_SMOOTH;
                cu->actnu = BLI_countlist(editnurb);
-               cu->lastsel = NULL;
+               cu->actvert = CU_ACT_NONE;
 
                BKE_nurb_test2D(nu);
        }
index ce6c8f8354b2093b5914aa60d8ad7a66942dcc53..296d70959386d7e0765e777117c41ccec41b50fa 100644 (file)
@@ -51,10 +51,10 @@ void    ED_operatormacros_curve(void);
 void    ED_keymap_curve(struct wmKeyConfig *keyconf);
 
 /* editcurve.c */
-void ED_curve_transform(struct Curve *cv, float mat[4][4]);
-void CU_deselect_all(struct Object *obedit);
-void CU_select_all(struct Object *obedit);
-void CU_select_swap(struct Object *obedit);
+void ED_curve_transform(struct Curve *cu, float mat[4][4]);
+void ED_curve_deselect_all(struct EditNurb *editnurb);
+void ED_curve_select_all(struct EditNurb *editnurb);
+void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
 
 
 void    undo_push_curve(struct bContext *C, const char *name);
@@ -80,7 +80,7 @@ void    free_editText(struct Object *obedit);
 
 void    ED_text_to_object(struct bContext *C, struct Text *text, int split_lines);
 
-int CU_select_nth(struct Object *obedit, int nth);
+bool ED_curve_select_nth(struct Curve *cu, int nth);
 
 void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count);
 void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count);
@@ -88,10 +88,9 @@ struct Nurb *ED_curve_nurbcpy(struct Nurb *src, int count);
 
 int ED_curve_updateAnimPaths(struct Curve *cu);
 
-int ED_curve_actSelection(struct Curve *cu, float center[3]);
+bool ED_curve_active_center(struct Curve *cu, float center[3]);
 
 /* debug only */
 void printknots(struct Object *obedit);
 
 #endif /* __ED_CURVE_H__ */
-
index 4e353b18be87e5d3db1f02fc3b9497f6e3603bcf..1d4d61afef93bcfb59dfc551fc4b0755090fe7a5 100644 (file)
@@ -124,7 +124,7 @@ enum {
        TH_HANDLE_SEL_AUTOCLAMP,
 
        TH_ACTIVE_SPLINE,
-       TH_LASTSEL_POINT,
+       TH_ACTIVE_VERT, /* equivalent of TH_EDITMESH_ACTIVE for splines */
 
        TH_SYNTAX_B,
        TH_SYNTAX_V,
index 63f4681c77909132d2acc9dc4445ad70f82e6f16..181e8de3f3d9f1ad473a8643306bf36f042bc3a9 100644 (file)
@@ -372,7 +372,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
                                        cp = ts->nurb_sel_vline; break;
                                case TH_ACTIVE_SPLINE:
                                        cp = ts->act_spline; break;
-                               case TH_LASTSEL_POINT:
+                               case TH_ACTIVE_VERT:
                                        cp = ts->lastsel_point; break;
                                case TH_HANDLE_FREE:
                                        cp = ts->handle_free; break;
index 8209d5db8cd04db2989987886ee273850e4f869c..924e88babf1828b410466c3e187aa6bbead91e86 100644 (file)
@@ -498,15 +498,17 @@ static int effector_add_exec(bContext *C, wmOperator *op)
        type = RNA_enum_get(op->ptr, "type");
 
        if (type == PFIELD_GUIDE) {
+               Curve *cu;
                ob = ED_object_add_type(C, OB_CURVE, loc, rot, FALSE, layer);
                if (!ob)
                        return OPERATOR_CANCELLED;
 
                rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"));
-               ((Curve *)ob->data)->flag |= CU_PATH | CU_3D;
+               cu = ob->data;
+               cu->flag |= CU_PATH | CU_3D;
                ED_object_editmode_enter(C, 0);
                ED_object_new_primitive_matrix(C, ob, loc, rot, mat, FALSE);
-               BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
+               BLI_addtail(&cu->editnurb->nurbs, add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
                if (!enter_editmode)
                        ED_object_editmode_exit(C, EM_FREEDATA);
        }
index 05583f90ba362a407206ff998c251c6c729213ab..0caf679d775f8f900bfe895e246943425b7f39cb 100644 (file)
@@ -1854,7 +1854,7 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
                                        if (bp->hide == 0) {
                                                /* check for active BPoint and ensure selected */
                                                if ((bp == actbp) && (bp->f1 & SELECT)) {
-                                                       UI_ThemeColor(TH_LASTSEL_POINT);
+                                                       UI_ThemeColor(TH_ACTIVE_VERT);
                                                        bglVertex3fv(dl ? co : bp->vec);
                                                        UI_ThemeColor(color);
                                                }
@@ -5358,7 +5358,7 @@ static void drawhandlesN_active(Nurb *nu)
        glLineWidth(1);
 }
 
-static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, void *lastsel)
+static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert)
 {
        BezTriple *bezt;
        BPoint *bp;
@@ -5383,8 +5383,8 @@ static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, void *
                a = nu->pntsu;
                while (a--) {
                        if (bezt->hide == 0) {
-                               if (sel == 1 && bezt == lastsel) {
-                                       UI_ThemeColor(TH_LASTSEL_POINT);
+                               if (sel == 1 && bezt == vert) {
+                                       UI_ThemeColor(TH_ACTIVE_VERT);
                                        bglVertex3fv(bezt->vec[1]);
 
                                        if (!hide_handles) {
@@ -5411,8 +5411,8 @@ static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, void *
                a = nu->pntsu * nu->pntsv;
                while (a--) {
                        if (bp->hide == 0) {
-                               if (bp == lastsel) {
-                                       UI_ThemeColor(TH_LASTSEL_POINT);
+                               if (bp == vert) {
+                                       UI_ThemeColor(TH_ACTIVE_VERT);
                                        bglVertex3fv(bp->vec);
                                        UI_ThemeColor(color);
                                }
@@ -5621,6 +5621,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        Curve *cu = ob->data;
        Nurb *nu;
        BevList *bl;
+       const void *vert = BKE_curve_vert_active_get(cu);
        const bool hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
        int index;
        unsigned char wire_col[3];
@@ -5700,7 +5701,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
        
        for (nu = nurb; nu; nu = nu->next) {
-               drawvertsN(nu, 1, hide_handles, cu->lastsel);
+               drawvertsN(nu, 1, hide_handles, vert);
        }
        
        if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
index d18fb452022976650c966901497221ef02f7863d..8dfb0e86ac2587f5c9f24a94a9e4ce4c482cf169 100644 (file)
@@ -62,6 +62,7 @@
 
 #include "BKE_armature.h"
 #include "BKE_context.h"
+#include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_mball.h"
 #include "BKE_mesh.h"
@@ -537,7 +538,6 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BP
        if (BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) {
                if (bp) {
                        bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
-                       if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL;
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
@@ -555,8 +555,6 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BP
                                        bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
                                }
                        }
-
-                       if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL;
                }
        }
 }
@@ -571,10 +569,11 @@ static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short
        view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
 
        if (extend == false && select)
-               CU_deselect_all(vc->obedit);
+               ED_curve_deselect_all(vc->obedit->data);
 
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
        nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+       BKE_curve_nurb_vert_active_validate(vc->obedit->data);
 }
 
 static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2])
@@ -1710,7 +1709,6 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoi
        if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
                if (bp) {
                        bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
-                       if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL;
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
@@ -1728,8 +1726,6 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoi
                                        bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
                                }
                        }
-
-                       if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL;
                }
        }
 }
@@ -1740,10 +1736,11 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool ex
        view3d_userdata_boxselect_init(&data, vc, rect, select);
 
        if (extend == false && select)
-               CU_deselect_all(vc->obedit);
+               ED_curve_deselect_all(vc->obedit->data);
 
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
        nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+       BKE_curve_nurb_vert_active_validate(vc->obedit->data);
 
        return OPERATOR_FINISHED;
 }
@@ -2474,8 +2471,6 @@ static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint
        if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
                if (bp) {
                        bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
-
-                       if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL;
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
@@ -2493,8 +2488,6 @@ static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint
                                        bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
                                }
                        }
-
-                       if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL;
                }
        }
 }
@@ -2506,6 +2499,7 @@ static void nurbscurve_circle_select(ViewContext *vc, const bool select, const i
 
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
        nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+       BKE_curve_nurb_vert_active_validate(vc->obedit->data);
 }
 
 
index 85a2da10596bf145feabf94197a86afacbfcd4b4..55ecc53fd01cc1aa67877953ff09d5eaad91a836 100644 (file)
@@ -1667,7 +1667,7 @@ void calculateCenter(TransInfo *t)
                                        float center[3];
                                        Curve *cu = (Curve *)t->obedit->data;
 
-                                       if (ED_curve_actSelection(cu, center)) {
+                                       if (ED_curve_active_center(cu, center)) {
                                                copy_v3_v3(t->center, center);
                                                calculateCenter2D(t);
                                                break;
index ddbb05f2536cfaf1b66f8a472dc9687a397b63de..fc4e5fcb8e57da90415c86ae46190f956810bbe4 100644 (file)
@@ -397,7 +397,7 @@ int calc_manipulator_stats(const bContext *C)
                        Curve *cu = obedit->data;
                        float center[3];
 
-                       if (v3d->around == V3D_ACTIVE && ED_curve_actSelection(cu, center)) {
+                       if (v3d->around == V3D_ACTIVE && ED_curve_active_center(cu, center)) {
                                calc_tw_center(scene, center);
                                totsel++;
                        }
index be8bc460764d88a819577d2be468c2ed69610210..1cb441b5b163dad198413998ce2ebb166bee08ed 100644 (file)
@@ -705,27 +705,15 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
                } /* end editmesh */
                else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                        Curve *cu = obedit->data;
-                       Nurb *nu;
-                       BezTriple *bezt;
+                       Nurb *nu = NULL;
+                       BezTriple *bezt = NULL;
                        int a;
                        ListBase *nurbs = BKE_curve_editNurbs_get(cu);
 
-                       if (activeOnly && cu->lastsel) {
-                               for (nu = nurbs->first; nu; nu = nu->next) {
-                                       if (nu->type == CU_BEZIER) {
-                                               if (ARRAY_HAS_ITEM((BezTriple *)cu->lastsel, nu->bezt, nu->pntsu)) {
-                                                       bezt = cu->lastsel;
-                                                       BKE_nurb_bezt_calc_normal(nu, bezt, normal);
-                                                       BKE_nurb_bezt_calc_plane(nu, bezt, plane);
-                                                       break;
-                                               }
-                                       }
-                                       else {
-                                               if (ARRAY_HAS_ITEM((BPoint *)cu->lastsel, nu->bp, nu->pntsu)) {
-                                                       /* do nothing */
-                                                       break;
-                                               }
-                                       }
+                       if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bezt)) {
+                               if (nu->type == CU_BEZIER) {
+                                       BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+                                       BKE_nurb_bezt_calc_plane(nu, bezt, plane);
                                }
                        }
                        else {
index 695df477e8b659290f9f00578052c3c18691c264..c7b6a8c43d34b65fd1f97155c3b29665d5a3a69f 100644 (file)
@@ -209,9 +209,10 @@ typedef struct Curve {
 
        /* edit, index in nurb list */
        int actnu;
-       /* edit, last selected point */
-       void *lastsel;
+       /* edit, index in active nurb (BPoint or BezTriple) */
+       int actvert;
 
+       char pad[4];
 
        /* font part */
        short lines;
@@ -248,7 +249,7 @@ typedef struct Curve {
        float ctime;                    /* current evaltime - for use by Objects parented to curves */
        float bevfac1, bevfac2;
 
-       char pad[4];
+       char pad2[4];
 } Curve;
 
 /* **************** CURVE ********************* */
@@ -325,6 +326,8 @@ typedef struct Curve {
 #define CU_NURB_ENDPOINT       2
 #define CU_NURB_BEZIER         4
 
+#define CU_ACT_NONE            -1
+
 /* *************** BEZTRIPLE **************** */
 
 /* h1 h2 (beztriple) */