diff options
author | Juho Vepsalainen <bebraw@gmail.com> | 2007-06-14 18:36:27 +0400 |
---|---|---|
committer | Juho Vepsalainen <bebraw@gmail.com> | 2007-06-14 18:36:27 +0400 |
commit | a499da719217a3009a7014203a91f914742da74a (patch) | |
tree | 14709a1d36e451f168d2f993323b4671d3a39387 /source/blender | |
parent | 0ed2e0e706de6aa322807602599528c207157666 (diff) |
Curve Selection Tool Refactor:
This commit refactors curve selection system to use certain curve selections
functions that encapsulate setting of selection flags. New function to select
adjacent control points was introduced too. Refactoring made it possible to
simplify certain existing selection functions quite a bit.
New functionality was delivered as well. Select more/less works now with NURBS
as expected. Also two new curve selection functions were added: Select Every Nth
and Select Random.
See http://wiki.blender.org/index.php/BlenderDev/Curve_Selection_Tools for
further information.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_curve.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 15 | ||||
-rw-r--r-- | source/blender/include/BDR_editcurve.h | 5 | ||||
-rw-r--r-- | source/blender/include/blendef.h | 5 | ||||
-rw-r--r-- | source/blender/src/editcurve.c | 887 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 14 | ||||
-rw-r--r-- | source/blender/src/space.c | 4 | ||||
-rw-r--r-- | source/blender/src/toolbox.c | 4 |
8 files changed, 503 insertions, 432 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 19c3c620419..ee63f678505 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -55,6 +55,7 @@ short curve_type( struct Curve *cu); void test_curve_type( struct Object *ob); void tex_space_curve( struct Curve *cu); int count_curveverts( struct ListBase *nurb); +int count_curveverts_without_handles( struct ListBase *nurb); void freeNurb( struct Nurb *nu); void freeNurblist( struct ListBase *lb); struct Nurb *duplicateNurb( struct Nurb *nu); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 142bedadc93..769c31ad8a9 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -324,7 +324,20 @@ int count_curveverts(ListBase *nurb) return tot; } - +int count_curveverts_without_handles(ListBase *nurb) +{ + Nurb *nu; + int tot=0; + + nu= nurb->first; + while(nu) { + if(nu->bezt) tot+= nu->pntsu; + else if(nu->bp) tot+= nu->pntsu*nu->pntsv; + + nu= nu->next; + } + return tot; +} /* **************** NURBS ROUTINES ******************** */ diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h index a6319f2333c..a8c36c3485b 100644 --- a/source/blender/include/BDR_editcurve.h +++ b/source/blender/include/BDR_editcurve.h @@ -78,11 +78,13 @@ void extrude_nurb(void); void makecyclicNurb(void); void selectconnected_nurb(void); void selectrow_nurb(void); -void selectends_nurb(int selFirst); +void selectend_nurb(short selfirst, short doswap, short selstatus); void select_more_nurb(void); void select_less_nurb(void); void select_next_nurb(void); void select_prev_nurb(void); +void select_random_nurb(void); +void select_every_nth_nurb(void); void adduplicate_nurb(void); void delNurb(void); void nurb_set_smooth(short event); @@ -98,4 +100,3 @@ int bezt_compare (const void *e1, const void *e2); extern void undo_push_curve(char *name); #endif /* BDR_EDITCURVE_H */ - diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 44833b66576..0b05d635593 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -87,13 +87,16 @@ #endif #define SELECT 1 +#define HIDDEN 1 +#define FIRST 1 #define ACTIVE 2 /*#ifdef WITH_VERSE*/ #define VERSE 3 /*#endif*/ #define DESELECT 0 #define NOT_YET 0 - +#define VISIBLE 0 +#define LAST 0 #define TESTBASE(base) ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) #define TESTBASELIB(base) ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index e4cd813f9cd..31083d860fc 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -50,6 +50,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_dynstr.h" +#include "BLI_rand.h" #include "DNA_curve_types.h" #include "DNA_ipo_types.h" @@ -111,6 +112,66 @@ float nurbcircle[8][2]= { {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0} }; +/* ******************* SELECTION FUNCTIONS ********************* */ + +/* returns 1 in case (de)selection was successful */ +static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden) +{ + if(bezt) { + if((bezt->hide==0) || (hidden==1)) { + if(selstatus==1) { /* selects */ + bezt->f1 |= flag; + bezt->f2 |= flag; + bezt->f3 |= flag; + return 1; + } + else { /* deselects */ + bezt->f1 &= ~flag; + bezt->f2 &= ~flag; + bezt->f3 &= ~flag; + return 1; + } + } + } + + return 0; +} + +/* returns 1 in case (de)selection was successful */ +static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden) +{ + if(bp) { + if((bp->hide==0) || (hidden==1)) { + if(selstatus==1) { + bp->f1 |= flag; + return 1; + } + else { + bp->f1 &= ~flag; + return 1; + } + } + } + + return 0; +} + +static short swap_selection_beztriple(BezTriple *bezt) +{ + if(bezt->f2 & 1) + return select_beztriple(bezt, DESELECT, 1, VISIBLE); + else + return select_beztriple(bezt, SELECT, 1, VISIBLE); +} + +static short swap_selection_bpoint(BPoint *bp) +{ + if(bp->f1 & 1) + return select_bpoint(bp, DESELECT, 1, VISIBLE); + else + return select_bpoint(bp, SELECT, 1, VISIBLE); +} + short isNurbsel(Nurb *nu) { BezTriple *bezt; @@ -161,6 +222,7 @@ int isNurbsel_count(Nurb *nu) return sel; } +/* ******************* PRINTS ********************* */ void printknots() { @@ -703,8 +765,8 @@ short extrudeflagNurb(int flag) nu->bp= newbp; a= nu->pntsu; while(a--) { - bp->f1 |= flag; - newbp->f1 &= ~flag; + select_bpoint(bp, SELECT, flag, HIDDEN); + select_bpoint(newbp, DESELECT, flag, HIDDEN); bp++; newbp++; } @@ -723,7 +785,7 @@ short extrudeflagNurb(int flag) bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - bp->f1 &= ~flag; + select_bpoint(bp, DESELECT, flag, HIDDEN); bp++; } @@ -747,7 +809,7 @@ short extrudeflagNurb(int flag) a= nu->pntsu; while(a--) { - bp->f1 |= flag; + select_bpoint(bp, SELECT, flag, HIDDEN); bp++; } @@ -793,7 +855,6 @@ short extrudeflagNurb(int flag) return ok; } - void adduplicateflagNurb(short flag) { Nurb *nu, *newnu; @@ -810,9 +871,7 @@ void adduplicateflagNurb(short flag) enda= -1; starta= a; while( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) { - bezt->f1 &= ~flag; - bezt->f2 &= ~flag; - bezt->f3 &= ~flag; + select_beztriple(bezt, DESELECT, flag, HIDDEN); enda=a; if(a>=nu->pntsu-1) break; a++; @@ -831,9 +890,7 @@ void adduplicateflagNurb(short flag) b= newnu->pntsu; bezt1= newnu->bezt; while(b--) { - bezt1->f1 |= flag; - bezt1->f2 |= flag; - bezt1->f3 |= flag; + select_beztriple(bezt1, SELECT, flag, HIDDEN); bezt1++; } @@ -850,7 +907,7 @@ void adduplicateflagNurb(short flag) enda= -1; starta= a; while(bp->f1 & flag) { - bp->f1 &= ~flag; + select_bpoint(bp, DESELECT, flag, HIDDEN); enda= a; if(a>=nu->pntsu-1) break; a++; @@ -868,7 +925,7 @@ void adduplicateflagNurb(short flag) b= newnu->pntsu; bp1= newnu->bp; while(b--) { - bp1->f1 |= flag; + select_bpoint(bp1, SELECT, flag, HIDDEN); bp1++; } @@ -931,7 +988,7 @@ void adduplicateflagNurb(short flag) for(b=0; b<nu->pntsu; b++, bp1++) { if(bp1->f1 & flag) { memcpy(bp, bp1, sizeof(BPoint)); - bp1->f1 &= ~flag; + select_bpoint(bp1, DESELECT, flag, HIDDEN); bp++; } } @@ -1026,87 +1083,116 @@ void switchdirection_knots(float *base, int tot) /* **************** EDIT ************************ */ -void deselectall_nurb() +/* next == 1 -> select next */ +/* next == -1 -> select previous */ +/* cont == 1 -> select continuously */ +/* selstatus, inverts behaviour */ +static void select_adjacent_cp(short next, short cont, short selstatus) { Nurb *nu; BezTriple *bezt; BPoint *bp; - int a, b; - - if(!G.vd || !(G.obedit->lay & G.vd->lay)) - return; - - a= 0; + int a; + short lastsel= 0, sel=0; + + if(next==0) return; + for(nu= editNurb.first; nu; nu= nu->next) { - if((nu->type & 7)==CU_BEZIER) { - b= nu->pntsu; + lastsel=0; + if((nu->type & 7)==CU_BEZIER) { + a= nu->pntsu; bezt= nu->bezt; - while(b--) { - if(bezt->hide==0) { - if(bezt->f1 & 1) { - a=1; - break; - } - if(bezt->f2 & 1) { - a=1; - break; - } - if(bezt->f3 & 1) { - a=1; - break; - } + if(next < 0) bezt= (nu->bezt + (a-1)); + while(a--) { + if(a-abs(next) < 0) break; + sel= 0; + if((lastsel==0) && (bezt->hide==0) && ((bezt->f2 & 1) || (selstatus==0))) { + bezt+=next; + if(!(bezt->f2 & 1) || (selstatus==0)) { + sel= select_beztriple(bezt, selstatus, 1, VISIBLE); + if((sel==1) && (cont==0)) lastsel= 1; + } } - bezt++; + else { + bezt+=next; + lastsel= 0; + } + /* move around in zigzag way so that we go through each */ + bezt-=(next-next/abs(next)); } } else { - b= nu->pntsu*nu->pntsv; + a= nu->pntsu*nu->pntsv; bp= nu->bp; - while(b--) { - if(bp->hide==0) { - if(bp->f1 & 1) { - a=1; - break; - } + if(next < 0) bp= (nu->bp + (a-1)); + while(a--) { + if(a-abs(next) < 0) break; + sel=0; + if((lastsel==0) && (bp->hide==0) && ((bp->f1 & 1) || (selstatus==0))) { + bp+=next; + if(!(bp->f1 & 1) || (selstatus==0)) { + sel= select_bpoint(bp, selstatus, 1, VISIBLE); + if((sel==1) && (cont==0)) lastsel= 1; + } } - bp++; + else { + bp+=next; + lastsel= 0; + } + /* move around in zigzag way so that we go through each */ + bp-=(next-next/abs(next)); } } - if(a) break; } +} + +static short nurb_has_selected_cps() +{ + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; for(nu= editNurb.first; nu; nu= nu->next) { - if((nu->type & 7)==1) { - b= nu->pntsu; + if((nu->type & 7)==CU_BEZIER) { + a= nu->pntsu; bezt= nu->bezt; - while(b--) { + while(a--) { if(bezt->hide==0) { - if(a) { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; - } - else { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; - } + if((bezt->f1 & 1) + || (bezt->f2 & 1) + || (bezt->f3 & 1)) return 1; } bezt++; } } else { - b= nu->pntsu*nu->pntsv; + a= nu->pntsu*nu->pntsv; bp= nu->bp; - while(b--) { - if(bp->hide==0) { - if(a) bp->f1 &= ~ 1; - else bp->f1 |= 1; - } + while(a--) { + if((bp->hide==0) && (bp->f1 & 1)) return 1; bp++; } } } + + return 0; +} + +void deselectall_nurb() +{ + if(!G.vd || !(G.obedit->lay & G.vd->lay)) + return; + + if(nurb_has_selected_cps()) { /* deselect all */ + selectend_nurb(FIRST, 0, DESELECT); /* set first control points as unselected */ + select_adjacent_cp(1, 1, DESELECT); /* cascade selection */ + } + else { /* select all */ + selectend_nurb(FIRST, 0, SELECT); /* set first control points as selected */ + select_adjacent_cp(1, 1, SELECT); /* cascade selection */ + } + countall(); allqueue(REDRAWVIEW3D, 0); BIF_undo_push("Deselect all"); @@ -1130,9 +1216,7 @@ void hideNurb(int swap) sel= 0; while(a--) { if(BEZSELECTED(bezt)) { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; + select_beztriple(bezt, DESELECT, 1, HIDDEN); bezt->hide= 1; } if(bezt->hide) sel++; @@ -1146,11 +1230,11 @@ void hideNurb(int swap) sel= 0; while(a--) { if(swap==0 && (bp->f1 & 1)) { - bp->f1 &= ~1; + select_bpoint(bp, DESELECT, 1, HIDDEN); bp->hide= 1; } else if(swap && (bp->f1 & 1)==0) { - bp->f1 &= ~1; + select_bpoint(bp, DESELECT, 1, HIDDEN); bp->hide= 1; } if(bp->hide) sel++; @@ -1182,9 +1266,7 @@ void revealNurb() a= nu->pntsu; while(a--) { if(bezt->hide) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + select_beztriple(bezt, SELECT, 1, HIDDEN); bezt->hide= 0; } bezt++; @@ -1195,7 +1277,7 @@ void revealNurb() a= nu->pntsu*nu->pntsv; while(a--) { if(bp->hide) { - bp->f1 |= 1; + select_bpoint(bp, SELECT, 1, HIDDEN); bp->hide= 0; } bp++; @@ -1239,10 +1321,7 @@ void selectswapNurb() bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { - if(bp->hide==0) { - if(bp->f1 & 1) bp->f1 &= ~1; - else bp->f1 |= 1; - } + swap_selection_bpoint(bp); bp++; } } @@ -2127,7 +2206,7 @@ void merge_2_nurb(Nurb *nu1, Nurb *nu2) for(u=0; u<nu1->pntsu; u++, bp++) { if(u<origu) { *bp= *bp1; bp1++; - bp->f1 &= ~SELECT; + select_bpoint(bp, SELECT, 1, HIDDEN); } else { *bp= *bp2; bp2++; @@ -2377,17 +2456,13 @@ void mouse_nurb() if(bezt) { - if(hand==1) { - bezt->f1|= 1; - bezt->f2|= 1; - bezt->f3|= 1; - } + if(hand==1) select_beztriple(bezt, SELECT, 1, HIDDEN); else if(hand==0) bezt->f1|= 1; else bezt->f3|= 1; } else { lastselbp= bp; - bp->f1 |= 1; + select_bpoint(bp, SELECT, 1, HIDDEN); } allqueue(REDRAWVIEW3D, 0); @@ -2395,16 +2470,8 @@ void mouse_nurb() else { if(bezt) { if(hand==1) { - if(bezt->f2 & 1) { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; - } - else { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; - } + if(bezt->f2 & 1) select_beztriple(bezt, DESELECT, 1, HIDDEN); + else select_beztriple(bezt, SELECT, 1, HIDDEN); } else if(hand==0) { if(bezt->f1 & 1) { @@ -2424,9 +2491,9 @@ void mouse_nurb() } } else { - if(bp->f1 & 1) bp->f1 &= ~1; + if(bp->f1 & 1) select_bpoint(bp, DESELECT, 1, HIDDEN); else { - bp->f1 |= 1; + select_bpoint(bp, SELECT, 1, HIDDEN); lastselbp= bp; } } @@ -2841,18 +2908,8 @@ void selectconnected_nurb() a= nu->pntsu; bezt= nu->bezt; while(a--) { - if(bezt->hide==0) { - if(G.qual & LR_SHIFTKEY) { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; - } - else { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; - } - } + if(G.qual & LR_SHIFTKEY) select_beztriple(bezt, DESELECT, 1, VISIBLE); + else select_beztriple(bezt, SELECT, 1, VISIBLE); bezt++; } } @@ -2860,14 +2917,8 @@ void selectconnected_nurb() a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { - if(bp->hide==0) { - if(G.qual & LR_SHIFTKEY) { - bp->f1 &= ~1; - } - else { - bp->f1 |= 1; - } - } + if(G.qual & LR_SHIFTKEY) select_bpoint(bp, DESELECT, 1, VISIBLE); + else select_bpoint(bp, SELECT, 1, VISIBLE); bp++; } } @@ -2915,10 +2966,10 @@ void selectrow_nurb() for(a=0; a<nu->pntsv; a++) { for(b=0; b<nu->pntsu; b++, bp++) { if(direction) { - if(a==v) if(bp->hide==0) bp->f1 |= 1; + if(a==v) select_bpoint(bp, SELECT, 1, VISIBLE); } else { - if(b==u) if(bp->hide==0) bp->f1 |= 1; + if(b==u) select_bpoint(bp, SELECT, 1, VISIBLE); } } } @@ -2931,56 +2982,58 @@ void selectrow_nurb() } -void selectends_nurb(int selFirst) +/* (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(short selfirst, short doswap, short selstatus) { Nurb *nu; BPoint *bp; BezTriple *bezt; int a; + short sel; if(G.obedit==0) return; for(nu= editNurb.first; nu; nu= nu->next) { + sel= 0; if((nu->type & 7)==CU_BEZIER) { a= nu->pntsu; /* which point? */ - if (selFirst==0) /* select last */ + if(selfirst==0) { /* select last */ bezt= (nu->bezt + (a-1)); - else /* select first */ + } + else { /* select first */ bezt= nu->bezt; + } - if (bezt->hide == 0) { - /* check if anything is selected */ - if (bezt->f1 & 1 || bezt->f2 & 1 || bezt->f3 & 1) { - /* deselct all handles */ - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; - } - else { - /* just select all handles */ - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; - } + while(a--) { + if(doswap) sel= swap_selection_beztriple(bezt); + else sel= select_beztriple(bezt, selstatus, 1, VISIBLE); + + if(sel==1) break; } } else { - /* ummm... doesn't really make sense, but... */ a= nu->pntsu*nu->pntsv; /* which point? */ - if (selFirst==0) /* select last */ + if(selfirst==0) { /* select last */ bp= (nu->bp + (a-1)); - else /* select first */ + } + else{ /* select first */ bp= nu->bp; - - if (bp->hide == 0) { - if (bp->f1 & 1) /* deselect */ - bp->f1 &= ~1; - else /* select */ - bp->f1 |= 1; + } + + while(a--) { + if (bp->hide == 0) { + if(doswap) sel= swap_selection_bpoint(bp); + else sel= select_bpoint(bp, selstatus, 1, VISIBLE); + + if(sel==1) break; + } } } } @@ -2992,60 +3045,9 @@ void selectends_nurb(int selFirst) void select_next_nurb() { - Nurb *nu; - BezTriple *bezt; - int *selectFlags; /* array of ints defining selection status */ - int totCount=0, totSel=0, totChange=0; - int i=0; - if(G.obedit==0) return; - for(nu= editNurb.first; nu; nu= nu->next) { - /* check what type of curve/nurb it is */ - if((nu->type & 7)==CU_BEZIER) { - totCount= nu->pntsu; - selectFlags= MEM_callocN(sizeof(int)*totCount, "selectlist"); - - /* find out which beztriples are selected */ - for (i=0; i<totCount; i++) { - bezt= (nu->bezt + i); - selectFlags[i]= BEZSELECTED(bezt); - if (selectFlags[i]) totSel++; - } - - /* check if anything is selected at all */ - if (totSel==0) { - MEM_freeN(selectFlags); - continue; - } - - /* find out which ones deserve an extra flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 1) { - if (((i+1) < totCount) && (selectFlags[i+1] == 0)) { - selectFlags[i+1]= 2; - totChange++; - } - } - } - - /* set select flags based on select flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 2) { - bezt = (nu->bezt + i); - - if (bezt->hide == 0) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; - } - } - } - - /* free tempolary array */ - MEM_freeN(selectFlags); - } - } + select_adjacent_cp(1, 0, SELECT); countall(); allqueue(REDRAWVIEW3D, 0); @@ -3054,281 +3056,326 @@ void select_next_nurb() void select_prev_nurb() { - Nurb *nu; - BezTriple *bezt; - int *selectFlags; /* array of ints defining selection status */ - int totCount=0, totSel=0, totChange=0; - int i=0; + if(G.obedit==0) return; + + select_adjacent_cp(-1, 0, SELECT); + + countall(); + allqueue(REDRAWVIEW3D, 0); + BIF_undo_push("Select Previous"); +} +void select_more_nurb() +{ + Nurb *nu; + BPoint *bp, *tempbp; + int a; + short sel= 0; + short *selbpoints; + if(G.obedit==0) return; - for(nu= editNurb.first; nu; nu= nu->next) { - /* check what type of curve/nurb it is */ - if((nu->type & 7)==CU_BEZIER) { - totCount= nu->pntsu; - selectFlags= MEM_callocN(sizeof(int)*totCount, "selectlist"); - - /* find out which beztriples are selected */ - for (i=0; i<totCount; i++) { - bezt= (nu->bezt + i); - selectFlags[i]= BEZSELECTED(bezt); - if (selectFlags[i]) totSel++; - } - - /* check if anything is selected at all */ - if (totSel==0) { - MEM_freeN(selectFlags); - continue; - } - - /* find out which ones deserve an extra flag */ - for (i= totCount-1; i>=0; i--) { - if (selectFlags[i] == 1) { - if (((i-1) >= 0) && (selectFlags[i-1] == 0)) { - selectFlags[i-1]= 2; - totChange++; + /* note that NURBS surface is a special case because we mimic */ + /* the behaviour 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(G.obedit->type==OB_SURF) { + for(nu= editNurb.first; nu; nu= nu->next) { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + selbpoints= MEM_callocN(sizeof(short)*a-nu->pntsu, "selectlist"); + while(a > 0) { + if((selbpoints[a]!=1) && (bp->hide==0) && (bp->f1 & 1)) { + /* upper control point */ + if(a%nu->pntsu != 0) { + tempbp= bp-1; + if(!(tempbp->f1 & 1)) select_bpoint(tempbp, SELECT, 1, 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 & 1)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); + /* make sure selected bpoint is discarded */ + if(sel == 1) selbpoints[a-nu->pntsu]= 1; } - } - } - - /* set select flags based on select flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 2) { - bezt = (nu->bezt + i); - if (bezt->hide == 0) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + /* right control point */ + if(a+nu->pntsu < nu->pntsu*nu->pntsv) { + tempbp= bp-nu->pntsu; + if(!(tempbp->f1 & 1)) select_bpoint(tempbp, SELECT, 1, 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 & 1)) sel= select_bpoint(tempbp, SELECT, 1, VISIBLE); + if(sel) { + bp++; + a--; + } + } } + + bp++; + a--; } - /* free tempolary array */ - MEM_freeN(selectFlags); + MEM_freeN(selbpoints); } } - + else { + select_adjacent_cp(1, 0, SELECT); + select_adjacent_cp(-1, 0, SELECT); + } + countall(); allqueue(REDRAWVIEW3D, 0); - BIF_undo_push("Select Previous"); + BIF_undo_push("Select More"); } -void select_more_nurb() +/* basic method: deselect if control point doesn't have all neighbours selected */ +void select_less_nurb() { Nurb *nu; - BezTriple *bezt; BPoint *bp; - int *selectFlags; /* array of ints defining selection status */ - int totCount=0, totSel=0, totChange=0, totU=0, totV=0; - int i=0, n=0, x=0; + BezTriple *bezt; + int a; + short sel= 0, lastsel= 0; + short *selbpoints; if(G.obedit==0) return; - for(nu= editNurb.first; nu; nu= nu->next) { - /* check what type of curve/nurb it is */ - if((nu->type & 7)==CU_BEZIER) { - totCount= nu->pntsu; - selectFlags= MEM_callocN(sizeof(int)*totCount, "selectlist"); - - /* find out which beztriples are selected */ - for (i=0; i<totCount; i++) { - bezt= (nu->bezt + i); - selectFlags[i]= BEZSELECTED(bezt); - if (selectFlags[i]) totSel++; - } - - /* check if anything is selected at all */ - if (totSel==0) { - MEM_freeN(selectFlags); - continue; - } - - /* find out which ones deserve an extra flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 1) { - if ((totCount > (i+1)) && (selectFlags[i+1] == 0)) { - selectFlags[i+1] = 2; - totChange++; + if(G.obedit->type==OB_SURF) { + for(nu= editNurb.first; nu; nu= nu->next) { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + selbpoints= MEM_callocN(sizeof(short)*a, "selectlist"); + while(a--) { + if((bp->hide==0) && (bp->f1 & 1)) { + sel= 0; + + /* check if neighbours have been selected */ + /* edges of surface are an exception */ + if((a+1)%nu->pntsu==0) sel++; + else { + bp--; + if((selbpoints[a+1]==1) || ((bp->hide==0) && (bp->f1 & 1))) sel++; + bp++; } - } - else { - if ((totCount > (i+1)) && (selectFlags[i+1] == 1)) { - selectFlags[i] = 2; - totChange++; + + if((a+1)%nu->pntsu==1) sel++; + else { + bp++; + if((bp->hide==0) && (bp->f1 & 1)) sel++; + bp--; } - } - } - - /* set select flags based on select flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 2) { - bezt = (nu->bezt + i); - if (bezt->hide == 0) { - bezt->f1 |= 1; - bezt->f2 |= 1; - bezt->f3 |= 1; + if(a+1 > nu->pntsu*nu->pntsv-nu->pntsu) sel++; + else { + bp-=nu->pntsu; + if((selbpoints[a+nu->pntsu]==1) || ((bp->hide==0) && (bp->f1 & 1))) sel++; + bp+=nu->pntsu; } + + if(a < nu->pntsu) sel++; + else { + bp+=nu->pntsu; + if((bp->hide==0) && (bp->f1 & 1)) sel++; + bp-=nu->pntsu; + } + + if(sel!=4) { + select_bpoint(bp, DESELECT, 1, VISIBLE); + selbpoints[a]= 1; + } } + else lastsel= 0; + + bp++; } - /* free tempolary array */ - MEM_freeN(selectFlags); + MEM_freeN(selbpoints); } - else { - totCount= nu->pntsu*nu->pntsv; - totU= nu->pntsu; - totV= nu->pntsv; - selectFlags= MEM_callocN(sizeof(int)*totCount, "selectlist"); - - /* find out which bpoints are selected */ - for (i=0; i<totCount; i++) { - bp = (nu->bp + i); - selectFlags[i]= (bp->f1 & 1); - if (selectFlags[i]) totSel++; - } - - /* check if anything selected */ - if (totSel==0) continue; - - /* find out which ones deserve an extra flag */ - /* FIXME: why the heck does this go wrong? */ - for (i=0; i<totV; i++) { - /* search column */ - for (n=0; n<totU; n++) { - x = ((i * totU) + n); - - if (selectFlags[i] == 1) { - if ((totU > (n+1)) && (selectFlags[x+1] == 0)) - selectFlags[x+1] = 2; - } - else { - if ((totU > (n+1)) && (selectFlags[x+1] == 1)) - selectFlags[i] = 2; + } + else { + for(nu= editNurb.first; nu; nu= nu->next) { + lastsel=0; + /* check what type of curve/nurb it is */ + if((nu->type & 7)==CU_BEZIER) { + a= nu->pntsu; + bezt= nu->bezt; + while(a--) { + if((bezt->hide==0) && (bezt->f2 & 1)) { + if(lastsel==1) sel= 1; + else sel= 0; + + /* check if neighbours have been selected */ + /* first and last are exceptions */ + if(a==nu->pntsu-1) sel++; + else { + bezt--; + if((bezt->hide==0) && (bezt->f2 & 1)) sel++; + bezt++; + } + + if(a==0) sel++; + else { + bezt++; + if((bezt->hide==0) && (bezt->f2 & 1)) sel++; + bezt--; + } + + if(sel!=2) { + select_beztriple(bezt, DESELECT, 1, VISIBLE); + lastsel= 1; + } + else lastsel= 0; } + else lastsel= 0; + + bezt++; } - - /* search row */ - /* - if (selectFlags[(i*totU)] == 1) { - if ((totV > (i+1)) && (selectFlags[((i+1)*totU)] == 0)) - selectFlags[((i+1)*totU)] = 2; - } - else { - if ((totV > (i+1)) && (selectFlags[((i+1)*totU)] == 1)) - selectFlags[(i*totU)] = 2; - } */ } - - /* set select flags based on select flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 2) { - bp = (nu->bp + i); - if (bp->hide == 0) bp->f1 |= 1; + else { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + while(a--) { + if((lastsel==0) && (bp->hide==0) && (bp->f1 & 1)) { + 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 & 1)) sel++; + bp++; + } + + if(a==0) sel++; + else { + bp++; + if((bp->hide==0) && (bp->f1 & 1)) sel++; + bp--; + } + + if(sel!=2) { + select_bpoint(bp, DESELECT, 1, VISIBLE); + lastsel= 1; + } + else lastsel= 0; + } + else lastsel= 0; + + bp++; } } - - /* free tempolary array */ - MEM_freeN(selectFlags); } } countall(); allqueue(REDRAWVIEW3D, 0); - BIF_undo_push("Select More"); + BIF_undo_push("Select Less"); } -void select_less_nurb() +/* this function could be moved elsewhere as it can be reused in other parts of the source needing randomized list */ +/* returns list containing -1 in indices that have been left out of the list. otherwise index contains reference */ +/* to next index. basically *list contains a linked list */ +static void generate_pickable_list(int *list, int size, int pickamount) +{ + int i, j, removable; + + BLI_srand( BLI_rand() ); /* random seed */ + + /* generate list in form 0->1, 1->2, 2->3, ... i-2->i-1, i->0 */ + for(i=0; i<size; i++) { + if(i == size-1) list[i]= 0; + else list[i]= i+1; + } + + for(i=0; i<size-pickamount; i++) { + removable= floor(BLI_frand()*(size-1)+0.5); /* with rounding. frand returns [0,1] */ + + /* seek proper item as the one randomly selected might not be appropriate */ + for(j=0; j<size; j++, removable++) { + if(list[removable] != -1) break; + if(removable == size-1) removable= -1; + } + + /* pick unwanted item out of the list */ + list[list[removable]]= -1; /* mark former last as invalid */ + + if(list[removable] == size-1) list[removable]= 0; + else list[removable]= list[removable]+1; + } +} + +void select_random_nurb() { Nurb *nu; - /* BPoint *bp; */ BezTriple *bezt; - int *selectFlags; /* array of ints*/ - int totCount=0, totSel=0, totChange=0, i; + BPoint *bp; + static short randfac= 50; + int amounttoselect, amountofcps, a, i, k= 0; + int *itemstobeselected; + + if(!G.obedit) return; - if(G.obedit==0) return; + if(!button(&randfac,0, 100,"Percentage:")) return; - for(nu= editNurb.first; nu; nu= nu->next) { - /* check what type of curve/nurb it is */ - if((nu->type & 7)==CU_BEZIER) { - totCount= nu->pntsu; - totSel= 0; - selectFlags= MEM_callocN(sizeof(int)*totCount, "selectlist"); - - /* find out which beztriples are selected */ - for (i=0; i<totCount; i++) { - bezt= (nu->bezt + i); - selectFlags[i]= BEZSELECTED(bezt); - if (selectFlags[i]) totSel++; - } - - /* determine best course of action */ - if (totSel<=1) { - /* not enough to select-less of */ - MEM_freeN(selectFlags); - continue; - } - else if (totSel==totCount) { - /* deselect first and last points */ - selectFlags[0]= 2; - selectFlags[totCount-1]= 2; - totChange= 2; - } - else { - /* find out which ones deserve an extra flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 1) { - if ((i < (totCount-1)) && (selectFlags[i+1] == 0)) { - selectFlags[i] = 2; - totChange++; - } - else if ((i != 0) && (selectFlags[i-1] == 0)) { - selectFlags[i] = 2; - totChange++; - } - } - } - - /* second pass - for the ends. done after as it may affect results */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 1) { - if ((i==0) && (i != (totCount-1)) && (selectFlags[i+1] == 1)) { - selectFlags[i] = 2; - totChange++; - } - else if ((i==(totCount-1)) && (i!=0) && (selectFlags[i-1] == 1)) { - selectFlags[i] = 2; - totChange++; - } - } - } - } - - /* set select flags based on select flag */ - for (i=0; i<totCount; i++) { - if (selectFlags[i] == 2) { - bezt = (nu->bezt + i); - - if (bezt->hide == 0) { - bezt->f1 &= ~1; - bezt->f2 &= ~1; - bezt->f3 &= ~1; - } - } + if(randfac == 0) return; + + amountofcps= count_curveverts_without_handles(&editNurb); + itemstobeselected= MEM_callocN(sizeof(int) * amountofcps, "selectitems"); + amounttoselect= floor(randfac * amountofcps / 100 + 0.5); + generate_pickable_list(itemstobeselected, amountofcps, amounttoselect); + + /* select elements */ + for(i=1, nu= editNurb.first; nu; nu= nu->next) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(itemstobeselected[k] != -1) select_beztriple(bezt, SELECT, 1, VISIBLE); + k++; + bezt++; } - - /* free tempolary array */ - MEM_freeN(selectFlags); } else { - /* TODO: figure out method of nurbs surfaces */ - } + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + if(itemstobeselected[k] != -1) select_bpoint(bp, SELECT, 1, VISIBLE); + k++; + bp++; + } + } } + + MEM_freeN(itemstobeselected); + + countall(); + allqueue(REDRAWVIEW3D, 0); + BIF_undo_push("Select Random"); +} + +void select_every_nth_nurb() +{ + static short nfac= 2; + + if(!G.obedit) return; + + if(!button(&nfac, 2, 25,"N:")) return; + + select_adjacent_cp(nfac, 1, SELECT); + select_adjacent_cp(-nfac, 1, SELECT); countall(); allqueue(REDRAWVIEW3D, 0); - BIF_undo_push("Select Less"); + BIF_undo_push("Select Every Nth"); } void adduplicate_nurb() diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 21683920bf8..98b90485415 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1104,17 +1104,17 @@ void do_view3d_select_curvemenu(void *arg, int event) /* select connected control points */ /*case 4: G.qual |= LR_CTRLKEY; - selectconnected_nurb(); + select_connected_nurb(); G.qual &= ~LR_CTRLKEY; break;*/ case 5: /* select row (nurb) */ selectrow_nurb(); break; case 7: /* select/deselect first */ - selectends_nurb(1); + selectend_nurb(FIRST, 1, DESELECT); break; case 8: /* select/deselect last */ - selectends_nurb(0); + selectend_nurb(LAST, 1, DESELECT); break; case 9: /* select more */ select_more_nurb(); @@ -1128,6 +1128,12 @@ void do_view3d_select_curvemenu(void *arg, int event) case 12: /* select previous */ select_prev_nurb(); break; + case 13: /* select random */ + select_random_nurb(); + break; + case 14: /* select every nth */ + select_every_nth_nurb(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1147,6 +1153,8 @@ static uiBlock *view3d_select_curvemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Every Nth", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); if (OBACT->type == OB_SURF) { uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index ec43d55a2bd..e3085468442 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2501,11 +2501,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if ( (G.qual==LR_CTRLKEY) && (G.obedit) && (G.obedit->type==OB_CURVE) ) select_less_nurb(); - /* else if ( (G.qual==LR_CTRLKEY) && (G.obedit) && (G.obedit->type==OB_SURF) ) select_less_nurb(); - */ else { persptoetsen(event); doredraw= 1; @@ -2519,11 +2517,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if ( (G.qual==LR_CTRLKEY) && (G.obedit) && (G.obedit->type==OB_CURVE) ) select_more_nurb(); - /* else if ( (G.qual==LR_CTRLKEY) && (G.obedit) && (G.obedit->type==OB_SURF) ) select_more_nurb(); - */ else { persptoetsen(event); doredraw= 1; diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 1ef328272d6..d888eb22667 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -949,7 +949,9 @@ static TBitem tb_curve_select[]= { { 0, "SEPR", 0, NULL}, { 0, "(De)select All|A", 2, NULL}, { 0, "Inverse", 3, NULL}, -{ 0, "Row|Shift R", 5, NULL}, +{ 0, "Random...", 13, NULL}, +{ 0, "Every Nth", 14, NULL}, +{ 0, "Row|Shift R", 5, NULL}, /* shouldn't be visible in case of bezier curves*/ { 0, "SEPR", 0, NULL}, { 0, "(De)select First", 7, NULL}, { 0, "(De)select Last", 8, NULL}, |