Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-07-08 16:24:16 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-07-08 17:09:26 +0300
commit4a328a76895c4f03b528b3c7e251475e76c68351 (patch)
tree6a876d72be674294f63d3619b4464c4e8c262b0b
parentde6b4dc7f7f5e78ebfefdfe804218a69631d778e (diff)
EditCurve: move selection into own file
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/curve_intern.h50
-rw-r--r--source/blender/editors/curve/editcurve.c1133
-rw-r--r--source/blender/editors/curve/editcurve_select.c1156
-rw-r--r--source/blender/editors/include/ED_curve.h13
5 files changed, 1214 insertions, 1139 deletions
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 1b877c0fba9..66c281df5fa 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -37,6 +37,7 @@ set(SRC
curve_ops.c
editcurve.c
editcurve_add.c
+ editcurve_select.c
editfont.c
curve_intern.h
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 579f149ea8b..bb0abf44744 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -37,6 +37,7 @@ struct ListBase;
struct EditNurb;
struct Object;
struct wmOperatorType;
+struct ViewContext;
/* editfont.c */
enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
@@ -44,6 +45,25 @@ enum { CASE_LOWER, CASE_UPPER };
enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD,
PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+typedef enum eVisible_Types {
+ HIDDEN = true,
+ VISIBLE = false,
+} eVisible_Types;
+
+typedef enum eEndPoint_Types {
+ FIRST = true,
+ LAST = false,
+} eEndPoint_Types;
+
+typedef enum eCurveElem_Types {
+ CURVE_VERTEX = 0,
+ CURVE_SEGMENT,
+} eCurveElem_Types;
+
+/* internal select utils */
+bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden);
+bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden);
+
void FONT_OT_text_insert(struct wmOperatorType *ot);
void FONT_OT_line_break(struct wmOperatorType *ot);
void FONT_OT_insert_lorem(struct wmOperatorType *ot);
@@ -98,19 +118,6 @@ void CURVE_OT_smooth_weight(struct wmOperatorType *ot);
void CURVE_OT_smooth_radius(struct wmOperatorType *ot);
void CURVE_OT_smooth_tilt(struct wmOperatorType *ot);
-void CURVE_OT_de_select_first(struct wmOperatorType *ot);
-void CURVE_OT_de_select_last(struct wmOperatorType *ot);
-void CURVE_OT_select_all(struct wmOperatorType *ot);
-void CURVE_OT_select_linked(struct wmOperatorType *ot);
-void CURVE_OT_select_linked_pick(struct wmOperatorType *ot);
-void CURVE_OT_select_row(struct wmOperatorType *ot);
-void CURVE_OT_select_next(struct wmOperatorType *ot);
-void CURVE_OT_select_previous(struct wmOperatorType *ot);
-void CURVE_OT_select_more(struct wmOperatorType *ot);
-void CURVE_OT_select_less(struct wmOperatorType *ot);
-void CURVE_OT_select_random(struct wmOperatorType *ot);
-void CURVE_OT_select_nth(struct wmOperatorType *ot);
-
void CURVE_OT_switch_direction(struct wmOperatorType *ot);
void CURVE_OT_subdivide(struct wmOperatorType *ot);
void CURVE_OT_make_segment(struct wmOperatorType *ot);
@@ -121,11 +128,28 @@ void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
+bool ED_curve_pick_vert(
+ struct ViewContext *vc, short sel, const int mval[2],
+ struct Nurb **r_nurb, struct BezTriple **r_bezt, struct BPoint **r_bp, short *r_handle);
+
/* helper functions */
void ed_editnurb_translate_flag(struct ListBase *editnurb, short flag, const float vec[3]);
bool ed_editnurb_extrude_flag(struct EditNurb *editnurb, short flag);
bool ed_editnurb_spin(float viewmat[4][4], struct Object *obedit, const float axis[3], const float cent[3]);
+/* editcurve_select.c */
+void CURVE_OT_de_select_first(struct wmOperatorType *ot);
+void CURVE_OT_de_select_last(struct wmOperatorType *ot);
+void CURVE_OT_select_all(struct wmOperatorType *ot);
+void CURVE_OT_select_linked(struct wmOperatorType *ot);
+void CURVE_OT_select_linked_pick(struct wmOperatorType *ot);
+void CURVE_OT_select_row(struct wmOperatorType *ot);
+void CURVE_OT_select_next(struct wmOperatorType *ot);
+void CURVE_OT_select_previous(struct wmOperatorType *ot);
+void CURVE_OT_select_more(struct wmOperatorType *ot);
+void CURVE_OT_select_less(struct wmOperatorType *ot);
+void CURVE_OT_select_random(struct wmOperatorType *ot);
+void CURVE_OT_select_nth(struct wmOperatorType *ot);
/* editcurve_add.c */
void CURVE_OT_primitive_bezier_curve_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 1a10814bbf1..d17c05a4491 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -37,9 +37,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_bitmap.h"
#include "BLI_math.h"
-#include "BLI_rand.h"
#include "BLI_ghash.h"
#include "BLF_translation.h"
@@ -96,23 +94,7 @@ typedef struct {
Nurb *orig_nu;
} CVKeyIndex;
-typedef enum eVisible_Types {
- HIDDEN = true,
- VISIBLE = false,
-} eVisible_Types;
-
-typedef enum eEndPoint_Types {
- FIRST = true,
- LAST = false,
-} eEndPoint_Types;
-
-typedef enum eCurveElem_Types {
- CURVE_VERTEX = 0,
- CURVE_SEGMENT,
-} eCurveElem_Types;
-
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
-static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
static int curve_delete_segments(Object *obedit, const bool split);
@@ -127,61 +109,6 @@ ListBase *object_editcurve_get(Object *ob)
/* ******************* SELECTION FUNCTIONS ********************* */
-
-/* returns 1 in case (de)selection was successful */
-static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
-{
- if ((bezt->hide == 0) || (hidden == HIDDEN)) {
- if (selstatus == SELECT) { /* selects */
- bezt->f1 |= flag;
- bezt->f2 |= flag;
- bezt->f3 |= flag;
- return true;
- }
- else { /* deselects */
- bezt->f1 &= ~flag;
- bezt->f2 &= ~flag;
- bezt->f3 &= ~flag;
- return true;
- }
- }
-
- return false;
-}
-
-/* returns 1 in case (de)selection was successful */
-static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
-{
- if ((bp->hide == 0) || (hidden == 1)) {
- if (selstatus == SELECT) {
- bp->f1 |= flag;
- return true;
- }
- else {
- bp->f1 &= ~flag;
- return true;
- }
- }
-
- return false;
-}
-
-static bool swap_selection_beztriple(BezTriple *bezt)
-{
- if (bezt->f2 & SELECT)
- return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- else
- return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
-}
-
-static bool swap_selection_bpoint(BPoint *bp)
-{
- if (bp->f1 & SELECT)
- return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- else
- return select_bpoint(bp, SELECT, SELECT, VISIBLE);
-}
-
int isNurbsel(Nurb *nu)
{
BezTriple *bezt;
@@ -1407,64 +1334,6 @@ void ED_curve_deselect_all(EditNurb *editnurb)
}
}
-void ED_curve_select_all(EditNurb *editnurb)
-{
- Nurb *nu;
- int a;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt;
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- bezt->f1 |= SELECT;
- bezt->f2 |= SELECT;
- bezt->f3 |= SELECT;
- }
- }
- }
- else if (nu->bp) {
- BPoint *bp;
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->hide == 0)
- bp->f1 |= SELECT;
- }
- }
- }
-}
-
-void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
-{
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
-
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- bezt->f2 ^= SELECT; /* always do the center point */
- if (!hide_handles) {
- bezt->f1 ^= SELECT;
- bezt->f3 ^= SELECT;
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- swap_selection_bpoint(bp);
- bp++;
- }
- }
- }
-}
-
/******************** separate operator ***********************/
static int separate_exec(bContext *C, wmOperator *op)
@@ -2925,274 +2794,6 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/***************** selection utility *************************/
-
-/* next == 1 -> select next */
-/* next == -1 -> select previous */
-/* cont == 1 -> select continuously */
-/* selstatus, inverts behavior */
-static void select_adjacent_cp(ListBase *editnurb, short next,
- const bool cont, const bool selstatus)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- bool lastsel = false;
-
- if (next == 0) return;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- if (next < 0) bezt = &nu->bezt[a - 1];
- while (a--) {
- if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
- bezt += next;
- if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
- short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = true;
- }
- }
- else {
- bezt += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bezt -= (next - next / abs(next));
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- if (next < 0) bp = &nu->bp[a - 1];
- while (a--) {
- if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
- bp += next;
- if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
- short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = true;
- }
- }
- else {
- bp += next;
- lastsel = false;
- }
- /* move around in zigzag way so that we go through each */
- bp -= (next - next / abs(next));
- }
- }
- }
-}
-
-/**************** select start/end operators **************/
-
-/* (de)selects first or last of visible part of each Nurb depending on selFirst
- * selFirst: defines the end of which to select
- * doswap: defines if selection state of each first/last control point is swapped
- * selstatus: selection status in case doswap is false
- */
-void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
-{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- Curve *cu;
- int a;
-
- if (obedit == NULL) return;
-
- cu = (Curve *)obedit->data;
- cu->actvert = CU_ACT_NONE;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bezt = &nu->bezt[a - 1];
- }
- else { /* select first */
- bezt = nu->bezt;
- }
-
- while (a--) {
- bool sel;
- if (doswap) sel = swap_selection_beztriple(bezt);
- else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
-
- if (sel == true) break;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
-
- /* which point? */
- if (selfirst == LAST) { /* select last */
- bp = &nu->bp[a - 1];
- }
- else { /* select first */
- bp = nu->bp;
- }
-
- while (a--) {
- if (bp->hide == 0) {
- bool sel;
- if (doswap) sel = swap_selection_bpoint(bp);
- else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
-
- if (sel == true) break;
- }
- }
- }
- }
-}
-
-static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
-
- selectend_nurb(obedit, FIRST, true, DESELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_de_select_first(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select First";
- ot->idname = "CURVE_OT_de_select_first";
- ot->description = "(De)select first of visible part of each NURBS";
-
- /* api cfirstbacks */
- ot->exec = de_select_first_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
-
- selectend_nurb(obedit, LAST, true, DESELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_de_select_last(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select Last";
- ot->idname = "CURVE_OT_de_select_last";
- ot->description = "(De)select last of visible part of each NURBS";
-
- /* api clastbacks */
- ot->exec = de_select_last_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/******************* de select all operator ***************/
-
-static bool nurb_has_selected_cps(ListBase *editnurb)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if (bezt->hide == 0) {
- if ((bezt->f1 & SELECT) ||
- (bezt->f2 & SELECT) ||
- (bezt->f3 & SELECT))
- {
- return 1;
- }
- }
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if ((bp->hide == 0) && (bp->f1 & SELECT)) return 1;
- bp++;
- }
- }
- }
-
- return 0;
-}
-
-static int de_select_all_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- if (nurb_has_selected_cps(editnurb))
- action = SEL_DESELECT;
- }
-
- switch (action) {
- case SEL_SELECT:
- ED_curve_select_all(cu->editnurb);
- break;
- case SEL_DESELECT:
- ED_curve_deselect_all(cu->editnurb);
- break;
- case SEL_INVERT:
- ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
- break;
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(cu);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "CURVE_OT_select_all";
- ot->description = "(De)select all control points";
-
- /* api callbacks */
- ot->exec = de_select_all_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_select_all(ot);
-}
-
/********************** hide operator *********************/
static int hide_exec(bContext *C, wmOperator *op)
@@ -3754,7 +3355,7 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
/******************** find nearest ************************/
-static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void ED_curve_pick_vert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; } *data = userData;
@@ -3790,7 +3391,9 @@ static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp,
}
}
-static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], Nurb **nurb, BezTriple **bezt, BPoint **bp)
+bool ED_curve_pick_vert(
+ ViewContext *vc, short sel, const int mval[2],
+ Nurb **r_nurb, BezTriple **r_bezt, BPoint **r_bp, short *r_handle)
{
/* (sel == 1): selected gets a disadvantage */
/* in nurb and bezt or bp the nearest is written */
@@ -3804,13 +3407,17 @@ static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2],
data.mval_fl[1] = mval[1];
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_nurb = data.nurb;
+ *r_bezt = data.bezt;
+ *r_bp = data.bp;
- *nurb = data.nurb;
- *bezt = data.bezt;
- *bp = data.bp;
+ if (r_handle) {
+ *r_handle = data.hpoint;
+ }
- return data.hpoint;
+ return (data.bezt || data.bp);
}
static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt, BPoint **bp)
@@ -4637,9 +4244,8 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
location[0] = mval[0];
location[1] = mval[1];
- hand = findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp);
- if (bezt || bp) {
+ if (ED_curve_pick_vert(&vc, 1, location, &nu, &bezt, &bp, &hand)) {
if (extend) {
if (bezt) {
if (hand == 1) {
@@ -5545,717 +5151,6 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in");
}
-/***************** select linked operator ******************/
-
-static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- ListBase *nurbs = &editnurb->nurbs;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- select_beztriple(bezt, SELECT, SELECT, VISIBLE);
- bezt++;
- }
- break;
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- select_bpoint(bp, SELECT, SELECT, VISIBLE);
- bp++;
- }
- break;
- }
- bp++;
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- return select_linked_exec(C, op);
-}
-
-void CURVE_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked All";
- ot->idname = "CURVE_OT_select_linked";
- ot->description = "Select all control points linked to active one";
-
- /* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
-}
-
-
-/***************** select linked pick operator ******************/
-
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Object *obedit = CTX_data_edit_object(C);
- ViewContext vc;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
-
- view3d_operator_needs_opengl(C);
- view3d_set_viewcontext(C, &vc);
-
- findnearestNurbvert(&vc, 1, event->mval, &nu, &bezt, &bp);
-
- if (bezt) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- bezt++;
- }
- }
- else if (bp) {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- bp++;
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- if (!select) {
- BKE_curve_nurb_vert_active_validate(obedit->data);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_linked_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "CURVE_OT_select_linked_pick";
- ot->description = "Select all control points linked to already selected ones";
-
- /* api callbacks */
- ot->invoke = select_linked_pick_invoke;
- ot->poll = ED_operator_editsurfcurve_region_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them");
-}
-
-/***************** select row operator **********************/
-
-static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = obedit->data;
- ListBase *editnurb = object_editcurve_get(obedit);
- static BPoint *last = NULL;
- static int direction = 0;
- Nurb *nu = NULL;
- BPoint *bp = NULL;
- int u = 0, v = 0, a, b;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
- return OPERATOR_CANCELLED;
-
- if (last == bp) {
- direction = 1 - direction;
- BKE_nurbList_flag_set(editnurb, 0);
- }
- last = bp;
-
- u = cu->actvert % nu->pntsu;
- v = cu->actvert / nu->pntsu;
- bp = nu->bp;
- for (a = 0; a < nu->pntsv; a++) {
- for (b = 0; b < nu->pntsu; b++, bp++) {
- if (direction) {
- if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- else {
- if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_row(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Control Point Row";
- ot->idname = "CURVE_OT_select_row";
- ot->description = "Select a row of control points including active one";
-
- /* api callbacks */
- ot->exec = select_row_exec;
- ot->poll = ED_operator_editsurf;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select next operator **********************/
-
-static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
-
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_next(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Next";
- ot->idname = "CURVE_OT_select_next";
- ot->description = "Select control points following already selected ones along the curves";
-
- /* api callbacks */
- ot->exec = select_next_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select previous operator **********************/
-
-static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
-
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_previous(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Previous";
- ot->idname = "CURVE_OT_select_previous";
- ot->description = "Select control points preceding already selected ones along the curves";
-
- /* api callbacks */
- ot->exec = select_previous_exec;
- ot->poll = ED_operator_editcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/***************** select more operator **********************/
-
-static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp, *tempbp;
- int a;
- short sel = 0;
-
- /* note that NURBS surface is a special case because we mimic */
- /* the behavior of "select more" of mesh tools. */
- /* The algorithm is designed to work in planar cases so it */
- /* may not be optimal always (example: end of NURBS sphere) */
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a > 0) {
- if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- /* upper control point */
- if (a % nu->pntsu != 0) {
- tempbp = bp - 1;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
-
- /* left control point. select only if it is not selected already */
- if (a - nu->pntsu > 0) {
- sel = 0;
- tempbp = bp + nu->pntsu;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- /* make sure selected bpoint is discarded */
- if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
- }
-
- /* right control point */
- if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
- tempbp = bp - nu->pntsu;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- }
-
- /* lower control point. skip next bp in case selection was made */
- if (a % nu->pntsu != 1) {
- sel = 0;
- tempbp = bp + 1;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
- if (sel) {
- bp++;
- a--;
- }
- }
- }
-
- bp++;
- a--;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- select_adjacent_cp(editnurb, 1, 0, SELECT);
- select_adjacent_cp(editnurb, -1, 0, SELECT);
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "CURVE_OT_select_more";
- ot->description = "Select control points directly linked to already selected ones";
-
- /* api callbacks */
- ot->exec = select_more_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/******************** select less operator *****************/
-
-/* basic method: deselect if control point doesn't have all neighbors selected */
-static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int a;
- int sel = 0;
- short lastsel = false;
-
- if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
- BLI_bitmap *selbpoints;
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- selbpoints = BLI_BITMAP_NEW(a, "selectlist");
- while (a--) {
- if ((bp->hide == 0) && (bp->f1 & SELECT)) {
- sel = 0;
-
- /* check if neighbors have been selected */
- /* edges of surface are an exception */
- if ((a + 1) % nu->pntsu == 0) {
- sel++;
- }
- else {
- bp--;
- if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
- bp++;
- }
-
- if ((a + 1) % nu->pntsu == 1) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp--;
- }
-
- if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
- sel++;
- }
- else {
- bp -= nu->pntsu;
- if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
- bp += nu->pntsu;
- }
-
- if (a < nu->pntsu) {
- sel++;
- }
- else {
- bp += nu->pntsu;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp -= nu->pntsu;
- }
-
- if (sel != 4) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- BLI_BITMAP_ENABLE(selbpoints, a);
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
-
- MEM_freeN(selbpoints);
- }
- }
- else {
- for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = false;
- /* check what type of curve/nurb it is */
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
- sel = (lastsel == 1);
-
- /* check if neighbors have been selected */
- /* first and last are exceptions */
- if (a == nu->pntsu - 1) {
- sel++;
- }
- else {
- bezt--;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
- bezt++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bezt++;
- if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
- bezt--;
- }
-
- if (sel != 2) {
- select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) {
- if (lastsel != 0) sel = 1;
- else sel = 0;
-
- /* first and last are exceptions */
- if (a == nu->pntsu * nu->pntsv - 1) {
- sel++;
- }
- else {
- bp--;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp++;
- }
-
- if (a == 0) {
- sel++;
- }
- else {
- bp++;
- if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
- bp--;
- }
-
- if (sel != 2) {
- select_bpoint(bp, DESELECT, SELECT, VISIBLE);
- lastsel = true;
- }
- else {
- lastsel = false;
- }
- }
- else {
- lastsel = false;
- }
-
- bp++;
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "CURVE_OT_select_less";
- ot->description = "Reduce current selection by deselecting boundary elements";
-
- /* api callbacks */
- ot->exec = select_less_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/********************** select random *********************/
-
-static void curve_select_random(ListBase *editnurb, float randfac, bool select)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (!bezt->hide) {
- if (BLI_frand() < randfac) {
- select_beztriple(bezt, select, SELECT, VISIBLE);
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- if (!bp->hide) {
- if (BLI_frand() < randfac) {
- select_bpoint(bp, select, SELECT, VISIBLE);
- }
- }
- bp++;
- }
- }
- }
-}
-
-static int curve_select_random_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
-
- curve_select_random(editnurb, randfac, select);
- BKE_curve_nurb_vert_active_validate(obedit->data);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_random(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Random";
- ot->idname = "CURVE_OT_select_random";
- ot->description = "Randomly select some control points";
-
- /* api callbacks */
- ot->exec = curve_select_random_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
-}
-
-/********************* every nth number of point *******************/
-
-static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset)
-{
- int a, start;
-
- start = bezt - nu->bezt;
- a = nu->pntsu;
- bezt = &nu->bezt[a - 1];
-
- while (a--) {
- const int depth = abs(start - a);
- if ((offset + depth) % (skip + nth) >= skip) {
- select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
- }
-
- bezt--;
- }
-}
-
-static void select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset)
-{
- int a, startrow, startpnt;
- int row, pnt;
-
- startrow = (bp - nu->bp) / nu->pntsu;
- startpnt = (bp - nu->bp) % nu->pntsu;
-
- a = nu->pntsu * nu->pntsv;
- bp = &nu->bp[a - 1];
- row = nu->pntsv - 1;
- pnt = nu->pntsu - 1;
-
- while (a--) {
- const int depth = abs(pnt - startpnt) + abs(row - startrow);
- if ((offset + depth) % (skip + nth) >= skip) {
- select_bpoint(bp, DESELECT, SELECT, HIDDEN);
- }
-
- pnt--;
- if (pnt < 0) {
- pnt = nu->pntsu - 1;
- row--;
- }
-
- bp--;
- }
-}
-
-bool ED_curve_select_nth(Curve *cu, int nth, int skip, int offset)
-{
- Nurb *nu = NULL;
- void *vert = NULL;
-
- if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
- return false;
-
- if (nu->bezt) {
- select_nth_bezt(nu, vert, nth, skip, offset);
- }
- else {
- select_nth_bp(nu, vert, nth, skip, offset);
- }
-
- return true;
-}
-
-static int select_nth_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- const int nth = RNA_int_get(op->ptr, "nth") - 1;
- const int skip = RNA_int_get(op->ptr, "skip");
- int offset = RNA_int_get(op->ptr, "offset");
-
- /* so input of offset zero ends up being (nth - 1) */
- offset = mod_i(offset, nth + skip);
-
- if (!ED_curve_select_nth(obedit->data, nth, skip, offset)) {
- if (obedit->type == OB_SURF) {
- BKE_report(op->reports, RPT_ERROR, "Surface has not got active point");
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Curve has not got active point");
- }
-
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void CURVE_OT_select_nth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Checker Deselect";
- ot->description = "Deselect every other vertex";
- ot->idname = "CURVE_OT_select_nth";
-
- /* api callbacks */
- ot->exec = select_nth_exec;
- ot->poll = ED_operator_editsurfcurve;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
- RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
- RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
-}
-
/********************** add duplicate operator *********************/
static int duplicate_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
new file mode 100644
index 00000000000..0a8c05ba16d
--- /dev/null
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -0,0 +1,1156 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/curve/editcurve_select.c
+ * \ingroup edcurve
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_view3d.h"
+#include "ED_curve.h"
+
+#include "curve_intern.h"
+
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+
+/* returns 1 in case (de)selection was successful */
+bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
+{
+ if ((bezt->hide == 0) || (hidden == HIDDEN)) {
+ if (selstatus == SELECT) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return true;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* returns 1 in case (de)selection was successful */
+bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
+{
+ if ((bp->hide == 0) || (hidden == 1)) {
+ if (selstatus == SELECT) {
+ bp->f1 |= flag;
+ return true;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool swap_selection_beztriple(BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ else
+ return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+}
+
+static bool swap_selection_bpoint(BPoint *bp)
+{
+ if (bp->f1 & SELECT)
+ return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ else
+ return select_bpoint(bp, SELECT, SELECT, VISIBLE);
+}
+
+
+void ED_curve_select_all(EditNurb *editnurb)
+{
+ Nurb *nu;
+ int a;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple *bezt;
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ bezt->f1 |= SELECT;
+ bezt->f2 |= SELECT;
+ bezt->f3 |= SELECT;
+ }
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp;
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (bp->hide == 0)
+ bp->f1 |= SELECT;
+ }
+ }
+ }
+}
+
+void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide == 0) {
+ bezt->f2 ^= SELECT; /* always do the center point */
+ if (!hide_handles) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ swap_selection_bpoint(bp);
+ bp++;
+ }
+ }
+ }
+}
+
+/**
+ * \param next: -1/1 for prev/next
+ * \param cont: when true select continuously
+ * \param selstatus: inverts behavior
+ */
+static void select_adjacent_cp(
+ ListBase *editnurb, short next,
+ const bool cont, const bool selstatus)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ bool lastsel = false;
+
+ if (next == 0) return;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ if (next < 0) bezt = &nu->bezt[a - 1];
+ while (a--) {
+ if (a - abs(next) < 0) break;
+ if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
+ bezt += next;
+ if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+ if ((sel == 1) && (cont == 0)) lastsel = true;
+ }
+ }
+ else {
+ bezt += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bezt -= (next - next / abs(next));
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ if (next < 0) bp = &nu->bp[a - 1];
+ while (a--) {
+ if (a - abs(next) < 0) break;
+ if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
+ bp += next;
+ if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+ if ((sel == 1) && (cont == 0)) lastsel = true;
+ }
+ }
+ else {
+ bp += next;
+ lastsel = false;
+ }
+ /* move around in zigzag way so that we go through each */
+ bp -= (next - next / abs(next));
+ }
+ }
+ }
+}
+
+/**************** select start/end operators **************/
+
+/* (de)selects first or last of visible part of each Nurb depending on selFirst
+ * selFirst: defines the end of which to select
+ * doswap: defines if selection state of each first/last control point is swapped
+ * selstatus: selection status in case doswap is false
+ */
+static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
+{
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ Curve *cu;
+ int a;
+
+ if (obedit == NULL) return;
+
+ cu = (Curve *)obedit->data;
+ cu->actvert = CU_ACT_NONE;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bezt = &nu->bezt[a - 1];
+ }
+ else { /* select first */
+ bezt = nu->bezt;
+ }
+
+ while (a--) {
+ bool sel;
+ if (doswap) sel = swap_selection_beztriple(bezt);
+ else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
+
+ if (sel == true) break;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+
+ /* which point? */
+ if (selfirst == LAST) { /* select last */
+ bp = &nu->bp[a - 1];
+ }
+ else { /* select first */
+ bp = nu->bp;
+ }
+
+ while (a--) {
+ if (bp->hide == 0) {
+ bool sel;
+ if (doswap) sel = swap_selection_bpoint(bp);
+ else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
+
+ if (sel == true) break;
+ }
+ }
+ }
+ }
+}
+
+static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, FIRST, true, DESELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_first(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select First";
+ ot->idname = "CURVE_OT_de_select_first";
+ ot->description = "(De)select first of visible part of each NURBS";
+
+ /* api cfirstbacks */
+ ot->exec = de_select_first_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+
+ selectend_nurb(obedit, LAST, true, DESELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_de_select_last(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select Last";
+ ot->idname = "CURVE_OT_de_select_last";
+ ot->description = "(De)select last of visible part of each NURBS";
+
+ /* api clastbacks */
+ ot->exec = de_select_last_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/******************* de select all operator ***************/
+
+static bool nurb_has_selected_cps(ListBase *editnurb)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (bezt->hide == 0) {
+ if ((bezt->f1 & SELECT) ||
+ (bezt->f2 & SELECT) ||
+ (bezt->f3 & SELECT))
+ {
+ return 1;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) return 1;
+ bp++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int de_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ if (nurb_has_selected_cps(editnurb))
+ action = SEL_DESELECT;
+ }
+
+ switch (action) {
+ case SEL_SELECT:
+ ED_curve_select_all(cu->editnurb);
+ break;
+ case SEL_DESELECT:
+ ED_curve_deselect_all(cu->editnurb);
+ break;
+ case SEL_INVERT:
+ ED_curve_select_swap(cu->editnurb, (cu->drawflag & CU_HIDE_HANDLES) != 0);
+ break;
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(cu);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "CURVE_OT_select_all";
+ ot->description = "(De)select all control points";
+
+ /* api callbacks */
+ ot->exec = de_select_all_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_select_all(ot);
+}
+
+
+
+/***************** select linked operator ******************/
+
+static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = (Curve *)obedit->data;
+ EditNurb *editnurb = cu->editnurb;
+ ListBase *nurbs = &editnurb->nurbs;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+ bezt++;
+ }
+ break;
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ bp++;
+ }
+ break;
+ }
+ bp++;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return select_linked_exec(C, op);
+}
+
+void CURVE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "CURVE_OT_select_linked";
+ ot->description = "Select all control points linked to active one";
+
+ /* api callbacks */
+ ot->exec = select_linked_exec;
+ ot->invoke = select_linked_invoke;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+}
+
+
+/***************** select linked pick operator ******************/
+
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ViewContext vc;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+
+ view3d_operator_needs_opengl(C);
+ view3d_set_viewcontext(C, &vc);
+
+ if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu, &bezt, &bp, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (bezt) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ bezt++;
+ }
+ }
+ else if (bp) {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ bp++;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ if (!select) {
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->idname = "CURVE_OT_select_linked_pick";
+ ot->description = "Select all control points linked to already selected ones";
+
+ /* api callbacks */
+ ot->invoke = select_linked_pick_invoke;
+ ot->poll = ED_operator_editsurfcurve_region_view3d;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them");
+}
+
+/***************** select row operator **********************/
+
+static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ static BPoint *last = NULL;
+ static int direction = 0;
+ Nurb *nu = NULL;
+ BPoint *bp = NULL;
+ int u = 0, v = 0, a, b;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
+ return OPERATOR_CANCELLED;
+
+ if (last == bp) {
+ direction = 1 - direction;
+ BKE_nurbList_flag_set(editnurb, 0);
+ }
+ last = bp;
+
+ u = cu->actvert % nu->pntsu;
+ v = cu->actvert / nu->pntsu;
+ bp = nu->bp;
+ for (a = 0; a < nu->pntsv; a++) {
+ for (b = 0; b < nu->pntsu; b++, bp++) {
+ if (direction) {
+ if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ else {
+ if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_row(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Control Point Row";
+ ot->idname = "CURVE_OT_select_row";
+ ot->description = "Select a row of control points including active one";
+
+ /* api callbacks */
+ ot->exec = select_row_exec;
+ ot->poll = ED_operator_editsurf;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select next operator **********************/
+
+static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_next(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Next";
+ ot->idname = "CURVE_OT_select_next";
+ ot->description = "Select control points following already selected ones along the curves";
+
+ /* api callbacks */
+ ot->exec = select_next_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select previous operator **********************/
+
+static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_previous(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Previous";
+ ot->idname = "CURVE_OT_select_previous";
+ ot->description = "Select control points preceding already selected ones along the curves";
+
+ /* api callbacks */
+ ot->exec = select_previous_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/***************** select more operator **********************/
+
+static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp, *tempbp;
+ int a;
+ short sel = 0;
+
+ /* note that NURBS surface is a special case because we mimic */
+ /* the behavior of "select more" of mesh tools. */
+ /* The algorithm is designed to work in planar cases so it */
+ /* may not be optimal always (example: end of NURBS sphere) */
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a > 0) {
+ if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ /* upper control point */
+ if (a % nu->pntsu != 0) {
+ tempbp = bp - 1;
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+
+ /* left control point. select only if it is not selected already */
+ if (a - nu->pntsu > 0) {
+ sel = 0;
+ tempbp = bp + nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ /* make sure selected bpoint is discarded */
+ if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
+ }
+
+ /* right control point */
+ if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
+ tempbp = bp - nu->pntsu;
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ }
+
+ /* lower control point. skip next bp in case selection was made */
+ if (a % nu->pntsu != 1) {
+ sel = 0;
+ tempbp = bp + 1;
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
+ if (sel) {
+ bp++;
+ a--;
+ }
+ }
+ }
+
+ bp++;
+ a--;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ select_adjacent_cp(editnurb, 1, 0, SELECT);
+ select_adjacent_cp(editnurb, -1, 0, SELECT);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "CURVE_OT_select_more";
+ ot->description = "Select control points directly linked to already selected ones";
+
+ /* api callbacks */
+ ot->exec = select_more_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/******************** select less operator *****************/
+
+/* basic method: deselect if control point doesn't have all neighbors selected */
+static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int a;
+ int sel = 0;
+ short lastsel = false;
+
+ if (obedit->type == OB_SURF) {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ BLI_bitmap *selbpoints;
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ selbpoints = BLI_BITMAP_NEW(a, "selectlist");
+ while (a--) {
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) {
+ sel = 0;
+
+ /* check if neighbors have been selected */
+ /* edges of surface are an exception */
+ if ((a + 1) % nu->pntsu == 0) {
+ sel++;
+ }
+ else {
+ bp--;
+ if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
+ bp++;
+ }
+
+ if ((a + 1) % nu->pntsu == 1) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp -= nu->pntsu;
+ if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
+ bp += nu->pntsu;
+ }
+
+ if (a < nu->pntsu) {
+ sel++;
+ }
+ else {
+ bp += nu->pntsu;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp -= nu->pntsu;
+ }
+
+ if (sel != 4) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ BLI_BITMAP_ENABLE(selbpoints, a);
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+
+ MEM_freeN(selbpoints);
+ }
+ }
+ else {
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ lastsel = false;
+ /* check what type of curve/nurb it is */
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
+ sel = (lastsel == 1);
+
+ /* check if neighbors have been selected */
+ /* first and last are exceptions */
+ if (a == nu->pntsu - 1) {
+ sel++;
+ }
+ else {
+ bezt--;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
+ bezt++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bezt++;
+ if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
+ bezt--;
+ }
+
+ if (sel != 2) {
+ select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) {
+ if (lastsel != 0) sel = 1;
+ else sel = 0;
+
+ /* first and last are exceptions */
+ if (a == nu->pntsu * nu->pntsv - 1) {
+ sel++;
+ }
+ else {
+ bp--;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp++;
+ }
+
+ if (a == 0) {
+ sel++;
+ }
+ else {
+ bp++;
+ if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
+ bp--;
+ }
+
+ if (sel != 2) {
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
+ }
+ }
+ else {
+ lastsel = false;
+ }
+
+ bp++;
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "CURVE_OT_select_less";
+ ot->description = "Reduce current selection by deselecting boundary elements";
+
+ /* api callbacks */
+ ot->exec = select_less_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** select random *********************/
+
+static void curve_select_random(ListBase *editnurb, float randfac, bool select)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (!bezt->hide) {
+ if (BLI_frand() < randfac) {
+ select_beztriple(bezt, select, SELECT, VISIBLE);
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ if (!bp->hide) {
+ if (BLI_frand() < randfac) {
+ select_bpoint(bp, select, SELECT, VISIBLE);
+ }
+ }
+ bp++;
+ }
+ }
+ }
+}
+
+static int curve_select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+
+ curve_select_random(editnurb, randfac, select);
+ BKE_curve_nurb_vert_active_validate(obedit->data);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->idname = "CURVE_OT_select_random";
+ ot->description = "Randomly select some control points";
+
+ /* api callbacks */
+ ot->exec = curve_select_random_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
+ "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
+ WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+}
+
+/********************* every nth number of point *******************/
+
+static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset)
+{
+ int a, start;
+
+ start = bezt - nu->bezt;
+ a = nu->pntsu;
+ bezt = &nu->bezt[a - 1];
+
+ while (a--) {
+ const int depth = abs(start - a);
+ if ((offset + depth) % (skip + nth) >= skip) {
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
+ }
+
+ bezt--;
+ }
+}
+
+static void select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset)
+{
+ int a, startrow, startpnt;
+ int row, pnt;
+
+ startrow = (bp - nu->bp) / nu->pntsu;
+ startpnt = (bp - nu->bp) % nu->pntsu;
+
+ a = nu->pntsu * nu->pntsv;
+ bp = &nu->bp[a - 1];
+ row = nu->pntsv - 1;
+ pnt = nu->pntsu - 1;
+
+ while (a--) {
+ const int depth = abs(pnt - startpnt) + abs(row - startrow);
+ if ((offset + depth) % (skip + nth) >= skip) {
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
+ }
+
+ pnt--;
+ if (pnt < 0) {
+ pnt = nu->pntsu - 1;
+ row--;
+ }
+
+ bp--;
+ }
+}
+
+bool ED_curve_select_nth(Curve *cu, int nth, int skip, int offset)
+{
+ Nurb *nu = NULL;
+ void *vert = NULL;
+
+ if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert))
+ return false;
+
+ if (nu->bezt) {
+ select_nth_bezt(nu, vert, nth, skip, offset);
+ }
+ else {
+ select_nth_bp(nu, vert, nth, skip, offset);
+ }
+
+ return true;
+}
+
+static int select_nth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ const int nth = RNA_int_get(op->ptr, "nth") - 1;
+ const int skip = RNA_int_get(op->ptr, "skip");
+ int offset = RNA_int_get(op->ptr, "offset");
+
+ /* so input of offset zero ends up being (nth - 1) */
+ offset = mod_i(offset, nth + skip);
+
+ if (!ED_curve_select_nth(obedit->data, nth, skip, offset)) {
+ if (obedit->type == OB_SURF) {
+ BKE_report(op->reports, RPT_ERROR, "Surface has not got active point");
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Curve has not got active point");
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_select_nth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Checker Deselect";
+ ot->description = "Deselect every other vertex";
+ ot->idname = "CURVE_OT_select_nth";
+
+ /* api callbacks */
+ ot->exec = select_nth_exec;
+ ot->poll = ED_operator_editsurfcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
+ RNA_def_int(ot->srna, "skip", 1, 1, INT_MAX, "Skip", "", 1, 100);
+ RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
+}
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index fee3d44b8eb..1718fe691d7 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -48,11 +48,6 @@ void ED_operatormacros_curve(void);
void ED_keymap_curve(struct wmKeyConfig *keyconf);
/* editcurve.c */
-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);
ListBase *object_editcurve_get(struct Object *ob);
@@ -68,6 +63,12 @@ int isNurbsel(struct Nurb *nu);
int join_curve_exec(struct bContext *C, struct wmOperator *op);
+/* editcurve_select.c */
+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);
+bool ED_curve_select_nth(struct Curve *cu, int nth, int skip, int offset);
+
/* editfont.h */
void undo_push_font(struct bContext *C, const char *name);
void make_editText(struct Object *obedit);
@@ -76,8 +77,6 @@ void free_editText(struct Object *obedit);
void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines);
-bool ED_curve_select_nth(struct Curve *cu, int nth, int skip, int offset);
-
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);